xref: /minix/minix/lib/libc/sys/mount.c (revision ebfedea0)
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 
20 static int rs_down(char *label)
21 {
22 	char cmd[200];
23 	if(strlen(_PATH_SERVICE)+strlen(label)+50 >= sizeof(cmd))
24 		return -1;
25 	sprintf(cmd, _PATH_SERVICE " down '%s'", label);
26 	return system(cmd);
27 }
28 
29 char *find_rslabel(char *args_line);
30 
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_SERVICE) + strlen(path) + strlen(label) +
129 	    strlen(args) + 50 >= sizeof(cmd)) {
130 		errno = E2BIG;
131 		return -1;
132 	}
133 
134 	sprintf(cmd, _PATH_SERVICE " %sup %s -label '%s' -args '%s %s %s%s'",
135 		reuse ? "-r ": "", path, label, special, name,
136 		args[0] ? "-o " : "", args);
137 
138 	if ((r = system(cmd)) != 0) {
139 		fprintf(stderr, "mount: couldn't run %s\n", cmd);
140 		errno = r;
141 		return -1;
142 	}
143   }
144 
145   /* Now perform mount(). */
146   memset(&m, 0, sizeof(m));
147   m.m_lc_vfs_mount.flags = mountflags;
148   m.m_lc_vfs_mount.devlen = special ? strlen(special) + 1 : 0;
149   m.m_lc_vfs_mount.pathlen = strlen(name) + 1;
150   m.m_lc_vfs_mount.typelen = strlen(type) + 1;
151   m.m_lc_vfs_mount.labellen = strlen(label) + 1;
152   m.m_lc_vfs_mount.dev = (vir_bytes)special;
153   m.m_lc_vfs_mount.path = (vir_bytes)name;
154   m.m_lc_vfs_mount.type = (vir_bytes)type;
155   m.m_lc_vfs_mount.label = (vir_bytes)label;
156   r = _syscall(VFS_PROC_NR, VFS_MOUNT, &m);
157 
158   if (r != OK && !use_existing) {
159 	/* If mount() failed, tell RS to shutdown FS process.
160 	 * No error check - won't do anything with this error anyway.
161 	 */
162 	rs_down(label);
163   }
164 
165   return r;
166 }
167 
168 int minix_umount(const char *name, int srvflags)
169 {
170   char label[MNT_LABEL_LEN];
171   message m;
172   int r;
173 
174   memset(&m, 0, sizeof(m));
175   m.m_lc_vfs_umount.name = (vir_bytes)name;
176   m.m_lc_vfs_umount.namelen = strlen(name) + 1;
177   m.m_lc_vfs_umount.label = (vir_bytes)label;
178   m.m_lc_vfs_umount.labellen = sizeof(label);
179   r = _syscall(VFS_PROC_NR, VFS_UMOUNT, &m);
180 
181   /* don't shut down the driver when exist flag is set */
182   if (!(srvflags & MS_EXISTING)) {
183 	  if (r == OK) {
184 		/* VFS returns the label of the unmounted file system to us. */
185 		rs_down(label);
186 	}
187   }
188 
189   return r;
190 }
191 
192 char *find_rslabel(char *args_line)
193 {
194   /**
195    * Find and return the rslabel as given as optional
196    * agument to the mount command e.g.
197    *  mount -o rslabel=bla
198    * or
199    *  mount -o rw,rslabel=bla
200    * or as found in fstab
201    **/
202   char *buf, *input,*saveptr;
203   buf = input = saveptr = NULL;
204 
205   if (args_line == NULL) return NULL;
206 
207   /* copy the input args_line we are going to modify it*/
208   input = strndup(args_line,20);
209   if (input == NULL) /* EOM */
210 	return NULL; /* it is not that bad to not find a label */
211 
212   /* locate rslabel= in the input */
213   buf = strstr(input,"rslabel=");
214   if (buf == NULL) {
215 	free(input);
216 	return NULL;
217   }
218 
219   /* tokenise on "," starting from rslabel (e.g null terminate )*/
220   buf = strtok_r(buf,",",&saveptr);
221   /* tokenise the result again using = and take the second entry */
222   buf = strtok_r(buf,"=",&saveptr);
223   buf = strtok_r(NULL,"=",&saveptr);
224   /* buf is now either NULL if there was no second token or
225    * the value we are searchig for
226    */
227   if (buf != NULL)
228 	buf = strdup(buf);
229   free(input);
230   return buf;
231 }
232 
233