diff --git a/doc/susp_aaip_0_2.txt b/doc/susp_aaip_0_2.txt index cc2dc63..673d7ab 100644 --- a/doc/susp_aaip_0_2.txt +++ b/doc/susp_aaip_0_2.txt @@ -173,9 +173,11 @@ The Value shall be an arbitrary number of ACL Entries: they are not aware of updates of this document which would assign a meaning to them. -If any of ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_OTHER are missing then the settings -from the PX field shall get into effect. If they exist then they shall override -the PX field. +The entries ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_OTHER must match the permission +bits of the PX field. This shall obey the peculiar rule that +ACL_USER_OBJ must match S_IRWXU, ACL_OTHER must match S_IRWXO, +ACL_MASK - if present - must match S_IRWXG, else ACL_GROUP must match S_IRWXG. +If there is ACL_USER_OBJ or ACL_GROUP_OBJ there must also be ACL_MASK. A numeric qualifier is a binary number of variable length. The Most Significant Byte comes first. The number shall be the "POSIX File User ID" resp. diff --git a/libisofs/aaip-os-freebsd.c b/libisofs/aaip-os-freebsd.c index 2403e61..a4ff677 100644 --- a/libisofs/aaip-os-freebsd.c +++ b/libisofs/aaip-os-freebsd.c @@ -63,7 +63,7 @@ int aaip_get_acl_text(char *path, char **text, int flag) if(flag & 16) { ret= stat(path, &stbuf); if(ret != -1) { - ret = aaip_cleanout_st_mode(*text, stbuf.st_mode, 2); + ret = aaip_cleanout_st_mode(*text, &(stbuf.st_mode), 2); if(!(ret & (7 | 64))) (*text)[0]= 0; } diff --git a/libisofs/aaip-os-linux.c b/libisofs/aaip-os-linux.c index 04fc24b..d14e1a8 100644 --- a/libisofs/aaip-os-linux.c +++ b/libisofs/aaip-os-linux.c @@ -61,7 +61,7 @@ int aaip_get_acl_text(char *path, char **text, int flag) if(flag & 16) { ret= stat(path, &stbuf); if(ret != -1) { - ret = aaip_cleanout_st_mode(*text, stbuf.st_mode, 2); + ret = aaip_cleanout_st_mode(*text, &(stbuf.st_mode), 2); if(!(ret & (7 | 64))) (*text)[0]= 0; } @@ -99,9 +99,18 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, int ret, retry= 0; char *list= NULL; ssize_t list_size= 0, i, num_names= 0, value_ret; - size_t a_acl_len= 0, d_acl_len= 0, acl_len= 0; - unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL; + size_t acl_len= 0; + unsigned char *acl= NULL; + +#define Aaip_os_linux_use_both_acL yes + +#ifdef Aaip_os_linux_use_both_acL + char *a_acl_text= NULL, *d_acl_text= NULL; +#else char *acl_text= NULL; + size_t a_acl_len= 0, d_acl_len= 0; + unsigned char *a_acl= NULL, *d_acl= NULL; +#endif if(flag & (1 << 15)) { /* Free memory */ if(*names != NULL) @@ -177,6 +186,21 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, } if(flag & 1) { /* Obtain ACL */ + +#ifdef Aaip_os_linux_use_both_acL + + /* access-ACL */ + aaip_get_acl_text(path, &a_acl_text, flag & 16); + aaip_get_acl_text(path, &d_acl_text, 1); + if(a_acl_text == NULL && d_acl_text == NULL) + {ret= 1; goto ex;} + ret= aaip_encode_both_acl(a_acl_text, d_acl_text, + &acl_len, &acl, (flag & 2)); + if(ret <= 0) + goto ex; + +#else /* Aaip_os_linux_use_both_acL */ + /* access-ACL */ ret= aaip_get_acl_text(path, &acl_text, flag & 16); if(ret <= 0) @@ -209,24 +233,40 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names, acl_len= a_acl_len; } +#endif /* ! Aaip_os_linux_use_both_acL */ + /* Set as attribute with empty name */; (*names)[*num_attrs]= strdup(""); if((*names)[*num_attrs] == NULL) {ret= -1; goto ex;} (*values)[*num_attrs]= (char *) acl; + acl= NULL; (*value_lengths)[*num_attrs]= acl_len; (*num_attrs)++; } ret= 1; ex:; +#ifdef Aaip_os_linux_use_both_acL + + if(a_acl_text != NULL) + aaip_get_acl_text("", &a_acl_text, 1 << 15); /* free */ + if(d_acl_text != NULL) + aaip_get_acl_text("", &d_acl_text, 1 << 15); /* free */ + +#else /* Aaip_os_linux_use_both_acL */ + if(a_acl != NULL) free(a_acl); if(d_acl != NULL) free(d_acl); + if(acl != NULL) + free(acl); if(acl_text != NULL) aaip_get_acl_text("", &acl_text, 1 << 15); /* free */ +#endif /* ! Aaip_os_linux_use_both_acL */ + if(ret <= 0 || (flag & (1 << 15))) { if(list != NULL) free(list); diff --git a/libisofs/aaip_0_2.c b/libisofs/aaip_0_2.c index a84842b..48a6e95 100644 --- a/libisofs/aaip_0_2.c +++ b/libisofs/aaip_0_2.c @@ -65,10 +65,10 @@ static int aaip_encode_pair(char *name, size_t attr_length, char *attr, @return >0 is the number of SUSP fields generated, 0 means error */ -unsigned int aaip_encode(char aa_name[2], - unsigned int num_attrs, char **names, - size_t *value_lengths, char **values, - size_t *result_len, unsigned char **result, int flag) +size_t aaip_encode(char aa_name[2], + size_t num_attrs, char **names, + size_t *value_lengths, char **values, + size_t *result_len, unsigned char **result, int flag) { size_t mem_size= 0, comp_size; unsigned int number_of_fields, i, num_recs, total_recs= 0, ret; @@ -426,50 +426,174 @@ 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 - bit1= like bit0 but return immediately if non-st_mode - ACL entry is found +int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, + size_t *result_len, unsigned char **result, int flag) +{ + int ret; + size_t a_acl_len= 0, d_acl_len= 0, acl_len= 0; + unsigned char *a_acl= NULL, *d_acl= NULL, *acl= NULL; + + if(a_acl_text != NULL) { + ret= aaip_encode_acl(a_acl_text, &a_acl_len, &a_acl, flag & 3); + if(ret <= 0) + goto ex; + } + if(d_acl_text != NULL) { + ret= aaip_encode_acl(d_acl_text, &d_acl_len, &d_acl, (flag & 3) | 4); + if(ret <= 0) + goto ex; + } + if(a_acl == NULL) { + acl= d_acl; + d_acl= NULL; + acl_len= d_acl_len; + } else if (d_acl == NULL) { + acl= a_acl; + a_acl= NULL; + acl_len= a_acl_len; + } else { + acl= calloc(a_acl_len + d_acl_len + 1, 1); + if(acl == NULL) + {ret = -1; goto ex;} + memcpy(acl, a_acl, a_acl_len); + memcpy(acl + a_acl_len, d_acl, d_acl_len); + acl_len= a_acl_len + d_acl_len; + } + *result= acl; + *result_len= acl_len; + ret= 1; +ex:; + if(a_acl != NULL) + free(a_acl); + if(d_acl != NULL) + free(d_acl); + return(ret); +} + + +/* Linux man 5 acl says: + The permissions defined by ACLs are a superset of the permissions speci- + fied by the file permission bits. The permissions defined for the file + owner correspond to the permissions of the ACL_USER_OBJ entry. The per- + missions defined for the file group correspond to the permissions of the + ACL_GROUP_OBJ entry, if the ACL has no ACL_MASK entry. If the ACL has an + ACL_MASK entry, then the permissions defined for the file group corre- + spond to the permissions of the ACL_MASK entry. The permissions defined + for the other class correspond to the permissions of the ACL_OTHER_OBJ + entry. + + Modification of the file permission bits results in the modification of + the permissions in the associated ACL entries. Modification of the per- + missions in the ACL entries results in the modification of the file per- + mission bits. + */ -int aaip_cleanout_st_mode(char *acl_text, mode_t st_mode, int flag) +/* Analyze occurence of ACL tag types in long text form. If not disabled by + parameter flag remove the entries of type "user::" , "group::" , "other::" , + or "other:" from an ACL in long text form if they match the bits in st_mode + as described by man 2 stat and man 5 acl. + @param acl_text The text to be analyzed and eventually shortened. + @param st_mode The component of struct stat which tells POSIX permission + bits and eventually shall take equivalent bits as read + from the ACL. The caller should submit a pointer + to the st_mode variable which holds permissions as + indicated by stat(2) resp. ECMA-119 and RRIP data. + @param flag bit0= do not remove entries, only determine return value + bit1= like bit0 but return immediately if a non-st_mode + ACL entry is found + bit2= update *st_mode by acl_text + ("user::" -> S_IRWXU, "mask::"|"group::" -> S_IRWXG, + "other::" -> S_IRWXO) + bit3= update acl_text by *st_mode (same mapping as bit 2 + but with reversed transfer direction) + @return <0 failure + >=0 tells in its bits which tag types were found. + The first three tell which types deviate from the + corresponding st_mode settings: + bit0= "other::" overrides S_IRWXO + bit1= "group::" overrides S_IRWXG (no "mask::" found) + 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 (no "mask::" found) + bit5= "user::" matches S_IRWXU + Given the nature of ACLs nearly all combinations are + possible although some would come from invalid ACLs. + bit6= other ACL tag types are present. Particularly: + bit7= "user:...:" is present + bit8= "group:...:" is present + bit9= "mask::" is present +*/ +int aaip_cleanout_st_mode(char *acl_text, mode_t *in_st_mode, int flag) { char *rpt, *wpt, *npt, *cpt; - mode_t m; - int overriders= 0; + mode_t m, list_mode, st_mode; + int tag_types= 0, has_mask= 0, do_cleanout = 0; + + list_mode= st_mode= *in_st_mode; + do_cleanout = !(flag & 15); + + has_mask= strncmp(acl_text, "mask:", 5) == 0 || + strstr(acl_text, "\nmask:") != NULL; + if(has_mask && (flag & 2)) + return(64 | 512); 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; + if(strncmp(rpt, "user:", 5) == 0) { + if(rpt[5] == ':' && 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; + list_mode= (list_mode & ~S_IRWXU) | m; + if((st_mode & S_IRWXU) == (m & S_IRWXU)) { + tag_types|= 32; continue; + } + if(flag & 8) { + cpt[0]= st_mode & S_IRUSR ? 'r' : '-'; + cpt[1]= st_mode & S_IWUSR ? 'w' : '-'; + cpt[2]= st_mode & S_IXUSR ? 'x' : '-'; + } + tag_types|= 4; + } else { + tag_types|= 64 | 128; } - overriders|= 4; - } else 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; + } else if(strncmp(rpt, "group:", 6) == 0) { + if(rpt[6] == ':' && npt - rpt == 10 && !has_mask) { + /* oddly: mask overrides group in st_mode */ + 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; + list_mode= (list_mode & ~S_IRWXG) | m; + if((st_mode & S_IRWXG) == (m & S_IRWXG)) { + tag_types|= 16; continue; + } + if(flag & 8) { + cpt[0]= st_mode & S_IRGRP ? 'r' : '-'; + cpt[1]= st_mode & S_IWGRP ? 'w' : '-'; + cpt[2]= st_mode & S_IXGRP ? 'x' : '-'; + } + tag_types|= 2; + } else { + if(rpt[6] == ':' && npt - rpt == 10) + tag_types|= 1024; + else + tag_types|= 64 | 256; } - overriders|= 2; } else if(strncmp(rpt, "other::", 7) == 0 && npt - rpt == 10) { cpt= rpt + 7; others_st_mode:; @@ -480,66 +604,103 @@ others_st_mode:; m|= S_IWOTH; if(cpt[2] == 'x') m|= S_IXOTH; + list_mode= (list_mode & ~S_IRWXO) | m; if((st_mode & S_IRWXO) == (m & S_IRWXO)) { - overriders|= 8; + tag_types|= 8; continue; } - overriders|= 1; + if(flag & 8) { + cpt[0]= st_mode & S_IROTH ? 'r' : '-'; + cpt[1]= st_mode & S_IWOTH ? 'w' : '-'; + cpt[2]= st_mode & S_IXOTH ? 'x' : '-'; + } + tag_types|= 1; } else if(strncmp(rpt, "other:", 6) == 0 && npt - rpt == 9) { cpt= rpt + 7; goto others_st_mode; + } else if(strncmp(rpt, "mask::", 6) == 0 && npt - rpt == 9) { + /* oddly: mask overrides group in st_mode */ + cpt= rpt + 6; +mask_st_mode:; + m= 0; + if(cpt[0] == 'r') + m|= S_IRGRP; + if(cpt[1] == 'w') + m|= S_IWGRP; + if(cpt[2] == 'x') + m|= S_IXGRP; + list_mode= (list_mode & ~S_IRWXG) | m; + tag_types|= 64 | 512; + if(flag & 8) { + cpt[0]= st_mode & S_IRGRP ? 'r' : '-'; + cpt[1]= st_mode & S_IWGRP ? 'w' : '-'; + cpt[2]= st_mode & S_IXGRP ? 'x' : '-'; + } + } else if(strncmp(rpt, "mask:", 5) == 0 && npt - rpt == 8) { + cpt= rpt + 5; + goto mask_st_mode; } else if(*rpt != 0) { - overriders|= 64; + tag_types|= 64; } if (flag & 2) - return overriders; + goto ex; if(wpt == rpt) { wpt= npt + 1; continue; } - if(!(flag & 3)) + if(do_cleanout) memmove(wpt, rpt, 1 + npt - rpt); wpt+= 1 + npt - rpt; } - if(!(flag & 3)) { + if(do_cleanout) { if(wpt == acl_text) *wpt= 0; else if(*(wpt - 1) != 0) *wpt= 0; } - return(overriders); +ex:; + if(flag & 4) + *in_st_mode= list_mode; + return(tag_types); } -/* Important: acl_text must provide 32 bytes more than its current length ! +/* Important: acl_text must provide 42 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; + int tag_types= 0; - overriders = aaip_cleanout_st_mode(acl_text, st_mode, 1); - if(!(overriders & (4 | 32))) { + tag_types = aaip_cleanout_st_mode(acl_text, &st_mode, 1); + if(!(tag_types & (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))) { + if(!(tag_types & (2 | 16 | 1024))) { 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))) { + if(!(tag_types & (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' : '-'); } + if((tag_types & (128 | 256)) && !(tag_types & 512)) { + wpt= acl_text + strlen(acl_text); + sprintf(wpt, "mask::%c%c%c\n", + st_mode & S_IRGRP ? 'r' : '-', + st_mode & S_IWGRP ? 'w' : '-', + st_mode & S_IXGRP ? 'x' : '-'); + } return(1); } diff --git a/libisofs/aaip_0_2.h b/libisofs/aaip_0_2.h index caf94a2..2b54ed6 100644 --- a/libisofs/aaip_0_2.h +++ b/libisofs/aaip_0_2.h @@ -32,10 +32,9 @@ @return >0 is the number of SUSP fields generated, 0 means error */ -unsigned int aaip_encode(char aa_name[2], - unsigned int num_attrs, char **names, - size_t *value_lengths, char **values, - size_t *result_len, unsigned char **result, int flag); +size_t aaip_encode(char aa_name[2], size_t num_attrs, char **names, + size_t *value_lengths, char **values, + size_t *result_len, unsigned char **result, int flag); /* ------ ACL representation ------ */ @@ -58,38 +57,73 @@ 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. +/* Convert an "access" and "default" ACL from long text form into the value + of an Arbitrary Attribute. According to AAIP 0.2 this value is to be stored + together with an empty name. + @param a_acl_text The "access" ACL in long text form. + Submit NULL if there is no such ACL to be encoded. + @param d_acl_text The "default" ACL in long text form. + Submit NULL if there is no such ACL to be encoded. + @param result_len Number of bytes in the resulting value + @param result *result will point to the start of the result string. + This is malloc() memory which needs to be freed when + no longer needed + @param flag Bitfield for control purposes + bit0= count only + bit1= use numeric qualifiers rather than names + @return >0 means ok + 0 means error +*/ +int aaip_encode_both_acl(char *a_acl_text, char *d_acl_text, + size_t *result_len, unsigned char **result, int flag); + + +/* Analyze occurence of ACL tag types in long text form. If not disabled by + parameter flag remove the entries of type "user::" , "group::" , "other::" , + or "other:" from an ACL in long text form if they match the bits in st_mode + as described by man 2 stat and man 5 acl. + @param acl_text The text to be analyzed and eventually shortened. + @param st_mode The component of struct stat which tells POSIX permission + bits and eventually shall take equivalent bits as read + from the ACL. The caller should submit a pointer + to the st_mode variable which holds permissions as + indicated by stat(2) resp. ECMA-119 and RRIP data. @param flag bit0= do not remove entries, only determine return value bit1= like bit0 but return immediately if a non-st_mode ACL entry is found + bit2= update *st_mode by acl_text + ("user::" -> S_IRWXU, "mask::"|"group::" -> S_IRWXG, + "other::" -> S_IRWXO) + bit3= update acl_text by *st_mode (same mapping as bit 2 + but with reversed transfer direction) @return <0 failure - >=0 tells in its bits which tag types are present. + >=0 tells in its bits which tag types were found. The first three tell which types deviate from the corresponding st_mode settings: bit0= "other::" overrides S_IRWXO - bit1= "group::" overrides S_IRWXG + bit1= "group::" overrides S_IRWXG (no "mask::" found) 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 + bit4= "group::" matches S_IRWXG (no "mask::" found) bit5= "user::" matches S_IRWXU - Given the nature of ACLs all 64 combinations are - possible although some show inner contradictions. - bit6= other ACL tag types are present + Given the nature of ACLs nearly all combinations are + possible although some would come from invalid ACLs. + bit6= other ACL tag types are present. Particularly: + bit7= "user:...:" is present + bit8= "group:...:" is present + bit9= "mask::" is present + bit10= "group::" found and "mask::" exists + */ -int aaip_cleanout_st_mode(char *acl_text, mode_t st_mode, int flag); +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 + text. Append "mask::" if missing although "user:...:" or "group:...:" + is present. Eventually set it to S_IRWXG bits of st_mode. + @param acl_text The text to be made longer. It must offer 43 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. diff --git a/libisofs/fs_local.c b/libisofs/fs_local.c index d8c86e0..3e13815 100644 --- a/libisofs/fs_local.c +++ b/libisofs/fs_local.c @@ -481,9 +481,8 @@ void lfs_free(IsoFileSource *src) static int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) { - unsigned int uret; int ret; - size_t num_attrs = 0, *value_lengths = NULL, result_len; + size_t num_attrs = 0, *value_lengths = NULL, result_len, sret; char *path = NULL, **names = NULL, **values = NULL; unsigned char *result = NULL; @@ -500,9 +499,9 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag) ret = ISO_FILE_ERROR; goto ex; } - uret = aaip_encode("AA", (unsigned int) num_attrs, names, + sret = aaip_encode("AA", num_attrs, names, value_lengths, values, &result_len, &result, 0); - if (uret == 0) { + if (sret == 0) { ret = ISO_OUT_OF_MEM; goto ex; } diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index a07bcfb..42f36cd 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -4126,6 +4126,7 @@ int aaip_xinfo_func(void *data, int flag); #endif /* Libisofs_with_aaiP */ +/* ts A90116 */ /** * Get an eventual ACL which is associated with the node. * The result will be in "long" text form as of man acl resp. acl_to_text(). @@ -4142,7 +4143,7 @@ int aaip_xinfo_func(void *data, int flag); * (Linux directories can have a "default" ACL which influences * the permissions of newly created files.) * bit4= if no ACL is available: return *text == NULL - else: produce ACL from POSIX permissions + * else: produce ACL from POSIX permissions * bit15= free memory and return 1 * @return * 2 ACL produced from POSIX permissions @@ -4155,15 +4156,47 @@ int aaip_xinfo_func(void *data, int flag); int iso_node_get_acl_text(IsoNode *node, char **text, int flag); +/* ts A90119 */ +/** + * Set the ACL of the given node to the list in parameter text or delete it. + * + * @param node + * The node that is to be manipulated. + * @param text + * The ACL text to be set into effect. NULL will delete an eventually + * existing ACL of the node. + * @param flag + * Bitfield for control purposes + * bit0= set "default" ACL rather than "access" ACL + * (Linux directories can have a "default" ACL which influences + * the permissions of newly created files.) + * bit1= ignore text but rather update eventual "access" ACL to the POSIX + * permissions of node. If no ACL exists, then do nothing and + * return success. + * @return + * > 0 success + * <=0 failure + */ +int iso_node_set_acl_text(IsoNode *node, char *text, int flag); + + +/* ts A90118 */ /* Set the ACL of the given file in the local filesystem to a given list - in long text form. - @param disk_path Path to the file - @param text The input text (0 terminated, ACL long text form) - @param flag Bitfield for control purposes - bit0= set default ACL rather than access ACL - @return >0 ok - 0 no ACL manipulation adapter available - -1 failure of system ACL service (see errno) + * in long text form. + * + * @param disk_path + * Path to the file + * @param text + * The input text (0 terminated, ACL long text form) + * @param flag + * Bitfield for control purposes + * bit0= set default ACL rather than access ACL + * @return + * > 0 ok + * 0 no ACL manipulation adapter available + * -1 failure of system ACL service (see errno) + * + * @since 0.6.14 */ int iso_local_set_acl_text(char *disk_path, char *text, int flag); diff --git a/libisofs/node.c b/libisofs/node.c index f124529..4338ed6 100644 --- a/libisofs/node.c +++ b/libisofs/node.c @@ -290,26 +290,12 @@ void iso_node_set_permissions(IsoNode *node, mode_t mode) node->mode = (node->mode & S_IFMT) | (mode & ~S_IFMT); #ifdef Libisofs_with_aaiP + /* ts A90119 */ -/* Linux man 5 acl says: - The permissions defined by ACLs are a superset of the permissions speci- - fied by the file permission bits. The permissions defined for the file - owner correspond to the permissions of the ACL_USER_OBJ entry. The per- - missions defined for the file group correspond to the permissions of the - ACL_GROUP_OBJ entry, if the ACL has no ACL_MASK entry. If the ACL has an - ACL_MASK entry, then the permissions defined for the file group corre- - spond to the permissions of the ACL_MASK entry. The permissions defined - for the other class correspond to the permissions of the ACL_OTHER_OBJ - entry. + /* If the node has ACL info : update ACL */; + iso_node_set_acl_text(node, "", 2); - Modification of the file permission bits results in the modification of - the permissions in the associated ACL entries. Modification of the per- - missions in the ACL entries results in the modification of the file per- - mission bits. - -*/ - /* >>> if the node has ACL info : */ - /* >>> update ACL */; + /* >>> actually iso_node_set_permissions() would need a return value now */ #endif @@ -1439,6 +1425,60 @@ int iso_node_get_attrs(IsoNode *node, size_t *num_attrs, } +/* ts A90121 */ +int iso_node_set_attrs(IsoNode *node, size_t num_attrs, char **names, + size_t *value_lengths, char **values, int flag) +{ + int ret; + size_t sret, result_len; + unsigned char *result; + + sret = aaip_encode("AA", num_attrs, names, value_lengths, values, + &result_len, &result, 0); + if (sret == 0) + return ISO_OUT_OF_MEM; + + ret = iso_node_remove_xinfo(node, aaip_xinfo_func); + if (ret < 0) + return ret; + ret = iso_node_add_xinfo(node, aaip_xinfo_func, result); + if (ret < 0) + return ret; + if (ret == 0) { + + /* >>> something is messed up with xinfo */; + + return ISO_ERROR; + } + return 1; +} + + +static +int iso_decode_acl(unsigned char *v_data, size_t v_len, size_t *consumed, + char **text, size_t *text_fill, int flag) +{ + int ret; + + ret = aaip_decode_acl(v_data, v_len, + consumed, NULL, (size_t) 0, text_fill, 1); + if (ret <= 0) + return 0; + if (text_fill == 0) + return 0; + *text = calloc(*text_fill + 42, 1); /* 42 for aaip_update_acl_st_mode */ + if (*text == NULL) + return ISO_OUT_OF_MEM; + ret = aaip_decode_acl(v_data, v_len, + consumed, *text, *text_fill, text_fill, 0); + if (ret <= 0) { + free(*text); + return 0; + } + return ret; +} + + /* ts A90116 */ int iso_node_get_acl_text(IsoNode *node, char **text, int flag) { @@ -1486,29 +1526,17 @@ int iso_node_get_acl_text(IsoNode *node, char **text, int flag) v_len -= consumed; } - ret = aaip_decode_acl(v_data, v_len, - &consumed, NULL, (size_t) 0, &text_fill, 1); - if (ret <= 0) + ret = iso_decode_acl(v_data, v_len, &consumed, text, &text_fill, 0); + if (ret == 0) goto bad_decode; - if (text_fill == 0) { - ret = 0; + if (ret < 0) goto ex; - } - *text = calloc(text_fill + 32, 1); /* 32 for aaip_update_acl_st_mode */ - if (*text == NULL) { - ret = ISO_OUT_OF_MEM; - goto ex; - } - ret = aaip_decode_acl(v_data, v_len, - &consumed, *text, text_fill, &text_fill, 0); - if (ret <= 0) - goto bad_decode; break; } if (*text == NULL && !(flag & 16)) { from_posix = 1; - *text = calloc(32, 1); /* 32 for aaip_update_acl_st_mode */ + *text = calloc(42, 1); /* 42 for aaip_update_acl_st_mode */ } if (*text != NULL) { st_mode = iso_node_get_permissions(node); @@ -1543,6 +1571,199 @@ bad_decode:; } +/* ts A90119 */ +int iso_node_set_acl_text(IsoNode *node, char *acl_text, int flag) +{ + size_t num_attrs = 0, *value_lengths = NULL, i, consumed; + size_t a_text_fill = 0, d_text_fill = 0; + size_t v_len, acl_len= 0; + char **names = NULL, **values = NULL, *a_text = NULL, *d_text = NULL; + char **new_names, **new_values; + size_t *new_value_lengths; + char **tpt; + unsigned char *v_data, *acl= NULL; + int ret; + mode_t st_mode; + +#ifdef Libisofs_with_aaiP + + if (flag & 2) { /* want to update ACL by st_mode */ + st_mode = iso_node_get_permissions(node); + } else { + + /* >>> validate and rectify text */; + + } + + ret = iso_node_get_attrs(node, &num_attrs, &names, + &value_lengths, &values, 0); + if (ret < 0) + return ret; + + for(i = 0; i < num_attrs; i++) { + if (names[i][0]) /* searching the empty name */ + continue; + v_data = (unsigned char *) values[i]; + v_len = value_lengths[i]; + /* "access" ACL */; + ret = iso_decode_acl(v_data, v_len, &consumed, &a_text, &a_text_fill, + 0); + if (ret == 0) + goto bad_decode; + if (ret < 0) + goto ex; + if (ret == 2) { + /* "default" ACL */; + v_data += consumed; + v_len -= consumed; + ret = iso_decode_acl(v_data, v_len, &consumed, &d_text, + &d_text_fill, 0); + if (ret == 0) + goto bad_decode; + if (ret < 0) + goto ex; + } + + if (flag & 2) { + /* Update "access" ACL by st_mode */ + if (a_text == NULL) { + ret = 1; + goto ex; + } + ret = aaip_cleanout_st_mode(a_text, &st_mode, 8); + if (ret < 0) + goto bad_decode; + } else { + if (flag & 1) + tpt = &d_text; + else + tpt = &a_text; + if (*tpt != NULL) { + free(*tpt); + *tpt = NULL; + } + if (acl_text != 0) { + *tpt = calloc(strlen(acl_text) + 1, 1); + if (*tpt == NULL) { + ret = ISO_OUT_OF_MEM; + goto ex; + } + memcpy(*tpt, acl_text, strlen(acl_text)); + } + } + if (a_text != NULL || d_text != NULL) + ret = aaip_encode_both_acl(a_text, d_text, &acl_len, &acl, 0); + else + ret = 1; + if (ret <= 0) { + ret = ISO_OUT_OF_MEM; + goto ex; + } + + /* replace variable value */; + if (values[i] != NULL) + free(values[i]); + values[i] = (char *) acl; + acl = NULL; + value_lengths[i] = acl_len; + + /* Encode attributes and attach to node */ + ret = iso_node_set_attrs(node, num_attrs, names, value_lengths, values, + 0); + goto ex; + } + + /* There is no ACL yet */ + if ((flag & 2) || acl_text == NULL) { + /* thus no need to update ACL by st_mode or to delete ACL */ + ret = 1; + goto ex; + } + if (flag & 1) + ret = aaip_encode_both_acl(NULL, acl_text, &acl_len, &acl, 0); + else + ret = aaip_encode_both_acl(acl_text, NULL, &acl_len, &acl, 0); + if (ret <= 0) { + + /* >>> cannot encode */; + + ret = ISO_ERROR; + goto ex; + } + + /* Enlarge attribute list */ + new_names = realloc(names, (num_attrs + 1) * sizeof(char *)); + if (new_names == NULL) { + ret = ISO_OUT_OF_MEM; + goto ex; + } + names = new_names; + new_values = realloc(values, (num_attrs + 1) * sizeof(char *)); + if (new_values == NULL) { + ret = ISO_OUT_OF_MEM; + goto ex; + } + values = new_values; + new_value_lengths = realloc(value_lengths, + (num_attrs + 1) * sizeof(size_t)); + if (new_value_lengths == NULL) { + ret = ISO_OUT_OF_MEM; + goto ex; + } + value_lengths = new_value_lengths; + + /* Set new ACL attribute */ + names[num_attrs] = strdup(""); + if (names[num_attrs] == NULL) { + ret = ISO_OUT_OF_MEM; + goto ex; + } + values[num_attrs] = (char *) acl; + acl = NULL; + value_lengths[num_attrs] = acl_len; + num_attrs++; + + /* Encode attributes and attach to node */ + ret = iso_node_set_attrs(node, num_attrs, names, value_lengths, values, 0); + if (ret < 0) + goto ex; + + ret = 1; +ex:; + iso_node_get_attrs(node, &num_attrs, &names, + &value_lengths, &values, 1 << 15); /* free memory */ + if (a_text != NULL) + free(a_text); + if (d_text != NULL) + free(d_text); + if(acl != NULL) + free(acl); + return ret; + +bad_decode:; + + /* >>> something is wrong with the attribute value */; + + /* >>> invent better error code */ + ret = ISO_ERROR; + goto ex; + +#else /* Libisofs_with_aaiP */ + + if (text != NULL) { + + /* >>> No ACL enabled in program code */; + + return(0); + } + return (1); + +#endif /* ! Libisofs_with_aaiP */ + +} + + +/* ts A90118 */ int iso_local_set_acl_text(char *disk_path, char *text, int flag) {