Mercurial > hg > toybox
comparison toys/pending/mount.c @ 1385:ffc015bddb26 draft 0.4.9
Autodetect --bind and --loop mounts in a way that doesn't interfere with network filesystems or -t newtype mounts that trigger a module load.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sun, 06 Jul 2014 23:43:29 -0500 |
parents | 9fd2bcedbeb5 |
children | 487716951287 |
comparison
equal
deleted
inserted
replaced
1384:4a7438307429 | 1385:ffc015bddb26 |
---|---|
64 {"loud", ~MS_SILENT}, | 64 {"loud", ~MS_SILENT}, |
65 {"shared", MS_SHARED}, {"rshared", MS_SHARED|MS_REC}, | 65 {"shared", MS_SHARED}, {"rshared", MS_SHARED|MS_REC}, |
66 {"slave", MS_SLAVE}, {"rslave", MS_SLAVE|MS_REC}, | 66 {"slave", MS_SLAVE}, {"rslave", MS_SLAVE|MS_REC}, |
67 {"private", MS_PRIVATE}, {"rprivate", MS_SLAVE|MS_REC}, | 67 {"private", MS_PRIVATE}, {"rprivate", MS_SLAVE|MS_REC}, |
68 {"unbindable", MS_UNBINDABLE}, {"runbindable", MS_UNBINDABLE|MS_REC}, | 68 {"unbindable", MS_UNBINDABLE}, {"runbindable", MS_UNBINDABLE|MS_REC}, |
69 {"remount", MS_REMOUNT}, {"bind", MS_BIND}, {"move", MS_MOVE}, | 69 {"remount", MS_REMOUNT}, {"move", MS_MOVE}, |
70 // mand dirsync rec iversion strictatime | 70 // mand dirsync rec iversion strictatime |
71 }; | 71 }; |
72 | 72 |
73 for (;;) { | 73 for (;;) { |
74 char *comma = strchr(new, ','); | 74 char *comma = strchr(new, ','); |
108 FILE *fp = 0; | 108 FILE *fp = 0; |
109 int rc = EINVAL; | 109 int rc = EINVAL; |
110 | 110 |
111 if (toys.optflags & FLAG_f) return; | 111 if (toys.optflags & FLAG_f) return; |
112 | 112 |
113 // Autodetect bind mount or filesystem type | |
113 if (!type) { | 114 if (!type) { |
114 struct stat stdev, stdir; | 115 struct stat stdev, stdir; |
115 | 116 |
116 if (!stat(dev, &stdev) && !stat(dir, &stdir)) { | 117 if (!stat(dev, &stdev) && !stat(dir, &stdir) |
117 if (S_ISREG(stdev.st_mode)) { | 118 && ((S_ISREG(stdev.st_mode) && S_ISREG(stdir.st_mode)) |
118 // Loopback mount? | 119 || (S_ISDIR(stdev.st_mode) && S_ISDIR(stdir.st_mode)))) |
119 if (S_ISDIR(stdir.st_mode)) { | 120 { |
120 char *losetup[] = {"losetup", "-fs", dev, 0}; | 121 flags |= MS_BIND; |
121 int pipes[2], len; | 122 } else fp = xfopen("/proc/filesystems", "r"); |
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 } | 123 } |
139 | 124 |
140 for (;;) { | 125 for (;;) { |
141 char *buf = 0; | 126 char *buf = 0; |
142 | 127 |
157 if (i) type[i-1] = 0; | 142 if (i) type[i-1] = 0; |
158 } | 143 } |
159 if (toys.optflags & FLAG_v) | 144 if (toys.optflags & FLAG_v) |
160 printf("try '%s' type '%s' on '%s'\n", dev, type, dir); | 145 printf("try '%s' type '%s' on '%s'\n", dev, type, dir); |
161 rc = mount(dev, dir, type, flags, opts); | 146 rc = mount(dev, dir, type, flags, opts); |
147 | |
148 // Looking for bind mounts in autodetect above isn't good enough because | |
149 // "mount -t ext2 fs.img dir" is valid, but if you _do_ accept bind mounts | |
150 // with -t how do you tell "-t cifs" isn't looking for a block device if | |
151 // it's not in /proc/filesystems yet because the module that won't be | |
152 // loaded until you try the mount, and if you can't then DEVICE | |
153 // existing as a file would cause a false positive loopback mount. | |
154 // | |
155 // Solution: try mount, let the kernel tell us it wanted a block device, | |
156 // do the loopback setup and retry the mount. | |
157 if (rc && errno == ENOTBLK) { | |
158 char *losetup[] = {"losetup", "-fs", dev, 0}; | |
159 int pipes[2], len; | |
160 pid_t pid; | |
161 | |
162 if (flags & MS_RDONLY) losetup[1] = "-fsr"; | |
163 pid = xpopen(losetup, pipes); | |
164 len = readall(pipes[1], toybuf, sizeof(toybuf)-1); | |
165 if (!xpclose(pid, pipes) && len > 1) { | |
166 if (toybuf[len-1] == '\n') --len; | |
167 toybuf[len] = 0; | |
168 dev = toybuf; | |
169 | |
170 continue; | |
171 } else error_msg("losetup failed %d", len); | |
172 } | |
173 | |
162 if (!fp || (rc && errno != EINVAL)) break; | 174 if (!fp || (rc && errno != EINVAL)) break; |
163 free(buf); | 175 free(buf); |
164 } | 176 } |
165 if (fp) fclose(fp); | 177 if (fp) fclose(fp); |
166 | 178 |