Introduction
Introduction Statistics Contact Development Disclaimer Help
mount.c - ubase - suckless linux base utils
git clone git://git.suckless.org/ubase
Log
Files
Refs
README
LICENSE
---
mount.c (7313B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <sys/mount.h>
3 #include <sys/stat.h>
4 #include <sys/types.h>
5 #include <sys/wait.h>
6
7 #include <errno.h>
8 #include <limits.h>
9 #include <mntent.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14
15 #include "text.h"
16 #include "util.h"
17
18 #define FSOPTS_MAXLEN 512
19
20 struct {
21 const char *opt;
22 const char *notopt;
23 unsigned long v;
24 } optnames[] = {
25 { "defaults", NULL, 0 },
26 { "remount", NULL, MS_REMOUNT },
27 { "ro", "rw", MS_RDONLY },
28 { "sync", "async", MS_SYNCHRONOUS },
29 { "dirsync", NULL, MS_DIRSYNC },
30 { "nodev", "dev", MS_NODEV },
31 { "noatime", "atime", MS_NOATIME },
32 { "noauto", "auto", 0 },
33 { "nodiratime", "diratime", MS_NODIRATIME },
34 { "noexec", "exec", MS_NOEXEC },
35 { "nosuid", "suid", MS_NOSUID },
36 { "mand", "nomand", MS_MANDLOCK },
37 { "relatime", "norelatime", MS_RELATIME },
38 { "bind", NULL, MS_BIND },
39 { NULL, NULL, 0 }
40 };
41
42 static unsigned long argflags = 0;
43 static char fsopts[FSOPTS_MAXLEN] = "";
44
45 static char *
46 findtype(const char *types, const char *t)
47 {
48 const char *p;
49 size_t len;
50
51 for (len = strlen(t); (p = strstr(types, t)); types = p + len) {
52 if (!strncmp(p, t, len) && (p[len] == '\0' || p[len] == …
53 return (char *)p;
54 }
55 return NULL;
56 }
57
58 static void
59 parseopts(const char *popts, unsigned long *flags, char *data, size_t da…
60 {
61 unsigned int i, validopt;
62 size_t optlen, dlen = 0;
63 const char *name, *e;
64
65 name = popts;
66 data[0] = '\0';
67 do {
68 if ((e = strstr(name, ",")))
69 optlen = e - name;
70 else
71 optlen = strlen(name);
72
73 validopt = 0;
74 for (i = 0; optnames[i].opt; i++) {
75 if (optnames[i].opt &&
76 !strncmp(name, optnames[i].opt, optlen)) {
77 *flags |= optnames[i].v;
78 validopt = 1;
79 break;
80 }
81 if (optnames[i].notopt &&
82 !strncmp(name, optnames[i].notopt, optlen)) {
83 *flags &= ~optnames[i].v;
84 validopt = 1;
85 break;
86 }
87 }
88
89 if (!validopt && optlen > 0) {
90 /* unknown option, pass as data option to mount(…
91 if (dlen + optlen + 2 >= datasiz)
92 return; /* prevent overflow */
93 if (dlen)
94 data[dlen++] = ',';
95 memcpy(&data[dlen], name, optlen);
96 dlen += optlen;
97 data[dlen] = '\0';
98 }
99 name = e + 1;
100 } while (e);
101 }
102
103 static int
104 mounthelper(const char *fsname, const char *dir, const char *fstype)
105 {
106 pid_t pid;
107 char eprog[PATH_MAX];
108 char const *eargv[10];
109 int status, i;
110
111 pid = fork();
112 switch(pid) {
113 case -1:
114 break;
115 case 0:
116 snprintf(eprog, sizeof(eprog), "mount.%s", fstype);
117
118 i = 0;
119 eargv[i++] = eprog;
120 if (argflags & MS_BIND)
121 eargv[i++] = "-B";
122 if (argflags & MS_MOVE)
123 eargv[i++] = "-M";
124 if (argflags & MS_REC)
125 eargv[i++] = "-R";
126
127 if (fsopts[0]) {
128 eargv[i++] = "-o";
129 eargv[i++] = fsopts;
130 }
131 eargv[i++] = fsname;
132 eargv[i++] = dir;
133 eargv[i] = NULL;
134
135 execvp(eprog, (char * const *)eargv);
136 if (errno == ENOENT)
137 _exit(1);
138 weprintf("execvp:");
139 _exit(1);
140 break;
141 default:
142 if (waitpid(pid, &status, 0) < 0) {
143 weprintf("waitpid:");
144 return -1;
145 }
146 if (WIFEXITED(status))
147 return WEXITSTATUS(status);
148 else if (WIFSIGNALED(status))
149 return 1;
150 break;
151 }
152 return 0;
153 }
154
155 static int
156 mounted(const char *dir)
157 {
158 FILE *fp;
159 struct mntent *me, mebuf;
160 struct stat st1, st2;
161 char linebuf[256];
162
163 if (stat(dir, &st1) < 0) {
164 weprintf("stat %s:", dir);
165 return 0;
166 }
167 if (!(fp = setmntent("/proc/mounts", "r")))
168 eprintf("setmntent %s:", "/proc/mounts");
169
170 while ((me = getmntent_r(fp, &mebuf, linebuf, sizeof(linebuf))))…
171 if (stat(me->mnt_dir, &st2) < 0) {
172 weprintf("stat %s:", me->mnt_dir);
173 continue;
174 }
175 if (st1.st_dev == st2.st_dev &&
176 st1.st_ino == st2.st_ino)
177 return 1;
178 }
179 endmntent(fp);
180
181 return 0;
182 }
183
184 static void
185 usage(void)
186 {
187 eprintf("usage: %s [-BMRan] [-t fstype] [-o options] [source] [t…
188 argv0);
189 }
190
191 int
192 main(int argc, char *argv[])
193 {
194 char *types = NULL, data[FSOPTS_MAXLEN] = "", *resolvpath = NULL;
195 char *files[] = { "/proc/mounts", "/etc/fstab", NULL };
196 const char *source, *target;
197 struct mntent *me = NULL;
198 int aflag = 0, status = 0, i, r;
199 unsigned long flags = 0;
200 FILE *fp;
201
202 ARGBEGIN {
203 case 'B':
204 argflags |= MS_BIND;
205 break;
206 case 'M':
207 argflags |= MS_MOVE;
208 break;
209 case 'R':
210 argflags |= MS_REC;
211 break;
212 case 'a':
213 aflag = 1;
214 break;
215 case 'o':
216 estrlcat(fsopts, EARGF(usage()), sizeof(fsopts));
217 parseopts(fsopts, &flags, data, sizeof(data));
218 break;
219 case 't':
220 types = EARGF(usage());
221 break;
222 case 'n':
223 break;
224 default:
225 usage();
226 } ARGEND;
227
228 if (argc < 1 && aflag == 0) {
229 if (!(fp = fopen(files[0], "r")))
230 eprintf("fopen %s:", files[0]);
231 concat(fp, files[0], stdout, "<stdout>");
232 fclose(fp);
233 return 0;
234 }
235
236 if (aflag == 1)
237 goto mountall;
238
239 source = argv[0];
240 target = argv[1];
241
242 if (!target) {
243 target = argv[0];
244 source = NULL;
245 if (strcmp(target, "/") != 0) {
246 if (!(resolvpath = realpath(target, NULL)))
247 eprintf("realpath %s:", target);
248 target = resolvpath;
249 }
250 }
251
252 for (i = 0; files[i]; i++) {
253 if (!(fp = setmntent(files[i], "r"))) {
254 if (strcmp(files[i], "/proc/mounts") != 0)
255 weprintf("setmntent %s:", files[i]);
256 continue;
257 }
258 while ((me = getmntent(fp))) {
259 if (strcmp(me->mnt_dir, target) == 0 ||
260 strcmp(me->mnt_fsname, target) == 0 ||
261 (source && strcmp(me->mnt_dir, source) == 0) …
262 (source && strcmp(me->mnt_fsname, source) == …
263 if (!source) {
264 target = me->mnt_dir;
265 source = me->mnt_fsname;
266 }
267 if (!fsopts[0])
268 estrlcat(fsopts, me->mnt_opts, s…
269 parseopts(fsopts, &flags, data, …
270 if (!types)
271 types = me->mnt_type;
272 goto mountsingle;
273 }
274 }
275 endmntent(fp);
276 fp = NULL;
277 }
278 if (!source)
279 eprintf("can't find %s in /etc/fstab\n", target);
280
281 mountsingle:
282 r = mounthelper(source, target, types);
283 if (r == -1)
284 status = 1;
285 if (r > 0 && mount(source, target, types, argflags | flags, data…
286 weprintf("mount: %s:", source);
287 status = 1;
288 }
289 if (fp)
290 endmntent(fp);
291 free(resolvpath);
292 return status;
293
294 mountall:
295 if (!(fp = setmntent("/etc/fstab", "r")))
296 eprintf("setmntent %s:", "/etc/fstab");
297 while ((me = getmntent(fp))) {
298 /* has "noauto" option or already mounted: skip */
299 if (hasmntopt(me, MNTOPT_NOAUTO) || mounted(me->mnt_dir))
300 continue;
301 flags = 0;
302 fsopts[0] = '\0';
303 if (strlcat(fsopts, me->mnt_opts, sizeof(fsopts)) >= siz…
304 weprintf("%s: option string too long\n", me->mnt…
305 status = 1;
306 continue;
307 }
308 parseopts(fsopts, &flags, data, sizeof(data));
309 /* if -t types specified:
310 * if non-match, skip
311 * if match and prefixed with "no", skip */
312 if (types &&
313 ((types[0] == 'n' && types[1] == 'o' &&
314 findtype(types + 2, me->mnt_type)) ||
315 (!findtype(types, me->mnt_type))))
316 continue;
317
318 r = mounthelper(me->mnt_fsname, me->mnt_dir, me->mnt_typ…
319 if (r > 0 && mount(me->mnt_fsname, me->mnt_dir, me->mnt_…
320 argflags | flags, data) < 0) {
321 weprintf("mount: %s:", me->mnt_fsname);
322 status = 1;
323 }
324 }
325 endmntent(fp);
326
327 return status;
328 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.