1 #include <sys/cdefs.h>
2 #include "namespace.h"
3 #include <lib.h>
4
5 #include <string.h>
6 #include <sys/mount.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <sys/stat.h>
10 #include <minix/paths.h>
11 #include <minix/rs.h>
12 #include <minix/syslib.h>
13 #include <unistd.h>
14 #define OK 0
15
16 #define FSDEFAULT "mfs"
17
18 static char fspath[] = "/service/:/usr/pkg/service/"; /* Must include trailing '/' */
19
rs_down(char * label)20 static int rs_down(char *label)
21 {
22 char cmd[200];
23 if(strlen(_PATH_MINIX_SERVICE)+strlen(label)+50 >= sizeof(cmd))
24 return -1;
25 sprintf(cmd, _PATH_MINIX_SERVICE " down '%s'", label);
26 return system(cmd);
27 }
28
29 char *find_rslabel(char *args_line);
30
minix_mount(char * special,char * name,int mountflags,int srvflags,char * type,char * args)31 int minix_mount(char *special, char *name, int mountflags, int srvflags,
32 char *type, char *args)
33 {
34 int r;
35 message m;
36 struct stat statbuf;
37 char label[MNT_LABEL_LEN];
38 char path[PATH_MAX];
39 char cmd[200];
40 char *p;
41 char *rslabel;
42 int reuse = 0;
43 int use_existing = 0;
44
45 /* Default values. */
46 if (type == NULL) type = __UNCONST(FSDEFAULT);
47 if (args == NULL) args = __UNCONST("");
48 reuse = 0;
49 memset(path, '\0', sizeof(path));
50
51 /* Check service flags. */
52 if(srvflags & MS_REUSE)
53 reuse = 1;
54
55 if(srvflags & MS_EXISTING)
56 use_existing = 1;
57
58 /* Make a label for the file system process. This label must be unique and
59 * may currently not exceed 16 characters including terminating null. For
60 * requests with an associated block device, we use the last path component
61 * name of the block special file (truncated to 12 characters, which is
62 * hopefully enough). For requests with no associated block device, we use
63 * the device number and inode of the mount point, in hexadecimal form.
64 */
65 if (!use_existing) {
66 if (special) {
67 p = strrchr(special, '/');
68 p = p ? p + 1 : special;
69 if (strchr(p, '\'')) {
70 errno = EINVAL;
71 return -1;
72 }
73 snprintf(label, MNT_LABEL_LEN, "fs_%.12s", p);
74 } else {
75 /* check for a rslabel option in the arguments and try to use
76 * that.
77 */
78 rslabel = find_rslabel(args);
79 if (rslabel != NULL){
80 snprintf(label, MNT_LABEL_LEN, "%s", rslabel);
81 free(rslabel);
82 } else {
83 if (stat(name, &statbuf) < 0) return -1;
84 snprintf(label, MNT_LABEL_LEN, "fs_%llx_%llx", statbuf.st_dev, statbuf.st_ino);
85 }
86 }
87 } else {
88 /* label to long? */
89 if (strlen(type) < MNT_LABEL_LEN) {
90 snprintf(label, MNT_LABEL_LEN, "%s", type);
91 } else {
92 errno = ENOMEM;
93 return -1;
94 }
95 }
96
97 /* Sanity check on user input. */
98 if(strchr(args, '\'')) {
99 errno = EINVAL;
100 return -1;
101 }
102 /* start the fs-server if not using existing one */
103 if (!use_existing) {
104 /* See if the given type is even remotely valid. */
105
106 char *testpath;
107 testpath = strtok(fspath, ":");
108
109 do {
110 if (strlen(testpath) + strlen(type) >= sizeof(path)) {
111 errno = E2BIG;
112 return(-1);
113 }
114
115 strcpy(path, testpath);
116 strcat(path, type);
117
118 if (access(path, F_OK) == 0) break;
119
120 } while ((testpath = strtok(NULL, ":")) != NULL);
121
122 if (testpath == NULL) {
123 /* We were not able to find type somewhere in "fspath" */
124 errno = EINVAL;
125 return(-1);
126 }
127
128 if (strlen(_PATH_MINIX_SERVICE) + strlen(path) + strlen(label) +
129 strlen(args) + 50 >= sizeof(cmd)) {
130 errno = E2BIG;
131 return -1;
132 }
133
134 sprintf(cmd, _PATH_MINIX_SERVICE
135 " %sup %s -label '%s' -args '%s %s %s%s'",
136 reuse ? "-r ": "", path, label, special, name,
137 args[0] ? "-o " : "", args);
138
139 if ((r = system(cmd)) != 0) {
140 fprintf(stderr, "mount: couldn't run %s\n", cmd);
141 errno = r;
142 return -1;
143 }
144 }
145
146 /* Now perform mount(). */
147 memset(&m, 0, sizeof(m));
148 m.m_lc_vfs_mount.flags = mountflags;
149 m.m_lc_vfs_mount.devlen = special ? strlen(special) + 1 : 0;
150 m.m_lc_vfs_mount.pathlen = strlen(name) + 1;
151 m.m_lc_vfs_mount.typelen = strlen(type) + 1;
152 m.m_lc_vfs_mount.labellen = strlen(label) + 1;
153 m.m_lc_vfs_mount.dev = (vir_bytes)special;
154 m.m_lc_vfs_mount.path = (vir_bytes)name;
155 m.m_lc_vfs_mount.type = (vir_bytes)type;
156 m.m_lc_vfs_mount.label = (vir_bytes)label;
157 r = _syscall(VFS_PROC_NR, VFS_MOUNT, &m);
158
159 if (r != OK && !use_existing) {
160 /* If mount() failed, tell RS to shutdown FS process.
161 * No error check - won't do anything with this error anyway.
162 */
163 rs_down(label);
164 }
165
166 return r;
167 }
168
minix_umount(const char * name,int srvflags)169 int minix_umount(const char *name, int srvflags)
170 {
171 char label[MNT_LABEL_LEN];
172 message m;
173 int r;
174
175 memset(&m, 0, sizeof(m));
176 m.m_lc_vfs_umount.name = (vir_bytes)name;
177 m.m_lc_vfs_umount.namelen = strlen(name) + 1;
178 m.m_lc_vfs_umount.label = (vir_bytes)label;
179 m.m_lc_vfs_umount.labellen = sizeof(label);
180 r = _syscall(VFS_PROC_NR, VFS_UMOUNT, &m);
181
182 /* don't shut down the driver when exist flag is set */
183 if (!(srvflags & MS_EXISTING)) {
184 if (r == OK) {
185 /* VFS returns the label of the unmounted file system to us. */
186 rs_down(label);
187 }
188 }
189
190 return r;
191 }
192
find_rslabel(char * args_line)193 char *find_rslabel(char *args_line)
194 {
195 /**
196 * Find and return the rslabel as given as optional
197 * agument to the mount command e.g.
198 * mount -o rslabel=bla
199 * or
200 * mount -o rw,rslabel=bla
201 * or as found in fstab
202 **/
203 char *buf, *input,*saveptr;
204 buf = input = saveptr = NULL;
205
206 if (args_line == NULL) return NULL;
207
208 /* copy the input args_line we are going to modify it*/
209 input = strndup(args_line,20);
210 if (input == NULL) /* EOM */
211 return NULL; /* it is not that bad to not find a label */
212
213 /* locate rslabel= in the input */
214 buf = strstr(input,"rslabel=");
215 if (buf == NULL) {
216 free(input);
217 return NULL;
218 }
219
220 /* tokenise on "," starting from rslabel (e.g null terminate )*/
221 buf = strtok_r(buf,",",&saveptr);
222 /* tokenise the result again using = and take the second entry */
223 buf = strtok_r(buf,"=",&saveptr);
224 buf = strtok_r(NULL,"=",&saveptr);
225 /* buf is now either NULL if there was no second token or
226 * the value we are searchig for
227 */
228 if (buf != NULL)
229 buf = strdup(buf);
230 free(input);
231 return buf;
232 }
233
234