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 18*50a1aef1SLionel Sambuc static char fspath[] = "/service/:/usr/pkg/service/"; /* Must include trailing '/' */ 19433d6423SLionel Sambuc 20433d6423SLionel Sambuc static int rs_down(char *label) 21433d6423SLionel Sambuc { 22433d6423SLionel Sambuc char cmd[200]; 23433d6423SLionel Sambuc if(strlen(_PATH_SERVICE)+strlen(label)+50 >= sizeof(cmd)) 24433d6423SLionel Sambuc return -1; 25433d6423SLionel Sambuc sprintf(cmd, _PATH_SERVICE " down '%s'", label); 26433d6423SLionel Sambuc return system(cmd); 27433d6423SLionel Sambuc } 28433d6423SLionel Sambuc 29433d6423SLionel Sambuc char *find_rslabel(char *args_line); 30433d6423SLionel Sambuc 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 128433d6423SLionel Sambuc if (strlen(_PATH_SERVICE) + strlen(path) + strlen(label) + 129433d6423SLionel Sambuc strlen(args) + 50 >= sizeof(cmd)) { 130433d6423SLionel Sambuc errno = E2BIG; 131433d6423SLionel Sambuc return -1; 132433d6423SLionel Sambuc } 133433d6423SLionel Sambuc 134433d6423SLionel Sambuc sprintf(cmd, _PATH_SERVICE " %sup %s -label '%s' -args '%s %s %s%s'", 135433d6423SLionel Sambuc reuse ? "-r ": "", path, label, special, name, 136433d6423SLionel Sambuc args[0] ? "-o " : "", args); 137433d6423SLionel Sambuc 138433d6423SLionel Sambuc if ((r = system(cmd)) != 0) { 139433d6423SLionel Sambuc fprintf(stderr, "mount: couldn't run %s\n", cmd); 140433d6423SLionel Sambuc errno = r; 141433d6423SLionel Sambuc return -1; 142433d6423SLionel Sambuc } 143433d6423SLionel Sambuc } 144433d6423SLionel Sambuc 145433d6423SLionel Sambuc /* Now perform mount(). */ 146433d6423SLionel Sambuc memset(&m, 0, sizeof(m)); 147433d6423SLionel Sambuc m.m_lc_vfs_mount.flags = mountflags; 148433d6423SLionel Sambuc m.m_lc_vfs_mount.devlen = special ? strlen(special) + 1 : 0; 149433d6423SLionel Sambuc m.m_lc_vfs_mount.pathlen = strlen(name) + 1; 150433d6423SLionel Sambuc m.m_lc_vfs_mount.typelen = strlen(type) + 1; 151433d6423SLionel Sambuc m.m_lc_vfs_mount.labellen = strlen(label) + 1; 152433d6423SLionel Sambuc m.m_lc_vfs_mount.dev = (vir_bytes)special; 153433d6423SLionel Sambuc m.m_lc_vfs_mount.path = (vir_bytes)name; 154433d6423SLionel Sambuc m.m_lc_vfs_mount.type = (vir_bytes)type; 155433d6423SLionel Sambuc m.m_lc_vfs_mount.label = (vir_bytes)label; 156433d6423SLionel Sambuc r = _syscall(VFS_PROC_NR, VFS_MOUNT, &m); 157433d6423SLionel Sambuc 158433d6423SLionel Sambuc if (r != OK && !use_existing) { 159433d6423SLionel Sambuc /* If mount() failed, tell RS to shutdown FS process. 160433d6423SLionel Sambuc * No error check - won't do anything with this error anyway. 161433d6423SLionel Sambuc */ 162433d6423SLionel Sambuc rs_down(label); 163433d6423SLionel Sambuc } 164433d6423SLionel Sambuc 165433d6423SLionel Sambuc return r; 166433d6423SLionel Sambuc } 167433d6423SLionel Sambuc 168433d6423SLionel Sambuc int minix_umount(const char *name, int srvflags) 169433d6423SLionel Sambuc { 170433d6423SLionel Sambuc char label[MNT_LABEL_LEN]; 171433d6423SLionel Sambuc message m; 172433d6423SLionel Sambuc int r; 173433d6423SLionel Sambuc 174433d6423SLionel Sambuc memset(&m, 0, sizeof(m)); 175433d6423SLionel Sambuc m.m_lc_vfs_umount.name = (vir_bytes)name; 176433d6423SLionel Sambuc m.m_lc_vfs_umount.namelen = strlen(name) + 1; 177433d6423SLionel Sambuc m.m_lc_vfs_umount.label = (vir_bytes)label; 178433d6423SLionel Sambuc m.m_lc_vfs_umount.labellen = sizeof(label); 179433d6423SLionel Sambuc r = _syscall(VFS_PROC_NR, VFS_UMOUNT, &m); 180433d6423SLionel Sambuc 181433d6423SLionel Sambuc /* don't shut down the driver when exist flag is set */ 182433d6423SLionel Sambuc if (!(srvflags & MS_EXISTING)) { 183433d6423SLionel Sambuc if (r == OK) { 184433d6423SLionel Sambuc /* VFS returns the label of the unmounted file system to us. */ 185433d6423SLionel Sambuc rs_down(label); 186433d6423SLionel Sambuc } 187433d6423SLionel Sambuc } 188433d6423SLionel Sambuc 189433d6423SLionel Sambuc return r; 190433d6423SLionel Sambuc } 191433d6423SLionel Sambuc 192433d6423SLionel Sambuc char *find_rslabel(char *args_line) 193433d6423SLionel Sambuc { 194433d6423SLionel Sambuc /** 195433d6423SLionel Sambuc * Find and return the rslabel as given as optional 196433d6423SLionel Sambuc * agument to the mount command e.g. 197433d6423SLionel Sambuc * mount -o rslabel=bla 198433d6423SLionel Sambuc * or 199433d6423SLionel Sambuc * mount -o rw,rslabel=bla 200433d6423SLionel Sambuc * or as found in fstab 201433d6423SLionel Sambuc **/ 202433d6423SLionel Sambuc char *buf, *input,*saveptr; 203433d6423SLionel Sambuc buf = input = saveptr = NULL; 204433d6423SLionel Sambuc 205433d6423SLionel Sambuc if (args_line == NULL) return NULL; 206433d6423SLionel Sambuc 207433d6423SLionel Sambuc /* copy the input args_line we are going to modify it*/ 208433d6423SLionel Sambuc input = strndup(args_line,20); 209433d6423SLionel Sambuc if (input == NULL) /* EOM */ 210433d6423SLionel Sambuc return NULL; /* it is not that bad to not find a label */ 211433d6423SLionel Sambuc 212433d6423SLionel Sambuc /* locate rslabel= in the input */ 213433d6423SLionel Sambuc buf = strstr(input,"rslabel="); 214433d6423SLionel Sambuc if (buf == NULL) { 215433d6423SLionel Sambuc free(input); 216433d6423SLionel Sambuc return NULL; 217433d6423SLionel Sambuc } 218433d6423SLionel Sambuc 219433d6423SLionel Sambuc /* tokenise on "," starting from rslabel (e.g null terminate )*/ 220433d6423SLionel Sambuc buf = strtok_r(buf,",",&saveptr); 221433d6423SLionel Sambuc /* tokenise the result again using = and take the second entry */ 222433d6423SLionel Sambuc buf = strtok_r(buf,"=",&saveptr); 223433d6423SLionel Sambuc buf = strtok_r(NULL,"=",&saveptr); 224433d6423SLionel Sambuc /* buf is now either NULL if there was no second token or 225433d6423SLionel Sambuc * the value we are searchig for 226433d6423SLionel Sambuc */ 227433d6423SLionel Sambuc if (buf != NULL) 228433d6423SLionel Sambuc buf = strdup(buf); 229433d6423SLionel Sambuc free(input); 230433d6423SLionel Sambuc return buf; 231433d6423SLionel Sambuc } 232433d6423SLionel Sambuc 233