xref: /minix3/minix/lib/libc/sys/mount.c (revision c58da9fbc35f86051ff0a75e6dd91e937d83cfff)
1433d6423SLionel Sambuc #include <sys/cdefs.h>
2433d6423SLionel Sambuc #include "namespace.h"
3433d6423SLionel Sambuc #include <lib.h>
4433d6423SLionel Sambuc 
5433d6423SLionel Sambuc #include <string.h>
6433d6423SLionel Sambuc #include <sys/mount.h>
7433d6423SLionel Sambuc #include <stdlib.h>
8433d6423SLionel Sambuc #include <stdio.h>
9433d6423SLionel Sambuc #include <sys/stat.h>
10433d6423SLionel Sambuc #include <minix/paths.h>
11433d6423SLionel Sambuc #include <minix/rs.h>
12433d6423SLionel Sambuc #include <minix/syslib.h>
13433d6423SLionel Sambuc #include <unistd.h>
14433d6423SLionel Sambuc #define OK	0
15433d6423SLionel Sambuc 
16433d6423SLionel Sambuc #define FSDEFAULT "mfs"
17433d6423SLionel Sambuc 
1850a1aef1SLionel Sambuc static char fspath[] = "/service/:/usr/pkg/service/"; /* Must include trailing '/' */
19433d6423SLionel Sambuc 
rs_down(char * label)20433d6423SLionel Sambuc static int rs_down(char *label)
21433d6423SLionel Sambuc {
22433d6423SLionel Sambuc 	char cmd[200];
23*c58da9fbSDavid van Moolenbroek 	if(strlen(_PATH_MINIX_SERVICE)+strlen(label)+50 >= sizeof(cmd))
24433d6423SLionel Sambuc 		return -1;
25*c58da9fbSDavid van Moolenbroek 	sprintf(cmd, _PATH_MINIX_SERVICE " down '%s'", label);
26433d6423SLionel Sambuc 	return system(cmd);
27433d6423SLionel Sambuc }
28433d6423SLionel Sambuc 
29433d6423SLionel Sambuc char *find_rslabel(char *args_line);
30433d6423SLionel Sambuc 
minix_mount(char * special,char * name,int mountflags,int srvflags,char * type,char * args)31433d6423SLionel Sambuc int minix_mount(char *special, char *name, int mountflags, int srvflags,
32433d6423SLionel Sambuc 	  char *type, char *args)
33433d6423SLionel Sambuc {
34433d6423SLionel Sambuc   int r;
35433d6423SLionel Sambuc   message m;
36433d6423SLionel Sambuc   struct stat statbuf;
37433d6423SLionel Sambuc   char label[MNT_LABEL_LEN];
38433d6423SLionel Sambuc   char path[PATH_MAX];
39433d6423SLionel Sambuc   char cmd[200];
40433d6423SLionel Sambuc   char *p;
41433d6423SLionel Sambuc   char *rslabel;
42433d6423SLionel Sambuc   int reuse = 0;
43433d6423SLionel Sambuc   int use_existing = 0;
44433d6423SLionel Sambuc 
45433d6423SLionel Sambuc   /* Default values. */
46433d6423SLionel Sambuc   if (type == NULL) type = __UNCONST(FSDEFAULT);
47433d6423SLionel Sambuc   if (args == NULL) args = __UNCONST("");
48433d6423SLionel Sambuc   reuse = 0;
49433d6423SLionel Sambuc   memset(path, '\0', sizeof(path));
50433d6423SLionel Sambuc 
51433d6423SLionel Sambuc   /* Check service flags. */
52433d6423SLionel Sambuc   if(srvflags & MS_REUSE)
53433d6423SLionel Sambuc 	reuse = 1;
54433d6423SLionel Sambuc 
55433d6423SLionel Sambuc   if(srvflags & MS_EXISTING)
56433d6423SLionel Sambuc 	use_existing = 1;
57433d6423SLionel Sambuc 
58433d6423SLionel Sambuc   /* Make a label for the file system process. This label must be unique and
59433d6423SLionel Sambuc    * may currently not exceed 16 characters including terminating null. For
60433d6423SLionel Sambuc    * requests with an associated block device, we use the last path component
61433d6423SLionel Sambuc    * name of the block special file (truncated to 12 characters, which is
62433d6423SLionel Sambuc    * hopefully enough). For requests with no associated block device, we use
63433d6423SLionel Sambuc    * the device number and inode of the mount point, in hexadecimal form.
64433d6423SLionel Sambuc    */
65433d6423SLionel Sambuc   if (!use_existing) {
66433d6423SLionel Sambuc 	if (special) {
67433d6423SLionel Sambuc 		p = strrchr(special, '/');
68433d6423SLionel Sambuc 		p = p ? p + 1 : special;
69433d6423SLionel Sambuc 		if (strchr(p, '\'')) {
70433d6423SLionel Sambuc 			errno = EINVAL;
71433d6423SLionel Sambuc 			return -1;
72433d6423SLionel Sambuc 		}
73433d6423SLionel Sambuc 		snprintf(label, MNT_LABEL_LEN, "fs_%.12s", p);
74433d6423SLionel Sambuc 	} else {
75433d6423SLionel Sambuc 		/* check for a rslabel option in the arguments and try to use
76433d6423SLionel Sambuc 		 * that.
77433d6423SLionel Sambuc 		 */
78433d6423SLionel Sambuc 		rslabel = find_rslabel(args);
79433d6423SLionel Sambuc 		if (rslabel != NULL){
80433d6423SLionel Sambuc 			snprintf(label, MNT_LABEL_LEN, "%s", rslabel);
81433d6423SLionel Sambuc 			free(rslabel);
82433d6423SLionel Sambuc 		} else {
83433d6423SLionel Sambuc 			if (stat(name, &statbuf) < 0) return -1;
84433d6423SLionel Sambuc 			snprintf(label, MNT_LABEL_LEN, "fs_%llx_%llx", statbuf.st_dev, statbuf.st_ino);
85433d6423SLionel Sambuc 		}
86433d6423SLionel Sambuc 	}
87433d6423SLionel Sambuc   } else {
88433d6423SLionel Sambuc 		/* label to long? */
89433d6423SLionel Sambuc 		if (strlen(type) < MNT_LABEL_LEN) {
90433d6423SLionel Sambuc 			snprintf(label, MNT_LABEL_LEN, "%s", type);
91433d6423SLionel Sambuc 		} else {
92433d6423SLionel Sambuc 			errno = ENOMEM;
93433d6423SLionel Sambuc 			return -1;
94433d6423SLionel Sambuc 		}
95433d6423SLionel Sambuc   }
96433d6423SLionel Sambuc 
97433d6423SLionel Sambuc   /* Sanity check on user input. */
98433d6423SLionel Sambuc   if(strchr(args, '\'')) {
99433d6423SLionel Sambuc   	errno = EINVAL;
100433d6423SLionel Sambuc 	return -1;
101433d6423SLionel Sambuc   }
102433d6423SLionel Sambuc   /* start the fs-server if not using existing one */
103433d6423SLionel Sambuc   if (!use_existing) {
104433d6423SLionel Sambuc 	/* See if the given type is even remotely valid. */
105433d6423SLionel Sambuc 
106433d6423SLionel Sambuc 	char *testpath;
107433d6423SLionel Sambuc 	testpath = strtok(fspath, ":");
108433d6423SLionel Sambuc 
109433d6423SLionel Sambuc 	do {
110433d6423SLionel Sambuc 		if (strlen(testpath) + strlen(type) >= sizeof(path)) {
111433d6423SLionel Sambuc 			errno = E2BIG;
112433d6423SLionel Sambuc 			return(-1);
113433d6423SLionel Sambuc 		}
114433d6423SLionel Sambuc 
115433d6423SLionel Sambuc 		strcpy(path, testpath);
116433d6423SLionel Sambuc 		strcat(path, type);
117433d6423SLionel Sambuc 
118433d6423SLionel Sambuc 		if (access(path, F_OK) == 0) break;
119433d6423SLionel Sambuc 
120433d6423SLionel Sambuc 	} while ((testpath = strtok(NULL, ":")) != NULL);
121433d6423SLionel Sambuc 
122433d6423SLionel Sambuc 	if (testpath == NULL) {
123433d6423SLionel Sambuc 		/* We were not able to find type somewhere in "fspath" */
124433d6423SLionel Sambuc 		errno = EINVAL;
125433d6423SLionel Sambuc 		return(-1);
126433d6423SLionel Sambuc 	}
127433d6423SLionel Sambuc 
128*c58da9fbSDavid van Moolenbroek 	if (strlen(_PATH_MINIX_SERVICE) + strlen(path) + strlen(label) +
129433d6423SLionel Sambuc 	    strlen(args) + 50 >= sizeof(cmd)) {
130433d6423SLionel Sambuc 		errno = E2BIG;
131433d6423SLionel Sambuc 		return -1;
132433d6423SLionel Sambuc 	}
133433d6423SLionel Sambuc 
134*c58da9fbSDavid van Moolenbroek 	sprintf(cmd, _PATH_MINIX_SERVICE
135*c58da9fbSDavid van Moolenbroek 		" %sup %s -label '%s' -args '%s %s %s%s'",
136433d6423SLionel Sambuc 		reuse ? "-r ": "", path, label, special, name,
137433d6423SLionel Sambuc 		args[0] ? "-o " : "", args);
138433d6423SLionel Sambuc 
139433d6423SLionel Sambuc 	if ((r = system(cmd)) != 0) {
140433d6423SLionel Sambuc 		fprintf(stderr, "mount: couldn't run %s\n", cmd);
141433d6423SLionel Sambuc 		errno = r;
142433d6423SLionel Sambuc 		return -1;
143433d6423SLionel Sambuc 	}
144433d6423SLionel Sambuc   }
145433d6423SLionel Sambuc 
146433d6423SLionel Sambuc   /* Now perform mount(). */
147433d6423SLionel Sambuc   memset(&m, 0, sizeof(m));
148433d6423SLionel Sambuc   m.m_lc_vfs_mount.flags = mountflags;
149433d6423SLionel Sambuc   m.m_lc_vfs_mount.devlen = special ? strlen(special) + 1 : 0;
150433d6423SLionel Sambuc   m.m_lc_vfs_mount.pathlen = strlen(name) + 1;
151433d6423SLionel Sambuc   m.m_lc_vfs_mount.typelen = strlen(type) + 1;
152433d6423SLionel Sambuc   m.m_lc_vfs_mount.labellen = strlen(label) + 1;
153433d6423SLionel Sambuc   m.m_lc_vfs_mount.dev = (vir_bytes)special;
154433d6423SLionel Sambuc   m.m_lc_vfs_mount.path = (vir_bytes)name;
155433d6423SLionel Sambuc   m.m_lc_vfs_mount.type = (vir_bytes)type;
156433d6423SLionel Sambuc   m.m_lc_vfs_mount.label = (vir_bytes)label;
157433d6423SLionel Sambuc   r = _syscall(VFS_PROC_NR, VFS_MOUNT, &m);
158433d6423SLionel Sambuc 
159433d6423SLionel Sambuc   if (r != OK && !use_existing) {
160433d6423SLionel Sambuc 	/* If mount() failed, tell RS to shutdown FS process.
161433d6423SLionel Sambuc 	 * No error check - won't do anything with this error anyway.
162433d6423SLionel Sambuc 	 */
163433d6423SLionel Sambuc 	rs_down(label);
164433d6423SLionel Sambuc   }
165433d6423SLionel Sambuc 
166433d6423SLionel Sambuc   return r;
167433d6423SLionel Sambuc }
168433d6423SLionel Sambuc 
minix_umount(const char * name,int srvflags)169433d6423SLionel Sambuc int minix_umount(const char *name, int srvflags)
170433d6423SLionel Sambuc {
171433d6423SLionel Sambuc   char label[MNT_LABEL_LEN];
172433d6423SLionel Sambuc   message m;
173433d6423SLionel Sambuc   int r;
174433d6423SLionel Sambuc 
175433d6423SLionel Sambuc   memset(&m, 0, sizeof(m));
176433d6423SLionel Sambuc   m.m_lc_vfs_umount.name = (vir_bytes)name;
177433d6423SLionel Sambuc   m.m_lc_vfs_umount.namelen = strlen(name) + 1;
178433d6423SLionel Sambuc   m.m_lc_vfs_umount.label = (vir_bytes)label;
179433d6423SLionel Sambuc   m.m_lc_vfs_umount.labellen = sizeof(label);
180433d6423SLionel Sambuc   r = _syscall(VFS_PROC_NR, VFS_UMOUNT, &m);
181433d6423SLionel Sambuc 
182433d6423SLionel Sambuc   /* don't shut down the driver when exist flag is set */
183433d6423SLionel Sambuc   if (!(srvflags & MS_EXISTING)) {
184433d6423SLionel Sambuc 	  if (r == OK) {
185433d6423SLionel Sambuc 		/* VFS returns the label of the unmounted file system to us. */
186433d6423SLionel Sambuc 		rs_down(label);
187433d6423SLionel Sambuc 	}
188433d6423SLionel Sambuc   }
189433d6423SLionel Sambuc 
190433d6423SLionel Sambuc   return r;
191433d6423SLionel Sambuc }
192433d6423SLionel Sambuc 
find_rslabel(char * args_line)193433d6423SLionel Sambuc char *find_rslabel(char *args_line)
194433d6423SLionel Sambuc {
195433d6423SLionel Sambuc   /**
196433d6423SLionel Sambuc    * Find and return the rslabel as given as optional
197433d6423SLionel Sambuc    * agument to the mount command e.g.
198433d6423SLionel Sambuc    *  mount -o rslabel=bla
199433d6423SLionel Sambuc    * or
200433d6423SLionel Sambuc    *  mount -o rw,rslabel=bla
201433d6423SLionel Sambuc    * or as found in fstab
202433d6423SLionel Sambuc    **/
203433d6423SLionel Sambuc   char *buf, *input,*saveptr;
204433d6423SLionel Sambuc   buf = input = saveptr = NULL;
205433d6423SLionel Sambuc 
206433d6423SLionel Sambuc   if (args_line == NULL) return NULL;
207433d6423SLionel Sambuc 
208433d6423SLionel Sambuc   /* copy the input args_line we are going to modify it*/
209433d6423SLionel Sambuc   input = strndup(args_line,20);
210433d6423SLionel Sambuc   if (input == NULL) /* EOM */
211433d6423SLionel Sambuc 	return NULL; /* it is not that bad to not find a label */
212433d6423SLionel Sambuc 
213433d6423SLionel Sambuc   /* locate rslabel= in the input */
214433d6423SLionel Sambuc   buf = strstr(input,"rslabel=");
215433d6423SLionel Sambuc   if (buf == NULL) {
216433d6423SLionel Sambuc 	free(input);
217433d6423SLionel Sambuc 	return NULL;
218433d6423SLionel Sambuc   }
219433d6423SLionel Sambuc 
220433d6423SLionel Sambuc   /* tokenise on "," starting from rslabel (e.g null terminate )*/
221433d6423SLionel Sambuc   buf = strtok_r(buf,",",&saveptr);
222433d6423SLionel Sambuc   /* tokenise the result again using = and take the second entry */
223433d6423SLionel Sambuc   buf = strtok_r(buf,"=",&saveptr);
224433d6423SLionel Sambuc   buf = strtok_r(NULL,"=",&saveptr);
225433d6423SLionel Sambuc   /* buf is now either NULL if there was no second token or
226433d6423SLionel Sambuc    * the value we are searchig for
227433d6423SLionel Sambuc    */
228433d6423SLionel Sambuc   if (buf != NULL)
229433d6423SLionel Sambuc 	buf = strdup(buf);
230433d6423SLionel Sambuc   free(input);
231433d6423SLionel Sambuc   return buf;
232433d6423SLionel Sambuc }
233433d6423SLionel Sambuc 
234