xref: /minix3/minix/lib/libc/sys/mount.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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[] = "/sbin/:/usr/pkg/bin/"; /* 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