summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2010-12-11 20:47:01 +0000
committerCorinna Vinschen <corinna@vinschen.de>2010-12-11 20:47:01 +0000
commitd7b90bae797bd70222b29ee644d7145f7ebb8631 (patch)
treed7e3a07a4150986075740133d430cfa517f4401c
parent8acbc359df87c926df32d56ce799131cbaeadfba (diff)
downloadcygnal-d7b90bae797bd70222b29ee644d7145f7ebb8631.tar.gz
cygnal-d7b90bae797bd70222b29ee644d7145f7ebb8631.tar.bz2
cygnal-d7b90bae797bd70222b29ee644d7145f7ebb8631.zip
* setfacl.c (strchrnul): New function.
(getaclentry): Rewrite.
-rw-r--r--winsup/utils/ChangeLog5
-rw-r--r--winsup/utils/setfacl.c134
2 files changed, 71 insertions, 68 deletions
diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog
index 98c9983c9..659280961 100644
--- a/winsup/utils/ChangeLog
+++ b/winsup/utils/ChangeLog
@@ -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>
* cygpath.cc (get_device_name): Fix path length test.
diff --git a/winsup/utils/setfacl.c b/winsup/utils/setfacl.c
index 0dcf95cf9..f04cf2510 100644
--- a/winsup/utils/setfacl.c
+++ b/winsup/utils/setfacl.c
@@ -1,6 +1,6 @@
/* 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>
@@ -71,72 +71,74 @@ mode_t getperm (char *in)
| (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
getaclentry (action_t action, char *c, aclent_t *ace)
{
char *c2;
ace->a_type = 0;
- ace->a_id = -1;
+ ace->a_id = (uid_t) -1;
ace->a_perm = 0;
- if (!strncmp (c, "default:", 8)
- || !strncmp (c, "d:", 2))
+ /* First, check if we're handling a default entry. */
+ if (!strncmp (c, "default:", 8) || !strncmp (c, "d:", 2))
{
ace->a_type = ACL_DEFAULT;
c = strchr (c, ':') + 1;
}
- if (!strncmp (c, "user:", 5)
- || !strncmp (c, "u:", 2))
- {
+ /* c now points to the type. Check for next colon. If we find a colon,
+ 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;
- c = strchr (c, ':') + 1;
- }
- else if (!strncmp (c, "group:", 6)
- || !strncmp (c, "g:", 2))
- {
+ else if (!strcmp (c, "g") || !strcmp (c, "group"))
ace->a_type |= GROUP_OBJ;
- c = strchr (c, ':') + 1;
- }
- else if (!strncmp (c, "mask:", 5)
- || !strncmp (c, "m:", 2))
- {
+ else if (!strcmp (c, "m") || !strcmp (c, "mask"))
ace->a_type |= CLASS_OBJ;
- c = strchr (c, ':') + 1;
- }
- else if (!strncmp (c, "other:", 6)
- || !strncmp (c, "o:", 2))
- {
+ else if (!strcmp (c, "o") || !strcmp (c, "other"))
ace->a_type |= OTHER_OBJ;
- c = strchr (c, ':') + 1;
- }
else
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, ':')))
- {
- if (action == Delete)
- return FALSE;
- *c2 = '\0';
- }
- else if (action == Delete)
- {
- /* Only default ugo entries are allowed to be removed, not the
- standard ugo entries. */
- if (!(ace->a_type & ACL_DEFAULT))
- return FALSE;
- }
- 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))
+ /* 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 we delete, it must be a default entry since standard ugo entries
+ can't be deleted. */
+ c2 = strchrnul (c + 1, ':');
+ if (*c2 == ':')
+ *c2++ = '\0';
+ else if (action != Delete)
+ return FALSE;
+ else if (!(ace->a_type & ACL_DEFAULT))
+ return FALSE;
+ /* Fetch user/group id. */
+ if (isdigit ((unsigned char) *c))
{
char *c3;
@@ -158,33 +160,29 @@ getaclentry (action_t action, char *c, aclent_t *ace)
return FALSE;
ace->a_id = gr->gr_gid;
}
- if (c2 && c2 != c)
- {
- if (ace->a_type & USER_OBJ)
- {
- ace->a_type &= ~USER_OBJ;
- ace->a_type |= USER;
- }
- else
- {
- ace->a_type &= ~GROUP_OBJ;
- ace->a_type |= GROUP;
- }
+ if (ace->a_type & USER_OBJ)
+ {
+ ace->a_type &= ~USER_OBJ;
+ ace->a_type |= USER;
+ }
+ else
+ {
+ ace->a_type &= ~GROUP_OBJ;
+ ace->a_type |= GROUP;
}
- if (c2)
- c = c2 + 1;
+ /* Skip to next field. */
+ c = c2;
}
- /* FIXME: currently allow both :: and : */
- else if (*c == ':')
- c++;
if (action == Delete)
{
- if ((ace->a_type & (CLASS_OBJ | OTHER_OBJ))
- && *c)
- return FALSE;
+ /* Trailing garbage? */
+ if (*c)
+ return FALSE;
+ /* No, we're good. */
ace->a_perm = ILLEGAL_MODE;
return TRUE;
}
+ /* Check perms. */
if ((ace->a_perm = getperm (c)) == ILLEGAL_MODE)
return FALSE;
return TRUE;