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