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