Introduced AAIP code. Now linking with libacl.
(Todo: handle system dependy of -lacl in configure.ac)
This commit is contained in:
283
libisofs/aaip-os-freebsd.c
Normal file
283
libisofs/aaip-os-freebsd.c
Normal file
@@ -0,0 +1,283 @@
|
||||
|
||||
/*
|
||||
|
||||
aaip-os-freebsd.c
|
||||
Arbitrary Attribute Interchange Protocol , system adapter for getting and
|
||||
setting of ACLs and XFS-style Extended Attributes.
|
||||
|
||||
To be included by aaip_0_2.c
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/acl.h>
|
||||
|
||||
|
||||
/* ------------------------------ Getters --------------------------------- */
|
||||
|
||||
/* Obtain the ACL of the given file in long text form.
|
||||
@param path Path to the file
|
||||
@param text Will hold the result. This is a managed object which
|
||||
finally has to be freed by a call to this function
|
||||
with bit15 of flag.
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain default ACL rather than access ACL
|
||||
bit15= free text and return 1
|
||||
@return > 0 ok
|
||||
-1 failure of system ACL service (see errno)
|
||||
*/
|
||||
int aaip_get_acl_text(char *path, char **text, int flag)
|
||||
{
|
||||
acl_t acl= NULL;
|
||||
|
||||
if(flag & (1 << 15)) {
|
||||
if(*text != NULL)
|
||||
acl_free(text);
|
||||
*text= NULL;
|
||||
return(1);
|
||||
}
|
||||
*text= NULL;
|
||||
|
||||
/* Note: no ACL_TYPE_DEFAULT in FreeBSD */
|
||||
if(flag & 1)
|
||||
return(0);
|
||||
|
||||
acl= acl_get_file(path, ACL_TYPE_ACCESS);
|
||||
|
||||
if(acl == NULL)
|
||||
return(-1);
|
||||
*text= acl_to_text(acl, NULL);
|
||||
acl_free(acl);
|
||||
if(*text == NULL)
|
||||
return(-1);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Obtain the Extended Attributes and/or the ACLs of the given file in a form
|
||||
that is ready for aaip_encode().
|
||||
|
||||
Note: There are no Extended Attributes in FreeBSD. So only ACL will be
|
||||
obtained.
|
||||
|
||||
@param path Path to the file
|
||||
@param num_attrs Will return the number of name-value pairs
|
||||
@param names Will return an array of pointers to 0-terminated names
|
||||
@param value_lengths Will return an arry with the lenghts of values
|
||||
@param values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain ACL (access and eventually default)
|
||||
bit1= use numeric ACL qualifiers rather than names
|
||||
bit2= do not encode attributes other than ACL
|
||||
bit15= free memory of names, value_lengths, values
|
||||
@return >0 ok
|
||||
<=0 error
|
||||
*/
|
||||
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||
size_t **value_lengths, char ***values, int flag)
|
||||
{
|
||||
int ret, retry= 0;
|
||||
char *list= NULL;
|
||||
ssize_t list_size= 0, i, num_names, 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;
|
||||
char *acl_text= NULL;
|
||||
|
||||
if(flag & (1 << 15)) { /* Free memory */
|
||||
if(*names != NULL)
|
||||
list= (*names)[0];
|
||||
{ret= 1; goto ex;}
|
||||
}
|
||||
|
||||
*num_attrs= 0;
|
||||
*names= NULL;
|
||||
*value_lengths= NULL;
|
||||
*values= NULL;
|
||||
|
||||
if(flag & 1)
|
||||
num_names++;
|
||||
if(num_names == 0)
|
||||
{ret= 1; goto ex;}
|
||||
(*names)= calloc(num_names, sizeof(char *));
|
||||
(*value_lengths)= calloc(num_names, sizeof(size_t));
|
||||
(*values)= calloc(num_names, sizeof(char *));
|
||||
if(*names == NULL || *value_lengths == NULL || *values == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
|
||||
for(i= *num_attrs; i < num_names; i++)
|
||||
(*names)[i]= NULL;
|
||||
for(i= 0; i < num_names; i++) {
|
||||
(*values)[i]= NULL;
|
||||
(*value_lengths)[i]= 0;
|
||||
}
|
||||
|
||||
if(flag & 1) { /* Obtain ACL */
|
||||
/* access-ACL */
|
||||
ret= aaip_get_acl_text(path, &acl_text, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
ret= aaip_encode_acl(acl_text, &a_acl_len, &a_acl, flag & 2);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
|
||||
|
||||
/* Note: There are no default-ACL in FreeBSD */
|
||||
|
||||
/* Set as attribute with empty name */;
|
||||
(*names)[*num_attrs]= strdup("");
|
||||
if((*names)[*num_attrs] == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
(*values)[*num_attrs]= (char *) acl;
|
||||
(*value_lengths)[*num_attrs]= acl_len;
|
||||
(*num_attrs)++;
|
||||
}
|
||||
|
||||
ret= 1;
|
||||
ex:;
|
||||
if(a_acl != NULL)
|
||||
free(a_acl);
|
||||
if(d_acl != NULL)
|
||||
free(d_acl);
|
||||
if(acl_text != NULL)
|
||||
aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
|
||||
|
||||
if(ret <= 0 || (flag & (1 << 15))) {
|
||||
if(list != NULL)
|
||||
free(list);
|
||||
if(*names != NULL)
|
||||
free(*names);
|
||||
*names= NULL;
|
||||
if(*value_lengths != NULL)
|
||||
free(*value_lengths);
|
||||
*value_lengths= NULL;
|
||||
if(*values != NULL) {
|
||||
for(i= 0; i < *num_attrs; i++)
|
||||
free((*values)[i]);
|
||||
free(*values);
|
||||
}
|
||||
if(acl != NULL)
|
||||
free(acl);
|
||||
*values= NULL;
|
||||
*num_attrs= 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------ Setters --------------------------------- */
|
||||
|
||||
|
||||
/* Set the ACL of the given file to a given list in long text form.
|
||||
@param 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
|
||||
-1 failure of system ACL service (see errno)
|
||||
*/
|
||||
int aaip_set_acl_text(char *path, char *text, int flag)
|
||||
{
|
||||
int ret;
|
||||
acl_t acl= NULL;
|
||||
|
||||
acl= acl_from_text(text);
|
||||
if(acl == NULL) {
|
||||
ret= -1; goto ex;
|
||||
}
|
||||
|
||||
/* Note: no ACL_TYPE_DEFAULT in FreeBSD */
|
||||
if(flag & 1)
|
||||
{ret= 0; goto ex;}
|
||||
|
||||
ret= acl_set_file(path, ACL_TYPE_ACCESS, acl);
|
||||
|
||||
if(ret == -1)
|
||||
goto ex;
|
||||
ret= 1;
|
||||
ex:
|
||||
if(acl != NULL)
|
||||
acl_free(acl);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Bring the given attributes and/or ACLs into effect with the given file.
|
||||
|
||||
Note: There are no Extended Attributes in FreeBSD. So only ACL get set.
|
||||
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= decode and set ACLs
|
||||
( bit1= first clear all existing attributes of the file )
|
||||
( bit2= do not set attributes other than ACLs )
|
||||
@return 1 success
|
||||
-1 error memory allocation
|
||||
-2 error with decoding of ACL
|
||||
-3 error with setting ACL
|
||||
( -4 error with setting attribute )
|
||||
( -5 error with deleting attribute )
|
||||
|
||||
*/
|
||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values, int flag)
|
||||
{
|
||||
int ret, has_default_acl= 0;
|
||||
size_t i, consumed, acl_text_fill, list_size= 0;
|
||||
char *acl_text= NULL, *list= NULL;
|
||||
|
||||
for(i= 0; i < num_attrs; i++) {
|
||||
if(names[i] == NULL || values[i] == NULL)
|
||||
continue;
|
||||
if(names[i][0] == 0) { /* Decode ACLs */
|
||||
/* access ACL */
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
&consumed, NULL, 0, &acl_text_fill, 1);
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
acl_text= calloc(acl_text_fill, 1);
|
||||
if(acl_text == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
&consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
has_default_acl= (ret == 2);
|
||||
ret= aaip_set_acl_text(path, acl_text, 0);
|
||||
if(ret <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
if(has_default_acl) {
|
||||
free(acl_text);
|
||||
acl_text= NULL;
|
||||
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
|
||||
value_lengths[i] - consumed, &consumed,
|
||||
NULL, 0, &acl_text_fill, 1);
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
acl_text= calloc(acl_text_fill, 1);
|
||||
if(acl_text == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
|
||||
value_lengths[i] - consumed, &consumed,
|
||||
acl_text, acl_text_fill, &acl_text_fill, 0);
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
ret= aaip_set_acl_text(path, acl_text, 1);
|
||||
if(ret <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret= 1;
|
||||
ex:;
|
||||
if(acl_text != NULL)
|
||||
free(acl_text);
|
||||
if(list != NULL)
|
||||
free(list);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
371
libisofs/aaip-os-linux.c
Normal file
371
libisofs/aaip-os-linux.c
Normal file
@@ -0,0 +1,371 @@
|
||||
|
||||
/*
|
||||
|
||||
aaip-os-linux.c
|
||||
Arbitrary Attribute Interchange Protocol , system adapter for getting and
|
||||
setting of ACLs and XFS-style Extended Attributes.
|
||||
|
||||
To be included by aaip_0_2.c
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/acl.h>
|
||||
#include <attr/xattr.h>
|
||||
|
||||
#define Aaip_acl_attrnamE "system.posix_acl_access"
|
||||
|
||||
|
||||
/* ------------------------------ Getters --------------------------------- */
|
||||
|
||||
/* Obtain the ACL of the given file in long text form.
|
||||
@param path Path to the file
|
||||
@param text Will hold the result. This is a managed object which
|
||||
finally has to be freed by a call to this function
|
||||
with bit15 of flag.
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain default ACL rather than access ACL
|
||||
bit15= free text and return 1
|
||||
@return > 0 ok
|
||||
-1 failure of system ACL service (see errno)
|
||||
*/
|
||||
int aaip_get_acl_text(char *path, char **text, int flag)
|
||||
{
|
||||
acl_t acl= NULL;
|
||||
|
||||
if(flag & (1 << 15)) {
|
||||
if(*text != NULL)
|
||||
acl_free(text);
|
||||
*text= NULL;
|
||||
return(1);
|
||||
}
|
||||
*text= NULL;
|
||||
acl= acl_get_file(path, (flag & 1) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS);
|
||||
if(acl == NULL)
|
||||
return(-1);
|
||||
*text= acl_to_text(acl, NULL);
|
||||
acl_free(acl);
|
||||
if(*text == NULL)
|
||||
return(-1);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Obtain the Extended Attributes and/or the ACLs of the given file in a form
|
||||
that is ready for aaip_encode().
|
||||
@param path Path to the file
|
||||
@param num_attrs Will return the number of name-value pairs
|
||||
@param names Will return an array of pointers to 0-terminated names
|
||||
@param value_lengths Will return an arry with the lenghts of values
|
||||
@param values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain ACL (access and eventually default)
|
||||
bit1= use numeric ACL qualifiers rather than names
|
||||
bit2= do not obtain attributes other than ACL
|
||||
bit3= do not ignore eventual local ACL attribute
|
||||
(e.g. system.posix_acl_access)
|
||||
bit15= free memory of names, value_lengths, values
|
||||
@return >0 ok
|
||||
<=0 error
|
||||
*/
|
||||
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||
size_t **value_lengths, char ***values, int flag)
|
||||
{
|
||||
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;
|
||||
char *acl_text= NULL;
|
||||
|
||||
if(flag & (1 << 15)) { /* Free memory */
|
||||
if(*names != NULL)
|
||||
list= (*names)[0];
|
||||
{ret= 1; goto ex;}
|
||||
}
|
||||
|
||||
*num_attrs= 0;
|
||||
*names= NULL;
|
||||
*value_lengths= NULL;
|
||||
*values= NULL;
|
||||
|
||||
/* Set up arrays */
|
||||
if(!(flag & 4)) { /* Get xattr names */
|
||||
list_size= listxattr(path, list, 0);
|
||||
if(list_size == -1)
|
||||
{ret= -1; goto ex;}
|
||||
list= calloc(list_size, 1);
|
||||
if(list == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
list_size= listxattr(path, list, list_size);
|
||||
if(list_size == -1)
|
||||
{ret= -1; goto ex;}
|
||||
for(i= 0; i < list_size; i+= strlen(list + i) + 1)
|
||||
num_names++;
|
||||
}
|
||||
if(flag & 1)
|
||||
num_names++;
|
||||
if(num_names == 0)
|
||||
{ret= 1; goto ex;}
|
||||
(*names)= calloc(num_names, sizeof(char *));
|
||||
(*value_lengths)= calloc(num_names, sizeof(size_t));
|
||||
(*values)= calloc(num_names, sizeof(char *));
|
||||
if(*names == NULL || *value_lengths == NULL || *values == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
|
||||
if(!(flag & 4))
|
||||
for(i= 0; i < list_size && num_names > *num_attrs;
|
||||
i+= strlen(list + i) + 1) {
|
||||
if(!(flag & 8))
|
||||
if(strcmp(list + i, Aaip_acl_attrnamE) == 0)
|
||||
continue;
|
||||
(*names)[(*num_attrs)++]= list + i;
|
||||
}
|
||||
for(i= *num_attrs; i < num_names; i++)
|
||||
(*names)[i]= NULL;
|
||||
for(i= 0; i < num_names; i++) {
|
||||
(*values)[i]= NULL;
|
||||
(*value_lengths)[i]= 0;
|
||||
}
|
||||
|
||||
if(!(flag & 4)) { /* Get xattr values */
|
||||
for(i= 0; i < *num_attrs; i++) {
|
||||
if(!(flag & 8))
|
||||
if(strcmp((*names)[i], Aaip_acl_attrnamE) == 0)
|
||||
continue;
|
||||
value_ret= getxattr(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;}
|
||||
(*value_lengths)[i]= getxattr(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;
|
||||
}
|
||||
}
|
||||
|
||||
if(flag & 1) { /* Obtain ACL */
|
||||
/* access-ACL */
|
||||
ret= aaip_get_acl_text(path, &acl_text, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
ret= aaip_encode_acl(acl_text, &a_acl_len, &a_acl, flag & 2);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
|
||||
|
||||
/* eventually default-ACL */
|
||||
ret= aaip_get_acl_text(path, &acl_text, 1);
|
||||
if(ret > 0) {
|
||||
/* encode and append to a_acl */;
|
||||
ret= aaip_encode_acl(acl_text, &d_acl_len, &d_acl, (flag & 2) | 4);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
acl= calloc(a_acl_len + d_acl_len + 1, 1);
|
||||
if(acl == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
if(a_acl_len)
|
||||
memcpy(acl, a_acl, a_acl_len);
|
||||
if(d_acl_len)
|
||||
memcpy(acl + a_acl_len, d_acl, d_acl_len);
|
||||
acl_len= a_acl_len + d_acl_len;
|
||||
} else {
|
||||
acl= a_acl;
|
||||
a_acl= NULL;
|
||||
acl_len= a_acl_len;
|
||||
}
|
||||
|
||||
/* Set as attribute with empty name */;
|
||||
(*names)[*num_attrs]= strdup("");
|
||||
if((*names)[*num_attrs] == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
(*values)[*num_attrs]= (char *) acl;
|
||||
(*value_lengths)[*num_attrs]= acl_len;
|
||||
(*num_attrs)++;
|
||||
}
|
||||
|
||||
ret= 1;
|
||||
ex:;
|
||||
if(a_acl != NULL)
|
||||
free(a_acl);
|
||||
if(d_acl != NULL)
|
||||
free(d_acl);
|
||||
if(acl_text != NULL)
|
||||
aaip_get_acl_text("", &acl_text, 1 << 15); /* free */
|
||||
|
||||
if(ret <= 0 || (flag & (1 << 15))) {
|
||||
if(list != NULL)
|
||||
free(list);
|
||||
if(*names != NULL)
|
||||
free(*names);
|
||||
*names= NULL;
|
||||
if(*value_lengths != NULL)
|
||||
free(*value_lengths);
|
||||
*value_lengths= NULL;
|
||||
if(*values != NULL) {
|
||||
for(i= 0; i < *num_attrs; i++)
|
||||
free((*values)[i]);
|
||||
free(*values);
|
||||
}
|
||||
if(acl != NULL)
|
||||
free(acl);
|
||||
*values= NULL;
|
||||
*num_attrs= 0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------ Setters --------------------------------- */
|
||||
|
||||
|
||||
/* Set the ACL of the given file to a given list in long text form.
|
||||
@param 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
|
||||
-1 failure of system ACL service (see errno)
|
||||
*/
|
||||
int aaip_set_acl_text(char *path, char *text, int flag)
|
||||
{
|
||||
int ret;
|
||||
acl_t acl= NULL;
|
||||
|
||||
acl= acl_from_text(text);
|
||||
if(acl == NULL) {
|
||||
ret= -1; goto ex;
|
||||
}
|
||||
ret= acl_set_file(path, (flag & 1) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS, acl);
|
||||
if(ret == -1)
|
||||
goto ex;
|
||||
ret= 1;
|
||||
ex:
|
||||
if(acl != NULL)
|
||||
acl_free(acl);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Bring the given attributes and/or ACLs into effect with the given file.
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= decode and set ACLs
|
||||
bit1= first clear all existing attributes of the file
|
||||
bit2= do not set attributes other than ACLs
|
||||
bit3= do not ignore eventual ACL attribute
|
||||
(e.g. system.posix_acl_access)
|
||||
@return 1 success
|
||||
-1 error memory allocation
|
||||
-2 error with decoding of ACL
|
||||
-3 error with setting ACL
|
||||
-4 error with setting attribute
|
||||
-5 error with deleting attributes
|
||||
|
||||
*/
|
||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values, int flag)
|
||||
{
|
||||
int ret, has_default_acl= 0;
|
||||
size_t i, consumed, acl_text_fill, list_size= 0, acl_idx= 0;
|
||||
char *acl_text= NULL, *list= NULL;
|
||||
|
||||
if(flag & 2) /* Delete all file attributes */
|
||||
list_size= listxattr(path, list, 0);
|
||||
if(list_size > 0) { /* Delete all file attributes */
|
||||
list= calloc(list_size, 1);
|
||||
if(list == NULL)
|
||||
{ret= -5; goto ex;}
|
||||
list_size= listxattr(path, list, list_size);
|
||||
if(list_size == -1)
|
||||
{ret= -5; goto ex;}
|
||||
for(i= 0; i < list_size; i+= strlen(list + i) + 1) {
|
||||
if(!(flag & 8))
|
||||
if(strcmp(list + i, Aaip_acl_attrnamE) == 0)
|
||||
continue;
|
||||
ret= removexattr(path, list + i);
|
||||
if(ret == -1)
|
||||
{ret= -5; goto ex;}
|
||||
}
|
||||
free(list); list= NULL;
|
||||
}
|
||||
|
||||
for(i= 0; i < num_attrs; i++) {
|
||||
if(names[i] == NULL || values[i] == NULL)
|
||||
continue;
|
||||
if(names[i][0] == 0) { /* ACLs */
|
||||
if(flag & 1)
|
||||
acl_idx= i + 1;
|
||||
continue;
|
||||
}
|
||||
/* Extended Attribute */
|
||||
if((flag & 1) && !(flag & 8))
|
||||
if(strcmp(names[i], Aaip_acl_attrnamE) == 0)
|
||||
continue;
|
||||
ret= setxattr(path, names[i], values[i], value_lengths[i], 0);
|
||||
if(ret == -1)
|
||||
{ret= -4; goto ex;}
|
||||
}
|
||||
|
||||
/* Decode ACLs */
|
||||
if(acl_idx == 0)
|
||||
{ret= 1; goto ex;}
|
||||
i= acl_idx - 1;
|
||||
/* "access" ACL */
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
&consumed, NULL, 0, &acl_text_fill, 1);
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
acl_text= calloc(acl_text_fill, 1);
|
||||
if(acl_text == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
ret= aaip_decode_acl((unsigned char *) values[i], value_lengths[i],
|
||||
&consumed, acl_text, acl_text_fill, &acl_text_fill, 0);
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
has_default_acl= (ret == 2);
|
||||
ret= aaip_set_acl_text(path, acl_text, 0);
|
||||
if(ret <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
/* "default" ACL */
|
||||
if(has_default_acl) {
|
||||
free(acl_text);
|
||||
acl_text= NULL;
|
||||
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
|
||||
value_lengths[i] - consumed, &consumed,
|
||||
NULL, 0, &acl_text_fill, 1);
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
acl_text= calloc(acl_text_fill, 1);
|
||||
if(acl_text == NULL)
|
||||
{ret= -1; goto ex;}
|
||||
ret= aaip_decode_acl((unsigned char *) (values[i] + consumed),
|
||||
value_lengths[i] - consumed, &consumed,
|
||||
acl_text, acl_text_fill, &acl_text_fill, 0);
|
||||
if(ret <= 0)
|
||||
{ret= -2; goto ex;}
|
||||
ret= aaip_set_acl_text(path, acl_text, 1);
|
||||
if(ret <= 0)
|
||||
{ret= -3; goto ex;}
|
||||
}
|
||||
ret= 1;
|
||||
ex:;
|
||||
if(acl_text != NULL)
|
||||
free(acl_text);
|
||||
if(list != NULL)
|
||||
free(list);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
1693
libisofs/aaip_0_2.c
Normal file
1693
libisofs/aaip_0_2.c
Normal file
File diff suppressed because it is too large
Load Diff
381
libisofs/aaip_0_2.h
Normal file
381
libisofs/aaip_0_2.h
Normal file
@@ -0,0 +1,381 @@
|
||||
|
||||
/*
|
||||
|
||||
Arbitrary Attribute Interchange Protocol , AAIP version 0.2
|
||||
Demonstration program for encoding and decoding EA and ACL.
|
||||
|
||||
See http://libburnia-project.org/wiki/AAIP
|
||||
or doc/susp_aaip_0_2.txt
|
||||
|
||||
test/aaip_0.2.h - Public declarations
|
||||
|
||||
*/
|
||||
|
||||
#ifndef Aaip_h_is_includeD
|
||||
#define Aaip_h_is_includeD yes
|
||||
|
||||
|
||||
/* --------------------------------- Encoder ---------------------------- */
|
||||
|
||||
/* Convert an array of Arbitrary Attributes into a series of AAIP fields.
|
||||
@param aa_name The 2 byte SUSP Signature Word of the fields
|
||||
@param num_attrs Number of attributes
|
||||
@param names Array of pointers to 0 terminated name strings
|
||||
@param value_lengths Array of byte lengths for each value
|
||||
@param values Array of pointers to the value bytes
|
||||
@param result_len Number of bytes in the resulting SUSP field string
|
||||
@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= set CONTINUE bit of last AA field to 1
|
||||
@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);
|
||||
|
||||
|
||||
/* ------ ACL representation ------ */
|
||||
|
||||
/* Convert an 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 acl_text The ACL in long text form
|
||||
@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_acl(char *acl_text,
|
||||
size_t *result_len, unsigned char **result, int flag);
|
||||
|
||||
|
||||
/* ------ OS interface ------ */
|
||||
|
||||
/* Obtain the ACL of the given file in long text form.
|
||||
@param path Path to the file
|
||||
@param text Will hold the result. This is a managed object which
|
||||
finally has to be freed by a call to this function
|
||||
with bit15 of flag.
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain default ACL rather than access ACL
|
||||
bit15= free text and return 1
|
||||
@return > 0 ok
|
||||
-1 failure of system ACL service (see errno)
|
||||
*/
|
||||
int aaip_get_acl_text(char *path, char **text, int flag);
|
||||
|
||||
|
||||
/* Obtain the Extended Attributes and/or the ACLs of the given file in a form
|
||||
that is ready for aaip_encode(). The returned data objects finally have
|
||||
to be freed by a call with flag bit 15.
|
||||
@param path Path to the file
|
||||
@param num_attrs Will return the number of name-value pairs
|
||||
@param names Will return an array of pointers to 0-terminated names
|
||||
@param value_lengths Will return an arry with the lenghts of values
|
||||
@param values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= obtain ACLs (access and eventually default) via
|
||||
system ACL API and encode
|
||||
bit1= use numeric ACL qualifiers rather than names
|
||||
bit2= do not obtain attributes other than ACLs
|
||||
bit3= do not ignore eventual ACL attribute
|
||||
(e.g. system.posix_acl_access)
|
||||
bit15= free memory of names, value_lengths, values
|
||||
@return >0 ok
|
||||
<=0 error
|
||||
*/
|
||||
int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
|
||||
size_t **value_lengths, char ***values, int flag);
|
||||
|
||||
|
||||
/* --------------------------------- Decoder ---------------------------- */
|
||||
|
||||
/*
|
||||
The AAIP decoder offers several levels of abstraction of which the
|
||||
lower two avoid the use of dynamic memory. It provides a stateful decoding
|
||||
context with a small buffer which delivers results to caller provided
|
||||
memory locations.
|
||||
|
||||
The lowest level is the stream-like Component Level Interface. It allows
|
||||
to decode very many very long attributes.
|
||||
|
||||
Next is the Pair Level Interface which delivers to fixly sized storage for
|
||||
name and value. It allows to decode very many attributes.
|
||||
|
||||
The List Level Interface uses dynamic memory allocation to provide arrays
|
||||
of names, values and value lengths. It is intended for moderately sized
|
||||
attribute lists but may also be used as alternative to Pair Level.
|
||||
*/
|
||||
|
||||
|
||||
/* The AAIP decoder context.
|
||||
*/
|
||||
struct aaip_state;
|
||||
|
||||
|
||||
/* Obtain the size in bytes of an aaip_state object.
|
||||
*/
|
||||
size_t aaip_sizeof_aaip_state(void);
|
||||
|
||||
|
||||
/* Initialize a AAIP decoder context.
|
||||
This has to be done before the first AA field of a node is processed.
|
||||
The caller has to provide the storage of the struct aaip_state.
|
||||
@param aaip The AAIP decoder context to be initialized
|
||||
@param aa_name The Signature Word (advised is "AA")
|
||||
@param flag Bitfield for control purposes
|
||||
submit 0
|
||||
@return <=0 error , >0 ok
|
||||
*/
|
||||
int aaip_init_aaip_state(struct aaip_state *aaip, char aa_name[2], int flag);
|
||||
|
||||
|
||||
/* ------------------------- Component Level Interface ------------------- */
|
||||
/*
|
||||
Provides support for unlimited component size but demands the caller
|
||||
to have a growing storage facility resp. to do own oversize handling.
|
||||
|
||||
This interface expects moderatly sized input pieces and will hand out
|
||||
moderately sized result pieces. The number of transactions is virtually
|
||||
unlimited.
|
||||
*/
|
||||
|
||||
/* Submit small data chunk for decoding.
|
||||
The return value will tell whether data are pending for being fetched.
|
||||
@param aaip The AAIP decoder context
|
||||
@param data Not more than 2048 bytes input for the decoder
|
||||
@param num_data Number of bytes in data
|
||||
0 inquires the buffer status avoiding replies <= 0
|
||||
@param ready_bytes Number of decoded bytes ready for delivery
|
||||
@param flag Bitfield for control purposes
|
||||
@return -1= non-AA field detected
|
||||
*ready_bytes gives number of consumed bytes in data
|
||||
0= cannot accept data because buffer full
|
||||
1= no component record complete, submit more data
|
||||
2= component record complete, may be delivered
|
||||
3= component complete, may be delivered
|
||||
4= no component available, no more data expected, done
|
||||
*/
|
||||
int aaip_submit_data(struct aaip_state *aaip,
|
||||
unsigned char *data, size_t num_data,
|
||||
size_t *ready_bytes, int flag);
|
||||
|
||||
|
||||
/* Fetch the available part of current component.
|
||||
The return value will tell whether it belongs to name or to value and
|
||||
whether that name or value is completed now.
|
||||
@param aaip The AAIP decoder context
|
||||
@param result Has to point to storage for the component data
|
||||
@param result_size Gives the amount of provided result storage
|
||||
@param num_result Will tell the number of fetched result bytes
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= discard data rather than copying to result
|
||||
@return -2 = insufficient result_size
|
||||
-1 = no data ready for delivery
|
||||
0 = result holds the final part of a name
|
||||
1 = result holds an intermediate part of a name
|
||||
2 = result holds the final part of a value
|
||||
3 = result holds an intermediate part of a value
|
||||
*/
|
||||
int aaip_fetch_data(struct aaip_state *aaip,
|
||||
char *result, size_t result_size, size_t *num_result,
|
||||
int flag);
|
||||
|
||||
|
||||
/* Skip the current component and eventually the following value component.
|
||||
This has to be called if fetching of a component shall be aborted
|
||||
but the next component resp. pair shall be fetchable again.
|
||||
aaip_submit_data() will not indicate readiness for fetching until all
|
||||
bytes of the skipped components are submitted. Those bytes get discarded.
|
||||
@param aaip The AAIP decoder context
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= do not skip value if current component is name
|
||||
@return <=0 error , 1= now in skip state, 2= not in skip state
|
||||
*/
|
||||
int aaip_skip_component(struct aaip_state *aaip, int flag);
|
||||
|
||||
|
||||
/* ------------------------- Pair Level Interface ------------------------ */
|
||||
/*
|
||||
Provides support for names and values of limited size. The limits are
|
||||
given by the caller who has to provide the storage for name and value.
|
||||
|
||||
This interface expects moderatly sized input pieces.
|
||||
The number of input transcations is virtually unlimited.
|
||||
The number of pair transactions after aaip_init() should be limited
|
||||
to 4 billion.
|
||||
*/
|
||||
|
||||
|
||||
/* Accept raw input data and collect a pair of name and value.
|
||||
The return value will indicate whether the pair is complete, whether more
|
||||
pairs are complete or whether more data are desired. No input data will be
|
||||
accepted as long as complete pairs are pending. The end of the attribute
|
||||
list will be indicated.
|
||||
@param aaip The AAIP decoder context
|
||||
@param data The raw data to decode
|
||||
@param num_data Number of data bytes provided
|
||||
@param consumed Returns the number of consumed data bytes
|
||||
@param name Buffer to build the name string
|
||||
@param name_size Maximum number of bytes in name
|
||||
@param name_fill Holds the current buffer fill of name
|
||||
@param value Buffer to build the value string
|
||||
@param value_size Maximum number of bytes in value
|
||||
@param value_fill Holds the current buffer fill of value
|
||||
@param flag Bitfield for control purposes - submit 0 for now
|
||||
@return <0 error
|
||||
0 data not accepted, first fetch pending pairs with num_data == 0
|
||||
1 name and value are not valid yet, submit more data
|
||||
2 name and value are valid, submit more data
|
||||
3 name and value are valid, pairs pending, fetch with num_data == 0
|
||||
4 name and value are valid, no more data expected
|
||||
5 name and value are not valid, no more data expected
|
||||
|
||||
*/
|
||||
int aaip_decode_pair(struct aaip_state *aaip,
|
||||
unsigned char *data, size_t num_data, size_t *consumed,
|
||||
char *name, size_t name_size, size_t *name_fill,
|
||||
char *value, size_t value_size, size_t *value_fill,
|
||||
int flag);
|
||||
|
||||
|
||||
/* Inquire the number of pairs which were skipped because being oversized.
|
||||
@param aaip The AAIP decoder context
|
||||
@param flag Bitfield for control purposes - submit 0 for now
|
||||
@return The number of pairs skipped since aaip_init()
|
||||
*/
|
||||
unsigned int aaip_get_pairs_skipped(struct aaip_state *aaip, int flag);
|
||||
|
||||
|
||||
/* ------------------------- List Level Interface ------------------------ */
|
||||
/*
|
||||
Provides support for names and values of limited size. The limits are
|
||||
given for total memory consumption and for number of attributes.
|
||||
|
||||
Iterated decoding is supported as long as no single attribute exceeds
|
||||
the memory limit.
|
||||
*/
|
||||
|
||||
/* Accept raw input data and collect arrays of name pointers, value lengths
|
||||
and value pointers. A handle object will emerge which finally has to be
|
||||
be freed by a call with bit 15.
|
||||
@param handle The decoding context.
|
||||
It will be created by this call with flag bit 0 or if
|
||||
*handle == NULL. This handle has to be the same as long
|
||||
as decoding goes on and finally has to be freed by a
|
||||
call with bit15.
|
||||
@param aa_name The Signature Word (advised is "AA")
|
||||
@param memory_limit Maximum number of bytes to allocate
|
||||
@param num_attr_limit Maximum number of name-value pairs to allocate
|
||||
@param data The raw data to decode
|
||||
@param num_data Number of data bytes provided
|
||||
@param consumed Returns the number of consumed data bytes
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= this is the first call for a file object
|
||||
bit15= end decoding :
|
||||
Free handle and its intermediate list memory.
|
||||
@return <=0 error
|
||||
1 not complete yet, submit more data
|
||||
2 arrays are complete, call aaip_get_decoded_attrs()
|
||||
3 limit exceeded, not complete yet, call with bit15 and give up
|
||||
4 limit exceeded, call aaip_get_decoded_attrs() and try again
|
||||
*/
|
||||
int aaip_decode_attrs(struct aaip_state **handle, char aa_name[2],
|
||||
size_t memory_limit, size_t num_attr_limit,
|
||||
unsigned char *data, size_t num_data, size_t *consumed,
|
||||
int flag);
|
||||
|
||||
|
||||
/* Obtain the resulting attributes when aaip_decode_attrs() indicates to
|
||||
be done or to have the maximum possible amount of result ready.
|
||||
The returned data objects get detached from handle making it ready for
|
||||
the next round of decoding with possibly a different input source. The
|
||||
returned data objects finally have to be freed by a call with flag bit 15.
|
||||
@param handle The decoding context created by aaip_decode_attrs()
|
||||
@param num_attrs Will return the number of name-value pairs
|
||||
@param names Will return an array of pointers to 0-terminated names
|
||||
@param value_lengths Will return an arry with the lenghts of values
|
||||
@param values Will return an array of pointers to 8-bit values
|
||||
@param flag Bitfield for control purposes
|
||||
bit15= free memory of names, value_lengths, values
|
||||
*/
|
||||
int aaip_get_decoded_attrs(struct aaip_state **handle, size_t *num_attrs,
|
||||
char ***names, size_t **value_lengths, char ***values,
|
||||
int flag);
|
||||
|
||||
|
||||
/* ------ ACL representation ------ */
|
||||
|
||||
/* Convert an AAIP 0.2 ACL attribute value into the long text form of ACL.
|
||||
@param data The raw data to decode
|
||||
@param num_data Number of data bytes provided
|
||||
@param consumed Returns the number of consumed data bytes
|
||||
@param acl_text Will be filled with ACL long text form
|
||||
@param acl_text_size Maximum number of bytes to be written to acl_text
|
||||
@param acl_text_fill Will return the number of bytes in acl_text
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= count only, do not really produce bytes:
|
||||
acl_text will not be touched,
|
||||
acl_text_size will be ignored,
|
||||
*acl_text_fill will return the counted number
|
||||
bit1= expected is a default ACL (see return value 2)
|
||||
@return 1 success
|
||||
2 success, begin of default/access ACL encountered,
|
||||
submit data + *consumed for access/default ACL
|
||||
-1 error with reading of qualifier
|
||||
-2 error with writing of ACL text line
|
||||
-3 version mismatch
|
||||
-4 unknown tag type encountered
|
||||
*/
|
||||
int aaip_decode_acl(unsigned char *data, size_t num_data, size_t *consumed,
|
||||
char *acl_text, size_t acl_text_size,
|
||||
size_t *acl_text_fill, int flag);
|
||||
|
||||
|
||||
/* ------ OS interface ------ */
|
||||
|
||||
/* Set the ACL of the given file to a given list in long text form.
|
||||
@param 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
|
||||
-1 failure of system ACL service (see errno)
|
||||
*/
|
||||
int aaip_set_acl_text(char *path, char *text, int flag);
|
||||
|
||||
|
||||
/* Bring the given attributes and/or ACLs into effect with the given file.
|
||||
@param path Path to the file
|
||||
@param num_attrs Number of attributes
|
||||
@param names Array of pointers to 0 terminated name strings
|
||||
@param value_lengths Array of byte lengths for each attribute payload
|
||||
@param values Array of pointers to the attribute payload bytes
|
||||
@param flag Bitfield for control purposes
|
||||
bit0= decode and set ACLs
|
||||
bit1= first clear all existing attributes of the file
|
||||
bit2= do not set attributes other than ACLs
|
||||
bit3= do not ignore eventual ACL attribute
|
||||
(e.g. system.posix_acl_access)
|
||||
@return 1 success
|
||||
-1 error memory allocation
|
||||
-2 error with decoding of ACL
|
||||
-3 error with setting ACL
|
||||
-4 error with setting attribute
|
||||
-5 error with deleting attributes
|
||||
|
||||
*/
|
||||
int aaip_set_attr_list(char *path, size_t num_attrs, char **names,
|
||||
size_t *value_lengths, char **values, int flag);
|
||||
|
||||
#endif /* ! Aaip_h_is_includeD */
|
||||
|
Reference in New Issue
Block a user