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().
This commit is contained in:
parent
7d45c88cff
commit
4b031b58ea
@ -99,10 +99,14 @@ int aaip_set_acl_text(char *path, char *text, int flag)
|
|||||||
-7 support of ACL not enabled at compile time
|
-7 support of ACL not enabled at compile time
|
||||||
*/
|
*/
|
||||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||||
size_t *value_lengths, char **values, int flag)
|
size_t *value_lengths, char **values, int *errnos,
|
||||||
|
int flag)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
for(i= 0; i < num_attrs; i++)
|
||||||
|
errnos[i]= 0;
|
||||||
|
|
||||||
for(i= 0; i < num_attrs; i++) {
|
for(i= 0; i < num_attrs; i++) {
|
||||||
if(names[i] == NULL || values[i] == NULL)
|
if(names[i] == NULL || values[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
@ -228,6 +228,10 @@ static int aaip_extattr_make_list(char *path, int attrnamespace,
|
|||||||
*list_size = 0;
|
*list_size = 0;
|
||||||
return(2);
|
return(2);
|
||||||
}
|
}
|
||||||
|
if(errno == EPERM && attrnamespace == EXTATTR_NAMESPACE_SYSTEM) {
|
||||||
|
*list_size = 0;
|
||||||
|
return(3);
|
||||||
|
}
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
if(*list_size == 0)
|
if(*list_size == 0)
|
||||||
@ -312,6 +316,54 @@ static int aaip_extattr_make_namelist(char *path, char *attrnamespace,
|
|||||||
return(1);
|
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 */
|
#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
|
bit4= do not return trivial ACL that matches st_mode
|
||||||
bit5= in case of symbolic link: inquire link target
|
bit5= in case of symbolic link: inquire link target
|
||||||
bit15= free memory of names, value_lengths, values
|
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
|
<=0 error
|
||||||
-1= out of memory
|
-1= out of memory
|
||||||
-2= program error with prediction of result size
|
-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;
|
size_t a_acl_len= 0;
|
||||||
#endif
|
#endif
|
||||||
#ifdef Libisofs_with_freebsd_extattR
|
#ifdef Libisofs_with_freebsd_extattR
|
||||||
char *list= NULL, *user_list= NULL, *sys_list= NULL, *namept;
|
char *list= NULL, *user_list= NULL, *sys_list= NULL;
|
||||||
ssize_t value_ret, retry= 0, list_size= 0, user_list_size= 0;
|
ssize_t value_ret, list_size= 0, user_list_size= 0;
|
||||||
ssize_t sys_list_size= 0;
|
ssize_t sys_list_size= 0;
|
||||||
int attrnamespace;
|
int acl_names= 0, no_perm_for_system= 0;
|
||||||
int acl_names= 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(flag & (1 << 15)) { /* Free memory */
|
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);
|
&sys_list, &sys_list_size, flag & 32);
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -1; goto ex;}
|
{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 */
|
/* 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++) {
|
for(i= 0; (size_t) i < *num_attrs; i++) {
|
||||||
if(strncmp((*names)[i], "user.", 5) == 0) {
|
value_ret= get_single_attr(path, (*names)[i], *value_lengths + i,
|
||||||
attrnamespace= EXTATTR_NAMESPACE_USER;
|
*values + i, flag & (8 | 32));
|
||||||
namept= (*names)[i] + 5;
|
if(value_ret <= 0)
|
||||||
} else {
|
|
||||||
if(!(flag & 8))
|
|
||||||
continue;
|
|
||||||
attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
|
|
||||||
namept= (*names)[i] + 7;
|
|
||||||
}
|
|
||||||
/* Predict length of value */
|
|
||||||
if(flag & 32) /* follow link */
|
|
||||||
value_ret= extattr_get_file(path, attrnamespace, namept,
|
|
||||||
NULL, (size_t) 0);
|
|
||||||
else
|
|
||||||
value_ret= extattr_get_link(path, attrnamespace, namept,
|
|
||||||
NULL, (size_t) 0);
|
|
||||||
if(value_ret == -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
(*values)[i]= calloc(value_ret + 1, 1);
|
|
||||||
if((*values)[i] == NULL)
|
|
||||||
{ret= -1; goto ex;}
|
{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 */
|
if(flag & 1) { /* Obtain ACL */
|
||||||
/* access-ACL */
|
/* access-ACL */
|
||||||
aaip_get_acl_text(path, &a_acl_text, flag & (16 | 32));
|
aaip_get_acl_text(path, &a_acl_text, flag & (16 | 32));
|
||||||
if(a_acl_text == NULL)
|
if(a_acl_text == NULL) {
|
||||||
{ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */
|
/* 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);
|
ret= aaip_encode_acl(a_acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2);
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
@ -514,7 +536,7 @@ int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
|||||||
|
|
||||||
#endif /* Libisofs_with_aaip_acL */
|
#endif /* Libisofs_with_aaip_acL */
|
||||||
|
|
||||||
ret= 1;
|
ret= 1 + no_perm_for_system;
|
||||||
ex:;
|
ex:;
|
||||||
#ifdef Libisofs_with_aaip_acL
|
#ifdef Libisofs_with_aaip_acL
|
||||||
if(a_acl != NULL)
|
if(a_acl != NULL)
|
||||||
@ -773,6 +795,15 @@ static int aaip_extattr_delete_names(char *path, int attrnamespace,
|
|||||||
#endif /* Libisofs_with_freebsd_extattR */
|
#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.
|
/* Bring the given attributes and/or ACLs into effect with the given file.
|
||||||
@param flag Bitfield for control purposes
|
@param flag Bitfield for control purposes
|
||||||
bit0= decode and set ACLs
|
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
|
bit5= in case of symbolic link: manipulate link target
|
||||||
bit6= tolerate inappropriate presence or absence of
|
bit6= tolerate inappropriate presence or absence of
|
||||||
directory default ACL
|
directory default ACL
|
||||||
|
bit7= void setting a name value pair if it already
|
||||||
|
exists and has the desired value.
|
||||||
@return 1 success
|
@return 1 success
|
||||||
-1 error memory allocation
|
-1 error memory allocation
|
||||||
-2 error with decoding of ACL
|
-2 error with decoding of ACL
|
||||||
@ -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::
|
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
|
||||||
*/
|
*/
|
||||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||||
size_t *value_lengths, char **values, int flag)
|
size_t *value_lengths, char **values,
|
||||||
|
int *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;
|
size_t i, consumed, acl_text_fill, acl_idx= 0;
|
||||||
char *acl_text= NULL;
|
char *acl_text= NULL;
|
||||||
#ifdef Libisofs_with_freebsd_extattR
|
#ifdef Libisofs_with_freebsd_extattR
|
||||||
char *user_list= NULL, *sys_list= NULL, *namept;
|
char *user_list= NULL, *sys_list= NULL, *namept, *old_value;
|
||||||
ssize_t user_list_size= 0, sys_list_size= 0;
|
ssize_t user_list_size= 0, sys_list_size= 0, value_ret;
|
||||||
int attrnamespace;
|
int attrnamespace;
|
||||||
|
size_t old_value_l;
|
||||||
|
int skip;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
for(i= 0; i < num_attrs; i++)
|
||||||
|
errnos[i]= 0;
|
||||||
|
|
||||||
#ifdef Libisofs_with_freebsd_extattR
|
#ifdef Libisofs_with_freebsd_extattR
|
||||||
|
|
||||||
if(flag & 2) { /* Delete all file attributes */
|
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;
|
attrnamespace= EXTATTR_NAMESPACE_SYSTEM;
|
||||||
namept= names[i] + 7;
|
namept= names[i] + 7;
|
||||||
} else {
|
} 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)
|
if(flag & 32)
|
||||||
ret= extattr_set_file(path, attrnamespace, namept,
|
ret= extattr_set_file(path, attrnamespace, namept,
|
||||||
values[i], value_lengths[i]);
|
values[i], value_lengths[i]);
|
||||||
else
|
else
|
||||||
ret= extattr_set_link(path, attrnamespace, namept,
|
ret= extattr_set_link(path, attrnamespace, namept,
|
||||||
values[i], value_lengths[i]);
|
values[i], value_lengths[i]);
|
||||||
if(ret == -1)
|
if(ret == -1) {
|
||||||
{ret= -4; goto ex;}
|
register_errno(errnos, i, errno);
|
||||||
|
if(end_ret != 1)
|
||||||
|
end_ret= -4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -879,8 +937,12 @@ 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)
|
if(acl_idx == 0)
|
||||||
{ret= 1; goto ex;}
|
{ret= end_ret; goto ex;}
|
||||||
i= acl_idx - 1;
|
i= acl_idx - 1;
|
||||||
|
|
||||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
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
|
#ifdef Libisofs_with_aaip_acL
|
||||||
ret= aaip_set_acl_text(path, acl_text, flag & (32 | 64));
|
ret= aaip_set_acl_text(path, acl_text, flag & (32 | 64));
|
||||||
|
if(ret == -1)
|
||||||
|
register_errno(errnos, i, errno);
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -3; goto ex;}
|
{ret= -3; goto ex;}
|
||||||
#else
|
#else
|
||||||
@ -911,7 +975,7 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
if(has_default_acl && !(flag & 64))
|
if(has_default_acl && !(flag & 64))
|
||||||
{ret= -3; goto ex;}
|
{ret= -3; goto ex;}
|
||||||
|
|
||||||
ret= 1;
|
ret= end_ret;
|
||||||
ex:;
|
ex:;
|
||||||
if(acl_text != NULL)
|
if(acl_text != NULL)
|
||||||
free(acl_text);
|
free(acl_text);
|
||||||
|
@ -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
|
/* Obtain the Extended Attributes and/or the ACLs of the given file in a form
|
||||||
that is ready for aaip_encode().
|
that is ready for aaip_encode().
|
||||||
@param path Path to the file
|
@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
|
bit4= do not return trivial ACL that matches st_mode
|
||||||
bit5= in case of symbolic link: inquire link target
|
bit5= in case of symbolic link: inquire link target
|
||||||
bit15= free memory of names, value_lengths, values
|
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
|
<=0 error
|
||||||
-1= out of memory
|
-1= out of memory
|
||||||
-2= program error with prediction of result size
|
-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
|
#endif
|
||||||
#ifdef Libisofs_with_aaip_xattR
|
#ifdef Libisofs_with_aaip_xattR
|
||||||
char *list= NULL;
|
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
|
#define Libisofs_aaip_get_attr_activE yes
|
||||||
#endif
|
#endif
|
||||||
#ifdef Libisofs_aaip_get_attr_activE
|
#ifdef Libisofs_aaip_get_attr_activE
|
||||||
@ -288,27 +325,10 @@ ex:;
|
|||||||
if(!(flag & 8))
|
if(!(flag & 8))
|
||||||
if(strncmp((*names)[i], "user.", 5))
|
if(strncmp((*names)[i], "user.", 5))
|
||||||
continue;
|
continue;
|
||||||
if(flag & 32)
|
value_ret= get_single_attr(path, (*names)[i], *value_lengths + i,
|
||||||
value_ret= getxattr(path, (*names)[i], NULL, 0);
|
*values + i, flag & 32);
|
||||||
else
|
if(value_ret <= 0)
|
||||||
value_ret= lgetxattr(path, (*names)[i], NULL, 0);
|
|
||||||
if(value_ret == -1)
|
|
||||||
continue;
|
|
||||||
(*values)[i]= calloc(value_ret + 1, 1);
|
|
||||||
if((*values)[i] == NULL)
|
|
||||||
{ret= -1; goto ex;}
|
{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.
|
/* Bring the given attributes and/or ACLs into effect with the given file.
|
||||||
@param flag Bitfield for control purposes
|
@param flag Bitfield for control purposes
|
||||||
bit0= decode and set ACLs
|
bit0= decode and set ACLs
|
||||||
@ -445,6 +474,9 @@ ex:
|
|||||||
bit5= in case of symbolic link: manipulate link target
|
bit5= in case of symbolic link: manipulate link target
|
||||||
bit6= tolerate inappropriate presence or absence of
|
bit6= tolerate inappropriate presence or absence of
|
||||||
directory default ACL
|
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
|
@return 1 success
|
||||||
-1 error memory allocation
|
-1 error memory allocation
|
||||||
-2 error with decoding of ACL
|
-2 error with decoding of ACL
|
||||||
@ -457,20 +489,25 @@ ex:
|
|||||||
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
|
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
|
||||||
*/
|
*/
|
||||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||||
size_t *value_lengths, char **values, int flag)
|
size_t *value_lengths, char **values,
|
||||||
|
int *errnos, int flag)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret, end_ret= 1;
|
||||||
size_t i, consumed, acl_text_fill, acl_idx= 0;
|
size_t i, consumed, acl_text_fill, acl_idx= 0;
|
||||||
char *acl_text= NULL;
|
char *acl_text= NULL;
|
||||||
#ifdef Libisofs_with_aaip_xattR
|
#ifdef Libisofs_with_aaip_xattR
|
||||||
char *list= NULL;
|
char *list= NULL, *old_value;
|
||||||
ssize_t list_size= 0;
|
ssize_t list_size= 0, value_ret;
|
||||||
|
size_t old_value_l;
|
||||||
|
int skip;
|
||||||
#endif
|
#endif
|
||||||
#ifdef Libisofs_with_aaip_acL
|
#ifdef Libisofs_with_aaip_acL
|
||||||
size_t h_consumed;
|
size_t h_consumed;
|
||||||
int has_default_acl= 0;
|
int has_default_acl= 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
for(i= 0; i < num_attrs; i++)
|
||||||
|
errnos[i]= 0;
|
||||||
|
|
||||||
#ifdef Libisofs_with_aaip_xattR
|
#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
|
#ifdef Libisofs_with_aaip_xattR
|
||||||
|
|
||||||
|
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)
|
if(flag & 32)
|
||||||
ret= setxattr(path, names[i], values[i], value_lengths[i], 0);
|
ret= setxattr(path, names[i], values[i], value_lengths[i], 0);
|
||||||
else
|
else
|
||||||
ret= lsetxattr(path, names[i], values[i], value_lengths[i], 0);
|
ret= lsetxattr(path, names[i], values[i], value_lengths[i], 0);
|
||||||
if(ret == -1)
|
if(ret == -1) {
|
||||||
{ret= -4; goto ex;}
|
register_errno(errnos, i);
|
||||||
|
end_ret= -4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -541,8 +594,12 @@ 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)
|
if(acl_idx == 0)
|
||||||
{ret= 1; goto ex;}
|
{ret= end_ret; goto ex;}
|
||||||
i= acl_idx - 1;
|
i= acl_idx - 1;
|
||||||
/* "access" ACL */
|
/* "access" ACL */
|
||||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||||
@ -566,6 +623,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
has_default_acl= (ret == 2);
|
has_default_acl= (ret == 2);
|
||||||
|
|
||||||
ret= aaip_set_acl_text(path, acl_text, flag & 32);
|
ret= aaip_set_acl_text(path, acl_text, flag & 32);
|
||||||
|
if(ret == -1)
|
||||||
|
register_errno(errnos, i);
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -3; goto ex;}
|
{ret= -3; goto ex;}
|
||||||
/* "default" ACL */
|
/* "default" ACL */
|
||||||
@ -590,6 +649,8 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -2; goto ex;}
|
{ret= -2; goto ex;}
|
||||||
ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32));
|
ret= aaip_set_acl_text(path, acl_text, 1 | (flag & 32));
|
||||||
|
if(ret == -1)
|
||||||
|
register_errno(errnos, i);
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
{ret= -3; goto ex;}
|
{ret= -3; goto ex;}
|
||||||
} else {
|
} else {
|
||||||
@ -601,7 +662,7 @@ int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret= 1;
|
ret= end_ret;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -2188,6 +2188,11 @@ ex:;
|
|||||||
/* ----------------------- Adapter for operating systems ----------------- */
|
/* ----------------------- Adapter for operating systems ----------------- */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Libisofs_use_os_dummY
|
||||||
|
|
||||||
|
#include "aaip-os-dummy.c"
|
||||||
|
|
||||||
|
#else
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
|
|
||||||
#include "aaip-os-freebsd.c"
|
#include "aaip-os-freebsd.c"
|
||||||
@ -2239,4 +2244,5 @@ ex:;
|
|||||||
#endif /* ! __NetBSD__ */
|
#endif /* ! __NetBSD__ */
|
||||||
#endif /* ! __FreeBSD_kernel__ */
|
#endif /* ! __FreeBSD_kernel__ */
|
||||||
#endif /* ! __FreeBSD__ */
|
#endif /* ! __FreeBSD__ */
|
||||||
|
#endif /* ! Libisofs_use_os_dummY */
|
||||||
|
|
||||||
|
@ -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::
|
ISO_AAIP_ACL_MULT_OBJ multiple entries of user::, group::, other::
|
||||||
*/
|
*/
|
||||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||||
size_t *value_lengths, char **values, int flag);
|
size_t *value_lengths, char **values,
|
||||||
|
int *errnos, int flag);
|
||||||
|
|
||||||
#endif /* ! Aaip_h_is_includeD */
|
#endif /* ! Aaip_h_is_includeD */
|
||||||
|
|
||||||
|
@ -254,7 +254,9 @@ int default_create_node(IsoNodeBuilder *builder, IsoImage *image,
|
|||||||
1 | (image->builder_ignore_acl << 1) |
|
1 | (image->builder_ignore_acl << 1) |
|
||||||
(image->builder_ignore_ea << 2) |
|
(image->builder_ignore_ea << 2) |
|
||||||
(image->builder_take_all_ea << 3));
|
(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);
|
ret = iso_node_add_xinfo(new, aaip_xinfo_func, aa_string);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
|
@ -499,7 +499,7 @@ void lfs_free(IsoFileSource *src)
|
|||||||
static
|
static
|
||||||
int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
|
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;
|
size_t num_attrs = 0, *value_lengths = NULL, result_len;
|
||||||
ssize_t sret;
|
ssize_t sret;
|
||||||
char *path = NULL, **names = NULL, **values = NULL;
|
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;
|
ret = ISO_FILE_ERROR;
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
|
if(ret == 2)
|
||||||
|
no_non_user_perm= 1;
|
||||||
|
|
||||||
if (num_attrs == 0)
|
if (num_attrs == 0)
|
||||||
result = NULL;
|
result = NULL;
|
||||||
else {
|
else {
|
||||||
@ -540,7 +543,7 @@ int lfs_get_aa_string(IsoFileSource *src, unsigned char **aa_string, int flag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*aa_string = result;
|
*aa_string = result;
|
||||||
ret = 1;
|
ret = 1 + no_non_user_perm;
|
||||||
ex:;
|
ex:;
|
||||||
if (path != NULL)
|
if (path != NULL)
|
||||||
free(path);
|
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);
|
(flag & (1 | 4 | 8 | 32 | (1 << 15))) | 2 | 16);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
return ISO_AAIP_NO_GET_LOCAL;
|
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,
|
int iso_local_set_attrs_errno(char *disk_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;
|
||||||
|
|
||||||
ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths,
|
ret = aaip_set_attr_list(disk_path, num_attrs, names, value_lengths,
|
||||||
values, (flag & (8 | 32 | 64)) | !(flag & 1));
|
values, errnos,
|
||||||
|
(flag & (8 | 32 | 64 | 128)) | !(flag & 1));
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
return ISO_OUT_OF_MEM;
|
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)
|
int iso_local_get_perms_wo_acl(char *disk_path, mode_t *st_mode, int flag)
|
||||||
{
|
{
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
|
@ -203,6 +203,7 @@ int iso_image_new(const char *name, IsoImage **image)
|
|||||||
img->hfsplus_blessed[i] = NULL;
|
img->hfsplus_blessed[i] = NULL;
|
||||||
img->collision_warnings = 0;
|
img->collision_warnings = 0;
|
||||||
img->imported_sa_info = NULL;
|
img->imported_sa_info = NULL;
|
||||||
|
img->blind_on_local_get_attrs = 0;
|
||||||
|
|
||||||
*image = img;
|
*image = img;
|
||||||
return ISO_SUCCESS;
|
return ISO_SUCCESS;
|
||||||
@ -1137,3 +1138,15 @@ int iso_image_truncate_name(IsoImage *image, const char *name, char **namept,
|
|||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -247,6 +247,11 @@ struct Iso_Image
|
|||||||
/* Contains the assessment of boot aspects of the loaded image */
|
/* Contains the assessment of boot aspects of the loaded image */
|
||||||
struct iso_imported_sys_area *imported_sa_info;
|
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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -867,6 +867,10 @@ struct IsoFileSource_Iface
|
|||||||
* The caller is responsible for finally calling free()
|
* The caller is responsible for finally calling free()
|
||||||
* on non-NULL results.
|
* on non-NULL results.
|
||||||
* @return 1 means success (*aa_string == NULL is possible)
|
* @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
|
* <0 means failure and must b a valid libisofs error code
|
||||||
* (e.g. ISO_FILE_ERROR if no better one can be found).
|
* (e.g. ISO_FILE_ERROR if no better one can be found).
|
||||||
* @since 0.6.14
|
* @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);
|
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.
|
* Locate a node by its absolute path in the image.
|
||||||
* The IsoImage context defines a maximum permissible name length and a mode
|
* 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
|
* bit15= free memory
|
||||||
* @return
|
* @return
|
||||||
* 1 ok
|
* 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
|
* < 0 failure
|
||||||
*
|
*
|
||||||
* @since 0.6.14
|
* @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
|
* Array of byte lengths for each attribute payload
|
||||||
* @param values
|
* @param values
|
||||||
* Array of pointers to the attribute payload bytes
|
* 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
|
* @param flag
|
||||||
* Bitfield for control purposes
|
* Bitfield for control purposes
|
||||||
* bit0= do not attach ACLs from an eventual attribute with empty name
|
* 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."
|
* I.e. those with a name which does not begin by "user."
|
||||||
* bit5= in case of symbolic link: manipulate link target
|
* bit5= in case of symbolic link: manipulate link target
|
||||||
* bit6= @since 1.1.6
|
* bit6= @since 1.1.6
|
||||||
tolerate inappropriate presence or absence of
|
* tolerate inappropriate presence or absence of
|
||||||
* directory "default" ACL
|
* directory "default" ACL
|
||||||
|
* bit7= @since 1.5.0
|
||||||
|
* avoid setting a name value pair if it already exists and
|
||||||
|
* has the desired value.
|
||||||
* @return
|
* @return
|
||||||
* 1 = ok
|
* 1 = ok
|
||||||
* < 0 = error
|
* < 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
|
* @since 0.6.14
|
||||||
*/
|
*/
|
||||||
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,
|
||||||
|
@ -153,6 +153,7 @@ iso_image_set_volume_id;
|
|||||||
iso_image_tree_clone;
|
iso_image_tree_clone;
|
||||||
iso_image_unref;
|
iso_image_unref;
|
||||||
iso_image_update_sizes;
|
iso_image_update_sizes;
|
||||||
|
iso_image_was_blind_attrs;
|
||||||
iso_init;
|
iso_init;
|
||||||
iso_init_with_flag;
|
iso_init_with_flag;
|
||||||
iso_interval_reader_destroy;
|
iso_interval_reader_destroy;
|
||||||
@ -166,6 +167,7 @@ iso_local_get_attrs;
|
|||||||
iso_local_get_perms_wo_acl;
|
iso_local_get_perms_wo_acl;
|
||||||
iso_local_set_acl_text;
|
iso_local_set_acl_text;
|
||||||
iso_local_set_attrs;
|
iso_local_set_attrs;
|
||||||
|
iso_local_set_attrs_errno;
|
||||||
iso_md5_clone;
|
iso_md5_clone;
|
||||||
iso_md5_compute;
|
iso_md5_compute;
|
||||||
iso_md5_end;
|
iso_md5_end;
|
||||||
|
Loading…
Reference in New Issue
Block a user