=item *
One or more ACL permissions, indicated either by combining the individual
-letters or by one of the four acceptable shorthand words.
+letters or by one of the four acceptable shorthand words, optionally
+followed by a single plus (+) or minus (-) chracter to request a relative
+ACL change
=back
pat rlidwka
pat:friends rli
+The following example demonstrates the use of the + and - options to
+modfiy ACLs relative to the existing set
+
+ % fs setacl dir . -acl pat:friends r-
+ % fs listacl -path .
+ Access list for . is
+ Normal rights:
+ pat rlidwka
+ pat:friends li
+ % fs setacl dir . acl pat:friends w+
+ % fs listacl -path .
+ Access list for . is
+ Normal rights:
+ pat rlidwka
+ pat:friends wli
+
=head1 PRIVILEGE REQUIRED
The issuer must have the C<a> (administer) permission on the directory's
return tspace;
}
-enum rtype {add, destroy, deny};
+ /* added relative add resp. delete */
+ /* (so old add really means to set) */
+enum rtype { add, destroy, deny, reladd, reldel };
static afs_int32
Convert(char *arights, int dfs, enum rtype *rtypep)
{
afs_int32 mode;
char tc;
+ char *tcp;
*rtypep = add; /* add rights, by default */
+ /* analyze last character of string */
+ tcp = arights + strlen(arights);
+ if ( tcp-- > arights ) { /* assure non-empty string */
+ if ( *tcp == '+' )
+ *rtypep = reladd; /* '+' indicates more rights */
+ else if ( *tcp == '-' )
+ *rtypep = reldel; /* '-' indicates less rights */
+ else if ( *tcp == '=' )
+ *rtypep = add; /* '=' also allows old behaviour */
+ else
+ tcp++; /* back to original null byte */
+ *tcp = '\0'; /* do not disturb old strcmp-s */
+ }
+
if (dfs) {
if (!strcmp(arights, "null")) {
*rtypep = deny;
return 0;
}
mode = 0;
- for(; (tc = *arights) != '\0'; arights++) {
+ tcp = arights;
+ while ((tc = *tcp++)) {
if (dfs) {
if (tc == '-')
continue;
}
static void
-ChangeList (struct Acl *al, afs_int32 plus, char *aname, afs_int32 arights)
+ChangeList (struct Acl *al, afs_int32 plus, char *aname, afs_int32 arights,
+ enum rtpe *artypep)
{
struct AclEntry *tlist;
tlist = (plus ? al->pluslist : al->minuslist);
tlist = FindList (tlist, aname);
if (tlist) {
/* Found the item already in the list. */
- tlist->rights = arights;
+ /* modify rights in case of reladd */
+ /* and reladd only, use standard - */
+ /* add, ie. set - otherwise */
+ if ( artypep == NULL )
+ tlist->rights = arights;
+ else if ( *artypep == reladd )
+ tlist->rights |= arights;
+ else if ( *artypep == reldel )
+ tlist->rights &= ~arights;
+ else
+ tlist->rights = arights;
+
if (plus)
al->nplus -= PruneList(&al->pluslist, al->dfs);
else
al->nminus -= PruneList(&al->minuslist, al->dfs);
return;
}
+ if ( artypep != NULL && *artypep == reldel )
+ /* can't reduce non-existing rights */
+ return;
+
/* Otherwise we make a new item and plug in the new data. */
tlist = (struct AclEntry *) malloc(sizeof (struct AclEntry));
assert(tlist);
plusp = 0;
if (rtype == destroy && ta->dfs)
rights = -1;
- ChangeList(ta, plusp, ui->data, rights);
+ ChangeList(ta, plusp, ui->data, rights, &rtype);
}
blob.in = AclToString(ta);
blob.out_size=0;
}
}
for (tp = fa->pluslist;tp;tp=tp->next)
- ChangeList(ta, 1, tp->name, tp->rights);
+ ChangeList(ta, 1, tp->name, tp->rights, NULL);
for (tp = fa->minuslist;tp;tp=tp->next)
- ChangeList(ta, 0, tp->name, tp->rights);
+ ChangeList(ta, 0, tp->name, tp->rights, NULL);
blob.in = AclToString(ta);
blob.out_size=0;
if( FAILED(StringCbLength(blob.in, sizeof(space), &len))) {
return tspace;
}
-enum rtype { add, destroy, deny };
+ /* added relative add resp. delete */
+ /* (so old add really means to set) */
+enum rtype { add, destroy, deny, reladd, reldel };
static afs_int32
Convert(char *arights, int dfs, enum rtype *rtypep)
{
- int i, len;
afs_int32 mode;
char tc;
+ char *tcp; /* to walk through the rights string */
*rtypep = add; /* add rights, by default */
+ /* analyze last character of string */
+ tcp = arights + strlen(arights);
+ if ( tcp-- > arights ) { /* assure non-empty string */
+ if ( *tcp == '+' )
+ *rtypep = reladd; /* '+' indicates more rights */
+ else if ( *tcp == '-' )
+ *rtypep = reldel; /* '-' indicates less rights */
+ else if ( *tcp == '=' )
+ *rtypep = add; /* '=' also allows old behaviour */
+ else
+ tcp++; /* back to original null byte */
+ *tcp = '\0'; /* do not disturb old strcmp-s */
+ }
+
if (dfs) {
if (!strcmp(arights, "null")) {
*rtypep = deny;
*rtypep = destroy; /* Remove entire entry */
return 0;
}
- len = strlen(arights);
mode = 0;
- for (i = 0; i < len; i++) {
- tc = *arights++;
+ tcp = arights;
+ while ((tc = *tcp++ )) {
if (dfs) {
if (tc == '-')
continue;
}
static void
-ChangeList(struct Acl *al, afs_int32 plus, char *aname, afs_int32 arights)
+ChangeList(struct Acl *al, afs_int32 plus, char *aname, afs_int32 arights,
+ enum rtype *artypep)
{
struct AclEntry *tlist;
tlist = (plus ? al->pluslist : al->minuslist);
tlist = FindList(tlist, aname);
if (tlist) {
- /* Found the item already in the list. */
- tlist->rights = arights;
+ /* Found the item already in the list.
+ * modify rights in case of reladd and reladd only,
+ * use standard - add, ie. set - otherwise
+ */
+ if ( artypep == NULL )
+ tlist->rights = arights;
+ else if ( *artypep == reladd )
+ tlist->rights |= arights;
+ else if ( *artypep == reldel )
+ tlist->rights &= ~arights;
+ else
+ tlist->rights = arights;
+
if (plus)
al->nplus -= PruneList(&al->pluslist, al->dfs);
else
al->nminus -= PruneList(&al->minuslist, al->dfs);
return;
}
+ if ( artypep != NULL && *artypep == reldel )
+ return; /* can't reduce non-existing rights */
+
/* Otherwise we make a new item and plug in the new data. */
tlist = (struct AclEntry *)malloc(sizeof(struct AclEntry));
assert(tlist);
plusp = 0;
if (rtype == destroy && ta->dfs)
rights = -1;
- ChangeList(ta, plusp, ui->data, rights);
+ ChangeList(ta, plusp, ui->data, rights, &rtype);
}
blob.in = AclToString(ta);
blob.out_size = 0;
}
strcpy(ta->cell, fa->cell);
}
+ /* NULL rtype for standard handling */
for (tp = fa->pluslist; tp; tp = tp->next)
- ChangeList(ta, 1, tp->name, tp->rights);
+ ChangeList(ta, 1, tp->name, tp->rights, NULL);
for (tp = fa->minuslist; tp; tp = tp->next)
- ChangeList(ta, 0, tp->name, tp->rights);
+ ChangeList(ta, 0, tp->name, tp->rights, NULL);
blob.in = AclToString(ta);
blob.out_size = 0;
blob.in_size = 1 + strlen(blob.in);