diff options
author | ahrens <none@none> | 2005-10-31 11:33:35 -0800 |
---|---|---|
committer | ahrens <none@none> | 2005-10-31 11:33:35 -0800 |
commit | fa9e4066f08beec538e775443c5be79dd423fcab (patch) | |
tree | 576d99665e57bb7cb70584431adb08c14d47e3ce /usr/src/lib/libsec/common/acltext.c | |
parent | f1b64740276f67fc6914c1d855f2af601efe99ac (diff) | |
download | illumos-joyent-fa9e4066f08beec538e775443c5be79dd423fcab.tar.gz |
PSARC 2002/240 ZFS
6338653 Integrate ZFS
PSARC 2004/652 - DKIOCFLUSH
5096886 Write caching disks need mechanism to flush cache to physical media
Diffstat (limited to 'usr/src/lib/libsec/common/acltext.c')
-rw-r--r-- | usr/src/lib/libsec/common/acltext.c | 801 |
1 files changed, 757 insertions, 44 deletions
diff --git a/usr/src/lib/libsec/common/acltext.c b/usr/src/lib/libsec/common/acltext.c index da3195379c..75b0dc7857 100644 --- a/usr/src/lib/libsec/common/acltext.c +++ b/usr/src/lib/libsec/common/acltext.c @@ -32,9 +32,15 @@ #include <string.h> #include <limits.h> #include <stdlib.h> +#include <errno.h> #include <sys/param.h> #include <sys/types.h> #include <sys/acl.h> +#include <aclutils.h> +#include <libintl.h> + + +extern acl_t *acl_alloc(enum acl_type); /* * acltotext() converts each ACL entry to look like this: @@ -64,8 +70,21 @@ static char *strappend(char *, char *); static char *convert_perm(char *, o_mode_t); static int increase_length(struct dynaclstr *, size_t); -#define FREE free(aclp);\ - free(allocp) +static int +acl_str_to_id(char *str, int *id) +{ + char *end; + uid_t value; + + value = strtol(str, &end, 10); + + if (errno != 0 || *end != '\0') + return (EACL_INVALID_USER_GROUP); + + *id = value; + + return (0); +} /* * Convert internal acl representation to external representation. @@ -213,8 +232,8 @@ acltotext(aclent_t *aclp, int aclcnt) * The comma at the end is not prescribed by the man pages. * But it is needed not to break the old programs. */ -aclent_t * -aclfromtext(char *aclstr, int *aclcnt) +static int +aclent_aclfromtext(char *aclstr, acl_t **ret_aclp) { char *fieldp; char *tp; @@ -224,23 +243,29 @@ aclfromtext(char *aclstr, int *aclcnt) int entry_type; int id; int len; + int error; o_mode_t perm; aclent_t *tmpaclp; - aclent_t *aclp; + acl_t *aclp; struct group *groupp; struct passwd *passwdp; - *aclcnt = 0; aclp = NULL; if (! aclstr) return (NULL); + aclp = acl_alloc(ACLENT_T); + if (aclp == NULL) { + return (EACL_MEM_ERROR); + } + + *ret_aclp = NULL; + len = strlen(aclstr); if ((aclimport = allocp = strdup(aclstr)) == NULL) { - fprintf(stderr, "malloc() failed\n"); - return (NULL); + return (EACL_MEM_ERROR); } if (aclimport[len - 1] == ',') @@ -256,32 +281,33 @@ aclfromtext(char *aclstr, int *aclcnt) nextp = tp + 1; } - *aclcnt += 1; + aclp->acl_cnt += 1; /* * get additional memory: * can be more efficient by allocating a bigger block * each time. */ - if (*aclcnt > 1) - tmpaclp = (aclent_t *)realloc(aclp, - sizeof (aclent_t) * (*aclcnt)); + if (aclp->acl_cnt > 1) + tmpaclp = (aclent_t *)realloc(aclp->acl_aclp, + sizeof (aclent_t) * (aclp->acl_cnt)); else tmpaclp = (aclent_t *)malloc(sizeof (aclent_t)); if (tmpaclp == NULL) { free(allocp); - if (aclp) - free(aclp); - return (NULL); + acl_free(aclp); + return (EACL_MEM_ERROR); } - aclp = tmpaclp; - tmpaclp = aclp + (*aclcnt - 1); + aclp->acl_aclp = tmpaclp; + tmpaclp = (aclent_t *)aclp->acl_aclp + (aclp->acl_cnt - 1); /* look for entry type field */ tp = strchr(aclimport, ':'); if (tp == NULL) { - FREE; - return (NULL); + free(allocp); + if (aclp) + acl_free(aclp); + return (EACL_ENTRY_ERROR); } else *tp = '\0'; if (strcmp(aclimport, "user") == 0) { @@ -313,8 +339,9 @@ aclfromtext(char *aclstr, int *aclcnt) else if (strcmp(aclimport, "defaultother") == 0) entry_type = DEF_OTHER_OBJ; else { - FREE; - return (NULL); + free(allocp); + acl_free(aclp); + return (EACL_ENTRY_ERROR); } /* look for user/group name */ @@ -324,8 +351,9 @@ aclfromtext(char *aclstr, int *aclcnt) fieldp = tp + 1; tp = strchr(fieldp, ':'); if (tp == NULL) { - FREE; - return (NULL); + free(allocp); + acl_free(aclp); + return (EACL_INVALID_USER_GROUP); } else *tp = '\0'; if (fieldp != tp) { @@ -341,32 +369,37 @@ aclfromtext(char *aclstr, int *aclcnt) * change. Use the friendlier interface * getpwnam(). */ + error = 0; passwdp = getpwnam(fieldp); if (passwdp == NULL) { - (void) fprintf(stderr, - "user %s not found\n", fieldp); - id = UID_NOBODY; /* nobody */ - } - else + error = acl_str_to_id(fieldp, + &id); + } else { id = passwdp->pw_uid; + } + + if (error) { + free(allocp); + acl_free(aclp); + return (error); + } + } else { + error = 0; if (entry_type == GROUP || entry_type == DEF_GROUP) { groupp = getgrnam(fieldp); if (groupp == NULL) { - (void) fprintf(stderr, - "group %s not found\n", - fieldp); - /* no group? */ - id = GID_NOBODY; + error = acl_str_to_id( + fieldp, &id); } - else + if (error == 0) id = groupp->gr_gid; - } else { - (void) fprintf(stderr, - "acl import errors\n"); - FREE; - return (NULL); + } + if (error) { + free(allocp); + acl_free(aclp); + return (error); } } } else { @@ -390,8 +423,9 @@ aclfromtext(char *aclstr, int *aclcnt) fieldp = tp + 1; if (strlen(fieldp) != 3) { /* not "rwx" format */ - FREE; - return (NULL); + free(allocp); + acl_free(aclp); + return (EACL_PERM_MASK_ERROR); } else { char s[] = "rwx"; int mask = 0x04; @@ -402,8 +436,9 @@ aclfromtext(char *aclstr, int *aclcnt) if (fieldp[i] == s[i]) perm |= mask; else if (fieldp[i] != '-') { - FREE; - return (NULL); + free(allocp); + acl_free(aclp); + return (EACL_PERM_MASK_ERROR); } } } @@ -414,9 +449,30 @@ aclfromtext(char *aclstr, int *aclcnt) aclimport = nextp; } free(allocp); - return (aclp); + *ret_aclp = aclp; + return (0); +} + +aclent_t * +aclfromtext(char *aclstr, int *aclcnt) +{ + acl_t *aclp; + aclent_t *aclentp; + int error; + + error = aclent_aclfromtext(aclstr, &aclp); + if (error) + return (NULL); + + aclentp = aclp->acl_aclp; + aclp->acl_aclp = NULL; + acl_free(aclp); + + *aclcnt = aclp->acl_cnt; + return (aclentp); } + static char * strappend(char *where, char *newstr) { @@ -443,6 +499,129 @@ convert_perm(char *where, o_mode_t perm) return (where); } +static char * +ace_convert_perm(char *where, mode_t perm, int isdir, int iflags) +{ + char *start = where; + + /* + * The following mneumonics all have the + * same value. The only difference is the + * first value is for files and second for directories + * ACE_READ_DATA/ACE_LIST_DIRECTORY + * ACE_WRITE_DATA/ACE_ADD_FILE + * ACE_APPEND_DATA/ACE_ADD_SUBDIRECTORY + */ + + /* + * If ACE is a directory, but inheritance indicates its + * for a file then print permissions for file rather than + * dir. + */ + if (isdir) { + if (perm & ACE_LIST_DIRECTORY) { + if (iflags == ACE_FILE_INHERIT_ACE) + where = strappend(where, "read_data/"); + else + where = strappend(where, + "list_directory/read_data/"); + } + if (perm & ACE_ADD_FILE) { + if (iflags == ACE_FILE_INHERIT_ACE) + where = strappend(where, "write_data/"); + else + where = strappend(where, + "add_file/write_data/"); + } + if (perm & ACE_ADD_SUBDIRECTORY) { + if (iflags == ACE_FILE_INHERIT_ACE) + where = strappend(where, "append_data/"); + else + where = strappend(where, + "add_subdirectory/append_data/"); + } + } else { + if (perm & ACE_READ_DATA) + where = strappend(where, "read_data/"); + if (perm & ACE_WRITE_DATA) + where = strappend(where, "write_data/"); + if (perm & ACE_APPEND_DATA) + where = strappend(where, "append_data/"); + } + if (perm & ACE_READ_NAMED_ATTRS) + where = strappend(where, "read_xattr/"); + if (perm & ACE_WRITE_NAMED_ATTRS) + where = strappend(where, "write_xattr/"); + if (perm & ACE_EXECUTE) + where = strappend(where, "execute/"); + if (perm & ACE_DELETE_CHILD) + where = strappend(where, "delete_child/"); + if (perm & ACE_READ_ATTRIBUTES) + where = strappend(where, "read_attributes/"); + if (perm & ACE_WRITE_ATTRIBUTES) + where = strappend(where, "write_attributes/"); + if (perm & ACE_DELETE) + where = strappend(where, "delete/"); + if (perm & ACE_READ_ACL) + where = strappend(where, "read_acl/"); + if (perm & ACE_WRITE_ACL) + where = strappend(where, "write_acl/"); + if (perm & ACE_WRITE_OWNER) + where = strappend(where, "write_owner/"); + if (perm & ACE_SYNCHRONIZE) + where = strappend(where, "synchronize"); + + if (start[strlen(start) - 1] == '/') { + start[strlen(start) - 1] = '\0'; + where = start + strlen(start); + } + return (where); +} + +int +ace_permask(char *perm_tok, int *perm) +{ + if (strcmp(perm_tok, "read_data") == 0) + *perm |= ACE_READ_DATA; + else if (strcmp(perm_tok, "list_directory") == 0) + *perm |= ACE_LIST_DIRECTORY; + else if (strcmp(perm_tok, "write_data") == 0) + *perm |= ACE_WRITE_DATA; + else if (strcmp(perm_tok, "add_file") == 0) + *perm |= ACE_ADD_FILE; + else if (strcmp(perm_tok, "append_data") == 0) + *perm |= ACE_APPEND_DATA; + else if (strcmp(perm_tok, "add_subdirectory") == 0) + *perm |= ACE_ADD_SUBDIRECTORY; + else if (strcmp(perm_tok, "read_xattr") == 0) + *perm |= ACE_READ_NAMED_ATTRS; + else if (strcmp(perm_tok, "write_xattr") == 0) + *perm |= ACE_WRITE_NAMED_ATTRS; + else if (strcmp(perm_tok, "execute") == 0) + *perm |= ACE_EXECUTE; + else if (strcmp(perm_tok, "delete_child") == 0) + *perm |= ACE_DELETE_CHILD; + else if (strcmp(perm_tok, "read_attributes") == 0) + *perm |= ACE_READ_ATTRIBUTES; + else if (strcmp(perm_tok, "write_attributes") == 0) + *perm |= ACE_WRITE_ATTRIBUTES; + else if (strcmp(perm_tok, "delete") == 0) + *perm |= ACE_DELETE; + else if (strcmp(perm_tok, "read_acl") == 0) + *perm |= ACE_READ_ACL; + else if (strcmp(perm_tok, "write_acl") == 0) + *perm |= ACE_WRITE_ACL; + else if (strcmp(perm_tok, "write_owner") == 0) + *perm |= ACE_WRITE_OWNER; + else if (strcmp(perm_tok, "synchronize") == 0) + *perm |= ACE_SYNCHRONIZE; + else { + return (1); + } + + return (0); +} + /* * Callers should check the return code as this routine may change the string * pointer in dynaclstr. @@ -462,3 +641,537 @@ increase_length(struct dynaclstr *dacl, size_t increase) } else return (0); } + +/* + * ace_acltotext() conver each ace formatted acl to look like this: + * + * entry_type:uid^gid^name:perms:allow^deny[:flags][,] + * + * The maximum length of entry_type is 5 ("group") + * + * The max length of a uid^gid^name entry (in theory) is 8, hence we use + * LOGNAME_MAX. + * + * The length of a perms entry is 144 i.e read_data/write_data... + * to each acl entry. + * + * iflags: file_inherit/dir_inherit/inherit_only/no_propagate + * + */ + +#define ACE_ENTRYTYPLEN 6 +#define IFLAGS_SIZE 51 +#define ACCESS_TYPE_SIZE 5 +#define COLON_CNT 3 +#define PERMS_LEN 216 +#define ACE_ENTRY_SIZE (ACE_ENTRYTYPLEN + LOGNAME_MAX + PERMS_LEN +\ + ACCESS_TYPE_SIZE + IFLAGS_SIZE + COLON_CNT) + +static char * +ace_acltotext(acl_t *aceaclp) +{ + ace_t *aclp = aceaclp->acl_aclp; + int aclcnt = aceaclp->acl_cnt; + char *aclexport; + char *where; + char *start; + struct group *groupp; + struct passwd *passwdp; + struct dynaclstr *dstr; + int i, rtn; + int isdir = (aceaclp->acl_flags & ACL_IS_DIR); + size_t excess = 0; + + if (aclp == NULL) + return (NULL); + if ((dstr = malloc(sizeof (struct dynaclstr))) == NULL) + return (NULL); + dstr->bufsize = aclcnt * ACE_ENTRY_SIZE; + if ((dstr->aclexport = malloc(dstr->bufsize)) == NULL) + return (NULL); + *dstr->aclexport = '\0'; + where = dstr->aclexport; + + for (i = 0; i < aclcnt; i++, aclp++) { + switch (aclp->a_flags & 0xf040) { + case ACE_OWNER: + case 0: + if ((aclp->a_flags & 0xf040) == ACE_OWNER) + where = strappend(where, "owner@"); + else + where = strappend(where, "user:"); + if ((aclp->a_flags & 0xf040) == 0) { + passwdp = getpwuid(aclp->a_who); + if (passwdp == (struct passwd *)NULL) { + /* put in uid instead */ + (void) sprintf(where, "%d", + aclp->a_who); + } else { + excess = strlen(passwdp->pw_name) - + LOGNAME_MAX; + if (excess > 0) { + rtn = increase_length(dstr, + excess); + if (rtn == 1) + /* reset where */ + where = + dstr->aclexport + + strlen( + dstr->aclexport); + else + return (NULL); + } + where = strappend(where, + passwdp->pw_name); + } + } else { + where = strappend(where, ""); + } + where = strappend(where, ":"); + break; + case ACE_GROUP|ACE_IDENTIFIER_GROUP: + case ACE_IDENTIFIER_GROUP: + if ((aclp->a_flags & 0xf040) == + (ACE_GROUP | ACE_IDENTIFIER_GROUP)) + where = strappend(where, "group@"); + else + where = strappend(where, "group:"); + if (!(aclp->a_flags & ACE_GROUP)) { + groupp = getgrgid(aclp->a_who); + if (groupp == (struct group *)NULL) { + /* put in gid instead */ + (void) sprintf(where, + "%d", aclp->a_who); + } else { + excess = strlen(groupp->gr_name) - + LOGNAME_MAX; + if (excess > 0) { + rtn = increase_length(dstr, + excess); + if (rtn == 1) + /* reset where */ + where = + dstr->aclexport + + strlen( + dstr->aclexport); + else + return (NULL); + } + where = strappend(where, + groupp->gr_name); + } + } else { + where = strappend(where, ""); + } + where = strappend(where, ":"); + break; + case ACE_EVERYONE: + where = strappend(where, "everyone@:"); + break; + default: + free(dstr->aclexport); + free(dstr); + return (NULL); + + } + where = ace_convert_perm(where, aclp->a_access_mask, + isdir, (aclp->a_flags & + (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE))); + where = strappend(where, + (aclp->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) ? + ":allow" : ":deny"); + + /* + * slap on inheritance flags if we have any + */ + + if (aclp->a_flags & 0xf) { + where = strappend(where, ":"); + start = where; + if (aclp->a_flags & ACE_FILE_INHERIT_ACE) + where = strappend(where, "file_inherit/"); + if (aclp->a_flags & ACE_DIRECTORY_INHERIT_ACE) + where = strappend(where, "dir_inherit/"); + if (aclp->a_flags & ACE_NO_PROPAGATE_INHERIT_ACE) + where = strappend(where, "no_propagate/"); + if (aclp->a_flags & ACE_INHERIT_ONLY_ACE) + where = strappend(where, "inherit_only"); + + /* + * chop off trailing slash, if present + */ + if (start[strlen(start) - 1] == '/') { + start[strlen(start) - 1] = '\0'; + where = start + strlen(start); + } + } + if (i < aclcnt - 1) + where = strappend(where, ","); + } + aclexport = dstr->aclexport; + free(dstr); + return (aclexport); +} + +static int +build_iflags(char *str, int *iflags) +{ + + char *tok; + *iflags = 0; + + tok = strtok(str, "/"); + + if (tok == NULL) + return (1); + + do { + if (strcmp(tok, "file_inherit") == 0) + *iflags |= ACE_FILE_INHERIT_ACE; + else if (strcmp(tok, "dir_inherit") == 0) + *iflags |= ACE_DIRECTORY_INHERIT_ACE; + else if (strcmp(tok, "inherit_only") == 0) + *iflags |= ACE_INHERIT_ONLY_ACE; + else if (strcmp(tok, "no_propagate") == 0) + *iflags |= ACE_NO_PROPAGATE_INHERIT_ACE; + else + return (1); + } while (tok = strtok(NULL, "/")); + return (0); +} + +/* + * Convert external acl representation to internal representation. + * The accepted syntax is: <acl_entry>[,<acl_entry>]*[,] + * The comma at the end is not prescribed by the man pages. + * But it is needed not to break the old programs. + */ + +int +ace_aclfromtext(char *aclstr, acl_t **ret_aclp) +{ + char *fieldp; + char *tp; + char *nextp; + char *allocp; + char *aclimport; + char *str; + char *perm_tok; + int entry_type; + int id; + int type; + int iflags; + int len; + int error; + int32_t perm; + ace_t *tmpaclp; + acl_t *aclp; + struct group *groupp; + struct passwd *passwdp; + + if (! aclstr) + return (EACL_INVALID_STR); + + len = strlen(aclstr); + + aclp = acl_alloc(ACE_T); + if (aclp == NULL) { + return (EACL_MEM_ERROR); + } + + *ret_aclp = NULL; + + if ((aclimport = allocp = strdup(aclstr)) == NULL) { + return (EACL_MEM_ERROR); + } + + + if (aclimport[len - 1] == ',') + aclimport[len - 1] = '\0'; + + for (; aclimport; ) { + /* look for an ACL entry */ + tp = strchr(aclimport, ','); + if (tp == NULL) { + nextp = NULL; + } else { + *tp = '\0'; + nextp = tp + 1; + } + + aclp->acl_cnt += 1; + + /* + * get additional memory: + * can be more efficient by allocating a bigger block + * each time. + */ + if (aclp->acl_cnt > 1) + tmpaclp = (ace_t *)realloc(aclp->acl_aclp, + sizeof (ace_t) * (aclp->acl_cnt)); + else + tmpaclp = (ace_t *)malloc(sizeof (ace_t)); + if (tmpaclp == NULL) { + free(allocp); + acl_free(aclp); + return (EACL_MEM_ERROR); + } + aclp->acl_aclp = tmpaclp; + tmpaclp = (ace_t *)aclp->acl_aclp + (aclp->acl_cnt - 1); + + /* look for entry type field */ + tp = strchr(aclimport, ':'); + if (tp == NULL) { + free(allocp); + acl_free(aclp); + return (EACL_ENTRY_ERROR); + } else + *tp = '\0'; + if (strcmp(aclimport, "owner@") == 0) { + entry_type = ACE_OWNER; + } else if (strcmp(aclimport, "group@") == 0) { + entry_type = ACE_GROUP | ACE_IDENTIFIER_GROUP; + } else if (strcmp(aclimport, "everyone@") == 0) { + entry_type = ACE_EVERYONE; + } else if (strcmp(aclimport, "group") == 0) { + entry_type = ACE_IDENTIFIER_GROUP; + } else if (strcmp(aclimport, "user") == 0) { + entry_type = 0; + } else { + free(allocp); + acl_free(aclp); + return (EACL_ENTRY_ERROR); + } + + /* + * If not an abstraction owner@, group@ or everyone@ + * then we must have a user/group name next + */ + + if (entry_type == 0 || entry_type == ACE_IDENTIFIER_GROUP) { + fieldp = tp + 1; + tp = strchr(fieldp, ':'); + if (tp == NULL) { + free(allocp); + acl_free(aclp); + return (EACL_INVALID_USER_GROUP); + } else + *tp = '\0'; + if (fieldp != tp) { + /* + * The second field could be empty. We only care + * when the field has user/group name. + */ + if (entry_type == 0) { + /* + * The reentrant interface getpwnam_r() + * is uncommitted and subject to + * change. Use the friendlier interface + * getpwnam(). + */ + error = 0; + passwdp = getpwnam(fieldp); + if (passwdp == NULL) { + error = acl_str_to_id( + fieldp, &id); + } else { + id = passwdp->pw_uid; + } + + if (error) { + free(allocp); + acl_free(aclp); + return (error); + } + } else { + error = 0; + if (entry_type == + ACE_IDENTIFIER_GROUP) { + groupp = getgrnam(fieldp); + if (groupp == NULL) { + /* no group? */ + error = acl_str_to_id( + fieldp, &id); + } else + id = groupp->gr_gid; + + } else if ((entry_type == ACE_OWNER) || + (entry_type == + (ACE_IDENTIFIER_GROUP|ACE_GROUP)) || + (entry_type != ACE_EVERYONE)) { + error = EACL_FIELD_NOT_BLANK; + } else { + error = EACL_ENTRY_ERROR; + } + + if (error) { + free(allocp); + acl_free(aclp); + return (error); + } + } + } + } else { + id = -1; + } + + /* next field: permission */ + fieldp = tp + 1; + tp = strchr(fieldp, ':'); + if (tp == NULL) { + free(allocp); + acl_free(aclp); + return (EACL_PERM_MASK_ERROR); + } else + *tp = '\0'; + + perm = 0; + + perm_tok = strtok(fieldp, "/"); + if (perm_tok == NULL) { + perm = 0; + } else { + do { + if (ace_permask(perm_tok, &perm) != 0) { + free(allocp); + acl_free(aclp); + return (EACL_PERM_MASK_ERROR); + } + } while (perm_tok = strtok(NULL, "/")); + } + + /* grab allow/deny */ + fieldp = tp + 1; + tp = strchr(fieldp, ':'); + if (tp != NULL) + *tp = '\0'; + + if (strcmp(fieldp, "allow") == 0) + type = ACE_ACCESS_ALLOWED_ACE_TYPE; + else if (strcmp(fieldp, "deny") == 0) + type = ACE_ACCESS_DENIED_ACE_TYPE; + else { + free(allocp); + acl_free(aclp); + return (EACL_INVALID_ACCESS_TYPE); + } + + /* grab option inherit flags */ + + iflags = 0; + if (tp != NULL) { + fieldp = tp + 1; + if (fieldp != NULL) { + *tp = '\0'; + str = fieldp; + if (build_iflags(str, &iflags) != 0) { + free(allocp); + acl_free(aclp); + return (EACL_INHERIT_ERROR); + } + } else { + free(allocp); + acl_free(aclp); + return (EACL_UNKNOWN_DATA); + } + } + /* slap fields into ace_t structure */ + + tmpaclp->a_flags = entry_type; + tmpaclp->a_flags |= iflags; + tmpaclp->a_who = id; + tmpaclp->a_access_mask = perm; + tmpaclp->a_type = type; + aclimport = nextp; + } + free(allocp); + *ret_aclp = aclp; + return (0); +} + +char +*acl_totext(acl_t *aclp) +{ + if (aclp == NULL) + return (NULL); + + switch (aclp->acl_type) { + case ACE_T: + return (ace_acltotext(aclp)); + case ACLENT_T: + return (acltotext(aclp->acl_aclp, aclp->acl_cnt)); + } + return (NULL); +} + +int +acl_fromtext(const char *acltextp, acl_t **ret_aclp) +{ + acl_t *aclp; + char *token; + char *ptr; + char *textp; + enum acl_type flavor; + int colon_cnt = 0; + int error; + + /* + * first try and detect what type of acl entries we have + * + * aclent_t can have 1, 2 or 3 colons + * if 3 then must have word default: + * + * ace_t can have 2, 3 or 4 + * for 2 then must be owner@, group@ or everyone@ + */ + + textp = strdup(acltextp); + if (textp == NULL) + return (-1); + + token = strtok(textp, ","); + if (token == NULL) { + free(textp); + return (-1); + } + + for (ptr = token; *ptr; ptr++) { + if (*ptr == ':') + colon_cnt++; + } + + if (colon_cnt == 1 || colon_cnt == 2) { + if ((strncmp(acltextp, "owner@", 6) == 0) || + (strncmp(acltextp, "group@", 6) == 0) || + (strncmp(acltextp, "everyone@", 9) == 0)) + flavor = ACE_T; + else + flavor = ACLENT_T; + } else if (colon_cnt == 3) { + ptr = strtok(token, ":"); + if (ptr == NULL) { + free(textp); + return (EACL_MISSING_FIELDS); + } else if (strcmp(ptr, "default") == 0) { + flavor = ACLENT_T; + } else { + flavor = ACE_T; + } + } else if (colon_cnt == 4) { + flavor = ACE_T; + } else { + free(textp); + return (EACL_MISSING_FIELDS); + } + + + free(textp); + + if (flavor == ACLENT_T) + error = aclent_aclfromtext((char *)acltextp, &aclp); + else + error = ace_aclfromtext((char *)acltextp, &aclp); + + *ret_aclp = aclp; + return (error); +} |