Compare commits

...

38 Commits

Author SHA1 Message Date
5f76be9d76 Version leap to 1.2.0 2012-01-27 10:59:50 +01:00
305fe3f496 Updated changelog 2012-01-27 10:56:50 +01:00
191c3245af Corrected libburnia domain name in AAIP documentation 2012-01-24 14:48:42 +01:00
b5b30b1c75 Updated ChangeLog 2012-01-24 14:00:27 +01:00
6a1bbaa902 Extended influence of iso_write_opts_set_dir_rec_mtime() to Joliet and
ISO 9660:1999.
2012-01-14 15:54:25 +01:00
bddc44d1ca Added ./bootstrap script to release tarball 2011-12-03 15:58:38 +01:00
9b61ff377c Removing demo/.libs with make clean 2011-12-03 15:43:18 +01:00
22fed6bedb Reacted on warning of cppcheck 2011-10-09 18:26:13 +02:00
3433592f69 Version leap to 1.1.7 2011-09-27 14:33:07 +02:00
d787ecbcd9 Version leap to 1.1.6 2011-09-27 14:29:18 +02:00
182edb3a00 Updated changelog 2011-09-26 19:10:13 +02:00
cb25d4d4e5 Clarified a remark about maximum length of RR name parts in CA. 2011-09-26 18:23:24 +02:00
afdef92343 Moved version number macros higher in libisofs/libisofs.h 2011-09-24 16:38:20 +02:00
2bc7084315 Adaptions and remarks about GNU/Hurd 2011-08-30 19:20:18 +02:00
6d10908a58 Detecting and rejecting multiple entries of user::, group::, other:: in ACL text 2011-08-24 09:23:02 +02:00
2ba54fafe7 New optional tolerance towards failure to restore "default" ACLS on FreeBSD. 2011-08-23 12:40:09 +02:00
ca63dac7e3 Enabled recording and restoring of extattr on FreeBSD.
Gave up unconditional ACL support in favor of configure control.
2011-08-22 17:10:13 +02:00
f885da8087 Avoided to restore xattr of namespace "isofs" if non-"user" restoring is
enabled.
2011-08-22 15:57:16 +02:00
8438db02cf Avoided to call calloc() for 0 bytes when reading Linux xattr. 2011-08-22 12:37:11 +02:00
ce19db5e19 Bug fix: On Solaris: False out-of-memory errors when writing images. 2011-08-19 12:40:45 +02:00
aeb5258ae2 Removed rogue comma from FreeBSD ACL adapter 2011-08-18 16:06:33 +02:00
f10c2d7779 New API call iso_local_attr_support() 2011-08-18 15:07:31 +02:00
82bfcf429a Bug fix: No ACLs were recorded on FreeBSD. 2011-08-18 10:29:34 +02:00
8fb8c01a0f Corrected a theoretical flaw in a code path which is not yet used. 2011-08-18 10:28:41 +02:00
73910e2f3c Bug fix: ACL entries of groups and of user id 0 were not properly recorded
and cannot be restored.
2011-08-18 10:26:09 +02:00
9c5fc21679 Small change in a comment 2011-08-18 10:24:47 +02:00
3a82f213e0 Implemented direct iconv conversion for the case that the traditional
two-step conversion via character set "WCHAR_T" fails. E.g. on Solaris.
2011-08-11 18:22:49 +02:00
6892c734e2 Bug fix: The function for restoring ACLs and xattr returned error on
FreeBSD, even if no xattr were to be restored.
2011-08-09 19:00:03 +02:00
66f6937c17 Clarified stream version prescription and made internal stream data
instances static.
2011-08-09 14:59:19 +02:00
baa5b7cd42 Added missing symbol serial_id to libisofs.ver 2011-08-09 14:58:46 +02:00
f2658ef173 Started new development cycle 2011-08-09 12:32:04 +02:00
ecdb3aeb1d Version leap to 1.1.5 2011-08-08 13:58:43 +02:00
745a878884 Version leap to 1.1.4 2011-08-08 09:35:46 +02:00
6ae8386c23 Bug fix: The function for restoring ACLs and xattr returned error on systems
other than Linux and FreeBSD, even if nothing was to be restored.
2011-08-08 08:25:18 +02:00
b90e613246 Reacted on warnings of cppcheck 2011-07-11 12:44:12 +02:00
bbc3caf86b Reacted on warnings of cppcheck 2011-07-11 12:43:12 +02:00
b086d53274 Reacted on warnings of cppcheck 2011-07-11 12:41:30 +02:00
17b36623a6 Version leap to 1.1.3 2011-07-08 14:42:09 +02:00
21 changed files with 1235 additions and 251 deletions

View File

@ -1,3 +1,24 @@
libisofs-1.2.0.tar.gz Sat Jan 28 2012
===============================================================================
* Extended influence of iso_write_opts_set_dir_rec_mtime() to Joliet and
ISO 9660:1999.
libisofs-1.1.6.tar.gz Tue Sep 27 2011
===============================================================================
* Bug fix: On Solaris: False out-of-memory errors when writing images.
* Bug fix: On FreeBSD: No ACLs were recorded.
* Bug fix: ACL entries of groups and of user id 0 were not properly recorded
and cannot be restored.
* Bug fix: On FreeBSD: The function for restoring ACLs and xattr returned
error, even if no xattr were to be restored.
* New API call iso_local_attr_support()
* Enabled recording and restoring of extattr on FreeBSD.
libisofs-1.1.4.tar.gz Mon Aug 08 2011
===============================================================================
* Bug fix: The function for restoring ACLs and xattr returned error on systems
other than Linux and FreeBSD, even if nothing was to be restored.
libisofs-1.1.2.tar.gz Fri Jul 08 2011 libisofs-1.1.2.tar.gz Fri Jul 08 2011
=============================================================================== ===============================================================================
* New API call iso_image_get_bootcat() * New API call iso_image_get_bootcat()

View File

@ -220,6 +220,12 @@ demo_demo_SOURCES = demo/demo.c
# test/mocked_fsrc.h \ # test/mocked_fsrc.h \
# test/mocked_fsrc.c # test/mocked_fsrc.c
# "make clean" shall remove a few stubborn .libs directories
# which George Danchev reported Dec 03 2011.
# Learned from: http://www.gnu.org/software/automake/manual/automake.html#Clean
clean-local:
-rm -rf demo/.libs
## ========================================================================= ## ## ========================================================================= ##
## Build documentation (You need Doxygen for this to work) ## Build documentation (You need Doxygen for this to work)
@ -250,6 +256,7 @@ nodist_pkgconfig_DATA = \
# ts A80114 : added aaip-os* # ts A80114 : added aaip-os*
EXTRA_DIST = \ EXTRA_DIST = \
bootstrap \
libisofs-1.pc.in \ libisofs-1.pc.in \
version.h.in \ version.h.in \
doc/doxygen.conf.in \ doc/doxygen.conf.in \

View File

@ -1,4 +1,4 @@
AC_INIT([libisofs], [1.1.2], [http://libburnia-project.org]) AC_INIT([libisofs], [1.2.0], [http://libburnia-project.org])
AC_PREREQ([2.50]) AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h]) dnl AC_CONFIG_HEADER([config.h])
@ -40,8 +40,8 @@ dnl
dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match. dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match.
dnl dnl
LIBISOFS_MAJOR_VERSION=1 LIBISOFS_MAJOR_VERSION=1
LIBISOFS_MINOR_VERSION=1 LIBISOFS_MINOR_VERSION=2
LIBISOFS_MICRO_VERSION=2 LIBISOFS_MICRO_VERSION=0
LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
AC_SUBST(LIBISOFS_MAJOR_VERSION) AC_SUBST(LIBISOFS_MAJOR_VERSION)
@ -51,10 +51,10 @@ AC_SUBST(LIBISOFS_VERSION)
dnl Libtool versioning dnl Libtool versioning
LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
# 2011.07.08 development jump has not yet happened # 2012.01.28 development jump has not yet happened
# SONAME = 56 - 50 = 6 . Library name = libisofs.6.50.0 # SONAME = 62 - 56 = 6 . Library name = libisofs.6.56.0
LT_CURRENT=56 LT_CURRENT=62
LT_AGE=50 LT_AGE=56
LT_REVISION=0 LT_REVISION=0
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE` LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
@ -160,14 +160,19 @@ LIBBURNIA_SET_PKGCONFIG
dnl Add compiler-specific flags dnl Add compiler-specific flags
AC_ARG_ENABLE(libacl, AC_ARG_ENABLE(libacl,
[ --enable-libacl Enable use of libacl by libisofs, default=yes], [ --enable-libacl Enable use of ACL functions by libisofs, default=yes],
, enable_libacl=yes) , enable_libacl=yes)
if test "x$enable_libacl" = xyes; then if test "x$enable_libacl" = xyes; then
dnl Check whether there is libacl-devel and libacl-runtime. dnl Check whether there is libacl-devel and libacl-runtime.
dnl If not, erase this macro which would enable use of acl_to_text and others dnl If not, erase this macro which would enable use of acl_to_text and others
LIBACL_DEF="-DLibisofs_with_aaip_acL" LIBACL_DEF="-DLibisofs_with_aaip_acL"
dnl The empty yes case obviously causes -lacl to be linked dnl The empty yes case obviously causes -lacl to be linked
AC_CHECK_HEADER(sys/acl.h, AC_CHECK_LIB(acl, acl_to_text, , LIBACL_DEF= ), LIBACL_DEF= ) has_acl_h_but_no_func=0
AC_CHECK_HEADER(sys/acl.h, AC_CHECK_LIB(acl, acl_to_text, , has_acl_h_but_no_libacl=1 ), LIBACL_DEF= )
if test "$has_acl_h_but_no_libacl" = 1
then
AC_CHECK_LIB(c, acl_to_text, X= , LIBACL_DEF= )
fi
else else
LIBACL_DEF= LIBACL_DEF=
fi fi
@ -183,6 +188,11 @@ dnl Check whether there is the header for Linux xattr.
dnl If not, erase this macro which would enable use of listxattr and others dnl If not, erase this macro which would enable use of listxattr and others
XATTR_DEF="-DLibisofs_with_aaip_xattR" XATTR_DEF="-DLibisofs_with_aaip_xattR"
AC_CHECK_HEADER(attr/xattr.h, AC_CHECK_LIB(c, listxattr, X= , XATTR_DEF= ), XATTR_DEF= ) AC_CHECK_HEADER(attr/xattr.h, AC_CHECK_LIB(c, listxattr, X= , XATTR_DEF= ), XATTR_DEF= )
if test "x$XATTR_DEF" = x
then
XATTR_DEF="-DLibisofs_with_freebsd_extattR"
AC_CHECK_HEADER(sys/extattr.h, AC_CHECK_LIB(c, extattr_list_file, X=, XATTR_DEF= ), XATTR_DEF= )
fi
else else
XATTR_DEF= XATTR_DEF=
fi fi

View File

@ -157,9 +157,10 @@ types. "system." is file system dependent and often restricted in the
choice of names. "user." is portable and allows to choose about any name. choice of names. "user." is portable and allows to choose about any name.
Namespace "isofs." is defined for internal use of AAIP enhanced ISO 9660 Namespace "isofs." is defined for internal use of AAIP enhanced ISO 9660
file systems. Names in this namespace should be registered at libburnia.org. file systems. Names in this namespace should be registered at
libburnia-project.org.
Further namespaces may be registered at libburnia.org. Further namespaces may be registered at libburnia-project.org.
The reserved start bytes of names have the following meaning The reserved start bytes of names have the following meaning
0x01 escape reserved character at start of name 0x01 escape reserved character at start of name

View File

@ -11,7 +11,7 @@
To be included by aaip_0_2.c To be included by aaip_0_2.c
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+ Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
*/ */
@ -28,6 +28,29 @@
#include <sys/stat.h> #include <sys/stat.h>
/* ------------------------------ Inquiry --------------------------------- */
/* See also API iso_local_attr_support().
@param flag
Bitfield for control purposes
bit0= inquire availability of ACL
bit1= inquire availability of xattr
bit2 - bit7= Reserved for future types.
It is permissibile to set them to 1 already now.
bit8 and higher: reserved, submit 0
@return
Bitfield corresponding to flag. If bits are set, th
bit0= ACL adapter is enabled
bit1= xattr adapter is enabled
bit2 - bit7= Reserved for future types.
bit8 and higher: reserved, do not interpret these
*/
int aaip_local_attr_support(int flag)
{
return(0);
}
/* ------------------------------ Getters --------------------------------- */ /* ------------------------------ Getters --------------------------------- */
/* Obtain the ACL of the given file in long text form. /* Obtain the ACL of the given file in long text form.
@ -89,8 +112,12 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
continue; continue;
} }
/* Extended Attribute */ /* Extended Attribute */
if(!(flag & 4)) if(flag & 4)
return(-6); continue;
if(!(flag & 8))
if(strncmp(names[i], "user.", 5))
continue;
return(-6);
} }
if(flag & 2) if(flag & 2)
return(-6); return(-6);

View File

@ -7,7 +7,7 @@
To be included by aaip_0_2.c To be included by aaip_0_2.c
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2 Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
*/ */
@ -24,15 +24,51 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#ifndef Libisofs_with_aaip_acL
/* It seems ACL is fixely integrated in FreeBSD libc. There is no libacl. */
#define Libisofs_with_aaip_acL yes
#endif
#ifdef Libisofs_with_aaip_acL #ifdef Libisofs_with_aaip_acL
#include <sys/acl.h> #include <sys/acl.h>
#endif #endif
#ifdef Libisofs_with_freebsd_extattR
#include <sys/extattr.h>
#endif
/* <<< Use old ACL adapter code that is unable to deal with extattr */
/* # define Libisofs_old_freebsd_acl_adapteR */
/* ------------------------------ Inquiry --------------------------------- */
/* See also API iso_local_attr_support().
@param flag
Bitfield for control purposes
bit0= inquire availability of ACL
bit1= inquire availability of xattr
bit2 - bit7= Reserved for future types.
It is permissibile to set them to 1 already now.
bit8 and higher: reserved, submit 0
@return
Bitfield corresponding to flag. If bits are set, th
bit0= ACL adapter is enabled
bit1= xattr adapter is enabled
bit2 - bit7= Reserved for future types.
bit8 and higher: reserved, do not interpret these
*/
int aaip_local_attr_support(int flag)
{
int ret= 0;
#ifdef Libisofs_with_aaip_acL
if(flag & 1)
ret|= 1;
#endif
#ifdef Libisofs_with_freebsd_extattR
if(flag & 2)
ret|= 2;
#endif
return(ret);
}
/* ------------------------------ Getters --------------------------------- */ /* ------------------------------ Getters --------------------------------- */
@ -137,6 +173,349 @@ int aaip_get_acl_text(char *path, char **text, int flag)
} }
#ifndef Libisofs_old_freebsd_acl_adapteR
#ifdef Libisofs_with_freebsd_extattR
/*
@param flag Bitfield for control purposes
bit5= in case of symbolic link: inquire link target
*/
static int aaip_extattr_make_list(char *path, int attrnamespace,
char **list, ssize_t *list_size, int flag)
{
*list= NULL;
*list_size= 0;
/* man 2 extattr_list_file:
If data is NULL in a call to extattr_get_file() and extattr_list_file()
then the size of defined extended attribute data will be returned,
*/
if(flag & 32) /* follow link */
*list_size= extattr_list_file(path, attrnamespace, NULL, (size_t) 0);
else
*list_size= extattr_list_link(path, attrnamespace, NULL, (size_t) 0);
if(*list_size == -1)
return(0);
if(*list_size == 0)
return(2);
*list= calloc(*list_size, 1);
if(*list == NULL)
return(-1);
if(flag & 32)
*list_size= extattr_list_file(path, attrnamespace, *list,
(size_t) *list_size);
else
*list_size= extattr_list_link(path, attrnamespace, *list,
(size_t) *list_size);
if(*list_size == -1)
return(0);
return(1);
}
/*
@param flag Bitfield for control purposes
bit0= preserve existing namelist content
bit1= ignore names with NUL rather than returning error
*/
static int aaip_extattr_make_namelist(char *path, char *attrnamespace,
char *list, ssize_t list_size,
char **namelist, ssize_t *namelist_size,
ssize_t *num_names, int flag)
{
int i, j, len, new_bytes= 0, space_len;
char *new_list= NULL, *wpt;
if(!(flag & 1)) {
*namelist= NULL;
*namelist_size= 0;
*num_names= 0;
}
if(list_size <= 0)
return(1);
space_len= strlen(attrnamespace);
for(i= 0; i < list_size; i+= len + 1) {
len= *((unsigned char *) (list + i));
if(len == 0)
return ISO_AAIP_BAD_ATTR_NAME; /* empty name is reserved for ACL */
for(j= 0; j < len; j++)
if(list[i + 1 + j] == 0) {
if(flag & 2)
continue;
return ISO_AAIP_BAD_ATTR_NAME; /* names may not contain 0-bytes */
}
new_bytes+= space_len + 1 + len + 1;
}
if((flag & 1) && *namelist_size > 0)
new_bytes+= *namelist_size;
new_list= calloc(new_bytes, 1);
if(new_list == NULL)
return(ISO_OUT_OF_MEM);
wpt= new_list;
if((flag & 1) && *namelist_size > 0) {
memcpy(new_list, *namelist, *namelist_size);
wpt= new_list + *namelist_size;
}
for(i= 0; i < list_size; i+= len + 1) {
len= *((unsigned char *) (list + i));
if(flag & 2) {
for(j= 0; j < len; j++)
if(list[i + j] == 0)
continue;
}
memcpy(wpt, attrnamespace, space_len);
wpt[space_len]= '.';
wpt+= space_len + 1;
memcpy(wpt, list + i + 1, len);
wpt+= len;
*(wpt++)= 0;
(*num_names)++;
}
if((flag & 1) && *namelist != NULL)
free(*namelist);
*namelist= new_list;
*namelist_size= new_bytes;
return(1);
}
#endif /* Libisofs_with_freebsd_extattR */
/* Obtain the Extended Attributes and/or the ACLs of the given file in a form
that is ready for aaip_encode().
@param path Path to the file
@param num_attrs Will return the number of name-value pairs
@param names Will return an array of pointers to 0-terminated names
@param value_lengths Will return an arry with the lenghts of values
@param values Will return an array of pointers to 8-bit values
@param flag Bitfield for control purposes
bit0= obtain ACL (access and eventually default)
bit1= use numeric ACL qualifiers rather than names
bit2= do not obtain attributes other than ACL
bit3= do not ignore eventual non-user attributes
I.e. those with a name which does not begin
by "user."
bit4= do not return trivial ACL that matches st_mode
bit5= in case of symbolic link: inquire link target
bit15= free memory of names, value_lengths, values
@return >0 ok
<=0 error
-1= out of memory
-2= program error with prediction of result size
-3= error with conversion of name to uid or gid
*/
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
size_t **value_lengths, char ***values, int flag)
{
int ret;
ssize_t i, num_names= 0, acl_names= 0;
#ifdef Libisofs_with_aaip_acL
unsigned char *a_acl= NULL;
char *a_acl_text= NULL;
size_t a_acl_len= 0;
#endif
#ifdef Libisofs_with_freebsd_extattR
char *list= NULL, *user_list= NULL, *sys_list= NULL, *namept;
ssize_t value_ret, retry= 0, list_size= 0, user_list_size= 0;
ssize_t sys_list_size= 0;
int attrnamespace;
#endif
if(flag & (1 << 15)) { /* Free memory */
{ret= 1; goto ex;}
}
*num_attrs= 0;
*names= NULL;
*value_lengths= NULL;
*values= NULL;
/* Set up arrays */
#ifdef Libisofs_with_freebsd_extattR
if(!(flag & 4)) { /* Get extattr names */
/* Linux : Names are encoded as name NUL
FreeBSD: Names are encoded as length_byte:chars (no NUL)
AAIP demands names not to contain NUL bytes.
*/
/* Obtain lists of names
Must be done separately for namespaces. See man 9 extattr :
EXTATTR_NAMESPACE_USER , EXTATTR_NAMESPACE_SYSTEM
Must then be marked by "user." and "system." for libisofs use.
*/
ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER,
&user_list, &user_list_size, flag & 32);
if(ret <= 0)
{ret= -1; goto ex;}
if(flag & 8) {
ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_SYSTEM,
&sys_list, &sys_list_size, flag & 32);
if(ret <= 0)
{ret= -1; goto ex;}
}
/* Check for NUL in names, convert into a linuxish list of namespace.name */
ret= aaip_extattr_make_namelist(path, "user", user_list, user_list_size,
&list, &list_size, &num_names, 0);
if(ret <= 0)
goto ex;
ret= aaip_extattr_make_namelist(path, "system", sys_list, sys_list_size,
&list, &list_size, &num_names, 1);
if(ret <= 0)
goto ex;
}
#endif /* Libisofs_with_freebsd_extattR */
#ifdef Libisofs_with_aaip_acL
if(flag & 1) {
num_names++;
acl_names= 1;
}
#endif
if(num_names == 0)
{ret= 1; goto ex;}
(*names)= calloc(num_names, sizeof(char *));
(*value_lengths)= calloc(num_names, sizeof(size_t));
(*values)= calloc(num_names, sizeof(char *));
if(*names == NULL || *value_lengths == NULL || *values == NULL)
{ret= -1; goto ex;}
for(i= 0; i < num_names; i++) {
(*names)[i]= NULL;
(*values)[i]= NULL;
(*value_lengths)[i]= 0;
}
#ifdef Libisofs_with_freebsd_extattR
if(!(flag & 4)) { /* Get xattr values */
for(i= 0; i < list_size && (size_t) num_names - acl_names > *num_attrs;
i+= strlen(list + i) + 1) {
if(!(flag & 8))
if(strncmp(list + i, "user.", 5))
continue;
(*names)[(*num_attrs)++]= strdup(list + i);
if((*names)[(*num_attrs) - 1] == NULL)
{ret= -1; goto ex;}
}
for(i= 0; (size_t) i < *num_attrs; i++) {
if(strncmp((*names)[i], "user.", 5) == 0) {
attrnamespace= EXTATTR_NAMESPACE_USER;
namept= (*names)[i] + 5;
} else {
if(!(flag & 8))
continue;
attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
namept= (*names)[i] + 7;
}
/* Predict length of value */
if(flag & 32) /* follow link */
value_ret= extattr_get_file(path, attrnamespace, namept,
NULL, (size_t) 0);
else
value_ret= extattr_get_link(path, attrnamespace, namept,
NULL, (size_t) 0);
if(value_ret == -1)
continue;
(*values)[i]= calloc(value_ret + 1, 1);
if((*values)[i] == NULL)
{ret= -1; goto ex;}
/* Obtain value */
if(flag & 32) /* follow link */
value_ret= extattr_get_file(path, attrnamespace, namept,
(*values)[i], (size_t) value_ret);
else
value_ret= extattr_get_link(path, attrnamespace, namept,
(*values)[i], (size_t) value_ret);
if(value_ret == -1) { /* there could be a race condition */
if(retry++ > 5)
{ret= -1; goto ex;}
i--;
continue;
}
(*value_lengths)[i]= value_ret;
retry= 0;
}
}
#endif /* Libisofs_with_freebsd_extattR */
#ifdef Libisofs_with_aaip_acL
if(flag & 1) { /* Obtain ACL */
/* access-ACL */
aaip_get_acl_text(path, &a_acl_text, flag & (16 | 32));
if(a_acl_text == NULL)
{ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */
ret= aaip_encode_acl(a_acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2);
if(ret <= 0)
goto ex;
/* Note: There are no default-ACL in FreeBSD */
/* Set as attribute with empty name */;
(*names)[*num_attrs]= strdup("");
if((*names)[*num_attrs] == NULL)
{ret= -1; goto ex;}
(*values)[*num_attrs]= (char *) a_acl;
a_acl= NULL;
(*value_lengths)[*num_attrs]= a_acl_len;
(*num_attrs)++;
}
#endif /* Libisofs_with_aaip_acL */
ret= 1;
ex:;
#ifdef Libisofs_with_aaip_acL
if(a_acl != NULL)
free(a_acl);
if(a_acl_text != NULL)
aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
#endif
#ifdef Libisofs_with_freebsd_extattR
if(list != NULL)
free(list);
if(user_list != NULL)
free(user_list);
if(sys_list != NULL)
free(sys_list);
#endif
if(ret <= 0 || (flag & (1 << 15))) {
if(*names != NULL) {
for(i= 0; (size_t) i < *num_attrs; i++)
free((*names)[i]);
free(*names);
}
*names= NULL;
if(*value_lengths != NULL)
free(*value_lengths);
*value_lengths= NULL;
if(*values != NULL) {
for(i= 0; (size_t) i < *num_attrs; i++)
free((*values)[i]);
free(*values);
}
*values= NULL;
*num_attrs= 0;
}
return(ret);
}
#else /* ! Libisofs_old_freebsd_acl_adapteR */
/* Obtain the Extended Attributes and/or the ACLs of the given file in a form /* Obtain the Extended Attributes and/or the ACLs of the given file in a form
that is ready for aaip_encode(). that is ready for aaip_encode().
@ -152,20 +531,28 @@ int aaip_get_acl_text(char *path, char **text, int flag)
bit0= obtain ACL (access and eventually default) bit0= obtain ACL (access and eventually default)
bit1= use numeric ACL qualifiers rather than names bit1= use numeric ACL qualifiers rather than names
bit2= do not encode attributes other than ACL bit2= do not encode attributes other than ACL
bit3= -reserved- bit3= do not ignore eventual non-user attributes
I.e. those which are not from name space
EXTATTR_NAMESPACE_USER
bit4= do not return trivial ACL that matches st_mode bit4= do not return trivial ACL that matches st_mode
bit15= free memory of names, value_lengths, values bit15= free memory of names, value_lengths, values
@return >0 ok @return >0 ok
<=0 error <=0 error
-1= out of memory
-2= program error with prediction of result size
-3= error with conversion of name to uid or gid
*/ */
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
size_t **value_lengths, char ***values, int flag) size_t **value_lengths, char ***values, int flag)
{ {
int ret; int ret;
ssize_t i, num_names; ssize_t i, num_names;
size_t a_acl_len= 0, acl_len= 0;
unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL; #ifdef Libisofs_with_aaip_acL
size_t a_acl_len= 0;
unsigned char *a_acl= NULL;
char *acl_text= NULL; char *acl_text= NULL;
#endif
if(flag & (1 << 15)) { /* Free memory */ if(flag & (1 << 15)) { /* Free memory */
{ret= 1; goto ex;} {ret= 1; goto ex;}
@ -211,21 +598,22 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
(*names)[*num_attrs]= strdup(""); (*names)[*num_attrs]= strdup("");
if((*names)[*num_attrs] == NULL) if((*names)[*num_attrs] == NULL)
{ret= -1; goto ex;} {ret= -1; goto ex;}
(*values)[*num_attrs]= (char *) acl; (*values)[*num_attrs]= (char *) a_acl;
(*value_lengths)[*num_attrs]= acl_len; a_acl= NULL;
(*value_lengths)[*num_attrs]= a_acl_len;
(*num_attrs)++; (*num_attrs)++;
} }
#endif /* Libisofs_with_aaip_acL */ #endif /* ! Libisofs_with_aaip_acL */
ret= 1; ret= 1;
ex:; ex:;
#ifdef Libisofs_with_aaip_acL
if(a_acl != NULL) if(a_acl != NULL)
free(a_acl); free(a_acl);
if(d_acl != NULL)
free(d_acl);
if(acl_text != NULL) if(acl_text != NULL)
aaip_get_acl_text("", &acl_text, 1 << 15); /* free */ aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
#endif /* Libisofs_with_aaip_acL */
if(ret <= 0 || (flag & (1 << 15))) { if(ret <= 0 || (flag & (1 << 15))) {
if(*names != NULL) { if(*names != NULL) {
@ -242,14 +630,14 @@ ex:;
free((*values)[i]); free((*values)[i]);
free(*values); free(*values);
} }
if(acl != NULL)
free(acl);
*values= NULL; *values= NULL;
*num_attrs= 0; *num_attrs= 0;
} }
return(ret); return(ret);
} }
#endif /* Libisofs_old_freebsd_acl_adapteR */
/* ------------------------------ Setters --------------------------------- */ /* ------------------------------ Setters --------------------------------- */
@ -259,9 +647,14 @@ ex:;
@param text The input text (0 terminated, ACL long text form) @param text The input text (0 terminated, ACL long text form)
@param flag Bitfield for control purposes @param flag Bitfield for control purposes
bit0= set default ACL rather than access ACL bit0= set default ACL rather than access ACL
bit5= in case of symbolic link: manipulate link target
bit6= tolerate inappropriate presence or absence of
directory default ACL
@return > 0 ok @return > 0 ok
0 no suitable ACL manipulation adapter available
-1 failure of system ACL service (see errno) -1 failure of system ACL service (see errno)
-2 ACL support not enabled at compile time -2 attempt to manipulate ACL of a symbolic link
without bit5 resp. with no suitable link target
*/ */
int aaip_set_acl_text(char *path, char *text, int flag) int aaip_set_acl_text(char *path, char *text, int flag)
{ {
@ -302,13 +695,200 @@ ex:
#else /* Libisofs_with_aaip_acL */ #else /* Libisofs_with_aaip_acL */
return(-2); return(0);
#endif /* ! Libisofs_with_aaip_acL */ #endif /* ! Libisofs_with_aaip_acL */
} }
#ifndef Libisofs_old_freebsd_acl_adapteR
#ifdef Libisofs_with_freebsd_extattR
/*
@param flag Bitfield for control purposes
bit5= in case of symbolic link: manipulate link target
*/
static int aaip_extattr_delete_names(char *path, int attrnamespace,
char *list, ssize_t list_size, int flag)
{
int len;
char name[256];
ssize_t value_ret, i;
for(i= 0; i < list_size; i+= len + 1) {
len= *((unsigned char *) (list + i));
if(len > 0)
strncpy(name, list + i + 1, len);
name[len]= 0;
if(flag & 32)
value_ret= extattr_delete_file(path, attrnamespace, name);
else
value_ret= extattr_delete_file(path, attrnamespace, name);
if(value_ret == -1)
return(0);
}
return(1);
}
#endif /* Libisofs_with_freebsd_extattR */
/* Bring the given attributes and/or ACLs into effect with the given file.
@param flag Bitfield for control purposes
bit0= decode and set ACLs
bit1= first clear all existing attributes of the file
bit2= do not set attributes other than ACLs
bit3= do not ignore eventual non-user attributes.
I.e. those with a name which does not begin
by "user."
bit5= in case of symbolic link: manipulate link target
bit6= tolerate inappropriate presence or absence of
directory default ACL
@return 1 success
-1 error memory allocation
-2 error with decoding of ACL
-3 error with setting ACL
-4 error with setting attribute
-5 error with deleting attributes
-6 support of xattr not enabled at compile time
-7 support of ACL not enabled at compile time
-8 unsupported xattr namespace
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
*/
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
size_t *value_lengths, char **values, int flag)
{
int ret, has_default_acl= 0;
size_t i, consumed, acl_text_fill, acl_idx= 0;
char *acl_text= NULL;
#ifdef Libisofs_with_freebsd_extattR
char *user_list= NULL, *sys_list= NULL, *namept;
ssize_t user_list_size= 0, sys_list_size= 0;
int attrnamespace;
#endif
#ifdef Libisofs_with_freebsd_extattR
if(flag & 2) { /* Delete all file attributes */
ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_USER,
&user_list, &user_list_size, flag & 32);
if(ret <= 0)
{ret= -1; goto ex;}
ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_USER,
user_list, user_list_size, flag & 32);
if(ret <= 0)
{ret= -5; goto ex;}
if(flag & 8) {
ret= aaip_extattr_make_list(path, EXTATTR_NAMESPACE_SYSTEM,
&sys_list, &sys_list_size, flag & 32);
if(ret <= 0)
{ret= -5; goto ex;}
ret= aaip_extattr_delete_names(path, EXTATTR_NAMESPACE_SYSTEM,
sys_list, sys_list_size, flag & 32);
if(ret <= 0)
{ret= -5; goto ex;}
}
}
#endif /* Libisofs_with_freebsd_extattR */
for(i= 0; i < num_attrs; i++) {
if(names[i] == NULL || values[i] == NULL)
continue;
if(names[i][0] == 0) { /* ACLs */
if(flag & 1)
acl_idx= i + 1;
continue;
}
/* Extended Attribute */
if(flag & 4)
continue;
#ifdef Libisofs_with_freebsd_extattR
if(strncmp(names[i], "user.", 5) == 0) {
attrnamespace= EXTATTR_NAMESPACE_USER;
namept= names[i] + 5;
} else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8)) {
continue;
} else if(strncmp(names[i], "system.", 7) == 0) {
attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
namept= names[i] + 7;
} else {
{ret= -8; goto ex;}
}
if(flag & 32)
ret= extattr_set_file(path, attrnamespace, namept,
values[i], value_lengths[i]);
else
ret= extattr_set_link(path, attrnamespace, namept,
values[i], value_lengths[i]);
if(ret == -1)
{ret= -4; goto ex;}
#else
if(strncmp(names[i], "user.", 5) == 0)
;
else if(strncmp(names[i], "isofs.", 6) == 0 || !(flag & 8))
continue;
{ret= -6; goto ex;}
#endif /* Libisofs_with_freebsd_extattR */
}
/* Decode ACLs */
if(acl_idx == 0)
{ret= 1; goto ex;}
i= acl_idx - 1;
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
&consumed, NULL, 0, &acl_text_fill, 1);
if(ret < -3)
goto ex;
if(ret <= 0)
{ret= -2; goto ex;}
acl_text= calloc(acl_text_fill, 1);
if(acl_text == NULL)
{ret= -1; goto ex;}
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
&consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
if(ret < -3)
goto ex;
if(ret <= 0)
{ret= -2; goto ex;}
has_default_acl= (ret == 2);
#ifdef Libisofs_with_aaip_acL
ret= aaip_set_acl_text(path, acl_text, flag & (32 | 64));
if(ret <= 0)
{ret= -3; goto ex;}
#else
{ret= -7; goto ex;}
#endif
if(has_default_acl && !(flag & 64))
{ret= -3; goto ex;}
ret= 1;
ex:;
if(acl_text != NULL)
free(acl_text);
#ifdef Libisofs_with_freebsd_extattR
if(user_list != NULL)
free(user_list);
if(sys_list != NULL)
free(sys_list);
#endif /* Libisofs_with_freebsd_extattR */
return(ret);
}
#else /* ! Libisofs_old_freebsd_acl_adapteR */
/* Bring the given attributes and/or ACLs into effect with the given file. /* Bring the given attributes and/or ACLs into effect with the given file.
Note: There are no Extended Attributes in FreeBSD. So only ACL get set. Note: There are no Extended Attributes in FreeBSD. So only ACL get set.
@ -317,6 +897,9 @@ ex:
bit0= decode and set ACLs bit0= decode and set ACLs
( bit1= first clear all existing attributes of the file ) ( bit1= first clear all existing attributes of the file )
( bit2= do not set attributes other than ACLs ) ( bit2= do not set attributes other than ACLs )
( bit3= do not ignore eventual non-user attributes.
I.e. those with a name which does not begin
by "user." )
@return 1 success @return 1 success
-1 error memory allocation -1 error memory allocation
-2 error with decoding of ACL -2 error with decoding of ACL
@ -338,6 +921,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
continue; continue;
if(names[i][0] == 0) { /* Decode ACLs */ if(names[i][0] == 0) { /* Decode ACLs */
/* access ACL */ /* access ACL */
if(!(flag & 1))
continue;
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
&consumed, NULL, 0, &acl_text_fill, 1); &consumed, NULL, 0, &acl_text_fill, 1);
if(ret <= 0) if(ret <= 0)
@ -379,8 +964,14 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
if(ret <= 0) if(ret <= 0)
{ret= -3; goto ex;} {ret= -3; goto ex;}
} }
} else } else {
if(flag & 4)
continue;
if(!(flag & 8))
if(strncmp(names[i], "user.", 5))
continue;
was_xattr= 1; was_xattr= 1;
}
} }
ret= 1; ret= 1;
if(was_xattr) if(was_xattr)
@ -393,4 +984,5 @@ ex:;
return(ret); return(ret);
} }
#endif /* Libisofs_old_freebsd_acl_adapteR */

View File

@ -7,7 +7,7 @@
To be included by aaip_0_2.c To be included by aaip_0_2.c
Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+ Copyright (c) 2009 - 2011 Thomas Schmitt, libburnia project, GPLv2+
*/ */
@ -34,6 +34,40 @@
#endif #endif
/* ------------------------------ Inquiry --------------------------------- */
/* See also API iso_local_attr_support().
@param flag
Bitfield for control purposes
bit0= inquire availability of ACL
bit1= inquire availability of xattr
bit2 - bit7= Reserved for future types.
It is permissibile to set them to 1 already now.
bit8 and higher: reserved, submit 0
@return
Bitfield corresponding to flag. If bits are set, th
bit0= ACL adapter is enabled
bit1= xattr adapter is enabled
bit2 - bit7= Reserved for future types.
bit8 and higher: reserved, do not interpret these
*/
int aaip_local_attr_support(int flag)
{
int ret= 0;
#ifdef Libisofs_with_aaip_acL
if(flag & 1)
ret|= 1;
#endif
#ifdef Libisofs_with_aaip_xattR
if(flag & 2)
ret|= 2;
#endif
return(ret);
}
/* ------------------------------ Getters --------------------------------- */ /* ------------------------------ Getters --------------------------------- */
/* Obtain the ACL of the given file in long text form. /* Obtain the ACL of the given file in long text form.
@ -144,21 +178,24 @@ int aaip_get_acl_text(char *path, char **text, int flag)
bit15= free memory of names, value_lengths, values bit15= free memory of names, value_lengths, values
@return >0 ok @return >0 ok
<=0 error <=0 error
-1= out of memory
-2= program error with prediction of result size
-3= error with conversion of name to uid or gid
*/ */
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
size_t **value_lengths, char ***values, int flag) size_t **value_lengths, char ***values, int flag)
{ {
int ret; int ret;
char *list= NULL; ssize_t i, num_names= 0;
ssize_t list_size= 0, i, num_names= 0;
unsigned char *acl= NULL;
char *a_acl_text= NULL, *d_acl_text= NULL;
#ifdef Libisofs_with_aaip_acL #ifdef Libisofs_with_aaip_acL
unsigned char *acl= NULL;
char *a_acl_text= NULL, *d_acl_text= NULL;
size_t acl_len= 0; size_t acl_len= 0;
#endif #endif
#ifdef Libisofs_with_aaip_xattR #ifdef Libisofs_with_aaip_xattR
ssize_t value_ret, retry= 0; char *list= NULL;
ssize_t value_ret, retry= 0, list_size= 0;
#endif #endif
if(flag & (1 << 15)) { /* Free memory */ if(flag & (1 << 15)) { /* Free memory */
@ -171,39 +208,42 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
*values= NULL; *values= NULL;
/* Set up arrays */ /* Set up arrays */
if(!(flag & 4)) { /* Get xattr names */
#ifdef Libisofs_with_aaip_xattR #ifdef Libisofs_with_aaip_xattR
if(!(flag & 4)) { /* Get xattr names */
if(flag & 32) if(flag & 32)
list_size= listxattr(path, list, 0); list_size= listxattr(path, list, 0);
else else
list_size= llistxattr(path, list, 0); list_size= llistxattr(path, list, 0);
if(list_size == -1) if(list_size == -1) {
{ret= -1; goto ex;} if(errno == ENOSYS) /* Function not implemented */
list= calloc(list_size, 1); list_size= 0; /* Handle as if xattr was disabled at compile time */
if(list == NULL) else
{ret= -1; goto ex;} {ret= -1; goto ex;}
if(flag & 32) }
list_size= listxattr(path, list, list_size); if(list_size > 0) {
else list= calloc(list_size, 1);
list_size= llistxattr(path, list, list_size); if(list == NULL)
if(list_size == -1) {ret= -1; goto ex;}
{ret= -1; goto ex;} if(flag & 32)
list_size= listxattr(path, list, list_size);
#else /* Libisofs_with_aaip_xattR */ else
list_size= llistxattr(path, list, list_size);
list= strdup(""); if(list_size == -1)
{ret= -1; goto ex;}
#endif /* ! Libisofs_with_aaip_xattR */ }
for(i= 0; i < list_size; i+= strlen(list + i) + 1) for(i= 0; i < list_size; i+= strlen(list + i) + 1)
num_names++; num_names++;
} }
#endif /* ! Libisofs_with_aaip_xattR */
#ifdef Libisofs_with_aaip_acL #ifdef Libisofs_with_aaip_acL
if(flag & 1) if(flag & 1)
num_names++; num_names++;
#endif #endif
if(num_names == 0) if(num_names == 0)
@ -219,7 +259,10 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
(*values)[i]= NULL; (*values)[i]= NULL;
(*value_lengths)[i]= 0; (*value_lengths)[i]= 0;
} }
if(!(flag & 4)) {
#ifdef Libisofs_with_aaip_xattR
if(!(flag & 4)) { /* Get xattr values */
for(i= 0; i < list_size && (size_t) num_names > *num_attrs; for(i= 0; i < list_size && (size_t) num_names > *num_attrs;
i+= strlen(list + i) + 1) { i+= strlen(list + i) + 1) {
if(!(flag & 8)) if(!(flag & 8))
@ -229,11 +272,6 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
if((*names)[(*num_attrs) - 1] == NULL) if((*names)[(*num_attrs) - 1] == NULL)
{ret= -1; goto ex;} {ret= -1; goto ex;}
} }
}
#ifdef Libisofs_with_aaip_xattR
if(!(flag & 4)) { /* Get xattr values */
for(i= 0; (size_t) i < *num_attrs; i++) { for(i= 0; (size_t) i < *num_attrs; i++) {
if(!(flag & 8)) if(!(flag & 8))
if(strncmp((*names)[i], "user.", 5)) if(strncmp((*names)[i], "user.", 5))
@ -291,12 +329,19 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
ret= 1; ret= 1;
ex:; ex:;
#ifdef Libisofs_with_aaip_acL
if(a_acl_text != NULL) if(a_acl_text != NULL)
aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */ aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */
if(d_acl_text != NULL) if(d_acl_text != NULL)
aaip_get_acl_text("", &d_acl_text, 1 << 15); /* free */ aaip_get_acl_text("", &d_acl_text, 1 << 15); /* free */
if(acl != NULL)
free(acl);
#endif
#ifdef Libisofs_with_aaip_xattR
if(list != NULL) if(list != NULL)
free(list); free(list);
#endif
if(ret <= 0 || (flag & (1 << 15))) { if(ret <= 0 || (flag & (1 << 15))) {
if(*names != NULL) { if(*names != NULL) {
for(i= 0; (size_t) i < *num_attrs; i++) for(i= 0; (size_t) i < *num_attrs; i++)
@ -312,8 +357,6 @@ ex:;
free((*values)[i]); free((*values)[i]);
free(*values); free(*values);
} }
if(acl != NULL)
free(acl);
*values= NULL; *values= NULL;
*num_attrs= 0; *num_attrs= 0;
} }
@ -384,7 +427,9 @@ ex:
bit3= do not ignore eventual non-user attributes. bit3= do not ignore eventual non-user attributes.
I.e. those with a name which does not begin I.e. those with a name which does not begin
by "user." by "user."
bit5= in case of symbolic link: manipulate link target bit5= in case of symbolic link: manipulate link target
bit6= tolerate inappropriate presence or absense of
directory default ACL
@return 1 success @return 1 success
-1 error memory allocation -1 error memory allocation
-2 error with decoding of ACL -2 error with decoding of ACL
@ -393,6 +438,8 @@ ex:
-5 error with deleting attributes -5 error with deleting attributes
-6 support of xattr not enabled at compile time -6 support of xattr not enabled at compile time
-7 support of ACL not enabled at compile time -7 support of ACL not enabled at compile time
( -8 unsupported xattr namespace )
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
*/ */
int aaip_set_attr_list(char *path, size_t num_attrs, char **names, int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
size_t *value_lengths, char **values, int flag) size_t *value_lengths, char **values, int flag)
@ -447,7 +494,11 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
continue; continue;
} }
/* Extended Attribute */ /* Extended Attribute */
if((flag & 1) && !(flag & 8)) if(flag & 4)
continue;
if(strncmp(names[i], "isofs.", 6) == 0)
continue;
if(!(flag & 8))
if(strncmp(names[i], "user.", 5)) if(strncmp(names[i], "user.", 5))
continue; continue;
@ -475,6 +526,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
/* "access" ACL */ /* "access" ACL */
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
&consumed, NULL, 0, &acl_text_fill, 1); &consumed, NULL, 0, &acl_text_fill, 1);
if(ret < -3)
goto ex;
if(ret <= 0) if(ret <= 0)
{ret= -2; goto ex;} {ret= -2; goto ex;}
acl_text= calloc(acl_text_fill, 1); acl_text= calloc(acl_text_fill, 1);
@ -482,6 +535,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
{ret= -1; goto ex;} {ret= -1; goto ex;}
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
&consumed, acl_text, acl_text_fill, &acl_text_fill, 0); &consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
if(ret < -3)
goto ex;
if(ret <= 0) if(ret <= 0)
{ret= -2; goto ex;} {ret= -2; goto ex;}
has_default_acl= (ret == 2); has_default_acl= (ret == 2);
@ -500,6 +555,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed), ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
value_lengths[i] - consumed, &h_consumed, value_lengths[i] - consumed, &h_consumed,
NULL, 0, &acl_text_fill, 1); NULL, 0, &acl_text_fill, 1);
if(ret < -3)
goto ex;
if(ret <= 0) if(ret <= 0)
{ret= -2; goto ex;} {ret= -2; goto ex;}
acl_text= calloc(acl_text_fill, 1); acl_text= calloc(acl_text_fill, 1);
@ -508,11 +565,21 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed), ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
value_lengths[i] - consumed, &h_consumed, value_lengths[i] - consumed, &h_consumed,
acl_text, acl_text_fill, &acl_text_fill, 0); acl_text, acl_text_fill, &acl_text_fill, 0);
if(ret < -3)
goto ex;
if(ret <= 0) if(ret <= 0)
{ret= -2; goto ex;} {ret= -2; goto ex;}
ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32)); ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32));
if(ret <= 0) if(ret <= 0)
{ret= -3; goto ex;} {ret= -3; goto ex;}
} else {
if(!(flag & 64)) {
/* >>> ??? take offense from missing default ACL ?
??? does Linux demand a default ACL for directories with access ACL ?
*/;
}
} }
ret= 1; ret= 1;
ex:; ex:;

View File

@ -95,8 +95,8 @@ size_t aaip_encode(size_t num_attrs, char **names,
size_t *value_lengths, char **values, size_t *value_lengths, char **values,
size_t *result_len, unsigned char **result, int flag) size_t *result_len, unsigned char **result, int flag)
{ {
size_t mem_size= 0, comp_size; size_t mem_size= 0, comp_size, ret;
unsigned int number_of_fields, i, num_recs, ret; unsigned int number_of_fields, i, num_recs;
/* Predict memory needs, number of SUSP fields and component records */ /* Predict memory needs, number of SUSP fields and component records */
*result_len= 0; *result_len= 0;
@ -158,9 +158,9 @@ size_t aaip_encode(size_t num_attrs, char **names,
ret= 0; ret= 0;
for(i= 0; i < *result_len; i+= ((unsigned char *) (*result))[i + 2]) for(i= 0; i < *result_len; i+= ((unsigned char *) (*result))[i + 2])
ret++; ret++;
if(ret != number_of_fields) { if(ret != (int) number_of_fields) {
fprintf(stderr, "aaip_encode(): WRONG NUMBER OF FIELDS %d <> %d\n", fprintf(stderr, "aaip_encode(): WRONG NUMBER OF FIELDS %d <> %d\n",
number_of_fields, ret); (int) number_of_fields, ret);
} }
#endif /* Aaip_encode_debuG */ #endif /* Aaip_encode_debuG */
@ -268,7 +268,11 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
bit3= check for completeness of list and eventually bit3= check for completeness of list and eventually
fill up with entries deduced from st_mode fill up with entries deduced from st_mode
@return >0 means ok @return >0 means ok
0 means error <=0 means error
-1= out of memory
-2= program error with prediction of result size
-3= error with conversion of name to uid or gid
ISO_AAIP_ACL_MULT_OBJ= multiple entries of user::, group::, other::
*/ */
int aaip_encode_acl(char *acl_text, mode_t st_mode, int aaip_encode_acl(char *acl_text, mode_t st_mode,
size_t *result_len, unsigned char **result, int flag) size_t *result_len, unsigned char **result, int flag)
@ -279,8 +283,10 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
*result_len= 0; *result_len= 0;
bytes= aaip_encode_acl_text(acl_text, st_mode, bytes= aaip_encode_acl_text(acl_text, st_mode,
(size_t) 0, NULL, 1 | (flag & (2 | 4 | 8))); (size_t) 0, NULL, 1 | (flag & (2 | 4 | 8)));
if(bytes < -2)
return(bytes);
if(bytes < 0) if(bytes < 0)
return(0); return((int) bytes - 1);
if(flag & 1) { if(flag & 1) {
*result_len= bytes; *result_len= bytes;
return(1); return(1);
@ -292,9 +298,13 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
*result_len= bytes; *result_len= bytes;
bytes= aaip_encode_acl_text(acl_text, st_mode, *result_len, *result, bytes= aaip_encode_acl_text(acl_text, st_mode, *result_len, *result,
(flag & (2 | 4 | 8))); (flag & (2 | 4 | 8)));
if(bytes < -2)
return(bytes);
if(bytes < 0)
return((int) bytes - 1);
if((size_t) bytes != *result_len) { if((size_t) bytes != *result_len) {
*result_len= 0; *result_len= 0;
return(0); return(-2);
} }
return(1); return(1);
} }
@ -341,6 +351,9 @@ static int aaip_make_aaip_perms(int r, int w, int x)
fill up with entries deduced from st_mode fill up with entries deduced from st_mode
@return >=0 number of bytes produced resp. counted @return >=0 number of bytes produced resp. counted
<0 means error <0 means error
-1: result size overflow
-2: conversion errror with user name or group name
ISO_AAIP_ACL_MULT_OBJ: multiple entries of user::, group::, other::
*/ */
static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode, static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
size_t result_size, unsigned char *result, int flag) size_t result_size, unsigned char *result, int flag)
@ -386,6 +399,13 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
if(strncmp(rpt, "user:", 5) == 0) { if(strncmp(rpt, "user:", 5) == 0) {
if(cpt - rpt == 5) { if(cpt - rpt == 5) {
type= Aaip_ACL_USER_OBJ; type= Aaip_ACL_USER_OBJ;
if (has_u) {
/* >>> Duplicate u:: entry. */;
/* >>> ??? If it matches the previous one: ignore */
return((int) ISO_AAIP_ACL_MULT_OBJ);
}
has_u++; has_u++;
} else { } else {
if(cpt - (rpt + 5) >= name_size) if(cpt - (rpt + 5) >= name_size)
@ -398,8 +418,10 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
pwd= getpwnam(name); pwd= getpwnam(name);
if(pwd == NULL) { if(pwd == NULL) {
num= aaip_numeric_id(name, 0); num= aaip_numeric_id(name, 0);
if(num <= 0) if(num <= 0) {
goto user_by_name; /* ACL_USER is not part of AAIP 2.0 */
{ret= -2; goto ex;}
}
uid= huid= num; uid= huid= num;
} else } else
uid= huid= pwd->pw_uid; uid= huid= pwd->pw_uid;
@ -407,31 +429,44 @@ static ssize_t aaip_encode_acl_text(char *acl_text, mode_t st_mode,
for(i= 0; huid != 0; i++) for(i= 0; huid != 0; i++)
huid= huid >> 8; huid= huid >> 8;
qualifier_len= i; qualifier_len= i;
if(qualifier_len <= 0)
qualifier_len= 1;
for(i= 0; i < qualifier_len ; i++) for(i= 0; i < qualifier_len ; i++)
name[i]= uid >> (8 * (qualifier_len - i - 1)); name[i]= uid >> (8 * (qualifier_len - i - 1));
} else { } else {
user_by_name:;
type= Aaip_ACL_USER; type= Aaip_ACL_USER;
qualifier_len= strlen(name); qualifier_len= strlen(name);
if(qualifier_len <= 0)
qualifier_len= 1;
} }
qualifier= 1; qualifier= 1;
} }
} else if(strncmp(rpt, "group:", 6) == 0) { } else if(strncmp(rpt, "group:", 6) == 0) {
if(cpt - rpt == 6) { if(cpt - rpt == 6) {
type= Aaip_ACL_GROUP_OBJ; type= Aaip_ACL_GROUP_OBJ;
if (has_g) {
/* >>> Duplicate g:: entry. */;
/* >>> ??? If it matches the previous one: ignore */
return((int) ISO_AAIP_ACL_MULT_OBJ);
}
has_g++; has_g++;
} else { } else {
if(cpt - (rpt + 6) >= name_size) if(cpt - (rpt + 6) >= name_size)
continue; continue;
is_trivial= 0; is_trivial= 0;
strncpy(name, rpt + 6, cpt - (rpt + 6)); strncpy(name, rpt + 6, cpt - (rpt + 6));
name[cpt - (rpt + 6)]= 0;
if(flag & 2) { if(flag & 2) {
type= Aaip_ACL_GROUP_N; type= Aaip_ACL_GROUP_N;
grp= getgrnam(name); grp= getgrnam(name);
if(grp == NULL) { if(grp == NULL) {
num= aaip_numeric_id(name, 0); num= aaip_numeric_id(name, 0);
if(num <= 0) if(num <= 0) {
goto group_by_name; /* ACL_GROUP is not part of AAIP 2.0 */
{ret= -2; goto ex;}
}
gid= hgid= num; gid= hgid= num;
} else } else
gid= hgid= grp->gr_gid; gid= hgid= grp->gr_gid;
@ -439,18 +474,27 @@ user_by_name:;
for(i= 0; hgid != 0; i++) for(i= 0; hgid != 0; i++)
hgid= hgid >> 8; hgid= hgid >> 8;
qualifier_len= i; qualifier_len= i;
if(qualifier_len <= 0)
qualifier_len= 1;
for(i= 0; i < qualifier_len ; i++) for(i= 0; i < qualifier_len ; i++)
name[i]= gid >> (8 * (qualifier_len - i - 1)); name[i]= gid >> (8 * (qualifier_len - i - 1));
} else { } else {
group_by_name:;
type= Aaip_ACL_GROUP; type= Aaip_ACL_GROUP;
qualifier_len= strlen(name); qualifier_len= strlen(name);
if(qualifier_len <= 0)
qualifier_len= 1;
} }
qualifier= 1; qualifier= 1;
} }
} else if(strncmp(rpt, "other:", 6) == 0) { } else if(strncmp(rpt, "other:", 6) == 0) {
type= Aaip_ACL_OTHER; type= Aaip_ACL_OTHER;
if (has_o) {
/* >>> Duplicate o:: entry. */;
/* >>> ??? If it matches the previous one: ignore */
return((int) ISO_AAIP_ACL_MULT_OBJ);
}
has_o++; has_o++;
} else if(strncmp(rpt, "mask:", 5) == 0) { } else if(strncmp(rpt, "mask:", 5) == 0) {
type= Aaip_ACL_MASK; type= Aaip_ACL_MASK;
@ -2122,8 +2166,9 @@ int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
} }
ret= 1; ret= 1;
ex:; ex:;
*acl_text_fill= w_size;
if(flag & 1) if(flag & 1)
*acl_text_fill= w_size + 1; (*acl_text_fill)++;
LIBISO_FREE_MEM(name); LIBISO_FREE_MEM(name);
return(ret); return(ret);
} }
@ -2141,6 +2186,13 @@ ex:;
#include "aaip-os-linux.c" #include "aaip-os-linux.c"
/* August 2011: aaip-os-linux.c would also work for GNU/Hurd : ifdef __GNU__
Libraries and headers are present on Debian GNU/Hurd but there is no
ACL or xattr support in the filesystems yet.
Further, llistxattr() produces ENOSYS "Function not implemented".
So it makes few sense to enable it here.
*/
#else #else
#include "aaip-os-dummy.c" #include "aaip-os-dummy.c"

View File

@ -56,7 +56,11 @@ size_t aaip_encode(size_t num_attrs, char **names,
bit3= check for completeness of list and eventually bit3= check for completeness of list and eventually
fill up with entries deduced from st_mode fill up with entries deduced from st_mode
@return >0 means ok @return >0 means ok
0 means error <=0 means error
-1= out of memory
-2= program error with prediction of result size
-3= error with conversion of name to uid or gid
ISO_AAIP_ACL_MULT_OBJ= multiple entries of user::, group::, other::
*/ */
int aaip_encode_acl(char *acl_text, mode_t st_mode, int aaip_encode_acl(char *acl_text, mode_t st_mode,
size_t *result_len, unsigned char **result, int flag); size_t *result_len, unsigned char **result, int flag);
@ -80,7 +84,7 @@ int aaip_encode_acl(char *acl_text, mode_t st_mode,
bit3= check for completeness of list and eventually bit3= check for completeness of list and eventually
fill up with entries deduced from st_mode fill up with entries deduced from st_mode
@return >0 means ok @return >0 means ok
0 means error <=0 means error, see aaip_encode_acl
*/ */
int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode, int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, mode_t st_mode,
size_t *result_len, unsigned char **result, int flag); size_t *result_len, unsigned char **result, int flag);
@ -145,6 +149,24 @@ int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag);
/* ------ OS interface ------ */ /* ------ OS interface ------ */
/* See also API iso_local_attr_support().
@param flag
Bitfield for control purposes
bit0= inquire availability of ACL
bit1= inquire availability of xattr
bit2 - bit7= Reserved for future types.
It is permissibile to set them to 1 already now.
bit8 and higher: reserved, submit 0
@return
Bitfield corresponding to flag. If bits are set, th
bit0= ACL adapter is enabled
bit1= xattr adapter is enabled
bit2 - bit7= Reserved for future types.
bit8 and higher: reserved, do not interpret these
*/
int aaip_local_attr_support(int flag);
/* Obtain the ACL of the given file in long text form. /* Obtain the ACL of the given file in long text form.
@param path Path to the file @param path Path to the file
@param text Will hold the result. This is a managed object which @param text Will hold the result. This is a managed object which
@ -478,6 +500,8 @@ int aaip_set_acl_text(char *path, char *text, int flag);
-5 error with deleting attributes -5 error with deleting attributes
-6 support of xattr not enabled at compile time -6 support of xattr not enabled at compile time
-7 support of ACL not enabled at compile time -7 support of ACL not enabled at compile time
-8 unsupported xattr namespace
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
*/ */
int aaip_set_attr_list(char *path, size_t num_attrs, char **names, int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
size_t *value_lengths, char **values, int flag); size_t *value_lengths, char **values, int flag);

View File

@ -363,7 +363,7 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf; struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
IsoNode *iso; IsoNode *iso;
len_dr = 33 + len_fi + (len_fi % 2 ? 0 : 1); len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1);
memcpy(rec->file_id, name, len_fi); memcpy(rec->file_id, name, len_fi);
@ -402,7 +402,7 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
rec->len_dr[0] = len_dr + (info != NULL ? info->suf_len : 0); rec->len_dr[0] = len_dr + (info != NULL ? info->suf_len : 0);
iso_bb(rec->block, block - t->eff_partition_offset, 4); iso_bb(rec->block, block - t->eff_partition_offset, 4);
iso_bb(rec->length, len, 4); iso_bb(rec->length, len, 4);
if (t->dir_rec_mtime) { if (t->dir_rec_mtime & 1) {
iso= node->node; iso= node->node;
iso_datetime_7(rec->recording_time, iso_datetime_7(rec->recording_time,
t->replace_timestamps ? t->timestamp : iso->mtime, t->replace_timestamps ? t->timestamp : iso->mtime,
@ -629,7 +629,7 @@ int write_one_dir(Ecma119Image *t, Ecma119Node *dir, Ecma119Node *parent)
for (section = 0; section < nsections; ++section) { for (section = 0; section < nsections; ++section) {
/* compute len of directory entry */ /* compute len of directory entry */
len = fi_len + 33 + (fi_len % 2 ? 0 : 1); len = fi_len + 33 + ((fi_len % 2) ? 0 : 1);
if (need_version_number(t, child)) { if (need_version_number(t, child)) {
len += 2; len += 2;
} }
@ -2701,7 +2701,13 @@ int iso_write_opts_set_dir_rec_mtime(IsoWriteOpts *opts, int allow)
if (opts == NULL) { if (opts == NULL) {
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
} }
opts->dir_rec_mtime = allow ? 1 : 0; if (allow < 0)
allow = 1;
else if (allow & (1 << 14))
allow &= ~1;
else if (allow & 6)
allow |= 1;
opts->dir_rec_mtime = allow & 7;
return ISO_SUCCESS; return ISO_SUCCESS;
} }

View File

@ -202,8 +202,9 @@ struct iso_write_opts {
* to expect that we do have a creation timestamp with the source. * to expect that we do have a creation timestamp with the source.
* mkisofs writes mtimes and the result seems more suitable if mounted * mkisofs writes mtimes and the result seems more suitable if mounted
* without Rock Ridge support.) * without Rock Ridge support.)
* bit0= ECMA-119, bit1= Joliet, bit2= ISO 9660:1999
*/ */
unsigned int dir_rec_mtime :1; unsigned int dir_rec_mtime :3;
/** /**
* Compute MD5 checksum for the whole session and record it as index 0 of * Compute MD5 checksum for the whole session and record it as index 0 of
@ -476,8 +477,10 @@ struct ecma119_image
/* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12. */ /* Write AAIP as extension according to SUSP 1.10 rather than SUSP 1.12. */
unsigned int aaip_susp_1_10 :1; unsigned int aaip_susp_1_10 :1;
/* Store in ECMA-119 timestamp mtime of source */ /* Store in ECMA-119, Joliet, ISO 9660:1999 timestamp the mtime of source
unsigned int dir_rec_mtime :1; bit0= ECMA-119, bit1= Joliet, bit2= ISO 9660:1999.
*/
unsigned int dir_rec_mtime :3;
unsigned int md5_session_checksum :1; unsigned int md5_session_checksum :1;
unsigned int md5_file_checksums :2; unsigned int md5_file_checksums :2;

View File

@ -514,7 +514,10 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
&value_lengths, &values, &value_lengths, &values,
(!(flag & 2)) | 2 | (flag & 4) | 16); (!(flag & 2)) | 2 | (flag & 4) | 16);
if (ret <= 0) { if (ret <= 0) {
ret = ISO_FILE_ERROR; if (ret == -2)
ret = ISO_AAIP_NO_GET_LOCAL;
else
ret = ISO_FILE_ERROR;
goto ex; goto ex;
} }
if (num_attrs == 0) if (num_attrs == 0)
@ -816,6 +819,15 @@ int iso_local_filesystem_new(IsoFilesystem **fs)
} }
int iso_local_attr_support(int flag)
{
int ret;
ret= aaip_local_attr_support(flag & 255);
return ret;
}
int iso_local_get_acl_text(char *disk_path, char **text, int flag) int iso_local_get_acl_text(char *disk_path, char **text, int flag)
{ {
int ret; int ret;
@ -856,13 +868,19 @@ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names,
int ret; int ret;
ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths, ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths,
values, (flag & (8 | 32)) | !(flag & 1)); values, (flag & (8 | 32 | 64)) | !(flag & 1));
if (ret <= 0) { if (ret <= 0) {
if (ret == -1) if (ret == -1)
return ISO_OUT_OF_MEM; return ISO_OUT_OF_MEM;
if (ret == -2) if (ret == -2)
return ISO_AAIP_BAD_AASTRING; return ISO_AAIP_BAD_AASTRING;
return ISO_AAIP_NO_SET_LOCAL; if (ret >= -5)
return ISO_AAIP_NO_SET_LOCAL;
if (ret == -6 || ret == -7)
return ISO_AAIP_NOT_ENABLED;
if (ret == -8)
return ISO_AAIP_BAD_ATTR_NAME;
return ret;
} }
return 1; return 1;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2011 Thomas Schmitt * Copyright (c) 2011-2012 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -688,8 +688,9 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
: (uint8_t*)node->name; : (uint8_t*)node->name;
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf; struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
IsoNode *iso;
len_dr = 33 + len_fi + (len_fi % 2 ? 0 : 1); len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1);
memcpy(rec->file_id, name, len_fi); memcpy(rec->file_id, name, len_fi);
@ -719,7 +720,15 @@ void write_one_dir_record(Ecma119Image *t, Iso1999Node *node, int file_id,
rec->len_dr[0] = len_dr; rec->len_dr[0] = len_dr;
iso_bb(rec->block, block, 4); iso_bb(rec->block, block, 4);
iso_bb(rec->length, len, 4); iso_bb(rec->length, len, 4);
iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
/* was: iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
*/
iso= node->node;
iso_datetime_7(rec->recording_time,
(t->dir_rec_mtime & 4) ? ( t->replace_timestamps ?
t->timestamp : iso->mtime )
: t->now, t->always_gmt);
rec->flags[0] = ((node->type == ISO1999_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0); rec->flags[0] = ((node->type == ISO1999_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2); iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
rec->len_fi[0] = len_fi; rec->len_fi[0] = len_fi;
@ -837,7 +846,7 @@ int write_one_dir(Ecma119Image *t, Iso1999Node *dir)
/* compute len of directory entry */ /* compute len of directory entry */
fi_len = strlen(child->name); fi_len = strlen(child->name);
len = fi_len + 33 + (fi_len % 2 ? 0 : 1); len = fi_len + 33 + ((fi_len % 2) ? 0 : 1);
nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1; nsections = (child->type == ISO1999_FILE) ? child->info.file->nsections : 1;
for (section = 0; section < nsections; ++section) { for (section = 0; section < nsections; ++section) {

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2007 Vreixo Formoso * Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2007 Mario Danic * Copyright (c) 2007 Mario Danic
* Copyright (c) 2011 Thomas Schmitt * Copyright (c) 2011-2012 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -758,8 +758,9 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
: (uint8_t*)node->name; : (uint8_t*)node->name;
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf; struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
IsoNode *iso;
len_dr = 33 + len_fi + (len_fi % 2 ? 0 : 1); len_dr = 33 + len_fi + ((len_fi % 2) ? 0 : 1);
memcpy(rec->file_id, name, len_fi); memcpy(rec->file_id, name, len_fi);
@ -797,7 +798,15 @@ void write_one_dir_record(Ecma119Image *t, JolietNode *node, int file_id,
rec->len_dr[0] = len_dr; rec->len_dr[0] = len_dr;
iso_bb(rec->block, block - t->eff_partition_offset, 4); iso_bb(rec->block, block - t->eff_partition_offset, 4);
iso_bb(rec->length, len, 4); iso_bb(rec->length, len, 4);
iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
/* was: iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
*/
iso= node->node;
iso_datetime_7(rec->recording_time,
(t->dir_rec_mtime & 2) ? ( t->replace_timestamps ?
t->timestamp : iso->mtime )
: t->now, t->always_gmt);
rec->flags[0] = ((node->type == JOLIET_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0); rec->flags[0] = ((node->type == JOLIET_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
iso_bb(rec->vol_seq_number, (uint32_t) 1, 2); iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
rec->len_fi[0] = len_fi; rec->len_fi[0] = len_fi;

View File

@ -4,7 +4,7 @@
/* /*
* Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic * Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic
* Copyright (c) 2009-2011 Thomas Schmitt * Copyright (c) 2009-2012 Thomas Schmitt
* *
* This file is part of the libisofs project; you can redistribute it and/or * This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2 * modify it under the terms of the GNU General Public License version 2
@ -61,6 +61,88 @@
#include <stdlib.h> #include <stdlib.h>
/**
* The following two functions and three macros are utilities to help ensuring
* version match of application, compile time header, and runtime library.
*/
/**
* These three release version numbers tell the revision of this header file
* and of the API it describes. They are memorized by applications at
* compile time.
* They must show the same values as these symbols in ./configure.ac
* LIBISOFS_MAJOR_VERSION=...
* LIBISOFS_MINOR_VERSION=...
* LIBISOFS_MICRO_VERSION=...
* Note to anybody who does own work inside libisofs:
* Any change of configure.ac or libisofs.h has to keep up this equality !
*
* Before usage of these macros on your code, please read the usage discussion
* below.
*
* @since 0.6.2
*/
#define iso_lib_header_version_major 1
#define iso_lib_header_version_minor 2
#define iso_lib_header_version_micro 0
/**
* Get version of the libisofs library at runtime.
* NOTE: This function may be called before iso_init().
*
* @since 0.6.2
*/
void iso_lib_version(int *major, int *minor, int *micro);
/**
* Check at runtime if the library is ABI compatible with the given version.
* NOTE: This function may be called before iso_init().
*
* @return
* 1 lib is compatible, 0 is not.
*
* @since 0.6.2
*/
int iso_lib_is_compatible(int major, int minor, int micro);
/**
* Usage discussion:
*
* Some developers of the libburnia project have differing opinions how to
* ensure the compatibility of libaries and applications.
*
* It is about whether to use at compile time and at runtime the version
* numbers provided here. Thomas Schmitt advises to use them. Vreixo Formoso
* advises to use other means.
*
* At compile time:
*
* Vreixo Formoso advises to leave proper version matching to properly
* programmed checks in the the application's build system, which will
* eventually refuse compilation.
*
* Thomas Schmitt advises to use the macros defined here for comparison with
* the application's requirements of library revisions and to eventually
* break compilation.
*
* Both advises are combinable. I.e. be master of your build system and have
* #if checks in the source code of your application, nevertheless.
*
* At runtime (via iso_lib_is_compatible()):
*
* Vreixo Formoso advises to compare the application's requirements of
* library revisions with the runtime library. This is to allow runtime
* libraries which are young enough for the application but too old for
* the lib*.h files seen at compile time.
*
* Thomas Schmitt advises to compare the header revisions defined here with
* the runtime library. This is to enforce a strictly monotonous chain of
* revisions from app to header to library, at the cost of excluding some older
* libraries.
*
* These two advises are mutually exclusive.
*/
struct burn_source; struct burn_source;
/** /**
@ -878,15 +960,17 @@ extern ino_t serial_id;
struct IsoStream_Iface struct IsoStream_Iface
{ {
/* /*
* Current version of the interface, set to 1 or 2. * Current version of the interface.
* Version 0 (since 0.6.4) * Version 0 (since 0.6.4)
* deprecated but still valid. * deprecated but still valid.
* Version 1 (since 0.6.8) * Version 1 (since 0.6.8)
* update_size() added. * update_size() added.
* Version 2 (since 0.6.18) * Version 2 (since 0.6.18)
* get_input_stream() added. A filter stream must have version 2. * get_input_stream() added.
* A filter stream must have version 2 at least.
* Version 3 (since 0.6.20) * Version 3 (since 0.6.20)
* compare() added. A filter stream should have version 3. * compare() added.
* A filter stream should have version 3 at least.
* Version 4 (since 1.0.2) * Version 4 (since 1.0.2)
* clone_stream() added. * clone_stream() added.
*/ */
@ -1013,8 +1097,8 @@ struct IsoStream_Iface
* This is also appropriate if one has reason to implement stream.cmp_ino() * This is also appropriate if one has reason to implement stream.cmp_ino()
* without having an own special comparison algorithm. * without having an own special comparison algorithm.
* *
* With filter streams the decision whether the underlying chains of * With filter streams, the decision whether the underlying chains of
* streams match should be delegated to * streams match, should be delegated to
* iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0), * iso_stream_cmp_ino(iso_stream_get_input_stream(s1, 0),
* iso_stream_get_input_stream(s2, 0), 0); * iso_stream_get_input_stream(s2, 0), 0);
* *
@ -1186,89 +1270,6 @@ int iso_image_new(const char *name, IsoImage **image);
void iso_image_set_ignore_aclea(IsoImage *image, int what); void iso_image_set_ignore_aclea(IsoImage *image, int what);
/**
* The following two functions three macros are utilities to help ensuring
* version match of application, compile time header, and runtime library.
*/
/**
* Get version of the libisofs library at runtime.
* NOTE: This function may be called before iso_init().
*
* @since 0.6.2
*/
void iso_lib_version(int *major, int *minor, int *micro);
/**
* Check at runtime if the library is ABI compatible with the given version.
* NOTE: This function may be called before iso_init().
*
* @return
* 1 lib is compatible, 0 is not.
*
* @since 0.6.2
*/
int iso_lib_is_compatible(int major, int minor, int micro);
/**
* These three release version numbers tell the revision of this header file
* and of the API it describes. They are memorized by applications at
* compile time.
* They must show the same values as these symbols in ./configure.ac
* LIBISOFS_MAJOR_VERSION=...
* LIBISOFS_MINOR_VERSION=...
* LIBISOFS_MICRO_VERSION=...
* Note to anybody who does own work inside libisofs:
* Any change of configure.ac or libisofs.h has to keep up this equality !
*
* Before usage of these macros on your code, please read the usage discussion
* below.
*
* @since 0.6.2
*/
#define iso_lib_header_version_major 1
#define iso_lib_header_version_minor 1
#define iso_lib_header_version_micro 2
/**
* Usage discussion:
*
* Some developers of the libburnia project have differing opinions how to
* ensure the compatibility of libaries and applications.
*
* It is about whether to use at compile time and at runtime the version
* numbers provided here. Thomas Schmitt advises to use them. Vreixo Formoso
* advises to use other means.
*
* At compile time:
*
* Vreixo Formoso advises to leave proper version matching to properly
* programmed checks in the the application's build system, which will
* eventually refuse compilation.
*
* Thomas Schmitt advises to use the macros defined here for comparison with
* the application's requirements of library revisions and to eventually
* break compilation.
*
* Both advises are combinable. I.e. be master of your build system and have
* #if checks in the source code of your application, nevertheless.
*
* At runtime (via iso_lib_is_compatible()):
*
* Vreixo Formoso advises to compare the application's requirements of
* library revisions with the runtime library. This is to allow runtime
* libraries which are young enough for the application but too old for
* the lib*.h files seen at compile time.
*
* Thomas Schmitt advises to compare the header revisions defined here with
* the runtime library. This is to enforce a strictly monotonous chain of
* revisions from app to header to library, at the cost of excluding some older
* libraries.
*
* These two advises are mutually exclusive.
*/
/** /**
* Creates an IsoWriteOpts for writing an image. You should set the options * Creates an IsoWriteOpts for writing an image. You should set the options
* desired with the correspondent setters. * desired with the correspondent setters.
@ -1652,9 +1653,35 @@ int iso_write_opts_set_rrip_1_10_px_ino(IsoWriteOpts *opts, int enable);
int iso_write_opts_set_aaip_susp_1_10(IsoWriteOpts *opts, int oldvers); int iso_write_opts_set_aaip_susp_1_10(IsoWriteOpts *opts, int oldvers);
/** /**
* Store as ECMA-119 Directory Record timestamp the mtime of the source * Store as ECMA-119 Directory Record timestamp the mtime of the source node
* rather than the image creation time. * rather than the image creation time.
* If storing of mtime is enabled, then the settings of
* iso_write_opts_set_replace_timestamps() apply. (replace==1 will revoke,
* replace==2 will override mtime by iso_write_opts_set_default_timestamp().
* *
* Since version 1.2.0 this may apply also to Joliet and ISO 9660:1999. To
* reduce the probability of unwanted behavior changes between pre-1.2.0 and
* post-1.2.0, the bits for Joliet and ISO 9660:1999 also enable ECMA-119.
* The hopefully unlikely bit14 may then be used to disable mtime for ECMA-119.
*
* To enable mtime for all three directory trees, submit 7.
* To disable this feature completely, submit 0.
*
* @param opts
* The option set to be manipulated.
* @param allow
* If this parameter is negative, then mtime is enabled only for ECMA-119.
* With positive numbers, the parameter is interpreted as bit field :
* bit0= enable mtime for ECMA-119
* bit1= enable mtime for Joliet and ECMA-119
* bit2= enable mtime for ISO 9660:1999 and ECMA-119
* bit14= disable mtime for ECMA-119 although some of the other bits
* would enable it
* @since 1.2.0
* Before version 1.2.0 this applied only to ECMA-119 :
* 0 stored image creation time in ECMA-119 tree.
* Any other value caused storing of mtime.
* Joliet and ISO 9660:1999 always stored the image creation time.
* @since 0.6.12 * @since 0.6.12
*/ */
int iso_write_opts_set_dir_rec_mtime(IsoWriteOpts *opts, int allow); int iso_write_opts_set_dir_rec_mtime(IsoWriteOpts *opts, int allow);
@ -1782,8 +1809,10 @@ int iso_write_opts_set_default_gid(IsoWriteOpts *opts, gid_t gid);
/** /**
* 0 to use IsoNode timestamps, 1 to use recording time, 2 to use * 0 to use IsoNode timestamps, 1 to use recording time, 2 to use
* values from timestamp field. This has only meaning if RR extensions * values from timestamp field. This applies to the timestamps of Rock Ridge
* are enabled. * and if the use of mtime is enabled by iso_write_opts_set_dir_rec_mtime().
* In the latter case, value 1 will revoke the recording of mtime, value
* 2 will override mtime by iso_write_opts_set_default_timestamp().
* *
* @see iso_write_opts_set_default_timestamp * @see iso_write_opts_set_default_timestamp
* @since 0.6.2 * @since 0.6.2
@ -5789,6 +5818,30 @@ int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names,
* from local files. * from local files.
*/ */
/**
* Inquire whether local filesystem operations with ACL or xattr are enabled
* inside libisofs. They may be disabled because of compile time decisions.
* E.g. because the operating system does not support these features or
* because libisofs has not yet an adapter to use them.
*
* @param flag
* Bitfield for control purposes
* bit0= inquire availability of ACL
* bit1= inquire availability of xattr
* bit2 - bit7= Reserved for future types.
* It is permissibile to set them to 1 already now.
* bit8 and higher: reserved, submit 0
* @return
* Bitfield corresponding to flag. If bits are set, th
* bit0= ACL adapter is enabled
* bit1= xattr adapter is enabled
* bit2 - bit7= Reserved for future types.
* bit8 and higher: reserved, do not interpret these
*
* @since 1.1.6
*/
int iso_local_attr_support(int flag);
/** /**
* Get an ACL of the given file in the local filesystem in long text form. * Get an ACL of the given file in the local filesystem in long text form.
* *
@ -5832,7 +5885,7 @@ int iso_local_get_acl_text(char *disk_path, char **text, int flag);
* bit5= in case of symbolic link: manipulate link target * bit5= in case of symbolic link: manipulate link target
* @return * @return
* > 0 ok * > 0 ok
* 0 no ACL manipulation adapter available * 0 no ACL manipulation adapter available for desired ACL type
* -1 failure of system ACL service (see errno) * -1 failure of system ACL service (see errno)
* -2 attempt to manipulate ACL of a symbolic link without bit5 * -2 attempt to manipulate ACL of a symbolic link without bit5
* resp. with no suitable link target * resp. with no suitable link target
@ -5921,6 +5974,9 @@ int iso_local_get_attrs(char *disk_path, size_t *num_attrs, char ***names,
* bit3= do not ignore eventual non-user attributes. * bit3= do not ignore eventual non-user attributes.
* I.e. those with a name which does not begin by "user." * I.e. those with a name which does not begin by "user."
* bit5= in case of symbolic link: manipulate link target * bit5= in case of symbolic link: manipulate link target
* bit6= @since 1.1.6
tolerate inappropriate presence or absence of
* directory "default" ACL
* @return * @return
* 1 = ok * 1 = ok
* < 0 = error * < 0 = error
@ -6886,9 +6942,16 @@ int iso_md5_match(char first_md5[16], char second_md5[16]);
/** Reserved Rock Ridge leaf name (FAILURE, HIGH, -378) */ /** Reserved Rock Ridge leaf name (FAILURE, HIGH, -378) */
#define ISO_RR_NAME_RESERVED 0xE830FE86 #define ISO_RR_NAME_RESERVED 0xE830FE86
/** Rock Ridge path too long (FAILURE, HIGH, -379) */ /** Rock Ridge path too long (FAILURE, HIGH, -379) */
#define ISO_RR_PATH_TOO_LONG 0xE830FE85 #define ISO_RR_PATH_TOO_LONG 0xE830FE85
/** Attribute name cannot be represented (FAILURE, HIGH, -380) */
#define ISO_AAIP_BAD_ATTR_NAME 0xE830FE84
/** ACL text contains multiple entries of user::, group::, other::
(FAILURE, HIGH, -379) */
#define ISO_AAIP_ACL_MULT_OBJ 0xE830FE83
/* Internal developer note: /* Internal developer note:

View File

@ -125,6 +125,7 @@ iso_init;
iso_init_with_flag; iso_init_with_flag;
iso_lib_is_compatible; iso_lib_is_compatible;
iso_lib_version; iso_lib_version;
iso_local_attr_support;
iso_local_get_acl_text; iso_local_get_acl_text;
iso_local_get_attrs; iso_local_get_attrs;
iso_local_get_perms_wo_acl; iso_local_get_perms_wo_acl;
@ -311,5 +312,6 @@ iso_write_opts_set_will_cancel;
iso_zisofs_get_params; iso_zisofs_get_params;
iso_zisofs_get_refcounts; iso_zisofs_get_refcounts;
iso_zisofs_set_params; iso_zisofs_set_params;
serial_id;
local: *; local: *;
}; };

View File

@ -464,6 +464,10 @@ const char *iso_error_to_msg(int errcode)
return "Reserved Rock Ridge leaf name"; return "Reserved Rock Ridge leaf name";
case ISO_RR_PATH_TOO_LONG: case ISO_RR_PATH_TOO_LONG:
return "Rock Ridge path too long"; return "Rock Ridge path too long";
case ISO_AAIP_BAD_ATTR_NAME:
return "Attribute name cannot be represented";
case ISO_AAIP_ACL_MULT_OBJ:
return "ACL text contains multiple entries of user::, group::, other::";
default: default:
return "Unknown error"; return "Unknown error";
} }

View File

@ -2149,10 +2149,12 @@ int iso_node_set_acl_text(IsoNode *node, char *access_text, char *default_text,
ret = aaip_encode_both_acl(access_text, default_text, st_mode, ret = aaip_encode_both_acl(access_text, default_text, st_mode,
&acl_len, &acl, 2 | 8); &acl_len, &acl, 2 | 8);
} }
if (ret <= 0) { if (ret == -1)
ret = ISO_OUT_OF_MEM; ret = ISO_OUT_OF_MEM;
else if (ret <= 0 && ret >= -3)
ret = ISO_AAIP_BAD_ACL_TEXT;
if (ret <= 0)
goto ex; goto ex;
}
if(acl == NULL) { /* Delete whole ACL attribute */ if(acl == NULL) { /* Delete whole ACL attribute */
/* Update S_IRWXG by eventual "group::" ACL entry. /* Update S_IRWXG by eventual "group::" ACL entry.
@ -2205,6 +2207,8 @@ int iso_node_set_acl_text(IsoNode *node, char *access_text, char *default_text,
} }
ret = aaip_encode_both_acl(access_text, default_text, ret = aaip_encode_both_acl(access_text, default_text,
st_mode, &acl_len, &acl, 2 | 8); st_mode, &acl_len, &acl, 2 | 8);
if (ret < -3)
goto ex;
if (ret <= 0) { if (ret <= 0) {
ret = ISO_AAIP_BAD_ACL_TEXT; ret = ISO_AAIP_BAD_ACL_TEXT;
goto ex; goto ex;

View File

@ -988,7 +988,10 @@ int susp_calc_nm_sl_al(Ecma119Image *t, Ecma119Node *n, size_t space,
goto unannounced_ca; goto unannounced_ca;
namelen = namelen - (space - *su_size - 5); namelen = namelen - (space - *su_size - 5);
/* >>> Need to handle lengths > 250 */; /* >>> SUPER_LONG_RR: Need to handle CA part lengths > 250
(This cannot happen with name lengths <= 256, as a part
of the name will always fit into the directory entry.)
*/;
*ce = 5 + namelen; *ce = 5 + namelen;
*su_size = space; *su_size = space;
@ -1671,7 +1674,10 @@ int rrip_get_susp_fields(Ecma119Image *t, Ecma119Node *n, int type,
* ..and the part that goes to continuation area. * ..and the part that goes to continuation area.
*/ */
/* >>> Need a loop to handle lengths > 250 */; /* >>> SUPER_LONG_RR : Need a loop to handle CA lengths > 250
(This cannot happen with name lengths <= 256, as a part
of the name will always fit into the directory entry.)
*/;
ret = rrip_add_NM(t, info, name + namelen, strlen(name + namelen), ret = rrip_add_NM(t, info, name + namelen, strlen(name + namelen),
0, 1); 0, 1);

View File

@ -214,6 +214,7 @@ int fsrc_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
return ISO_SUCCESS; return ISO_SUCCESS;
} }
static
IsoStreamIface fsrc_stream_class = { IsoStreamIface fsrc_stream_class = {
4, /* version */ 4, /* version */
"fsrc", "fsrc",
@ -503,6 +504,7 @@ int cut_out_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
/* /*
* TODO update cut out streams to deal with update_size(). Seems hard. * TODO update cut out streams to deal with update_size(). Seems hard.
*/ */
static
IsoStreamIface cut_out_stream_class = { IsoStreamIface cut_out_stream_class = {
4, /* version */ 4, /* version */
"cout", "cout",
@ -748,6 +750,7 @@ int mem_clone_stream(IsoStream *old_stream, IsoStream **new_stream,
} }
static
IsoStreamIface mem_stream_class = { IsoStreamIface mem_stream_class = {
4, /* version */ 4, /* version */
"mem ", "mem ",

View File

@ -382,12 +382,13 @@ conv_error:;
int str2ascii(const char *icharset, const char *input, char **output) int str2ascii(const char *icharset, const char *input, char **output)
{ {
int result; int result;
wchar_t *wsrc_; wchar_t *wsrc_ = NULL;
char *ret; char *ret = NULL;
char *ret_; char *ret_ = NULL;
char *src; char *src;
struct iso_iconv_handle conv; struct iso_iconv_handle conv;
int conv_ret; int conv_ret;
int direct_conv = 0;
/* That while loop smells like a potential show stopper */ /* That while loop smells like a potential show stopper */
size_t loop_counter = 0, loop_limit = 3; size_t loop_counter = 0, loop_limit = 3;
@ -405,33 +406,54 @@ int str2ascii(const char *icharset, const char *input, char **output)
return ISO_NULL_POINTER; return ISO_NULL_POINTER;
} }
/* First try the traditional way via intermediate character set WCHAR_T.
* Up to August 2011 this was the only way. But it will not work if
* there is no character set "WCHAR_T". E.g. on Solaris.
*/
/* convert the string to a wide character string. Note: outbytes /* convert the string to a wide character string. Note: outbytes
* is in fact the number of characters in the string and doesn't * is in fact the number of characters in the string and doesn't
* include the last NULL character. * include the last NULL character.
*/ */
conv_ret = 0;
result = str2wchar(icharset, input, &wsrc_); result = str2wchar(icharset, input, &wsrc_);
if (result < 0) { if (result == (int) ISO_SUCCESS) {
goto fallback; src = (char *)wsrc_;
} numchars = wcslen(wsrc_);
src = (char *)wsrc_;
numchars = wcslen(wsrc_);
inbytes = numchars * sizeof(wchar_t); inbytes = numchars * sizeof(wchar_t);
loop_limit = inbytes + 3; loop_limit = inbytes + 3;
ret_ = malloc(numchars + 1); ret_ = malloc(numchars + 1);
if (ret_ == NULL) { if (ret_ == NULL) {
return ISO_OUT_OF_MEM; return ISO_OUT_OF_MEM;
} }
outbytes = numchars; outbytes = numchars;
ret = ret_; ret = ret_;
/* initialize iconv */ /* initialize iconv */
conv_ret = iso_iconv_open(&conv, "ASCII", "WCHAR_T", 0); conv_ret = iso_iconv_open(&conv, "ASCII", "WCHAR_T", 0);
if (conv_ret <= 0) {
free(wsrc_);
free(ret_);
}
} else if (result != (int) ISO_CHARSET_CONV_ERROR)
return result;
/* If this did not succeed : Try the untraditional direct conversion.
*/
if (conv_ret <= 0) { if (conv_ret <= 0) {
free(wsrc_); conv_ret = iso_iconv_open(&conv, "ASCII", (char *) icharset, 0);
free(ret_); if (conv_ret <= 0)
goto fallback; goto fallback;
direct_conv = 1;
src = (char *) input;
inbytes = strlen(input);
loop_limit = inbytes + 3;
outbytes = (inbytes + 1) * sizeof(uint16_t);
ret_ = malloc(outbytes);
if (ret_ == NULL)
return ISO_OUT_OF_MEM;
ret = ret_;
} }
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
@ -458,8 +480,13 @@ int str2ascii(const char *icharset, const char *input, char **output)
/* There was an error with one character but some other remain /* There was an error with one character but some other remain
* to be converted. That's probably a multibyte character. * to be converted. That's probably a multibyte character.
* See above comment. */ * See above comment. */
src += sizeof(wchar_t); if (direct_conv) {
inbytes -= sizeof(wchar_t); src++;
inbytes--;
} else {
src += sizeof(wchar_t);
inbytes -= sizeof(wchar_t);
}
if (!inbytes) if (!inbytes)
break; break;
@ -471,8 +498,9 @@ int str2ascii(const char *icharset, const char *input, char **output)
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
} }
iso_iconv_close(&conv, 0); iso_iconv_close(&conv, 0);
*ret='\0'; *ret = 0;
free(wsrc_); if (wsrc_ != NULL)
free(wsrc_);
*output = ret_; *output = ret_;
return ISO_SUCCESS; return ISO_SUCCESS;
@ -517,12 +545,13 @@ int cmp_ucsbe(const uint16_t *ucs, char c)
int str2ucs(const char *icharset, const char *input, uint16_t **output) int str2ucs(const char *icharset, const char *input, uint16_t **output)
{ {
int result; int result;
wchar_t *wsrc_; wchar_t *wsrc_ = NULL;
char *src; char *src;
char *ret; char *ret = NULL;
char *ret_; char *ret_ = NULL;
struct iso_iconv_handle conv; struct iso_iconv_handle conv;
int conv_ret; int conv_ret = 0;
int direct_conv = 0;
/* That while loop smells like a potential show stopper */ /* That while loop smells like a potential show stopper */
size_t loop_counter = 0, loop_limit = 3; size_t loop_counter = 0, loop_limit = 3;
@ -540,29 +569,50 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
* is in fact the number of characters in the string and doesn't * is in fact the number of characters in the string and doesn't
* include the last NULL character. * include the last NULL character.
*/ */
/* First try the traditional way via intermediate character set WCHAR_T.
* Up to August 2011 this was the only way. But it will not work if
* there is no character set "WCHAR_T". E.g. on Solaris.
*/
conv_ret = 0;
result = str2wchar(icharset, input, &wsrc_); result = str2wchar(icharset, input, &wsrc_);
if (result < 0) { if (result == (int) ISO_SUCCESS) {
src = (char *)wsrc_;
numchars = wcslen(wsrc_);
inbytes = numchars * sizeof(wchar_t);
loop_limit = inbytes + 3;
ret_ = malloc((numchars+1) * sizeof(uint16_t));
if (ret_ == NULL)
return ISO_OUT_OF_MEM;
outbytes = numchars * sizeof(uint16_t);
ret = ret_;
/* initialize iconv */
conv_ret = iso_iconv_open(&conv, "UCS-2BE", "WCHAR_T", 0);
if (conv_ret <= 0) {
free(wsrc_);
free(ret_);
}
} else if (result != (int) ISO_CHARSET_CONV_ERROR)
return result; return result;
}
src = (char *)wsrc_;
numchars = wcslen(wsrc_);
inbytes = numchars * sizeof(wchar_t); /* If this did not succeed : Try the untraditional direct conversion.
loop_limit = inbytes + 3; */
ret_ = malloc((numchars+1) * sizeof(uint16_t));
if (ret_ == NULL) {
return ISO_OUT_OF_MEM;
}
outbytes = numchars * sizeof(uint16_t);
ret = ret_;
/* initialize iconv */
conv_ret = iso_iconv_open(&conv, "UCS-2BE", "WCHAR_T", 0);
if (conv_ret <= 0) { if (conv_ret <= 0) {
free(wsrc_); conv_ret = iso_iconv_open(&conv, "UCS-2BE", (char *) icharset, 0);
free(ret_); if (conv_ret <= 0) {
return ISO_CHARSET_CONV_ERROR; return ISO_CHARSET_CONV_ERROR;
}
direct_conv = 1;
src = (char *) input;
inbytes = strlen(input);
loop_limit = inbytes + 3;
outbytes = (inbytes + 1) * sizeof(uint16_t);
ret_ = malloc(outbytes);
if (ret_ == NULL)
return ISO_OUT_OF_MEM;
ret = ret_;
} }
n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0); n = iso_iconv(&conv, &src, &inbytes, &ret, &outbytes, 0);
@ -589,8 +639,13 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
/* There was an error with one character but some other remain /* There was an error with one character but some other remain
* to be converted. That's probably a multibyte character. * to be converted. That's probably a multibyte character.
* See above comment. */ * See above comment. */
src += sizeof(wchar_t); if (direct_conv) {
inbytes -= sizeof(wchar_t); src++;
inbytes--;
} else {
src += sizeof(wchar_t);
inbytes -= sizeof(wchar_t);
}
if (!inbytes) if (!inbytes)
break; break;
@ -605,7 +660,8 @@ int str2ucs(const char *icharset, const char *input, uint16_t **output)
/* close the ucs string */ /* close the ucs string */
set_ucsbe((uint16_t*) ret, '\0'); set_ucsbe((uint16_t*) ret, '\0');
free(wsrc_); if (wsrc_ != NULL)
free(wsrc_);
*output = (uint16_t*)ret_; *output = (uint16_t*)ret_;
return ISO_SUCCESS; return ISO_SUCCESS;