From 1f980897f6947dd17eaa0190b2c1a23fb700636b Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Wed, 17 Jul 2019 10:53:22 +0200 Subject: fstree: add support for spaces in filenames This commit adds a mechanism to fstree_from_file to support filenames with spaces in them by quoting the entire string. Quote marks can still be used inside file names by escaping them with a backslash. Back slashes (if that is your thing) can also be escaped. Signed-off-by: David Oberhollenzer --- doc/gensquashfs.1 | 8 +++++++- lib/fstree/fstree_from_file.c | 36 +++++++++++++++++++++++++++--------- mkfs/options.c | 8 ++++++-- tests/fstree_from_file.c | 16 ++++++++++++++++ 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/doc/gensquashfs.1 b/doc/gensquashfs.1 index 8050dc6..c52ce70 100644 --- a/doc/gensquashfs.1 +++ b/doc/gensquashfs.1 @@ -100,7 +100,10 @@ l l l l l l rd. -;Absolute path of the entry in the image. +;T{ +Absolute path of the entry in the image. Can be put in quotes +if some components contain spaces. +T} ;T{ Optional location of the input file. Can be specified relative to either the description file or the pack directory. If omitted, the image path is used @@ -132,6 +135,9 @@ file /sbin/init 0755 0 0 ../init/sbin/init # Read from ./bin/bash relative to pack dir or listing path # /bin is created implicitly with default attributes. file /bin/bash 0755 0 0 + +# file name with a space in it and a "special" name +file "/opt/my app/\\"special\\"/data" 0600 0 0 .fi .in .SH AUTHOR diff --git a/lib/fstree/fstree_from_file.c b/lib/fstree/fstree_from_file.c index 13328d5..901e431 100644 --- a/lib/fstree/fstree_from_file.c +++ b/lib/fstree/fstree_from_file.c @@ -113,7 +113,7 @@ static int handle_line(fstree_t *fs, const char *filename, size_t line_num, char *line) { const char *extra = NULL, *msg = NULL; - char keyword[16], *path; + char keyword[16], *path, *ptr; unsigned int x; struct stat sb; size_t i; @@ -136,17 +136,35 @@ static int handle_line(fstree_t *fs, const char *filename, /* isolate path */ path = line + i; - for (; line[i] != '\0'; ++i) { - /* TODO: escape sequences to support spaces in path */ + if (*path == '"') { + ptr = path; + ++i; - if (isspace(line[i])) - break; - } + while (line[i] != '\0' && line[i] != '"') { + if (line[i] == '\\' && + (line[i + 1] == '"' || line[i + 1] == '\\')) { + *(ptr++) = line[i + 1]; + i += 2; + } else { + *(ptr++) = line[i++]; + } + } - if (!isspace(line[i])) - goto fail_ent; + if (line[i] != '"' || !isspace(line[i + 1])) + goto fail_ent; + + *ptr = '\0'; + ++i; + } else { + while (line[i] != '\0' && !isspace(line[i])) + ++i; + + if (!isspace(line[i])) + goto fail_ent; + + line[i++] = '\0'; + } - line[i++] = '\0'; while (isspace(line[i])) ++i; diff --git a/mkfs/options.c b/mkfs/options.c index 25f7453..2dab6b8 100644 --- a/mkfs/options.c +++ b/mkfs/options.c @@ -83,7 +83,8 @@ static const char *help_string = "pipe \n" "sock \n" "\n" -" Absolute path of the entry in the image.\n" +" Absolute path of the entry in the image. Can be put in quotes\n" +" if some components contain spaces.\n" " If given, location of the input file. Either absolute or relative\n" " to the description file. If omitted, the image path is used,\n" " relative to the description file.\n" @@ -107,7 +108,10 @@ static const char *help_string = " \n" " # Read bin/bash, relative to listing or pack dir.\n" " # Implicitly create /bin.\n" -" file /bin/bash 0755 0 0" +" file /bin/bash 0755 0 0\n" +" \n" +" # file name with a space in it.\n" +" file \"/opt/my app/\\\"special\\\"/data\" 0600 0 0\n" "\n\n"; void process_command_line(options_t *opt, int argc, char **argv) diff --git a/tests/fstree_from_file.c b/tests/fstree_from_file.c index c5b9b5b..f4fc345 100644 --- a/tests/fstree_from_file.c +++ b/tests/fstree_from_file.c @@ -14,6 +14,8 @@ static const char *testdesc = "nod /chardev 0600 6 7 c 13 37\n" "nod /blkdev 0600 8 9 b 42 21\n" "pipe /pipe 0644 10 11\n" +"dir \"/foo bar\" 0755 0 0\n" +"dir \"/foo bar/ test \\\"/\" 0755 0 0\n" " sock /sock 0555 12 13 "; int main(void) @@ -55,6 +57,20 @@ int main(void) assert(strcmp(n->name, "dir") == 0); assert(n->data.dir->children == NULL); + n = n->next; + assert(n->mode == (S_IFDIR | 0755)); + assert(n->uid == 0); + assert(n->gid == 0); + assert(strcmp(n->name, "foo bar") == 0); + assert(n->data.dir->children != NULL); + + assert(n->data.dir->children->next == NULL); + assert(n->data.dir->children->mode == (S_IFDIR | 0755)); + assert(n->data.dir->children->uid == 0); + assert(n->data.dir->children->gid == 0); + assert(strcmp(n->data.dir->children->name, " test \"") == 0); + assert(n->data.dir->children->data.dir->children == NULL); + n = n->next; assert(n->mode == (S_IFIFO | 0644)); assert(n->uid == 10); -- cgit v1.2.3