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 }