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_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 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 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 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