From 4b031b58eafef7022010df06ecbbb5c002b443c4 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Mon, 23 Oct 2017 10:36:10 +0200 Subject: [PATCH] New flag bit7 with iso_local_set_attrs() to avoid unnecessary write attempts. New return value 2 of IsoFileSource.get_aa_string() and iso_local_get_attrs(). New API calls iso_image_was_blind_attrs(), iso_local_set_attrs_errno(). --- libisofs/aaip-os-dummy.c | 6 +- libisofs/aaip-os-freebsd.c | 186 +++++++++++++++++++++++++------------ libisofs/aaip-os-linux.c | 131 +++++++++++++++++++------- libisofs/aaip_0_2.c | 6 ++ libisofs/aaip_0_2.h | 3 +- libisofs/builder.c | 4 +- libisofs/fs_local.c | 36 +++++-- libisofs/image.c | 13 +++ libisofs/image.h | 5 + libisofs/libisofs.h | 48 +++++++++- libisofs/libisofs.ver | 2 + 11 files changed, 334 insertions(+), 106 deletions(-) diff --git a/libisofs/aaip-os-dummy.c b/libisofs/aaip-os-dummy.c index 470680c..a84ad57 100644 --- a/libisofs/aaip-os-dummy.c +++ b/libisofs/aaip-os-dummy.c @@ -99,10 +99,14 @@ int aaip_set_acl_text(char *path, char *text, int flag) -7 support of ACL not enabled at compile time */ 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 *errnos, + int flag) { size_t i; + for(i= 0; i < num_attrs; i++) + errnos[i]= 0; + for(i= 0; i < num_attrs; i++) { if(names[i] == NULL || values[i] == NULL) continue; diff --git a/libisofs/aaip-os-freebsd.c b/libisofs/aaip-os-freebsd.c index 41ab412..6d4c036 100644 --- a/libisofs/aaip-os-freebsd.c +++ b/libisofs/aaip-os-freebsd.c @@ -228,6 +228,10 @@ static int aaip_extattr_make_list(char *path, int attrnamespace, *list_size = 0; return(2); } + if(errno == EPERM && attrnamespace == EXTATTR_NAMESPACE_SYSTEM) { + *list_size = 0; + return(3); + } return(0); } if(*list_size == 0) @@ -312,6 +316,54 @@ static int aaip_extattr_make_namelist(char *path, char *attrnamespace, return(1); } + +static int get_single_attr(char *path, char *name, size_t *value_length, + char **value_bytes, int flag) +{ + char *namept; + int attrnamespace; + ssize_t value_ret; + + *value_bytes= NULL; + *value_length= 0; + if(strncmp(name, "user.", 5) == 0) { + attrnamespace= EXTATTR_NAMESPACE_USER; + namept= name + 5; + } else { + if(!(flag & 8)) + return(0); + attrnamespace= EXTATTR_NAMESPACE_SYSTEM; + namept= name + 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) + return(0); + + *value_bytes= calloc(value_ret + 1, 1); + if(*value_bytes == NULL) + return(-1); + + /* Obtain value */ + if(flag & 32) /* follow link */ + value_ret= extattr_get_file(path, attrnamespace, namept, + *value_bytes, (size_t) value_ret); + else + value_ret= extattr_get_link(path, attrnamespace, namept, + *value_bytes, (size_t) value_ret); + if(value_ret == -1) { + free(*value_bytes); + *value_bytes= NULL; + *value_length= 0; + return(0); + } + *value_length= value_ret; + return(1); +} + #endif /* Libisofs_with_freebsd_extattR */ @@ -332,7 +384,8 @@ static int aaip_extattr_make_namelist(char *path, char *attrnamespace, 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 + @return 1 ok + 2 ok, no permission to inspect non-user namespaces <=0 error -1= out of memory -2= program error with prediction of result size @@ -350,11 +403,10 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, 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; + char *list= NULL, *user_list= NULL, *sys_list= NULL; + ssize_t value_ret, list_size= 0, user_list_size= 0; ssize_t sys_list_size= 0; - int attrnamespace; - int acl_names= 0; + int acl_names= 0, no_perm_for_system= 0; #endif if(flag & (1 << 15)) { /* Free memory */ @@ -391,6 +443,8 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, &sys_list, &sys_list_size, flag & 32); if(ret <= 0) {ret= -1; goto ex;} + if(ret == 3) + no_perm_for_system= 1; } /* Check for NUL in names, convert into a linuxish list of namespace.name */ @@ -445,45 +499,10 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, } 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) + value_ret= get_single_attr(path, (*names)[i], *value_lengths + i, + *values + i, flag & (8 | 32)); + if(value_ret <= 0) {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; } } @@ -494,8 +513,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, 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 */ + if(a_acl_text == NULL) { + /* empty ACL / only st_mode info was found in ACL */ + ret= 1 + no_perm_for_system; + goto ex; + } ret= aaip_encode_acl(a_acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2); if(ret <= 0) goto ex; @@ -514,7 +536,7 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, #endif /* Libisofs_with_aaip_acL */ - ret= 1; + ret= 1 + no_perm_for_system; ex:; #ifdef Libisofs_with_aaip_acL if(a_acl != NULL) @@ -773,6 +795,15 @@ static int aaip_extattr_delete_names(char *path, int attrnamespace, #endif /* Libisofs_with_freebsd_extattR */ +static void register_errno(int *errnos, int i, int in_errno) +{ + if(in_errno > 0) + errnos[i]= in_errno; + else + errnos[i]= -1; +} + + /* Bring the given attributes and/or ACLs into effect with the given file. @param flag Bitfield for control purposes bit0= decode and set ACLs @@ -784,6 +815,8 @@ static int aaip_extattr_delete_names(char *path, int attrnamespace, bit5= in case of symbolic link: manipulate link target bit6= tolerate inappropriate presence or absence of directory default ACL + bit7= void setting a name value pair if it already + exists and has the desired value. @return 1 success -1 error memory allocation -2 error with decoding of ACL @@ -796,17 +829,23 @@ static int aaip_extattr_delete_names(char *path, int attrnamespace, 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) + size_t *value_lengths, char **values, + int *errnos, int flag) { - int ret, has_default_acl= 0; + int ret, has_default_acl= 0, end_ret= 1; 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; + char *user_list= NULL, *sys_list= NULL, *namept, *old_value; + ssize_t user_list_size= 0, sys_list_size= 0, value_ret; int attrnamespace; + size_t old_value_l; + int skip; #endif + for(i= 0; i < num_attrs; i++) + errnos[i]= 0; + #ifdef Libisofs_with_freebsd_extattR if(flag & 2) { /* Delete all file attributes */ @@ -855,16 +894,35 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, attrnamespace= EXTATTR_NAMESPACE_SYSTEM; namept= names[i] + 7; } else { - {ret= -8; goto ex;} + register_errno(errnos, i, (int) EFAULT); + end_ret= -8; + continue; + } + skip= 0; + if(flag & 128) { + value_ret= get_single_attr(path, names[i], &old_value_l, + &old_value, flag & (8 | 32)); + if(value_ret > 0 && old_value_l == value_lengths[i]) { + if(memcmp(old_value, values[i], value_lengths[i]) == 0) + skip= 1; + } + if(old_value != NULL) + free(old_value); + } + if(!skip) { + 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) { + register_errno(errnos, i, errno); + if(end_ret != 1) + end_ret= -4; + continue; + } } - 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 @@ -879,8 +937,12 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, } /* Decode ACLs */ + /* It is important that this happens after restoring xattr which might be + representations of ACL, too. If isofs ACL are enabled, then they shall + override the xattr ones. + */ if(acl_idx == 0) - {ret= 1; goto ex;} + {ret= end_ret; goto ex;} i= acl_idx - 1; ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], @@ -902,6 +964,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, #ifdef Libisofs_with_aaip_acL ret= aaip_set_acl_text(path, acl_text, flag & (32 | 64)); + if(ret == -1) + register_errno(errnos, i, errno); if(ret <= 0) {ret= -3; goto ex;} #else @@ -911,7 +975,7 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, if(has_default_acl && !(flag & 64)) {ret= -3; goto ex;} - ret= 1; + ret= end_ret; ex:; if(acl_text != NULL) free(acl_text); diff --git a/libisofs/aaip-os-linux.c b/libisofs/aaip-os-linux.c index 11b7b34..4e03b6a 100644 --- a/libisofs/aaip-os-linux.c +++ b/libisofs/aaip-os-linux.c @@ -159,6 +159,41 @@ int aaip_get_acl_text(char *path, char **text, int flag) } +#ifdef Libisofs_with_aaip_xattR + +static int get_single_attr(char *path, char *name, size_t *value_length, + char **value_bytes, int flag) +{ + ssize_t value_ret; + + *value_bytes= NULL; + *value_length= 0; + if(flag & 32) + value_ret= getxattr(path, name, NULL, 0); + else + value_ret= lgetxattr(path, name, NULL, 0); + if(value_ret == -1) + return(0); + *value_bytes= calloc(value_ret + 1, 1); + if(*value_bytes == NULL) + return(-1); + if(flag & 32) + value_ret= getxattr(path, name, *value_bytes, value_ret); + else + value_ret= lgetxattr(path, name, *value_bytes, value_ret); + if(value_ret == -1) { + free(*value_bytes); + *value_bytes= NULL; + *value_length= 0; + return(0); + } + *value_length= value_ret; + return(1); +} + +#endif /* Libisofs_with_aaip_xattR */ + + /* 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 @@ -176,7 +211,9 @@ int aaip_get_acl_text(char *path, char **text, int flag) 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 + @return 1 ok + (reserved for FreeBSD: 2 ok, no permission to inspect + non-user namespaces.) <=0 error -1= out of memory -2= program error with prediction of result size @@ -195,7 +232,7 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, #endif #ifdef Libisofs_with_aaip_xattR char *list= NULL; - ssize_t value_ret, retry= 0, list_size= 0; + ssize_t value_ret, list_size= 0; #define Libisofs_aaip_get_attr_activE yes #endif #ifdef Libisofs_aaip_get_attr_activE @@ -288,27 +325,10 @@ ex:; if(!(flag & 8)) if(strncmp((*names)[i], "user.", 5)) continue; - if(flag & 32) - value_ret= getxattr(path, (*names)[i], NULL, 0); - else - value_ret= lgetxattr(path, (*names)[i], NULL, 0); - if(value_ret == -1) - continue; - (*values)[i]= calloc(value_ret + 1, 1); - if((*values)[i] == NULL) + value_ret= get_single_attr(path, (*names)[i], *value_lengths + i, + *values + i, flag & 32); + if(value_ret <= 0) {ret= -1; goto ex;} - if(flag & 32) - value_ret= getxattr(path, (*names)[i], (*values)[i], value_ret); - else - value_ret= lgetxattr(path, (*names)[i], (*values)[i], 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; } } @@ -434,6 +454,15 @@ ex: } +static void register_errno(int *errnos, int i) +{ + if(errno > 0) + errnos[i]= errno; + else + errnos[i]= -1; +} + + /* Bring the given attributes and/or ACLs into effect with the given file. @param flag Bitfield for control purposes bit0= decode and set ACLs @@ -445,6 +474,9 @@ ex: bit5= in case of symbolic link: manipulate link target bit6= tolerate inappropriate presence or absence of directory default ACL + bit7= @since 1.5.0 + avoid setting a name value pair if it already + exists and has the desired value. @return 1 success -1 error memory allocation -2 error with decoding of ACL @@ -457,20 +489,25 @@ ex: 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) + size_t *value_lengths, char **values, + int *errnos, int flag) { - int ret; + int ret, end_ret= 1; size_t i, consumed, acl_text_fill, acl_idx= 0; char *acl_text= NULL; #ifdef Libisofs_with_aaip_xattR - char *list= NULL; - ssize_t list_size= 0; + char *list= NULL, *old_value; + ssize_t list_size= 0, value_ret; + size_t old_value_l; + int skip; #endif #ifdef Libisofs_with_aaip_acL size_t h_consumed; int has_default_acl= 0; #endif + for(i= 0; i < num_attrs; i++) + errnos[i]= 0; #ifdef Libisofs_with_aaip_xattR @@ -525,12 +562,28 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, #ifdef Libisofs_with_aaip_xattR - if(flag & 32) - ret= setxattr(path, names[i], values[i], value_lengths[i], 0); - else - ret= lsetxattr(path, names[i], values[i], value_lengths[i], 0); - if(ret == -1) - {ret= -4; goto ex;} + skip= 0; + if(flag & 128) { + value_ret= get_single_attr(path, names[i], &old_value_l, + &old_value, flag & 32); + if(value_ret > 0 && old_value_l == value_lengths[i]) { + if(memcmp(old_value, values[i], value_lengths[i]) == 0) + skip= 1; + } + if(old_value != NULL) + free(old_value); + } + if(!skip) { + if(flag & 32) + ret= setxattr(path, names[i], values[i], value_lengths[i], 0); + else + ret= lsetxattr(path, names[i], values[i], value_lengths[i], 0); + if(ret == -1) { + register_errno(errnos, i); + end_ret= -4; + continue; + } + } #else @@ -540,9 +593,13 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, } -/* Decode ACLs */ + /* Decode ACLs */ + /* It is important that this happens after restoring xattr which might be + representations of ACL, too. If isofs ACL are enabled, then they shall + override the xattr ones. + */ if(acl_idx == 0) - {ret= 1; goto ex;} + {ret= end_ret; goto ex;} i= acl_idx - 1; /* "access" ACL */ ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i], @@ -566,6 +623,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, has_default_acl= (ret == 2); ret= aaip_set_acl_text(path, acl_text, flag & 32); + if(ret == -1) + register_errno(errnos, i); if(ret <= 0) {ret= -3; goto ex;} /* "default" ACL */ @@ -590,6 +649,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, if(ret <= 0) {ret= -2; goto ex;} ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32)); + if(ret == -1) + register_errno(errnos, i); if(ret <= 0) {ret= -3; goto ex;} } else { @@ -601,7 +662,7 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names, } } - ret= 1; + ret= end_ret; #else diff --git a/libisofs/aaip_0_2.c b/libisofs/aaip_0_2.c index d26e36b..e52baac 100644 --- a/libisofs/aaip_0_2.c +++ b/libisofs/aaip_0_2.c @@ -2188,6 +2188,11 @@ ex:; /* ----------------------- Adapter for operating systems ----------------- */ +#ifdef Libisofs_use_os_dummY + +#include "aaip-os-dummy.c" + +#else #ifdef __FreeBSD__ #include "aaip-os-freebsd.c" @@ -2239,4 +2244,5 @@ ex:; #endif /* ! __NetBSD__ */ #endif /* ! __FreeBSD_kernel__ */ #endif /* ! __FreeBSD__ */ +#endif /* ! Libisofs_use_os_dummY */ diff --git a/libisofs/aaip_0_2.h b/libisofs/aaip_0_2.h index 784e565..5c2b29e 100644 --- a/libisofs/aaip_0_2.h +++ b/libisofs/aaip_0_2.h @@ -507,7 +507,8 @@ int aaip_set_acl_text(char *path, char *text, int flag); 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); + size_t *value_lengths, char **values, + int *errnos, int flag); #endif /* ! Aaip_h_is_includeD */ diff --git a/libisofs/builder.c b/libisofs/builder.c index 77e3e2c..426868f 100644 --- a/libisofs/builder.c +++ b/libisofs/builder.c @@ -254,7 +254,9 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image, 1 | (image->builder_ignore_acl << 1) | (image->builder_ignore_ea << 2) | (image->builder_take_all_ea << 3)); - if (ret == 1 && aa_string != NULL) { + if(ret == 2) + image->blind_on_local_get_attrs = 1; + if (ret > 0 && aa_string != NULL) { ret = iso_node_add_xinfo(new, aaip_xinfo_func, aa_string); if (ret < 0) goto ex; diff --git a/libisofs/fs_local.c b/libisofs/fs_local.c index 7832281..c91dccc 100644 --- a/libisofs/fs_local.c +++ b/libisofs/fs_local.c @@ -499,7 +499,7 @@ void lfs_free(IsoFileSource *src) static int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) { - int ret; + int ret, no_non_user_perm= 0; size_t num_attrs = 0, *value_lengths = NULL, result_len; ssize_t sret; char *path = NULL, **names = NULL, **values = NULL; @@ -529,6 +529,9 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) ret = ISO_FILE_ERROR; goto ex; } + if(ret == 2) + no_non_user_perm= 1; + if (num_attrs == 0) result = NULL; else { @@ -540,7 +543,7 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) } } *aa_string = result; - ret = 1; + ret = 1 + no_non_user_perm; ex:; if (path != NULL) free(path); @@ -867,17 +870,19 @@ int iso_local_get_attrs(char *disk_path, size_t *num_attrs, char ***names, (flag & (1 | 4 | 8 | 32 | (1 << 15))) | 2 | 16); if (ret <= 0) return ISO_AAIP_NO_GET_LOCAL; - return 1; + return 1 + (ret == 2); } -int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names, - size_t *value_lengths, char **values, int flag) +int iso_local_set_attrs_errno(char *disk_path, size_t num_attrs, char **names, + size_t *value_lengths, char **values, + int *errnos, int flag) { int ret; ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths, - values, (flag & (8 | 32 | 64)) | !(flag & 1)); + values, errnos, + (flag & (8 | 32 | 64 | 128)) | !(flag & 1)); if (ret <= 0) { if (ret == -1) return ISO_OUT_OF_MEM; @@ -895,6 +900,25 @@ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names, } +int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names, + size_t *value_lengths, char **values, int flag) +{ + int ret; + int *errnos = NULL; + + if(num_attrs > 0) { + errnos= calloc(num_attrs, sizeof(int)); + if(errnos == NULL) + return ISO_OUT_OF_MEM; + } + ret= iso_local_set_attrs_errno(disk_path, num_attrs, names, value_lengths, + values, errnos, flag); + if(errnos != NULL) + free(errnos); + return ret; +} + + int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag) { struct stat stbuf; diff --git a/libisofs/image.c b/libisofs/image.c index 18696ab..b455de8 100644 --- a/libisofs/image.c +++ b/libisofs/image.c @@ -203,6 +203,7 @@ int iso_image_new(const char *name, IsoImage **image) img->hfsplus_blessed[i] = NULL; img->collision_warnings = 0; img->imported_sa_info = NULL; + img->blind_on_local_get_attrs = 0; *image = img; return ISO_SUCCESS; @@ -1137,3 +1138,15 @@ int iso_image_truncate_name(IsoImage *image, const char *name, char **namept, return ret; } + +/* API */ +int iso_image_was_blind_attrs(IsoImage *image, int flag) +{ + int ret; + + ret = image->blind_on_local_get_attrs; + if (flag & 1) + image->blind_on_local_get_attrs = 0; + return ret; +} + diff --git a/libisofs/image.h b/libisofs/image.h index 185ef17..320a904 100644 --- a/libisofs/image.h +++ b/libisofs/image.h @@ -247,6 +247,11 @@ struct Iso_Image /* Contains the assessment of boot aspects of the loaded image */ struct iso_imported_sys_area *imported_sa_info; + /* Whether some local filesystem xattr namespace could not be explored + * during node building. + */ + int blind_on_local_get_attrs; + }; diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 6dd7db1..ff766c8 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -867,6 +867,10 @@ struct IsoFileSource_Iface * The caller is responsible for finally calling free() * on non-NULL results. * @return 1 means success (*aa_string == NULL is possible) + * 2 means success, but it is possible that attributes + * exist in non-user namespaces which could not be + * explored due to lack of permission. + * @since 1.5.0 * <0 means failure and must b a valid libisofs error code * (e.g. ISO_FILE_ERROR if no better one can be found). * @since 0.6.14 @@ -6357,6 +6361,28 @@ int iso_tree_clone(IsoNode *node, */ int iso_tree_add_dir_rec(IsoImage *image, IsoDir *parent, const char *dir); +/** + * Inquire whether some local filesystem xattr namespace could not be explored + * during node building. This may happen due to lack of adminstrator privileges + * e.g. on FreeBSD namespace "system". + * It may well be that the processed local files have no attributes which + * would require special privileges. But already their existence was neither + * denied nor confirmed. + * + * @param image + * The image to inquire. + * @param flag + * Bitfield for control purposes: + * bit0 = reset internal value to 0 + * @return + * 1 = Exploration was prevented + * 0 = No such prevention occured + * + * @since 1.5.0 + */ +int iso_image_was_blind_attrs(IsoImage *image, int flag); + + /** * Locate a node by its absolute path in the image. * The IsoImage context defines a maximum permissible name length and a mode @@ -7585,6 +7611,9 @@ int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag); * bit15= free memory * @return * 1 ok + * 2 ok, but it is possible that attributes exist in non-user namespaces + * which could not be explored due to lack of permission. + * @since 1.5.0 * < 0 failure * * @since 0.6.14 @@ -7608,6 +7637,11 @@ int iso_local_get_attrs(char *disk_path, size_t *num_attrs, char ***names, * Array of byte lengths for each attribute payload * @param values * Array of pointers to the attribute payload bytes + * @param errnos + * Array of integers to return error numbers if encountered at the attempt + * to process the name-value pair at the given array index number: + * 0 = no error , -1 = unknown error + * >0 = errno as of local system calls to set xattr and ACLs * @param flag * Bitfield for control purposes * bit0= do not attach ACLs from an eventual attribute with empty name @@ -7615,12 +7649,24 @@ int iso_local_get_attrs(char *disk_path, size_t *num_attrs, char ***names, * I.e. those with a name which does not begin by "user." * bit5= in case of symbolic link: manipulate link target * bit6= @since 1.1.6 - tolerate inappropriate presence or absence of + * tolerate inappropriate presence or absence of * directory "default" ACL + * bit7= @since 1.5.0 + * avoid setting a name value pair if it already exists and + * has the desired value. * @return * 1 = ok * < 0 = error * + * @since 1.5.0 + */ +int iso_local_set_attrs_errno(char *disk_path, size_t num_attrs, char **names, + size_t *value_lengths, char **values, + int *errnos, int flag); +/** + * Older version of iso_local_set_attrs_errno() without the errnos array. + * All other parameters and the return value have the same meaning. + * * @since 0.6.14 */ int iso_local_set_attrs(char *disk_path, size_t num_attrs, char **names, diff --git a/libisofs/libisofs.ver b/libisofs/libisofs.ver index 5b90b2a..4f03ac4 100644 --- a/libisofs/libisofs.ver +++ b/libisofs/libisofs.ver @@ -153,6 +153,7 @@ iso_image_set_volume_id; iso_image_tree_clone; iso_image_unref; iso_image_update_sizes; +iso_image_was_blind_attrs; iso_init; iso_init_with_flag; iso_interval_reader_destroy; @@ -166,6 +167,7 @@ iso_local_get_attrs; iso_local_get_perms_wo_acl; iso_local_set_acl_text; iso_local_set_attrs; +iso_local_set_attrs_errno; iso_md5_clone; iso_md5_compute; iso_md5_end;