diff --git a/doc/susp_aaip_0_2.txt b/doc/susp_aaip_0_2.txt index b8a8b54..cc2dc63 100644 --- a/doc/susp_aaip_0_2.txt +++ b/doc/susp_aaip_0_2.txt @@ -330,4 +330,9 @@ SUSP 1.12 ftp://ftp.ymi.com/pub/rockridge/susp112.ps RRIP 1.12 ftp://ftp.ymi.com/pub/rockridge/rrip112.ps (especially field SL) +------------------------------------------------------------------------------- +Pending considerations: + +- shall "AA" be fixely defined as signature ? + diff --git a/libisofs/aaip-os-freebsd.c b/libisofs/aaip-os-freebsd.c index caa28da..dd1297b 100644 --- a/libisofs/aaip-os-freebsd.c +++ b/libisofs/aaip-os-freebsd.c @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -27,6 +28,9 @@ with bit15 of flag. @param flag Bitfield for control purposes bit0= obtain default ACL rather than access ACL + bit4= do not return entries which match the st_mode + permissions. If no other ACL entries exist: + set *text = NULL and return 2 bit15= free text and return 1 @return > 0 ok -1 failure of system ACL service (see errno) @@ -34,6 +38,8 @@ int aaip_get_acl_text(char *path, char **text, int flag) { acl_t acl= NULL; + struct stat stbuf; + int ret; if(flag & (1 << 15)) { if(*text != NULL) @@ -55,6 +61,16 @@ int aaip_get_acl_text(char *path, char **text, int flag) acl_free(acl); if(*text == NULL) return(-1); + if(flag & 16) { + ret= stat(path, &stbuf); + if(ret != -1) + aaip_cleanout_st_mode(*text, stbuf.st_mode, 0); + if((*text)[0] == 0 || strcmp(*text, "\n") == 0) { + acl_free(text); + *text= NULL; + return(2); + } + } return(1); } @@ -74,6 +90,8 @@ int aaip_get_acl_text(char *path, char **text, int flag) bit0= obtain ACL (access and eventually default) bit1= use numeric ACL qualifiers rather than names bit2= do not encode attributes other than ACL + bit3= -reserved- + bit4= do not return st_mode permissions in ACL. bit15= free memory of names, value_lengths, values @return >0 ok <=0 error @@ -118,9 +136,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, if(flag & 1) { /* Obtain ACL */ /* access-ACL */ - ret= aaip_get_acl_text(path, &acl_text, 0); + ret= aaip_get_acl_text(path, &acl_text, flag & 16); if(ret <= 0) goto ex; + if(ret == 2) + {ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */ ret= aaip_encode_acl(acl_text, &a_acl_len, &a_acl, flag & 2); if(ret <= 0) goto ex; diff --git a/libisofs/aaip-os-linux.c b/libisofs/aaip-os-linux.c index c0e36e9..7bf90a3 100644 --- a/libisofs/aaip-os-linux.c +++ b/libisofs/aaip-os-linux.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,9 @@ with bit15 of flag. @param flag Bitfield for control purposes bit0= obtain default ACL rather than access ACL + bit4= do not return entries which match the st_mode + permissions. If no other ACL entries exist: + set *text = NULL and return 2 bit15= free text and return 1 @return > 0 ok -1 failure of system ACL service (see errno) @@ -37,6 +41,8 @@ int aaip_get_acl_text(char *path, char **text, int flag) { acl_t acl= NULL; + struct stat stbuf; + int ret; if(flag & (1 << 15)) { if(*text != NULL) @@ -52,6 +58,16 @@ int aaip_get_acl_text(char *path, char **text, int flag) acl_free(acl); if(*text == NULL) return(-1); + if(flag & 16) { + ret= stat(path, &stbuf); + if(ret != -1) + aaip_cleanout_st_mode(*text, stbuf.st_mode, 0); + if((*text)[0] == 0 || strcmp(*text, "\n") == 0) { + acl_free(text); + *text= NULL; + return(2); + } + } return(1); } @@ -69,6 +85,7 @@ int aaip_get_acl_text(char *path, char **text, int flag) bit2= do not obtain attributes other than ACL bit3= do not ignore eventual local ACL attribute (e.g. system.posix_acl_access) + bit4= do not return st_mode permissions in ACL. bit15= free memory of names, value_lengths, values @return >0 ok <=0 error @@ -158,9 +175,11 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, if(flag & 1) { /* Obtain ACL */ /* access-ACL */ - ret= aaip_get_acl_text(path, &acl_text, 0); + ret= aaip_get_acl_text(path, &acl_text, flag & 16); if(ret <= 0) goto ex; + if(ret == 2) + {ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */ ret= aaip_encode_acl(acl_text, &a_acl_len, &a_acl, flag & 2); if(ret <= 0) goto ex; diff --git a/libisofs/aaip_0_2.c b/libisofs/aaip_0_2.c index 7cf9c74..9a0f1eb 100644 --- a/libisofs/aaip_0_2.c +++ b/libisofs/aaip_0_2.c @@ -17,6 +17,7 @@ #include #include #include +#include /* <<< */ @@ -425,6 +426,121 @@ group_by_name:; } +/* Remove the entries user::??? , group::??? , other::??? , other:??? + from an ACL in long text form if they match the bits in st_mode. + @param flag bit0= do not remove entries, only determine return value +*/ +int aaip_cleanout_st_mode(char *acl_text, mode_t st_mode, int flag) +{ + char *rpt, *wpt, *npt, *cpt; + mode_t m; + int overriders= 0; + + for(npt= wpt= rpt= acl_text; *npt != 0; rpt= npt + 1) { + npt= strchr(rpt, '\n'); + if(npt == NULL) + npt= rpt + strlen(rpt); + if(strncmp(rpt, "user::", 6) == 0 && npt - rpt == 9) { + cpt= rpt + 6; + m= 0; + if(cpt[0] == 'r') + m|= S_IRUSR; + if(cpt[1] == 'w') + m|= S_IWUSR; + if(cpt[2] == 'x') + m|= S_IXUSR; + if((st_mode & S_IRWXU) == (m & S_IRWXU)) { + overriders|= 32; + continue; + } + overriders|= 4; + } + if(strncmp(rpt, "group::", 7) == 0 && npt - rpt == 10) { + cpt= rpt + 7; + m= 0; + if(cpt[0] == 'r') + m|= S_IRGRP; + if(cpt[1] == 'w') + m|= S_IWGRP; + if(cpt[2] == 'x') + m|= S_IXGRP; + if((st_mode & S_IRWXG) == (m & S_IRWXG)) { + overriders|= 16; + continue; + } + overriders|= 2; + } + if(strncmp(rpt, "other::", 7) == 0 && npt - rpt == 10) { + cpt= rpt + 7; +others_st_mode:; + m= 0; + if(cpt[0] == 'r') + m|= S_IROTH; + if(cpt[1] == 'w') + m|= S_IWOTH; + if(cpt[2] == 'x') + m|= S_IXOTH; + if((st_mode & S_IRWXO) == (m & S_IRWXO)) { + overriders|= 8; + continue; + } + overriders|= 1; + } + if(strncmp(rpt, "other:", 6) == 0 && npt - rpt == 9) { + cpt= rpt + 7; + goto others_st_mode; + } + if(wpt == rpt) { + wpt= npt + 1; + continue; + } + if(!(flag & 1)) + memmove(wpt, rpt, 1 + npt - rpt); + wpt+= 1 + npt - rpt; + } + if(!(flag & 1)) { + if(wpt == acl_text) + *wpt= 0; + else if(*(wpt - 1) != 0) + *wpt= 0; + } + return(overriders); +} + + +/* Important: acl_text must provide 32 bytes more than its current length ! +*/ +int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag) +{ + char *wpt; + int overriders= 0; + + overriders = aaip_cleanout_st_mode(acl_text, st_mode, 1); + if(!(overriders & (4 | 32))) { + wpt= acl_text + strlen(acl_text); + sprintf(wpt, "user::%c%c%c\n", + st_mode & S_IRUSR ? 'r' : '-', + st_mode & S_IWUSR ? 'w' : '-', + st_mode & S_IXUSR ? 'x' : '-'); + } + if(!(overriders & (2 | 16))) { + wpt= acl_text + strlen(acl_text); + sprintf(wpt, "group::%c%c%c\n", + st_mode & S_IRGRP ? 'r' : '-', + st_mode & S_IWGRP ? 'w' : '-', + st_mode & S_IXGRP ? 'x' : '-'); + } + if(!(overriders & (1 | 8))) { + wpt= acl_text + strlen(acl_text); + sprintf(wpt, "other::%c%c%c\n", + st_mode & S_IROTH ? 'r' : '-', + st_mode & S_IWOTH ? 'w' : '-', + st_mode & S_IXOTH ? 'x' : '-'); + } + return(1); +} + + /* --------------------------------- Decoder ---------------------------- */ /* --- private --- */ diff --git a/libisofs/aaip_0_2.h b/libisofs/aaip_0_2.h index 2660c3b..5c86705 100644 --- a/libisofs/aaip_0_2.h +++ b/libisofs/aaip_0_2.h @@ -58,6 +58,44 @@ int aaip_encode_acl(char *acl_text, size_t *result_len, unsigned char **result, int flag); +/* Remove the entries of type "user::" , "group::" , "other::" , "other:" + from an ACL in long text form if they match the bits in st_mode. + @param acl_text The text to be shortened + @param st_mode The component of struct stat which shall take the + removed information. The caller should submit the st_mode + variable which holds permissions as indicated by ECMA-119 + and RRIP data. + @param flag bit0= do not remove entries, only determine return value + @return <0 failure + >=0 tells in six bits which tag types are present. + The first three tell which types deviate from the + corresponding st_mode settings: + bit0= "other::" overrides S_IRWXO + bit1= "group::" overrides S_IRWXG + bit2= "user::" overrides S_IRWXU + The second three tell which types comply with st_mode: + bit3= "other::" matches S_IRWXO + bit4= "group::" matches S_IRWXG + bit5= "user::" matches S_IRWXU + Given the nature of ACLs all 64 combinations are + possible although some show inner contradictions. +*/ +int aaip_cleanout_st_mode(char *acl_text, mode_t st_mode, int flag); + + +/* Append entries of type "user::" , "group::" , "other::" representing the + permission bits in st_mode if those tag types are not present in the ACL + text. + @param acl_text The text to be made longer. It must offer 33 bytes more + storage space than its length when it is submitted. + @param st_mode The component of struct stat which shall provide the + permission information. + @param flag Unused yet. Submit 0. + @return <0 failure +*/ +int aaip_add_acl_st_mode(char *acl_text, mode_t st_mode, int flag); + + /* ------ OS interface ------ */ /* Obtain the ACL of the given file in long text form. @@ -67,9 +105,13 @@ int aaip_encode_acl(char *acl_text, with bit15 of flag. @param flag Bitfield for control purposes bit0= obtain default ACL rather than access ACL + bit4= do not return entries which match the st_mode + permissions. If no other ACL entries exist: + set *text = NULL and return 2 bit15= free text and return 1 - @return > 0 ok - -1 failure of system ACL service (see errno) + @return 1 ok + 2 only st_mode permissions exist and bit 4 is set + -1 failure of system ACL service (see errno) */ int aaip_get_acl_text(char *path, char **text, int flag); @@ -89,6 +131,7 @@ int aaip_get_acl_text(char *path, char **text, int flag); bit2= do not obtain attributes other than ACLs bit3= do not ignore eventual ACL attribute (e.g. system.posix_acl_access) + bit4= do not return st_mode permissions in ACL. bit15= free memory of names, value_lengths, values @return >0 ok <=0 error diff --git a/libisofs/fs_local.c b/libisofs/fs_local.c index f8b4cd6..d8c86e0 100644 --- a/libisofs/fs_local.c +++ b/libisofs/fs_local.c @@ -489,11 +489,13 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) *aa_string = NULL; /* Obtain EAs and ACLs ("access" and "default"). ACLs encoded according - to AAIP ACL representation. + to AAIP ACL representation. Clean out st_mode ACL entries. */ path = iso_file_source_get_path(src); + + /* >>> make adjustable: bit4 = ignoring of st_mode ACL entries */ ret = aaip_get_attr_list(path, &num_attrs, &names, - &value_lengths, &values, 1 | 2); + &value_lengths, &values, 1 | 2 | 16); if (ret <= 0) { ret = ISO_FILE_ERROR; goto ex; diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index a3f622b..4933ee1 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -4141,9 +4141,12 @@ int aaip_xinfo_func(void *data, int flag); * bit0= obtain "default" ACL rather than "access" ACL * (Linux directories can have a "default" ACL which influences * the permissions of newly created files.) + * bit4= if no ACL available: return *text == NULL + else: produce ACL from PROSIX permissions * bit15= free memory and return 1 * @return - * 1 on success, + * 2 ACL produced from POSIX permissions + * 1 ACL was read from node * 0 if the desire ACL type is not available * < 0 on error * diff --git a/libisofs/node.c b/libisofs/node.c index db7f117..e9a608d 100644 --- a/libisofs/node.c +++ b/libisofs/node.c @@ -1421,7 +1421,8 @@ int iso_node_get_acl_text(IsoNode *node, char **text, int flag) size_t v_len; char **names = NULL, **values = NULL; unsigned char *v_data; - int ret; + int ret, from_posix= 0; + mode_t st_mode; if (flag & (1 << 15)) { if (*text != NULL) @@ -1468,7 +1469,7 @@ int iso_node_get_acl_text(IsoNode *node, char **text, int flag) ret = 0; goto ex; } - *text = calloc(text_fill, 1); + *text = calloc(text_fill + 32, 1); /* 32 for aaip_update_acl_st_mode */ if (*text == NULL) { ret = ISO_OUT_OF_MEM; goto ex; @@ -1479,8 +1480,21 @@ int iso_node_get_acl_text(IsoNode *node, char **text, int flag) goto bad_decode; break; } + + if (*text == NULL && !(flag & 16)) { + from_posix = 1; + *text = calloc(32, 1); /* 32 for aaip_update_acl_st_mode */ + } + if (*text != NULL) { + st_mode = iso_node_get_permissions(node); + aaip_add_acl_st_mode(*text, st_mode, 0); + text_fill = strlen(*text); + } - ret = (*text != NULL); + if (text == NULL) + ret = 0; + else + ret = 1 + from_posix; ex:; iso_node_get_attrs(node, &num_attrs, &names, &value_lengths, &values, 1 << 15); /* free memory */