]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
mkfs: substitute slashes with spaces in protofiles
authorDarrick J. Wong <djwong@kernel.org>
Wed, 1 Mar 2023 16:05:45 +0000 (08:05 -0800)
committerCarlos Maiolino <cem@kernel.org>
Fri, 3 Mar 2023 11:35:57 +0000 (12:35 +0100)
A user requested the ability to specify directory entry names in a
protofile that have spaces in them.  The protofile format itself does
not allow spaces (yay 1973-era protofiles!) but it does allow slashes.
Slashes aren't allowed in directory entry names, so we'll permit this
one gross hack.  After this, the protofile:

/
0 0
d--775 1000 1000
: Descending path /code/t/fstests
 get/isk.sh   ---775 1000 1000 /code/t/fstests/getdisk.sh
$

Will produce "get isk.h" in the root directory when used thusly:

# mkfs.xfs -p slashes_are_spaces=1,/tmp/protofile -f /dev/sda

Requested-by: Daan De Meyer <daan.j.demeyer@gmail.com>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
man/man8/mkfs.xfs.8.in
mkfs/proto.c
mkfs/proto.h
mkfs/xfs_mkfs.c

index e1ca40e5da64304c44153304db1613b2d267f26c..49e64d47ae43cd0be8f905cd22d86f4d5da31fba 100644 (file)
@@ -996,6 +996,12 @@ in the directory. A scan of the protofile is
 always terminated with the dollar (
 .B $
 ) token.
+.TP
+.BI slashes_are_spaces= value
+If set to 1, slashes ("/") in the first token of each line of the protofile
+are converted to spaces.
+This enables the creation of a filesystem containing filenames with spaces.
+By default, this is set to 0.
 .RE
 .TP
 .B \-q
index 7e3fc1b813492eb7f6f02f39fd49ad23b2aa8bd3..ea31cfe5cfc0f6feac373dbf3af6cdaedebd6b06 100644 (file)
@@ -21,6 +21,7 @@ static int newfile(xfs_trans_t *tp, xfs_inode_t *ip, int symlink, int logit,
 static char *newregfile(char **pp, int *len);
 static void rtinit(xfs_mount_t *mp);
 static long filesize(int fd);
+static int slashes_are_spaces;
 
 /*
  * Use this for block reservations needed for mkfs's conditions
@@ -171,6 +172,30 @@ getstr(
        return NULL;
 }
 
+/* Extract directory entry name from a protofile. */
+static char *
+getdirentname(
+       char    **pp)
+{
+       char    *p = getstr(pp);
+       char    *c = p;
+
+       if (!p)
+               return NULL;
+
+       if (!slashes_are_spaces)
+               return p;
+
+       /* Replace slash with space because slashes aren't allowed. */
+       while (*c) {
+               if (*c == '/')
+                       *c = ' ';
+               c++;
+       }
+
+       return p;
+}
+
 static void
 rsvfile(
        xfs_mount_t     *mp,
@@ -586,7 +611,7 @@ parseproto(
                        rtinit(mp);
                tp = NULL;
                for (;;) {
-                       name = getstr(pp);
+                       name = getdirentname(pp);
                        if (!name)
                                break;
                        if (strcmp(name, "$") == 0)
@@ -612,8 +637,10 @@ void
 parse_proto(
        xfs_mount_t     *mp,
        struct fsxattr  *fsx,
-       char            **pp)
+       char            **pp,
+       int             proto_slashes_are_spaces)
 {
+       slashes_are_spaces = proto_slashes_are_spaces;
        parseproto(mp, NULL, fsx, pp, NULL);
 }
 
index 3c4010afd19750725622a5448fea482be79dac25..be1ceb45421bfac52bd0648acce3626f5453e17f 100644 (file)
@@ -7,7 +7,8 @@
 #define MKFS_PROTO_H_
 
 char *setup_proto(char *fname);
-void parse_proto(struct xfs_mount *mp, struct fsxattr *fsx, char **pp);
+void parse_proto(struct xfs_mount *mp, struct fsxattr *fsx, char **pp,
+               int proto_slashes_are_spaces);
 void res_failed(int err);
 
 #endif /* MKFS_PROTO_H_ */
index 4248e6ec344846c980fa84ddc2ba35059daf056f..4399bf3792f9da0efaba82884fb5b7d13565f82d 100644 (file)
@@ -115,6 +115,7 @@ enum {
 
 enum {
        P_FILE = 0,
+       P_SLASHES,
        P_MAX_OPTS,
 };
 
@@ -651,6 +652,7 @@ static struct opt_params popts = {
        .ini_section = "proto",
        .subopts = {
                [P_FILE] = "file",
+               [P_SLASHES] = "slashes_are_spaces",
                [P_MAX_OPTS] = NULL,
        },
        .subopt_params = {
@@ -658,6 +660,12 @@ static struct opt_params popts = {
                  .conflicts = { { NULL, LAST_CONFLICT } },
                  .defaultval = SUBOPT_NEEDS_VAL,
                },
+               { .index = P_SLASHES,
+                 .conflicts = { { NULL, LAST_CONFLICT } },
+                 .minval = 0,
+                 .maxval = 1,
+                 .defaultval = 1,
+               },
        },
 };
 
@@ -881,6 +889,7 @@ struct cli_params {
        int     loginternal;
        int     lsunit;
        int     is_supported;
+       int     proto_slashes_are_spaces;
 
        /* parameters where 0 is not a valid value */
        int64_t agcount;
@@ -1779,6 +1788,9 @@ proto_opts_parser(
        struct cli_params       *cli)
 {
        switch (subopt) {
+       case P_SLASHES:
+               cli->proto_slashes_are_spaces = getnum(value, opts, subopt);
+               break;
        case P_FILE:
                fallthrough;
        default:
@@ -4368,7 +4380,7 @@ main(
        /*
         * Allocate the root inode and anything else in the proto file.
         */
-       parse_proto(mp, &cli.fsx, &protostring);
+       parse_proto(mp, &cli.fsx, &protostring, cli.proto_slashes_are_spaces);
 
        /*
         * Protect ourselves against possible stupidity