Mercurial > hg > toybox
comparison toys/lsb/mount.c @ 1594:9b906eb047e8 draft
Don't mount a filesystem over an existing one with the same /dev and /dir.
The OS mostly catches this for block devices, but calling "mount -a" twice
shouldn't overmount tmpfs entries with new tmpfs instances. (This needs a test
suite entry, and the test suite needs a root context to run in...)
author | Rob Landley <rob@landley.net> |
---|---|
date | Tue, 02 Dec 2014 03:17:34 -0600 |
parents | 22691dfb17b9 |
children | 58d9f1b61f0a |
comparison
equal
deleted
inserted
replaced
1593:f2cac60ab2d3 | 1594:9b906eb047e8 |
---|---|
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, "?O:afnrvwt:o*[-rw]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT)) | 9 USE_MOUNT(NEWTOY(mount, "?O:afnrvwt:o*[-rw]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT)) |
10 USE_NFSMOUNT(NEWTOY(nfsmount, "?<2>2", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT)) | 10 //USE_NFSMOUNT(NEWTOY(nfsmount, "?<2>2", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT)) |
11 | 11 |
12 config MOUNT | 12 config MOUNT |
13 bool "mount" | 13 bool "mount" |
14 default y | 14 default y |
15 help | 15 help |
32 This mount autodetects loopback mounts (a file on a directory) and | 32 This mount autodetects loopback mounts (a file on a directory) and |
33 bind mounts (file on file, directory on directory), so you don't need | 33 bind mounts (file on file, directory on directory), so you don't need |
34 to say --bind or --loop. You can also "mount -a /path" to mount everything | 34 to say --bind or --loop. You can also "mount -a /path" to mount everything |
35 in /etc/fstab under /path, even if it's noauto. | 35 in /etc/fstab under /path, even if it's noauto. |
36 | 36 |
37 config NFSMOUNT | 37 #config NFSMOUNT |
38 bool "nfsmount" | 38 # bool "nfsmount" |
39 default n | 39 # default n |
40 help | 40 # help |
41 usage: nfsmount SHARE DIR | 41 # usage: nfsmount SHARE DIR |
42 | 42 # |
43 Invoke an eldrich horror from the dawn of time. | 43 # Invoke an eldrich horror from the dawn of time. |
44 */ | 44 */ |
45 | 45 |
46 #define FOR_mount | 46 #define FOR_mount |
47 #include "toys.h" | 47 #include "toys.h" |
48 | 48 |
244 void mount_main(void) | 244 void mount_main(void) |
245 { | 245 { |
246 char *opts = 0, *dev = 0, *dir = 0, **ss; | 246 char *opts = 0, *dev = 0, *dir = 0, **ss; |
247 long flags = MS_SILENT; | 247 long flags = MS_SILENT; |
248 struct arg_list *o; | 248 struct arg_list *o; |
249 struct mtab_list *mtl, *mm, *remount = 0; | 249 struct mtab_list *mtl, *mtl2 = 0, *mm, *remount; |
250 | 250 |
251 // TODO | |
251 // remount | 252 // remount |
252 // - overmounts | 253 // - overmounts |
253 // shared subtree | 254 // shared subtree |
254 // -o parsed after fstab options | 255 // -o parsed after fstab options |
255 // test if mountpoint already exists (-o noremount?) | 256 // test if mountpoint already exists (-o noremount?) |
273 } | 274 } |
274 | 275 |
275 if ((toys.optflags & FLAG_a) && dir) error_exit("-a with >1 arg"); | 276 if ((toys.optflags & FLAG_a) && dir) error_exit("-a with >1 arg"); |
276 | 277 |
277 // For remount we need _last_ match (in case of overmounts), so traverse | 278 // For remount we need _last_ match (in case of overmounts), so traverse |
278 // in reverse order. | 279 // in reverse order. (Yes I'm using remount as a boolean for a bit here, |
279 if (comma_scan(opts, "remount", 1)) | 280 // the double cast is to get gcc to shut up about it.) |
280 remount = dlist_terminate(mtl = xgetmountlist("/proc/mounts")); | 281 remount = (void *)(long)comma_scan(opts, "remount", 1); |
282 if (((toys.optflags & FLAG_a) && !access("/proc/mounts", R_OK)) || remount) { | |
283 mm = dlist_terminate(mtl = mtl2 = xgetmountlist(0)); | |
284 if (remount) remount = mm; | |
285 } | |
281 | 286 |
282 // Do we need to do an /etc/fstab trawl? | 287 // Do we need to do an /etc/fstab trawl? |
283 // This covers -a, -o remount, one argument, all user mounts | 288 // This covers -a, -o remount, one argument, all user mounts |
284 if ((toys.optflags & FLAG_a) || (dev && (!dir || getuid() || remount))) { | 289 if ((toys.optflags & FLAG_a) || (dev && (!dir || getuid() || remount))) { |
285 if (!remount) dlist_terminate(mtl = xgetmountlist("/etc/fstab")); | 290 if (!remount) dlist_terminate(mtl = xgetmountlist("/etc/fstab")); |
286 | 291 |
287 for (mm = remount ? remount : mtl; mm; mm = (remount ? mm->prev : mm->next)) | 292 for (mm = remount ? remount : mtl; mm; mm = (remount ? mm->prev : mm->next)) |
288 { | 293 { |
294 char *aopts = 0; | |
295 struct mtab_list *mmm = 0; | |
289 int aflags, noauto, len; | 296 int aflags, noauto, len; |
290 char *aopts = 0; | |
291 | 297 |
292 // Check for noauto and get it out of the option list. (Unknown options | 298 // Check for noauto and get it out of the option list. (Unknown options |
293 // that make it to the kernel give filesystem drivers indigestion.) | 299 // that make it to the kernel give filesystem drivers indigestion.) |
294 noauto = comma_scan(mm->opts, "noauto", 1); | 300 noauto = comma_scan(mm->opts, "noauto", 1); |
301 | |
295 if (toys.optflags & FLAG_a) { | 302 if (toys.optflags & FLAG_a) { |
296 // "mount -a /path" to mount all entries under /path | 303 // "mount -a /path" to mount all entries under /path |
297 if (dev) { | 304 if (dev) { |
298 len = strlen(dev); | 305 len = strlen(dev); |
299 if (strncmp(dev, mm->dir, len) | 306 if (strncmp(dev, mm->dir, len) |
305 if (dir && strcmp(dir, mm->dir)) continue; | 312 if (dir && strcmp(dir, mm->dir)) continue; |
306 if (dev && strcmp(dev, mm->device) && (dir || strcmp(dev, mm->dir))) | 313 if (dev && strcmp(dev, mm->device) && (dir || strcmp(dev, mm->dir))) |
307 continue; | 314 continue; |
308 } | 315 } |
309 | 316 |
317 // Don't overmount the same dev on the same directory | |
318 // (Unless root explicitly says to in non -a mode.) | |
319 if (mtl2 && !remount) | |
320 for (mmm = mtl2; mmm; mmm = mmm->next) | |
321 if (!strcmp(mm->dir, mmm->dir) && !strcmp(mm->device, mmm->device)) | |
322 break; | |
323 | |
310 // user only counts from fstab, not opts. | 324 // user only counts from fstab, not opts. |
311 TT.okuser = comma_scan(mm->opts, "user", 1); | 325 if (!mmm) { |
312 aflags = flag_opts(mm->opts, flags, &aopts); | 326 TT.okuser = comma_scan(mm->opts, "user", 1); |
313 aflags = flag_opts(opts, aflags, &aopts); | 327 aflags = flag_opts(mm->opts, flags, &aopts); |
314 | 328 aflags = flag_opts(opts, aflags, &aopts); |
315 mount_filesystem(mm->device, mm->dir, mm->type, aflags, aopts); | 329 |
330 mount_filesystem(mm->device, mm->dir, mm->type, aflags, aopts); | |
331 } // TODO else if (getuid()) error_msg("already there") ? | |
316 free(aopts); | 332 free(aopts); |
317 | 333 |
318 if (!(toys.optflags & FLAG_a)) break; | 334 if (!(toys.optflags & FLAG_a)) break; |
319 } | 335 } |
320 if (CFG_TOYBOX_FREE) llist_traverse(mtl, free); | 336 if (CFG_TOYBOX_FREE) { |
337 llist_traverse(mtl, free); | |
338 llist_traverse(mtl2, free); | |
339 } | |
321 if (!mm && !(toys.optflags & FLAG_a)) | 340 if (!mm && !(toys.optflags & FLAG_a)) |
322 error_exit("'%s' not in %s", dir ? dir : dev, | 341 error_exit("'%s' not in %s", dir ? dir : dev, |
323 remount ? "/proc/mounts" : "fstab"); | 342 remount ? "/proc/mounts" : "fstab"); |
324 | 343 |
325 // show mounts from /proc/mounts | 344 // show mounts from /proc/mounts |