New API call iso_node_set_acl_text()

and automatic update of ACL entries by iso_node_set_permissions()
release-1.5.4.branch
Thomas Schmitt 14 years ago
parent d4ce4a7f88
commit 1150ee32a4
  1. 8
      doc/susp_aaip_0_2.txt
  2. 2
      libisofs/aaip-os-freebsd.c
  3. 46
      libisofs/aaip-os-linux.c
  4. 255
      libisofs/aaip_0_2.c
  5. 74
      libisofs/aaip_0_2.h
  6. 7
      libisofs/fs_local.c
  7. 51
      libisofs/libisofs.h
  8. 289
      libisofs/node.c

@ -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.

@ -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;
}

@ -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);

@ -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.
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.
*/
/* 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 non-st_mode
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 st_mode, int flag)
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);
}

@ -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.

@ -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;
}

@ -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);

@ -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.
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 */;
iso_node_set_acl_text(node, "", 2);
*/
/* >>> 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)
{

Loading…
Cancel
Save