1*cf5a6c84SAndroid Build Coastguard Worker /* mount.c - mount filesystems
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2014 Rob Landley <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker *
5*cf5a6c84SAndroid Build Coastguard Worker * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/mount.html
6*cf5a6c84SAndroid Build Coastguard Worker *
7*cf5a6c84SAndroid Build Coastguard Worker * Note: -hV is bad spec, haven't implemented -FsLU yet
8*cf5a6c84SAndroid Build Coastguard Worker * no mtab (/proc/mounts does it) so -n is NOP.
9*cf5a6c84SAndroid Build Coastguard Worker * TODO mount -o loop,autoclear (linux git 96c5865559ce)
10*cf5a6c84SAndroid Build Coastguard Worker * TODO mount jffs2.img dir (block2mtd)
11*cf5a6c84SAndroid Build Coastguard Worker * TODO fstab user
12*cf5a6c84SAndroid Build Coastguard Worker * TODO mount [^/]*:def = nfs, \\samba
13*cf5a6c84SAndroid Build Coastguard Worker
14*cf5a6c84SAndroid Build Coastguard Worker USE_MOUNT(NEWTOY(mount, "?RO:afnrvwt:o*[-rw]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
15*cf5a6c84SAndroid Build Coastguard Worker //USE_NFSMOUNT(NEWTOY(nfsmount, "<2>2", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
16*cf5a6c84SAndroid Build Coastguard Worker
17*cf5a6c84SAndroid Build Coastguard Worker config MOUNT
18*cf5a6c84SAndroid Build Coastguard Worker bool "mount"
19*cf5a6c84SAndroid Build Coastguard Worker default y
20*cf5a6c84SAndroid Build Coastguard Worker help
21*cf5a6c84SAndroid Build Coastguard Worker usage: mount [-afFrsvw] [-t TYPE] [-o OPTION,] [[DEVICE] DIR]
22*cf5a6c84SAndroid Build Coastguard Worker
23*cf5a6c84SAndroid Build Coastguard Worker Mount new filesystem(s) on directories. With no arguments, display existing
24*cf5a6c84SAndroid Build Coastguard Worker mounts.
25*cf5a6c84SAndroid Build Coastguard Worker
26*cf5a6c84SAndroid Build Coastguard Worker -a Mount all entries in /etc/fstab (with -t, only entries of that TYPE)
27*cf5a6c84SAndroid Build Coastguard Worker -O Only mount -a entries that have this option
28*cf5a6c84SAndroid Build Coastguard Worker -f Fake it (don't actually mount)
29*cf5a6c84SAndroid Build Coastguard Worker -r Read only (same as -o ro)
30*cf5a6c84SAndroid Build Coastguard Worker -w Read/write (default, same as -o rw)
31*cf5a6c84SAndroid Build Coastguard Worker -t Specify filesystem type
32*cf5a6c84SAndroid Build Coastguard Worker -v Verbose
33*cf5a6c84SAndroid Build Coastguard Worker
34*cf5a6c84SAndroid Build Coastguard Worker OPTIONS is a comma separated list of options, which can also be supplied
35*cf5a6c84SAndroid Build Coastguard Worker as --longopts.
36*cf5a6c84SAndroid Build Coastguard Worker
37*cf5a6c84SAndroid Build Coastguard Worker Autodetects loopback mounts (a file on a directory) and bind mounts (file
38*cf5a6c84SAndroid Build Coastguard Worker on file, directory on directory), so you don't need to say --bind or --loop.
39*cf5a6c84SAndroid Build Coastguard Worker You can also "mount -a /path" to mount everything in /etc/fstab under /path,
40*cf5a6c84SAndroid Build Coastguard Worker even if it's noauto. DEVICE starting with UUID= is identified by blkid -U,
41*cf5a6c84SAndroid Build Coastguard Worker and DEVICE starting with LABEL= is identified by blkid -L.
42*cf5a6c84SAndroid Build Coastguard Worker
43*cf5a6c84SAndroid Build Coastguard Worker #config SMBMOUNT
44*cf5a6c84SAndroid Build Coastguard Worker # bool "smbmount"
45*cf5a6c84SAndroid Build Coastguard Worker # default n
46*cf5a6c84SAndroid Build Coastguard Worker # helo
47*cf5a6c84SAndroid Build Coastguard Worker # usage: smbmount SHARE DIR
48*cf5a6c84SAndroid Build Coastguard Worker #
49*cf5a6c84SAndroid Build Coastguard Worker # Mount smb share with user/pasword prompt as necessary.
50*cf5a6c84SAndroid Build Coastguard Worker #
51*cf5a6c84SAndroid Build Coastguard Worker #config NFSMOUNT
52*cf5a6c84SAndroid Build Coastguard Worker # bool "nfsmount"
53*cf5a6c84SAndroid Build Coastguard Worker # default n
54*cf5a6c84SAndroid Build Coastguard Worker # help
55*cf5a6c84SAndroid Build Coastguard Worker # usage: nfsmount SHARE DIR
56*cf5a6c84SAndroid Build Coastguard Worker #
57*cf5a6c84SAndroid Build Coastguard Worker # Invoke an eldrich horror from the dawn of time.
58*cf5a6c84SAndroid Build Coastguard Worker */
59*cf5a6c84SAndroid Build Coastguard Worker
60*cf5a6c84SAndroid Build Coastguard Worker #define FOR_mount
61*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
62*cf5a6c84SAndroid Build Coastguard Worker
63*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
64*cf5a6c84SAndroid Build Coastguard Worker struct arg_list *o;
65*cf5a6c84SAndroid Build Coastguard Worker char *t, *O;
66*cf5a6c84SAndroid Build Coastguard Worker
67*cf5a6c84SAndroid Build Coastguard Worker unsigned long flags;
68*cf5a6c84SAndroid Build Coastguard Worker char *opts;
69*cf5a6c84SAndroid Build Coastguard Worker int okuser;
70*cf5a6c84SAndroid Build Coastguard Worker )
71*cf5a6c84SAndroid Build Coastguard Worker
72*cf5a6c84SAndroid Build Coastguard Worker // mount.tests should check for all of this:
73*cf5a6c84SAndroid Build Coastguard Worker // TODO detect existing identical mount (procfs with different dev name?)
74*cf5a6c84SAndroid Build Coastguard Worker // TODO user, users, owner, group, nofail
75*cf5a6c84SAndroid Build Coastguard Worker // TODO -p (passfd)
76*cf5a6c84SAndroid Build Coastguard Worker // TODO -a -t notype,type2
77*cf5a6c84SAndroid Build Coastguard Worker // TODO --subtree
78*cf5a6c84SAndroid Build Coastguard Worker // TODO make "mount --bind,ro old new" work (implicit -o remount)
79*cf5a6c84SAndroid Build Coastguard Worker // TODO mount -a
80*cf5a6c84SAndroid Build Coastguard Worker // TODO mount -o remount
81*cf5a6c84SAndroid Build Coastguard Worker // TODO fstab: lookup default options for mount
82*cf5a6c84SAndroid Build Coastguard Worker // TODO implement -v
83*cf5a6c84SAndroid Build Coastguard Worker // TODO "mount -a -o remount,ro" should detect overmounts
84*cf5a6c84SAndroid Build Coastguard Worker // TODO work out how that differs from "mount -ar"
85*cf5a6c84SAndroid Build Coastguard Worker // TODO what if you --bind mount a block device somewhere (file, dir, dev)
86*cf5a6c84SAndroid Build Coastguard Worker // TODO "touch servername; mount -t cifs servername path"
87*cf5a6c84SAndroid Build Coastguard Worker // TODO mount -o remount a user mount
88*cf5a6c84SAndroid Build Coastguard Worker // TODO mount image.img sub (auto-loopback) then umount image.img
89*cf5a6c84SAndroid Build Coastguard Worker // TODO mount UUID=blah
90*cf5a6c84SAndroid Build Coastguard Worker
91*cf5a6c84SAndroid Build Coastguard Worker // Strip flags out of comma separated list of options, return flags,.
92*cf5a6c84SAndroid Build Coastguard Worker // TODO: flip order and it's tagged array?
flag_opts(char * new,long flags,char ** more)93*cf5a6c84SAndroid Build Coastguard Worker static long flag_opts(char *new, long flags, char **more)
94*cf5a6c84SAndroid Build Coastguard Worker {
95*cf5a6c84SAndroid Build Coastguard Worker struct {
96*cf5a6c84SAndroid Build Coastguard Worker char *name;
97*cf5a6c84SAndroid Build Coastguard Worker long flags;
98*cf5a6c84SAndroid Build Coastguard Worker } opts[] = {
99*cf5a6c84SAndroid Build Coastguard Worker {"loop", 0}, {"defaults", 0}, {"quiet", 0}, // NOPs
100*cf5a6c84SAndroid Build Coastguard Worker {"user", 0}, {"nouser", 0}, // checked in fstab, ignored in -o
101*cf5a6c84SAndroid Build Coastguard Worker {"bind", MS_REC}, {"rbind", ~MS_REC}, // Autodetected but override defaults
102*cf5a6c84SAndroid Build Coastguard Worker {"ro", MS_RDONLY}, {"rw", ~MS_RDONLY},
103*cf5a6c84SAndroid Build Coastguard Worker {"nosuid", MS_NOSUID}, {"suid", ~MS_NOSUID},
104*cf5a6c84SAndroid Build Coastguard Worker {"nodev", MS_NODEV}, {"dev", ~MS_NODEV},
105*cf5a6c84SAndroid Build Coastguard Worker {"noexec", MS_NOEXEC}, {"exec", ~MS_NOEXEC},
106*cf5a6c84SAndroid Build Coastguard Worker {"sync", MS_SYNCHRONOUS}, {"async", ~MS_SYNCHRONOUS},
107*cf5a6c84SAndroid Build Coastguard Worker {"noatime", MS_NOATIME}, {"atime", ~MS_NOATIME},
108*cf5a6c84SAndroid Build Coastguard Worker {"norelatime", ~MS_RELATIME}, {"relatime", MS_RELATIME},
109*cf5a6c84SAndroid Build Coastguard Worker {"nodiratime", MS_NODIRATIME}, {"diratime", ~MS_NODIRATIME},
110*cf5a6c84SAndroid Build Coastguard Worker {"loud", ~MS_SILENT},
111*cf5a6c84SAndroid Build Coastguard Worker {"shared", MS_SHARED}, {"rshared", MS_SHARED|MS_REC},
112*cf5a6c84SAndroid Build Coastguard Worker {"slave", MS_SLAVE}, {"rslave", MS_SLAVE|MS_REC},
113*cf5a6c84SAndroid Build Coastguard Worker {"private", MS_PRIVATE}, {"rprivate", MS_SLAVE|MS_REC},
114*cf5a6c84SAndroid Build Coastguard Worker {"unbindable", MS_UNBINDABLE}, {"runbindable", MS_UNBINDABLE|MS_REC},
115*cf5a6c84SAndroid Build Coastguard Worker {"remount", MS_REMOUNT}, {"move", MS_MOVE},
116*cf5a6c84SAndroid Build Coastguard Worker // mand dirsync rec iversion strictatime
117*cf5a6c84SAndroid Build Coastguard Worker };
118*cf5a6c84SAndroid Build Coastguard Worker
119*cf5a6c84SAndroid Build Coastguard Worker if (new) for (;;) {
120*cf5a6c84SAndroid Build Coastguard Worker char *comma = strchr(new, ',');
121*cf5a6c84SAndroid Build Coastguard Worker int i;
122*cf5a6c84SAndroid Build Coastguard Worker
123*cf5a6c84SAndroid Build Coastguard Worker if (comma) *comma = 0;
124*cf5a6c84SAndroid Build Coastguard Worker
125*cf5a6c84SAndroid Build Coastguard Worker // If we recognize an option, apply flags
126*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < ARRAY_LEN(opts); i++) if (!strcasecmp(opts[i].name, new)) {
127*cf5a6c84SAndroid Build Coastguard Worker long ll = opts[i].flags;
128*cf5a6c84SAndroid Build Coastguard Worker
129*cf5a6c84SAndroid Build Coastguard Worker if (ll < 0) flags &= ll;
130*cf5a6c84SAndroid Build Coastguard Worker else flags |= ll;
131*cf5a6c84SAndroid Build Coastguard Worker
132*cf5a6c84SAndroid Build Coastguard Worker break;
133*cf5a6c84SAndroid Build Coastguard Worker }
134*cf5a6c84SAndroid Build Coastguard Worker
135*cf5a6c84SAndroid Build Coastguard Worker // If we didn't recognize it, keep string version
136*cf5a6c84SAndroid Build Coastguard Worker if (more && i == ARRAY_LEN(opts)) {
137*cf5a6c84SAndroid Build Coastguard Worker i = *more ? strlen(*more) : 0;
138*cf5a6c84SAndroid Build Coastguard Worker *more = xrealloc(*more, i + strlen(new) + 2);
139*cf5a6c84SAndroid Build Coastguard Worker if (i) (*more)[i++] = ',';
140*cf5a6c84SAndroid Build Coastguard Worker strcpy(i+*more, new);
141*cf5a6c84SAndroid Build Coastguard Worker }
142*cf5a6c84SAndroid Build Coastguard Worker
143*cf5a6c84SAndroid Build Coastguard Worker if (!comma) break;
144*cf5a6c84SAndroid Build Coastguard Worker *comma = ',';
145*cf5a6c84SAndroid Build Coastguard Worker new = comma + 1;
146*cf5a6c84SAndroid Build Coastguard Worker }
147*cf5a6c84SAndroid Build Coastguard Worker
148*cf5a6c84SAndroid Build Coastguard Worker return flags;
149*cf5a6c84SAndroid Build Coastguard Worker }
150*cf5a6c84SAndroid Build Coastguard Worker
mount_filesystem(char * dev,char * dir,char * type,unsigned long flags,char * opts)151*cf5a6c84SAndroid Build Coastguard Worker static void mount_filesystem(char *dev, char *dir, char *type,
152*cf5a6c84SAndroid Build Coastguard Worker unsigned long flags, char *opts)
153*cf5a6c84SAndroid Build Coastguard Worker {
154*cf5a6c84SAndroid Build Coastguard Worker FILE *fp = 0;
155*cf5a6c84SAndroid Build Coastguard Worker int rc = EINVAL;
156*cf5a6c84SAndroid Build Coastguard Worker char *buf = 0;
157*cf5a6c84SAndroid Build Coastguard Worker
158*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(f)) return;
159*cf5a6c84SAndroid Build Coastguard Worker
160*cf5a6c84SAndroid Build Coastguard Worker if (getuid()) {
161*cf5a6c84SAndroid Build Coastguard Worker if (TT.okuser) TT.okuser = 0;
162*cf5a6c84SAndroid Build Coastguard Worker else {
163*cf5a6c84SAndroid Build Coastguard Worker error_msg("'%s' not user mountable in fstab", dev);
164*cf5a6c84SAndroid Build Coastguard Worker
165*cf5a6c84SAndroid Build Coastguard Worker return;
166*cf5a6c84SAndroid Build Coastguard Worker }
167*cf5a6c84SAndroid Build Coastguard Worker }
168*cf5a6c84SAndroid Build Coastguard Worker
169*cf5a6c84SAndroid Build Coastguard Worker if (strstart(&dev, "UUID=")) {
170*cf5a6c84SAndroid Build Coastguard Worker char *s = chomp(xrunread((char *[]){"blkid", "-U", dev, 0}, 0));
171*cf5a6c84SAndroid Build Coastguard Worker
172*cf5a6c84SAndroid Build Coastguard Worker if (!s || strlen(s)>=sizeof(toybuf)) return error_msg("No uuid %s", dev);
173*cf5a6c84SAndroid Build Coastguard Worker strcpy(dev = toybuf, s);
174*cf5a6c84SAndroid Build Coastguard Worker free(s);
175*cf5a6c84SAndroid Build Coastguard Worker } else if (strstart(&dev, "LABEL=")) {
176*cf5a6c84SAndroid Build Coastguard Worker char *s = chomp(xrunread((char *[]){"blkid", "-L", dev, 0}, 0));
177*cf5a6c84SAndroid Build Coastguard Worker
178*cf5a6c84SAndroid Build Coastguard Worker if (!s || strlen(s)>=sizeof(toybuf)) return error_msg("No label %s", dev);
179*cf5a6c84SAndroid Build Coastguard Worker strcpy(dev = toybuf, s);
180*cf5a6c84SAndroid Build Coastguard Worker free(s);
181*cf5a6c84SAndroid Build Coastguard Worker }
182*cf5a6c84SAndroid Build Coastguard Worker
183*cf5a6c84SAndroid Build Coastguard Worker // Autodetect bind mount or filesystem type
184*cf5a6c84SAndroid Build Coastguard Worker
185*cf5a6c84SAndroid Build Coastguard Worker if (type && (!strcmp(type, "auto") || !strcmp(type, "none"))) type = 0;
186*cf5a6c84SAndroid Build Coastguard Worker if (flags & MS_MOVE) {
187*cf5a6c84SAndroid Build Coastguard Worker if (type) error_exit("--move with -t");
188*cf5a6c84SAndroid Build Coastguard Worker } else if (!type) {
189*cf5a6c84SAndroid Build Coastguard Worker struct stat stdev, stdir;
190*cf5a6c84SAndroid Build Coastguard Worker
191*cf5a6c84SAndroid Build Coastguard Worker // file on file or dir on dir is a --bind mount.
192*cf5a6c84SAndroid Build Coastguard Worker if (!stat(dev, &stdev) && !stat(dir, &stdir)
193*cf5a6c84SAndroid Build Coastguard Worker && ((S_ISREG(stdev.st_mode) && S_ISREG(stdir.st_mode))
194*cf5a6c84SAndroid Build Coastguard Worker || (S_ISDIR(stdev.st_mode) && S_ISDIR(stdir.st_mode))))
195*cf5a6c84SAndroid Build Coastguard Worker {
196*cf5a6c84SAndroid Build Coastguard Worker flags ^= MS_REC;
197*cf5a6c84SAndroid Build Coastguard Worker flags |= MS_BIND;
198*cf5a6c84SAndroid Build Coastguard Worker } else fp = xfopen("/proc/filesystems", "r");
199*cf5a6c84SAndroid Build Coastguard Worker } else if (!strcmp(type, "ignore")) return;
200*cf5a6c84SAndroid Build Coastguard Worker else if (!strcmp(type, "swap"))
201*cf5a6c84SAndroid Build Coastguard Worker toys.exitval |= xrun((char *[]){"swapon", "--", dev, 0});
202*cf5a6c84SAndroid Build Coastguard Worker
203*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
204*cf5a6c84SAndroid Build Coastguard Worker int fd = -1, ro = 0;
205*cf5a6c84SAndroid Build Coastguard Worker
206*cf5a6c84SAndroid Build Coastguard Worker // If type wasn't specified, try all of them in order.
207*cf5a6c84SAndroid Build Coastguard Worker if (fp && !buf) {
208*cf5a6c84SAndroid Build Coastguard Worker size_t i;
209*cf5a6c84SAndroid Build Coastguard Worker
210*cf5a6c84SAndroid Build Coastguard Worker if (getline(&buf, &i, fp)<1) {
211*cf5a6c84SAndroid Build Coastguard Worker error_msg("%s: need -t", dev);
212*cf5a6c84SAndroid Build Coastguard Worker break;
213*cf5a6c84SAndroid Build Coastguard Worker }
214*cf5a6c84SAndroid Build Coastguard Worker type = buf;
215*cf5a6c84SAndroid Build Coastguard Worker // skip nodev devices
216*cf5a6c84SAndroid Build Coastguard Worker if (!isspace(*type)) {
217*cf5a6c84SAndroid Build Coastguard Worker free(buf);
218*cf5a6c84SAndroid Build Coastguard Worker buf = 0;
219*cf5a6c84SAndroid Build Coastguard Worker
220*cf5a6c84SAndroid Build Coastguard Worker continue;
221*cf5a6c84SAndroid Build Coastguard Worker }
222*cf5a6c84SAndroid Build Coastguard Worker // trim whitespace
223*cf5a6c84SAndroid Build Coastguard Worker while (isspace(*type)) type++;
224*cf5a6c84SAndroid Build Coastguard Worker i = strlen(type);
225*cf5a6c84SAndroid Build Coastguard Worker if (i) type[i-1] = 0;
226*cf5a6c84SAndroid Build Coastguard Worker }
227*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(v)) printf("try '%s' type '%s' on '%s'\n", dev, type, dir);
228*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
229*cf5a6c84SAndroid Build Coastguard Worker rc = mount(dev, dir, type, flags, opts);
230*cf5a6c84SAndroid Build Coastguard Worker // Did we succeed, fail unrecoverably, or already try read-only?
231*cf5a6c84SAndroid Build Coastguard Worker if (!rc || (errno != EACCES && errno != EROFS) || (flags&MS_RDONLY))
232*cf5a6c84SAndroid Build Coastguard Worker break;
233*cf5a6c84SAndroid Build Coastguard Worker // If we haven't already tried it, use the BLKROSET ioctl to ensure
234*cf5a6c84SAndroid Build Coastguard Worker // that the underlying device isn't read-only.
235*cf5a6c84SAndroid Build Coastguard Worker if (fd == -1) {
236*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(v))
237*cf5a6c84SAndroid Build Coastguard Worker printf("trying BLKROSET ioctl on '%s'\n", dev);
238*cf5a6c84SAndroid Build Coastguard Worker if (-1 != (fd = open(dev, O_RDONLY))) {
239*cf5a6c84SAndroid Build Coastguard Worker rc = ioctl(fd, BLKROSET, &ro);
240*cf5a6c84SAndroid Build Coastguard Worker close(fd);
241*cf5a6c84SAndroid Build Coastguard Worker if (!rc) continue;
242*cf5a6c84SAndroid Build Coastguard Worker }
243*cf5a6c84SAndroid Build Coastguard Worker }
244*cf5a6c84SAndroid Build Coastguard Worker fprintf(stderr, "'%s' is read-only\n", dev);
245*cf5a6c84SAndroid Build Coastguard Worker flags |= MS_RDONLY;
246*cf5a6c84SAndroid Build Coastguard Worker }
247*cf5a6c84SAndroid Build Coastguard Worker
248*cf5a6c84SAndroid Build Coastguard Worker // Trying to autodetect loop mounts like bind mounts above (file on dir)
249*cf5a6c84SAndroid Build Coastguard Worker // isn't good enough because "mount -t ext2 fs.img dir" is valid, but if
250*cf5a6c84SAndroid Build Coastguard Worker // you _do_ accept loop mounts with -t how do you tell "-t cifs" isn't
251*cf5a6c84SAndroid Build Coastguard Worker // looking for a block device if it's not in /proc/filesystems yet
252*cf5a6c84SAndroid Build Coastguard Worker // because the fs module won't be loaded until you try the mount, and
253*cf5a6c84SAndroid Build Coastguard Worker // if you can't then DEVICE existing as a file would cause a false
254*cf5a6c84SAndroid Build Coastguard Worker // positive loopback mount (so "touch servername" becomes a potential
255*cf5a6c84SAndroid Build Coastguard Worker // denial of service attack...)
256*cf5a6c84SAndroid Build Coastguard Worker //
257*cf5a6c84SAndroid Build Coastguard Worker // Solution: try the mount, let the kernel tell us it wanted a block
258*cf5a6c84SAndroid Build Coastguard Worker // device, then do the loopback setup and retry the mount.
259*cf5a6c84SAndroid Build Coastguard Worker
260*cf5a6c84SAndroid Build Coastguard Worker if (rc && errno == ENOTBLK) {
261*cf5a6c84SAndroid Build Coastguard Worker char *losetup[] = {"losetup", (flags&MS_RDONLY)?"-fsr":"-fs", dev, 0};
262*cf5a6c84SAndroid Build Coastguard Worker
263*cf5a6c84SAndroid Build Coastguard Worker if ((dev = chomp(xrunread(losetup, 0)))) continue;
264*cf5a6c84SAndroid Build Coastguard Worker error_msg("%s failed", *losetup);
265*cf5a6c84SAndroid Build Coastguard Worker break;
266*cf5a6c84SAndroid Build Coastguard Worker }
267*cf5a6c84SAndroid Build Coastguard Worker
268*cf5a6c84SAndroid Build Coastguard Worker free(buf);
269*cf5a6c84SAndroid Build Coastguard Worker buf = 0;
270*cf5a6c84SAndroid Build Coastguard Worker if (!rc) break;
271*cf5a6c84SAndroid Build Coastguard Worker if (fp && (errno == EINVAL || errno == EBUSY)) continue;
272*cf5a6c84SAndroid Build Coastguard Worker
273*cf5a6c84SAndroid Build Coastguard Worker perror_msg("'%s'->'%s'", dev, dir);
274*cf5a6c84SAndroid Build Coastguard Worker
275*cf5a6c84SAndroid Build Coastguard Worker break;
276*cf5a6c84SAndroid Build Coastguard Worker }
277*cf5a6c84SAndroid Build Coastguard Worker if (fp) fclose(fp);
278*cf5a6c84SAndroid Build Coastguard Worker }
279*cf5a6c84SAndroid Build Coastguard Worker
mount_main(void)280*cf5a6c84SAndroid Build Coastguard Worker void mount_main(void)
281*cf5a6c84SAndroid Build Coastguard Worker {
282*cf5a6c84SAndroid Build Coastguard Worker char *opts = 0, *dev = 0, *dir = 0, **ss;
283*cf5a6c84SAndroid Build Coastguard Worker long flags = MS_SILENT;
284*cf5a6c84SAndroid Build Coastguard Worker struct arg_list *o;
285*cf5a6c84SAndroid Build Coastguard Worker struct mtab_list *mtl, *mtl2 = 0, *mm, *remount;
286*cf5a6c84SAndroid Build Coastguard Worker
287*cf5a6c84SAndroid Build Coastguard Worker // TODO
288*cf5a6c84SAndroid Build Coastguard Worker // remount
289*cf5a6c84SAndroid Build Coastguard Worker // - overmounts
290*cf5a6c84SAndroid Build Coastguard Worker // shared subtree
291*cf5a6c84SAndroid Build Coastguard Worker // -o parsed after fstab options
292*cf5a6c84SAndroid Build Coastguard Worker // test if mountpoint already exists (-o noremount?)
293*cf5a6c84SAndroid Build Coastguard Worker
294*cf5a6c84SAndroid Build Coastguard Worker // First pass; just accumulate string, don't parse flags yet. (This is so
295*cf5a6c84SAndroid Build Coastguard Worker // we can modify fstab entries with -a, or mtab with remount.)
296*cf5a6c84SAndroid Build Coastguard Worker for (o = TT.o; o; o = o->next) comma_collate(&opts, o->arg);
297*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(r)) comma_collate(&opts, "ro");
298*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(w)) comma_collate(&opts, "rw");
299*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(R)) comma_collate(&opts, "rbind");
300*cf5a6c84SAndroid Build Coastguard Worker
301*cf5a6c84SAndroid Build Coastguard Worker // Treat each --option as -o option
302*cf5a6c84SAndroid Build Coastguard Worker for (ss = toys.optargs; *ss; ss++) {
303*cf5a6c84SAndroid Build Coastguard Worker char *sss = *ss;
304*cf5a6c84SAndroid Build Coastguard Worker
305*cf5a6c84SAndroid Build Coastguard Worker // If you realy, really want to mount a file named "--", we support it.
306*cf5a6c84SAndroid Build Coastguard Worker if (sss[0]=='-' && sss[1]=='-' && sss[2]) comma_collate(&opts, sss+2);
307*cf5a6c84SAndroid Build Coastguard Worker else if (!dev) dev = sss;
308*cf5a6c84SAndroid Build Coastguard Worker else if (!dir) dir = sss;
309*cf5a6c84SAndroid Build Coastguard Worker // same message as lib/args.c ">2" which we can't use because --opts count
310*cf5a6c84SAndroid Build Coastguard Worker else error_exit("Max 2 arguments\n");
311*cf5a6c84SAndroid Build Coastguard Worker }
312*cf5a6c84SAndroid Build Coastguard Worker
313*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(a) && dir) error_exit("-a with >1 arg");
314*cf5a6c84SAndroid Build Coastguard Worker
315*cf5a6c84SAndroid Build Coastguard Worker // For remount we need _last_ match (in case of overmounts), so traverse
316*cf5a6c84SAndroid Build Coastguard Worker // in reverse order. (Yes I'm using remount as a boolean for a bit here,
317*cf5a6c84SAndroid Build Coastguard Worker // the double cast is to get gcc to shut up about it.)
318*cf5a6c84SAndroid Build Coastguard Worker remount = (void *)(long)comma_scan(opts, "remount", 0);
319*cf5a6c84SAndroid Build Coastguard Worker if ((FLAG(a) && !access("/proc/mounts", R_OK)) || remount) {
320*cf5a6c84SAndroid Build Coastguard Worker mm = dlist_terminate(mtl = mtl2 = xgetmountlist(0));
321*cf5a6c84SAndroid Build Coastguard Worker if (remount) remount = mm;
322*cf5a6c84SAndroid Build Coastguard Worker }
323*cf5a6c84SAndroid Build Coastguard Worker
324*cf5a6c84SAndroid Build Coastguard Worker // Do we need to do an /etc/fstab trawl?
325*cf5a6c84SAndroid Build Coastguard Worker // This covers -a, -o remount, one argument, all user mounts
326*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(a) || (dev && (!dir || getuid() || remount))) {
327*cf5a6c84SAndroid Build Coastguard Worker if (!remount) dlist_terminate(mtl = xgetmountlist("/etc/fstab"));
328*cf5a6c84SAndroid Build Coastguard Worker
329*cf5a6c84SAndroid Build Coastguard Worker for (mm = remount ? remount : mtl; mm; mm = (remount ? mm->prev : mm->next))
330*cf5a6c84SAndroid Build Coastguard Worker {
331*cf5a6c84SAndroid Build Coastguard Worker char *aopts = 0;
332*cf5a6c84SAndroid Build Coastguard Worker struct mtab_list *mmm = 0;
333*cf5a6c84SAndroid Build Coastguard Worker int aflags, noauto, len;
334*cf5a6c84SAndroid Build Coastguard Worker
335*cf5a6c84SAndroid Build Coastguard Worker // Check for noauto and get it out of the option list. (Unknown options
336*cf5a6c84SAndroid Build Coastguard Worker // that make it to the kernel give filesystem drivers indigestion.)
337*cf5a6c84SAndroid Build Coastguard Worker noauto = comma_scan(mm->opts, "noauto", 1);
338*cf5a6c84SAndroid Build Coastguard Worker
339*cf5a6c84SAndroid Build Coastguard Worker if (FLAG(a)) {
340*cf5a6c84SAndroid Build Coastguard Worker // "mount -a /path" to mount all entries under /path
341*cf5a6c84SAndroid Build Coastguard Worker if (dev) {
342*cf5a6c84SAndroid Build Coastguard Worker len = strlen(dev);
343*cf5a6c84SAndroid Build Coastguard Worker if (strncmp(dev, mm->dir, len)
344*cf5a6c84SAndroid Build Coastguard Worker || (mm->dir[len] && mm->dir[len] != '/')) continue;
345*cf5a6c84SAndroid Build Coastguard Worker } else if (noauto) continue; // never present in the remount case
346*cf5a6c84SAndroid Build Coastguard Worker if (!mountlist_istype(mm, TT.t) || !comma_scanall(mm->opts, TT.O))
347*cf5a6c84SAndroid Build Coastguard Worker continue;
348*cf5a6c84SAndroid Build Coastguard Worker } else {
349*cf5a6c84SAndroid Build Coastguard Worker if (dir && strcmp(dir, mm->dir)) continue;
350*cf5a6c84SAndroid Build Coastguard Worker if (strcmp(dev, mm->device) && (dir || strcmp(dev, mm->dir))) continue;
351*cf5a6c84SAndroid Build Coastguard Worker }
352*cf5a6c84SAndroid Build Coastguard Worker
353*cf5a6c84SAndroid Build Coastguard Worker // Don't overmount the same dev on the same directory
354*cf5a6c84SAndroid Build Coastguard Worker // (Unless root explicitly says to in non -a mode.)
355*cf5a6c84SAndroid Build Coastguard Worker if (mtl2 && !remount)
356*cf5a6c84SAndroid Build Coastguard Worker for (mmm = mtl2; mmm; mmm = mmm->next)
357*cf5a6c84SAndroid Build Coastguard Worker if (!strcmp(mm->dir, mmm->dir) && !strcmp(mm->device, mmm->device))
358*cf5a6c84SAndroid Build Coastguard Worker break;
359*cf5a6c84SAndroid Build Coastguard Worker
360*cf5a6c84SAndroid Build Coastguard Worker // user only counts from fstab, not opts.
361*cf5a6c84SAndroid Build Coastguard Worker if (!mmm) {
362*cf5a6c84SAndroid Build Coastguard Worker TT.okuser = comma_scan(mm->opts, "user", 1);
363*cf5a6c84SAndroid Build Coastguard Worker aflags = flag_opts(mm->opts, flags, &aopts);
364*cf5a6c84SAndroid Build Coastguard Worker aflags = flag_opts(opts, aflags, &aopts);
365*cf5a6c84SAndroid Build Coastguard Worker
366*cf5a6c84SAndroid Build Coastguard Worker mount_filesystem(mm->device, mm->dir, mm->type, aflags, aopts);
367*cf5a6c84SAndroid Build Coastguard Worker } // TODO else if (getuid()) error_msg("already there") ?
368*cf5a6c84SAndroid Build Coastguard Worker free(aopts);
369*cf5a6c84SAndroid Build Coastguard Worker
370*cf5a6c84SAndroid Build Coastguard Worker if (!FLAG(a)) break;
371*cf5a6c84SAndroid Build Coastguard Worker }
372*cf5a6c84SAndroid Build Coastguard Worker if (CFG_TOYBOX_FREE) {
373*cf5a6c84SAndroid Build Coastguard Worker llist_traverse(mtl, free);
374*cf5a6c84SAndroid Build Coastguard Worker llist_traverse(mtl2, free);
375*cf5a6c84SAndroid Build Coastguard Worker }
376*cf5a6c84SAndroid Build Coastguard Worker if (!mm && !FLAG(a))
377*cf5a6c84SAndroid Build Coastguard Worker error_exit("'%s' not in %s", dir ? dir : dev,
378*cf5a6c84SAndroid Build Coastguard Worker remount ? "/proc/mounts" : "fstab");
379*cf5a6c84SAndroid Build Coastguard Worker
380*cf5a6c84SAndroid Build Coastguard Worker // show mounts from /proc/mounts
381*cf5a6c84SAndroid Build Coastguard Worker } else if (!dev) {
382*cf5a6c84SAndroid Build Coastguard Worker for (mtl = xgetmountlist(0); mtl && (mm = dlist_pop(&mtl)); free(mm)) {
383*cf5a6c84SAndroid Build Coastguard Worker char *s = mm->device, *ss = "", *temp;
384*cf5a6c84SAndroid Build Coastguard Worker struct stat st;
385*cf5a6c84SAndroid Build Coastguard Worker
386*cf5a6c84SAndroid Build Coastguard Worker if (TT.t && strcmp(TT.t, mm->type)) continue;
387*cf5a6c84SAndroid Build Coastguard Worker if (*s == '/') {
388*cf5a6c84SAndroid Build Coastguard Worker if (!stat(mm->device, &st) && S_ISBLK(st.st_mode) &&
389*cf5a6c84SAndroid Build Coastguard Worker dev_major(st.st_rdev)==7)
390*cf5a6c84SAndroid Build Coastguard Worker {
391*cf5a6c84SAndroid Build Coastguard Worker temp = xmprintf("/sys/block/loop%d/loop/backing_file",
392*cf5a6c84SAndroid Build Coastguard Worker dev_minor(st.st_rdev));
393*cf5a6c84SAndroid Build Coastguard Worker s = chomp(readfile(temp, 0, 0));
394*cf5a6c84SAndroid Build Coastguard Worker free(temp);
395*cf5a6c84SAndroid Build Coastguard Worker if (s) {
396*cf5a6c84SAndroid Build Coastguard Worker ss = xmprintf(",file=%s"+!*mm->opts, s);
397*cf5a6c84SAndroid Build Coastguard Worker free(s);
398*cf5a6c84SAndroid Build Coastguard Worker };
399*cf5a6c84SAndroid Build Coastguard Worker }
400*cf5a6c84SAndroid Build Coastguard Worker s = xabspath(mm->device, 0);
401*cf5a6c84SAndroid Build Coastguard Worker }
402*cf5a6c84SAndroid Build Coastguard Worker xprintf("%s on %s type %s (%s%s)\n", s, mm->dir, mm->type, mm->opts, ss);
403*cf5a6c84SAndroid Build Coastguard Worker if (s != mm->device) free(s);
404*cf5a6c84SAndroid Build Coastguard Worker if (*ss) free(ss);
405*cf5a6c84SAndroid Build Coastguard Worker }
406*cf5a6c84SAndroid Build Coastguard Worker
407*cf5a6c84SAndroid Build Coastguard Worker // two arguments
408*cf5a6c84SAndroid Build Coastguard Worker } else {
409*cf5a6c84SAndroid Build Coastguard Worker char *more = 0;
410*cf5a6c84SAndroid Build Coastguard Worker
411*cf5a6c84SAndroid Build Coastguard Worker flags = flag_opts(opts, flags, &more);
412*cf5a6c84SAndroid Build Coastguard Worker mount_filesystem(dev, dir, TT.t, flags, more);
413*cf5a6c84SAndroid Build Coastguard Worker if (CFG_TOYBOX_FREE) free(more);
414*cf5a6c84SAndroid Build Coastguard Worker }
415*cf5a6c84SAndroid Build Coastguard Worker }
416