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