* setfacl.c (strchrnul): New function.

(getaclentry): Rewrite.
This commit is contained in:
Corinna Vinschen 2010-12-11 20:47:01 +00:00
parent 8acbc359df
commit d7b90bae79
2 changed files with 71 additions and 68 deletions

View File

@ -1,3 +1,8 @@
2010-12-11 Corinna Vinschen <corinna@vinschen.de>
* setfacl.c (strchrnul): New function.
(getaclentry): Rewrite.
2010-12-06 Corinna Vinschen <corinna@vinschen.de> 2010-12-06 Corinna Vinschen <corinna@vinschen.de>
* cygpath.cc (get_device_name): Fix path length test. * cygpath.cc (get_device_name): Fix path length test.

View File

@ -1,6 +1,6 @@
/* setfacl.c /* setfacl.c
Copyright 2000, 2001, 2002, 2003, 2006, 2008, 2009 Red Hat Inc. Copyright 2000, 2001, 2002, 2003, 2006, 2008, 2009, 2010 Red Hat Inc.
Written by Corinna Vinschen <vinschen@redhat.com> Written by Corinna Vinschen <vinschen@redhat.com>
@ -71,72 +71,74 @@ mode_t getperm (char *in)
| (in[2] == 'x' ? S_IXOTH : 0); | (in[2] == 'x' ? S_IXOTH : 0);
} }
/* GNU extension. Like strchr except that if c is not found, return pointer
to the trailing \0, rather than NULL. */
static char *
strchrnul (const char *s, int c)
{
while (*s && *s != c)
++s;
return (char *) s;
}
BOOL BOOL
getaclentry (action_t action, char *c, aclent_t *ace) getaclentry (action_t action, char *c, aclent_t *ace)
{ {
char *c2; char *c2;
ace->a_type = 0; ace->a_type = 0;
ace->a_id = -1; ace->a_id = (uid_t) -1;
ace->a_perm = 0; ace->a_perm = 0;
if (!strncmp (c, "default:", 8) /* First, check if we're handling a default entry. */
|| !strncmp (c, "d:", 2)) if (!strncmp (c, "default:", 8) || !strncmp (c, "d:", 2))
{ {
ace->a_type = ACL_DEFAULT; ace->a_type = ACL_DEFAULT;
c = strchr (c, ':') + 1; c = strchr (c, ':') + 1;
} }
if (!strncmp (c, "user:", 5) /* c now points to the type. Check for next colon. If we find a colon,
|| !strncmp (c, "u:", 2)) NUL it. Otherwise the string is invalid, except when deleting. */
{ c2 = strchrnul (c, ':');
if (*c2 == ':')
*c2++ = '\0';
else if (action != Delete)
return FALSE;
/* Fetch the type. */
if (!strcmp (c, "u") || !strcmp (c, "user"))
ace->a_type |= USER_OBJ; ace->a_type |= USER_OBJ;
c = strchr (c, ':') + 1; else if (!strcmp (c, "g") || !strcmp (c, "group"))
}
else if (!strncmp (c, "group:", 6)
|| !strncmp (c, "g:", 2))
{
ace->a_type |= GROUP_OBJ; ace->a_type |= GROUP_OBJ;
c = strchr (c, ':') + 1; else if (!strcmp (c, "m") || !strcmp (c, "mask"))
}
else if (!strncmp (c, "mask:", 5)
|| !strncmp (c, "m:", 2))
{
ace->a_type |= CLASS_OBJ; ace->a_type |= CLASS_OBJ;
c = strchr (c, ':') + 1; else if (!strcmp (c, "o") || !strcmp (c, "other"))
}
else if (!strncmp (c, "other:", 6)
|| !strncmp (c, "o:", 2))
{
ace->a_type |= OTHER_OBJ; ace->a_type |= OTHER_OBJ;
c = strchr (c, ':') + 1;
}
else else
return FALSE; return FALSE;
if (ace->a_type & (USER_OBJ | GROUP_OBJ)) /* Skip to next field. */
c = c2;
if (!*c && action != Delete)
return FALSE;
/* If this is a user or group entry, check if next char is a colon char.
If so, skip it, otherwise it's the name of a user or group. */
if (!(ace->a_type & (USER_OBJ | GROUP_OBJ)))
;
else if (*c == ':')
++c;
else if (*c)
{ {
if ((c2 = strchr (c, ':'))) /* c now points to the id. Check for next colon. If we find a colon,
{ NUL it. Otherwise the string is invalid, except when deleting.
if (action == Delete) If we delete, it must be a default entry since standard ugo entries
return FALSE; can't be deleted. */
*c2 = '\0'; c2 = strchrnul (c + 1, ':');
} if (*c2 == ':')
else if (action == Delete) *c2++ = '\0';
{ else if (action != Delete)
/* Only default ugo entries are allowed to be removed, not the return FALSE;
standard ugo entries. */ else if (!(ace->a_type & ACL_DEFAULT))
if (!(ace->a_type & ACL_DEFAULT)) return FALSE;
return FALSE; /* Fetch user/group id. */
} if (isdigit ((unsigned char) *c))
else
return FALSE;
if (!c2 && !*c) /* Deleting a default ug entry is allowed. */
;
else if (c2 == c)
{
if (action == Delete)
return FALSE;
}
else if (isdigit ((unsigned char) *c))
{ {
char *c3; char *c3;
@ -158,33 +160,29 @@ getaclentry (action_t action, char *c, aclent_t *ace)
return FALSE; return FALSE;
ace->a_id = gr->gr_gid; ace->a_id = gr->gr_gid;
} }
if (c2 && c2 != c) if (ace->a_type & USER_OBJ)
{ {
if (ace->a_type & USER_OBJ) ace->a_type &= ~USER_OBJ;
{ ace->a_type |= USER;
ace->a_type &= ~USER_OBJ;
ace->a_type |= USER;
}
else
{
ace->a_type &= ~GROUP_OBJ;
ace->a_type |= GROUP;
}
} }
if (c2) else
c = c2 + 1; {
ace->a_type &= ~GROUP_OBJ;
ace->a_type |= GROUP;
}
/* Skip to next field. */
c = c2;
} }
/* FIXME: currently allow both :: and : */
else if (*c == ':')
c++;
if (action == Delete) if (action == Delete)
{ {
if ((ace->a_type & (CLASS_OBJ | OTHER_OBJ)) /* Trailing garbage? */
&& *c) if (*c)
return FALSE; return FALSE;
/* No, we're good. */
ace->a_perm = ILLEGAL_MODE; ace->a_perm = ILLEGAL_MODE;
return TRUE; return TRUE;
} }
/* Check perms. */
if ((ace->a_perm = getperm (c)) == ILLEGAL_MODE) if ((ace->a_perm = getperm (c)) == ILLEGAL_MODE)
return FALSE; return FALSE;
return TRUE; return TRUE;