vm: fix failed alloc condition
[minix.git] / commands / mount / mount.c
blob1671e4f31536d22348a9528e9f39809d6c04dbed
1 /* mount - mount a file system Author: Andy Tanenbaum */
3 #include <errno.h>
4 #include <sys/types.h>
5 #include <limits.h>
6 #include <stdlib.h>
7 #include <dirent.h>
8 #include <string.h>
9 #include <sys/mount.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <minix/config.h>
13 #include <minix/const.h>
14 #include <minix/minlib.h>
15 #include <sys/svrctl.h>
16 #include <stdio.h>
17 #include "mfs/const.h"
18 #include <fstab.h>
20 #define MINIX_FS_TYPE "mfs"
22 int main(int argc, char **argv);
23 void list(void);
24 void usage(void);
25 void update_mtab(char *dev, char *mountpoint, char *fstype, int mountflags);
26 int mount_all(void);
28 static int write_mtab = 1;
30 int main(argc, argv)
31 int argc;
32 char *argv[];
34 int all = 0, i, v = 0, mountflags;
35 char **ap, *opt, *err, *type, *args, *device;
37 if (argc == 1) list(); /* just list /etc/mtab */
38 mountflags = 0;
39 type = NULL;
40 args = NULL;
41 ap = argv+1;
42 for (i = 1; i < argc; i++) {
43 if (argv[i][0] == '-') {
44 opt = argv[i]+1;
45 while (*opt != 0) switch (*opt++) {
46 case 'r': mountflags |= MS_RDONLY; break;
47 case 't': if (++i == argc) usage();
48 type = argv[i];
49 break;
50 case 'i': mountflags |= MS_REUSE; break;
51 case 'e': mountflags |= MS_EXISTING; break;
52 case 'n': write_mtab = 0; break;
53 case 'o': if (++i == argc) usage();
54 args = argv[i];
55 break;
56 case 'a': all = 1; break;
57 default: usage();
59 } else {
60 *ap++ = argv[i];
63 *ap = NULL;
64 argc = (ap - argv);
66 if (!all && (argc != 3 || *argv[1] == 0)) usage();
67 if (all == 1) {
68 return mount_all();
71 device = argv[1];
72 if (!strcmp(device, "none")) device = NULL;
74 if ((type == NULL || !strcmp(type, MINIX_FS_TYPE)) && device != NULL) {
75 /* auto-detect type and/or version */
76 v = fsversion(device, "mount");
77 switch (v) {
78 case FSVERSION_MFS1:
79 case FSVERSION_MFS2:
80 case FSVERSION_MFS3: type = MINIX_FS_TYPE; break;
81 case FSVERSION_EXT2: type = "ext2"; break;
85 if (mount(device, argv[2], mountflags, type, args) < 0) {
86 err = strerror(errno);
87 fprintf(stderr, "mount: Can't mount %s on %s: %s\n",
88 argv[1], argv[2], err);
89 return(EXIT_FAILURE);
92 /* The mount has completed successfully. Tell the user. */
93 printf("%s is read-%s mounted on %s\n",
94 argv[1], mountflags & MS_RDONLY ? "only" : "write", argv[2]);
96 /* Update /etc/mtab. */
97 update_mtab(argv[1], argv[2], type, mountflags);
98 return(EXIT_SUCCESS);
101 void
102 update_mtab(char *dev, char *mountpoint, char *fstype, int mountflags)
104 int n;
105 char *vs;
106 char special[PATH_MAX], mounted_on[PATH_MAX], version[10], rw_flag[10];
108 if (!write_mtab) return;
109 n = load_mtab("mount");
110 if (n < 0) exit(1); /* something is wrong. */
112 /* Loop on all the /etc/mtab entries, copying each one to the output
113 * buf. */
114 while (1) {
115 n = get_mtab_entry(special, mounted_on, version, rw_flag);
116 if (n < 0) break;
117 n = put_mtab_entry(special, mounted_on, version, rw_flag);
118 if (n < 0) {
119 std_err("mount: /etc/mtab has grown too large\n");
120 exit(1);
123 /* For MFS, use a version number. Otherwise, use the FS type name. */
124 if (!strcmp(fstype, MINIX_FS_TYPE)) {
125 vs = "MFSv3";
126 } else if (strlen(fstype) < sizeof(version)) {
127 vs = fstype;
128 } else {
129 vs = "-";
131 n = put_mtab_entry(dev, mountpoint, vs,
132 (mountflags & MS_RDONLY ? "ro" : "rw") );
133 if (n < 0) {
134 std_err("mount: /etc/mtab has grown too large\n");
135 exit(1);
138 n = rewrite_mtab("mount");
141 void list()
143 int n;
144 char special[PATH_MAX], mounted_on[PATH_MAX], version[10], rw_flag[10];
146 /* Read and print /etc/mtab. */
147 n = load_mtab("mount");
148 if (n < 0) exit(1);
150 while (1) {
151 n = get_mtab_entry(special, mounted_on, version, rw_flag);
152 if (n < 0) break;
153 printf("%s is read-%s mounted on %s (type %s)\n",
154 special, strcmp(rw_flag, "rw") == 0 ? "write" : "only",
155 mounted_on, version);
157 exit(0);
161 has_opt(char *mntopts, char *option)
163 char *optbuf, *opt;
164 int found = 0;
166 optbuf = strdup(mntopts);
167 for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
168 if (!strcmp(opt, option)) found = 1;
170 free (optbuf);
171 return(found);
176 mount_all()
178 struct fstab *fs;
179 int ro, mountflags;
180 char mountpoint[PATH_MAX];
181 char *device, *err;
183 while ((fs = getfsent()) != NULL) {
184 ro = 0;
185 mountflags = 0;
186 device = NULL;
187 if (realpath(fs->fs_file, mountpoint) == NULL) {
188 fprintf(stderr, "Can't mount on %s\n", fs->fs_file);
189 return(EXIT_FAILURE);
191 if (has_opt(fs->fs_mntops, "noauto"))
192 continue;
193 if (!strcmp(mountpoint, "/"))
194 continue; /* Not remounting root */
195 if (has_opt(fs->fs_mntops, "ro"))
196 ro = 1;
197 if (ro) {
198 mountflags |= MS_RDONLY;
201 device = fs->fs_spec;
202 /* passing a null string for block special device means don't
203 * use a device at all and this is what we need to do for
204 * entries starting with "none"
206 if (!strcmp(device, "none"))
207 device = NULL;
209 if (mount(device, mountpoint, mountflags, fs->fs_vfstype,
210 fs->fs_mntops) == 0) {
211 update_mtab(fs->fs_spec, fs->fs_file, fs->fs_vfstype,
212 mountflags);
213 } else {
214 err = strerror(errno);
215 fprintf(stderr, "mount: Can't mount %s on %s: %s\n",
216 fs->fs_spec, fs->fs_file, err);
217 return(EXIT_FAILURE);
220 return(EXIT_SUCCESS);
223 void usage()
225 std_err("Usage: mount [-a] [-r] [-e] [-t type] [-o options] special name\n");
226 exit(1);