diff options
author | Phillip Lougher <phillip@squashfs.org.uk> | 2014-08-31 02:22:08 +0100 |
---|---|---|
committer | Phillip Lougher <phillip@squashfs.org.uk> | 2014-08-31 02:22:08 +0100 |
commit | 051eafc838200122d9fc7217aafd8bead8b2307d (patch) | |
tree | afe23b798c3acd99c55d66ad1091c0eb59ba84de | |
parent | 84d9f63f4480009ff235c945df105160e1104dd1 (diff) | |
download | squashfs-tools-051eafc838200122d9fc7217aafd8bead8b2307d.tar.gz |
actions: fix symbolic mode parsing in the mode() action
When I implemented symbolic modes in the mode() action (i.e.
u+r-w) I made an oversight. I didn't realise the specification
allowed multiple =-+ sequences after the ownership specification.
In otherwords if you wanted to add r (+r) and remove w (-w)
from user, I assumed you would do u+r,u-w. After revisiting
the symbolic mode specification it turns out you should be able
to do u+r-w as a short cut to the previous specification. It
also should be obvious I don't tend to use the symbolic mode but
directly use the octal specification!
So fix the parser to allow multiple =-+ sequences.
So the syntax of the symbolic mode support goes from
[ugoa]+[+-=]PERMS
PERMS = [rwxXst]+ or [ugo]
to
[ugoa]*[[+-=]PERMS]+
PERMS = [rwxXst]+ or [ugo]
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
-rw-r--r-- | squashfs-tools/action.c | 172 | ||||
-rw-r--r-- | squashfs-tools/mksquashfs.c | 2 |
2 files changed, 93 insertions, 81 deletions
diff --git a/squashfs-tools/action.c b/squashfs-tools/action.c index 5275466..0808cde 100644 --- a/squashfs-tools/action.c +++ b/squashfs-tools/action.c @@ -1219,19 +1219,17 @@ static int parse_octal_mode_args(unsigned int mode, int bytes, int args, /* - * Parse symbolic mode of format [ugoa]+[+-=]PERMS + * Parse symbolic mode of format [ugoa]*[[+-=]PERMS]+ * PERMS = [rwxXst]+ or [ugo] */ -static struct mode_data *parse_sym_mode_arg(char *arg) +static int parse_sym_mode_arg(char *arg, struct mode_data **head, + struct mode_data **cur) { - struct mode_data *mode_data = malloc(sizeof(*mode_data)); - int mode = 0; + struct mode_data *mode_data; + int mode; int mask = 0; int op; - char X = 0; - - if (mode_data == NULL) - MEM_ERROR(); + char X; if (arg[0] != 'u' && arg[0] != 'g' && arg[0] != 'o' && arg[0] != 'a') { /* no ownership specifiers, default to a */ @@ -1261,102 +1259,116 @@ static struct mode_data *parse_sym_mode_arg(char *arg) } parse_operation: - switch(*arg) { - case '+': - op = ACTION_MODE_ADD; - break; - case '-': - op = ACTION_MODE_REM; - break; - case '=': - op = ACTION_MODE_SET; - break; - default: + /* trap a symbolic mode with just an ownership specification */ + if(*arg == '\0') { SYNTAX_ERROR("Action mode: Expected one of '+', '-' or '=', " - "got '%c'\n", *arg); + "got EOF\n"); goto failed; } - arg ++; + while(*arg != '\0') { + mode = 0; + X = 0; - /* Parse PERMS */ - if (*arg == 'u' || *arg == 'g' || *arg == 'o') { - /* PERMS = [ugo] */ - mode = - *arg; - if (*++arg != '\0') { - SYNTAX_ERROR("Action mode: permission 'u', 'g' or 'o' " - "has trailing characters\n"); + switch(*arg) { + case '+': + op = ACTION_MODE_ADD; + break; + case '-': + op = ACTION_MODE_REM; + break; + case '=': + op = ACTION_MODE_SET; + break; + default: + SYNTAX_ERROR("Action mode: Expected one of '+', '-' or " + "'=', got '%c'\n", *arg); goto failed; } - } else { - /* PERMS = [rwxXst]+ */ - while(*arg != '\0') { - switch(*arg) { - case 'r': - mode |= 0444; - break; - case 'w': - mode |= 0222; - break; - case 'x': - mode |= 0111; - break; - case 's': - mode |= 06000; - break; - case 't': - mode |= 01000; - break; - case 'X': - X = 1; - break; - default: - SYNTAX_ERROR("Action mode: unrecognised " - "permission '%c'\n", *arg); - goto failed; - } - + + arg ++; + + /* Parse PERMS */ + if (*arg == 'u' || *arg == 'g' || *arg == 'o') { + /* PERMS = [ugo] */ + mode = - *arg; arg ++; + } else { + /* PERMS = [rwxXst]* */ + while(1) { + switch(*arg) { + case 'r': + mode |= 0444; + break; + case 'w': + mode |= 0222; + break; + case 'x': + mode |= 0111; + break; + case 's': + mode |= 06000; + break; + case 't': + mode |= 01000; + break; + case 'X': + X = 1; + break; + case '+': + case '-': + case '=': + case '\0': + mode &= mask; + goto perms_parsed; + default: + SYNTAX_ERROR("Action mode: " + "unrecognised permission " + "'%c'\n", *arg); + goto failed; + } + + arg ++; + } } - mode &= mask; - } + +perms_parsed: + mode_data = malloc(sizeof(*mode_data)); + if (mode_data == NULL) + MEM_ERROR(); - mode_data->operation = op; - mode_data->mode = mode; - mode_data->mask = mask; - mode_data->X = X; - mode_data->next = NULL; + mode_data->operation = op; + mode_data->mode = mode; + mode_data->mask = mask; + mode_data->X = X; + mode_data->next = NULL; - return mode_data; + if (*cur) { + (*cur)->next = mode_data; + *cur = mode_data; + } else + *head = *cur = mode_data; + } + + return 1; failed: - free(mode_data); - return NULL; + return 0; } static int parse_sym_mode_args(struct action_entry *action, int args, char **argv, void **data) { - int i; + int i, res = 1; struct mode_data *head = NULL, *cur = NULL; - for (i = 0; i < args; i++) { - struct mode_data *entry = parse_sym_mode_arg(argv[i]); - - if (entry == NULL) - return 0; - - if (cur) { - cur->next = entry; - cur = entry; - } else - head = cur = entry; - } + for (i = 0; i < args && res; i++) + res = parse_sym_mode_arg(argv[i], &head, &cur); *data = head; - return 1; + return res; } diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c index 84fa545..e81e0b4 100644 --- a/squashfs-tools/mksquashfs.c +++ b/squashfs-tools/mksquashfs.c @@ -5089,7 +5089,7 @@ void calculate_queue_sizes(int mem, int *readq, int *fragq, int *bwriteq, #define VERSION() \ - printf("mksquashfs version 4.3-git (2014/08/23)\n");\ + printf("mksquashfs version 4.3-git (2014/08/30)\n");\ printf("copyright (C) 2014 Phillip Lougher "\ "<phillip@squashfs.org.uk>\n\n"); \ printf("This program is free software; you can redistribute it and/or"\ |