Mercurial > hg > toybox
comparison toys/pending/mount.c @ 1334:9fd2bcedbeb5 draft
mount: start on option parsing, implement loopback and bind mount autodetection.
author | Rob Landley <rob@landley.net> |
---|---|
date | Tue, 03 Jun 2014 06:27:24 -0500 |
parents | c3061b237c4c |
children | ffc015bddb26 |
comparison
equal
deleted
inserted
replaced
1333:fc1bb49e58a9 | 1334:9fd2bcedbeb5 |
---|---|
4 * | 4 * |
5 * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/mount.html | 5 * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/mount.html |
6 * Note: -hV is bad spec, haven't implemented -FsLU yet | 6 * Note: -hV is bad spec, haven't implemented -FsLU yet |
7 * no mtab (/proc/mounts does it) so -n is NOP. | 7 * no mtab (/proc/mounts does it) so -n is NOP. |
8 | 8 |
9 USE_MOUNT(NEWTOY(mount, ">2afnrvwt:o*[-rw]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT)) | 9 USE_MOUNT(NEWTOY(mount, "?>2afnrvwt:o*[-rw]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT)) |
10 | 10 |
11 config MOUNT | 11 config MOUNT |
12 bool "mount" | 12 bool "mount" |
13 default n | 13 default n |
14 help | 14 help |
25 -v verbose | 25 -v verbose |
26 | 26 |
27 OPTIONS is a comma separated list of options, which can also be supplied | 27 OPTIONS is a comma separated list of options, which can also be supplied |
28 as --longopts. | 28 as --longopts. |
29 | 29 |
30 | |
31 | |
32 config MOUNT_AUTODETECT | |
33 help | |
34 usage: mount | |
35 | |
36 This mount autodetects loopback mounts (a file on a directory) and | 30 This mount autodetects loopback mounts (a file on a directory) and |
37 bind mounts (file on file, directory on directory), so you don't need | 31 bind mounts (file on file, directory on directory), so you don't need |
38 to say --bind or --loop. | 32 to say --bind or --loop. |
39 */ | 33 */ |
40 | 34 |
47 | 41 |
48 unsigned long flags; | 42 unsigned long flags; |
49 char *opts; | 43 char *opts; |
50 ) | 44 ) |
51 | 45 |
52 static void do_mount(char *dev, char *dir, char *type, unsigned long flags, char *opts) | 46 // Strip flags out of comma separated list of options. |
47 // Return flags, | |
48 static long parse_opts(char *new, long flags, char **more) | |
49 { | |
50 struct { | |
51 char *name; | |
52 long flags; | |
53 } opts[] = { | |
54 // NOPs (we autodetect --loop and --bind) | |
55 {"loop", 0}, {"bind", 0}, {"defaults", 0}, {"quiet", 0}, | |
56 // {"noauto", 0}, {"swap", 0}, | |
57 {"ro", MS_RDONLY}, {"rw", ~MS_RDONLY}, | |
58 {"nosuid", MS_NOSUID}, {"suid", ~MS_NOSUID}, | |
59 {"nodev", MS_NODEV}, {"dev", ~MS_NODEV}, | |
60 {"noexec", MS_NOEXEC}, {"exec", ~MS_NOEXEC}, | |
61 {"sync", MS_SYNCHRONOUS}, {"async", ~MS_SYNCHRONOUS}, | |
62 {"noatime", MS_NOATIME}, {"atime", ~MS_NOATIME}, | |
63 {"nodiratime", MS_NODIRATIME}, {"diratime", ~MS_NODIRATIME}, | |
64 {"loud", ~MS_SILENT}, | |
65 {"shared", MS_SHARED}, {"rshared", MS_SHARED|MS_REC}, | |
66 {"slave", MS_SLAVE}, {"rslave", MS_SLAVE|MS_REC}, | |
67 {"private", MS_PRIVATE}, {"rprivate", MS_SLAVE|MS_REC}, | |
68 {"unbindable", MS_UNBINDABLE}, {"runbindable", MS_UNBINDABLE|MS_REC}, | |
69 {"remount", MS_REMOUNT}, {"bind", MS_BIND}, {"move", MS_MOVE}, | |
70 // mand dirsync rec iversion strictatime | |
71 }; | |
72 | |
73 for (;;) { | |
74 char *comma = strchr(new, ','); | |
75 int i; | |
76 | |
77 if (comma) *comma = 0; | |
78 | |
79 // If we recognize an option, apply flags | |
80 for (i = 0; i < ARRAY_LEN(opts); i++) if (!strcasecmp(opts[i].name, new)) { | |
81 long ll = opts[i].flags; | |
82 | |
83 if (ll < 0) flags &= ll; | |
84 else flags |= ll; | |
85 | |
86 break; | |
87 } | |
88 | |
89 // If we didn't recognize it, keep string version | |
90 if (more && i == ARRAY_LEN(opts)) { | |
91 i = *more ? strlen(*more) : 0; | |
92 *more = xrealloc(*more, i + strlen(new) + 2); | |
93 if (i) (*more)[i++] = ','; | |
94 strcpy(i+*more, new); | |
95 } | |
96 | |
97 if (!comma) break; | |
98 *comma = ','; | |
99 new = comma + 1; | |
100 } | |
101 | |
102 return flags; | |
103 } | |
104 | |
105 static void mount_filesystem(char *dev, char *dir, char *type, | |
106 unsigned long flags, char *opts) | |
53 { | 107 { |
54 FILE *fp = 0; | 108 FILE *fp = 0; |
55 int rc = EINVAL; | 109 int rc = EINVAL; |
56 | 110 |
57 if (toys.optflags & FLAG_f) return; | 111 if (toys.optflags & FLAG_f) return; |
58 | 112 |
59 if (!TT.type) fp = xfopen("/proc/filesystems", "r"); | 113 if (!type) { |
114 struct stat stdev, stdir; | |
115 | |
116 if (!stat(dev, &stdev) && !stat(dir, &stdir)) { | |
117 if (S_ISREG(stdev.st_mode)) { | |
118 // Loopback mount? | |
119 if (S_ISDIR(stdir.st_mode)) { | |
120 char *losetup[] = {"losetup", "-fs", dev, 0}; | |
121 int pipes[2], len; | |
122 pid_t pid; | |
123 | |
124 if (flags & MS_RDONLY) losetup[1] = "-fsr"; | |
125 pid = xpopen(losetup, pipes); | |
126 len = readall(pipes[1], toybuf, sizeof(toybuf)-1); | |
127 if (!xpclose(pid, pipes) && len > 1) { | |
128 if (toybuf[len-1] == '\n') --len; | |
129 toybuf[len] = 0; | |
130 dev = toybuf; | |
131 } else error_msg("losetup failed %d", len); | |
132 } else if (S_ISREG(stdir.st_mode)) flags |= MS_BIND; | |
133 } else if (S_ISDIR(stdev.st_mode) && S_ISDIR(stdir.st_mode)) | |
134 flags |= MS_BIND; | |
135 } | |
136 | |
137 if (!(flags & MS_BIND)) fp = xfopen("/proc/filesystems", "r"); | |
138 } | |
60 | 139 |
61 for (;;) { | 140 for (;;) { |
62 char *buf = 0; | 141 char *buf = 0; |
63 | 142 |
64 // If type wasn't specified, try all of them in order. | 143 // If type wasn't specified, try all of them in order. |
75 // trim whitespace | 154 // trim whitespace |
76 while (isspace(*type)) type++; | 155 while (isspace(*type)) type++; |
77 i = strlen(type); | 156 i = strlen(type); |
78 if (i) type[i-1] = 0; | 157 if (i) type[i-1] = 0; |
79 } | 158 } |
159 if (toys.optflags & FLAG_v) | |
160 printf("try '%s' type '%s' on '%s'\n", dev, type, dir); | |
80 rc = mount(dev, dir, type, flags, opts); | 161 rc = mount(dev, dir, type, flags, opts); |
81 if (!fp || (rc && errno != EINVAL)) break; | 162 if (!fp || (rc && errno != EINVAL)) break; |
82 free(buf); | 163 free(buf); |
83 } | 164 } |
84 if (fp) fclose(fp); | 165 if (fp) fclose(fp); |
86 if (rc) perror_msg("'%s' on '%s'", dev, dir); | 167 if (rc) perror_msg("'%s' on '%s'", dev, dir); |
87 } | 168 } |
88 | 169 |
89 void mount_main(void) | 170 void mount_main(void) |
90 { | 171 { |
172 long flags = MS_SILENT; | |
173 struct arg_list *o; | |
174 char *opts = 0; | |
175 | |
91 if (toys.optflags & FLAG_a) { | 176 if (toys.optflags & FLAG_a) { |
92 fprintf(stderr, "not yet\n"); | 177 fprintf(stderr, "not yet\n"); |
93 return; | 178 return; |
94 } | 179 } |
180 | |
181 if (toys.optflags & FLAG_r) flags |= MS_RDONLY; | |
182 if (toys.optflags & FLAG_w) flags &= ~MS_RDONLY; | |
183 for (o = TT.optlist; o; o = o->next) | |
184 flags = parse_opts(o->arg, flags, &opts); | |
95 | 185 |
96 // show mounts | 186 // show mounts |
97 if (!toys.optc) { | 187 if (!toys.optc) { |
98 struct mtab_list *mtl = xgetmountlist(0), *m; | 188 struct mtab_list *mtl = xgetmountlist(0), *m; |
99 | 189 |
110 // one argument: from fstab, remount, subtree | 200 // one argument: from fstab, remount, subtree |
111 } else if (toys.optc == 1) { | 201 } else if (toys.optc == 1) { |
112 fprintf(stderr, "not yet\n"); | 202 fprintf(stderr, "not yet\n"); |
113 return; | 203 return; |
114 // two arguments | 204 // two arguments |
115 } else do_mount(toys.optargs[0], toys.optargs[1], TT.type, 0, ""); | 205 } else mount_filesystem(toys.optargs[0], toys.optargs[1], TT.type, |
206 flags, opts ? opts : ""); | |
116 } | 207 } |