121156Sdist /* 221156Sdist * Copyright (c) 1980 Regents of the University of California. 321156Sdist * All rights reserved. The Berkeley software License Agreement 421156Sdist * specifies the terms and conditions for redistribution. 521156Sdist */ 621156Sdist 710811Ssam #ifndef lint 821156Sdist char copyright[] = 921156Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1021156Sdist All rights reserved.\n"; 1121156Sdist #endif not lint 121057Sbill 1321156Sdist #ifndef lint 14*38632Smckusick static char sccsid[] = "@(#)mount.c 5.10 (Berkeley) 08/16/89"; 1521156Sdist #endif not lint 1621156Sdist 1712808Ssam #include <sys/param.h> 1835339Sbostic #include <sys/file.h> 1938445Smckusick #include <sys/time.h> 2010811Ssam #include <fstab.h> 2116669Ssam #include <errno.h> 2235339Sbostic #include <stdio.h> 2338445Smckusick #include <strings.h> 2438445Smckusick #include <sys/dir.h> 2538445Smckusick #include <sys/uio.h> 2638445Smckusick #include <sys/namei.h> 2738445Smckusick #include <sys/mount.h> 2838445Smckusick #ifdef NFS 2938445Smckusick #include <sys/socket.h> 3038445Smckusick #include <sys/socketvar.h> 3138445Smckusick #include <netdb.h> 3238445Smckusick #include <rpc/rpc.h> 3338445Smckusick #include <rpc/pmap_clnt.h> 3438445Smckusick #include <rpc/pmap_prot.h> 3538445Smckusick #include <nfs/rpcv2.h> 3638445Smckusick #include <nfs/nfsv2.h> 3738445Smckusick #include <nfs/nfs.h> 3838445Smckusick #endif 391057Sbill 4035339Sbostic #define BADTYPE(type) \ 4135339Sbostic (strcmp(type, FSTAB_RO) && strcmp(type, FSTAB_RW) && \ 4235339Sbostic strcmp(type, FSTAB_RQ)) 4335339Sbostic #define SETTYPE(type) \ 4435339Sbostic (!strcmp(type, FSTAB_RW) || !strcmp(type, FSTAB_RQ)) 451057Sbill 4638445Smckusick static int fake, verbose, mnttype; 4738445Smckusick #ifdef NFS 4838445Smckusick int xdr_dir(), xdr_fh(); 49*38632Smckusick char *getnfsargs(); 5038445Smckusick struct nfs_args nfsargs = { 5138445Smckusick (struct sockaddr_in *)0, 5238445Smckusick (nfsv2fh_t *)0, 5338445Smckusick 0, 5438445Smckusick NFS_WSIZE, 5538445Smckusick NFS_RSIZE, 5638445Smckusick NFS_TIMEO, 5738445Smckusick NFS_RETRANS, 5838445Smckusick (char *)0, 5938445Smckusick }; 605073Sroot 6138445Smckusick struct nfhret { 6238445Smckusick u_long stat; 6338445Smckusick nfsv2fh_t nfh; 6438445Smckusick }; 6538445Smckusick int retrycnt = 10000; 6638445Smckusick #define BGRND 1 6738445Smckusick #define ISBGRND 2 6838445Smckusick int opflags = 0; 6938445Smckusick #endif 7038445Smckusick 711057Sbill main(argc, argv) 725073Sroot int argc; 735073Sroot char **argv; 741057Sbill { 7535339Sbostic extern char *optarg; 7635339Sbostic extern int optind; 7735339Sbostic register struct fstab *fs; 7835339Sbostic register int cnt; 79*38632Smckusick int all, ch, rval, sfake, i; 80*38632Smckusick long mntsize; 81*38632Smckusick struct statfs statfsbuf, *mntbuf; 8235339Sbostic char *type; 831057Sbill 8435339Sbostic all = 0; 8535339Sbostic type = NULL; 8638445Smckusick mnttype = MOUNT_UFS; 8738445Smckusick while ((ch = getopt(argc, argv, "afrwvt:o:")) != EOF) 8835339Sbostic switch((char)ch) { 8935339Sbostic case 'a': 9035339Sbostic all = 1; 9135339Sbostic break; 9235339Sbostic case 'f': 9335339Sbostic fake = 1; 9435339Sbostic break; 9535339Sbostic case 'r': 9612808Ssam type = FSTAB_RO; 9735339Sbostic break; 9835339Sbostic case 'v': 9935339Sbostic verbose = 1; 10035339Sbostic break; 10135339Sbostic case 'w': 10235339Sbostic type = FSTAB_RW; 10335339Sbostic break; 10438445Smckusick #ifdef NFS 10538445Smckusick case 't': 10638445Smckusick if (!strcmp(optarg, "nfs")) 10738445Smckusick mnttype = MOUNT_NFS; 10838445Smckusick break; 10938445Smckusick case 'o': 110*38632Smckusick getoptions(optarg, &nfsargs, &opflags, &retrycnt); 11138445Smckusick break; 11238445Smckusick #endif 11335339Sbostic case '?': 11435339Sbostic default: 11535339Sbostic usage(); 1165073Sroot } 11735339Sbostic argc -= optind; 11835339Sbostic argv += optind; 11935339Sbostic 12035339Sbostic /* NOSTRICT */ 12135339Sbostic 1224460Sroot if (all) { 12335369Sbostic rval = 0; 12435372Sbostic for (sfake = fake; fs = getfsent(); fake = sfake) { 12535372Sbostic if (BADTYPE(fs->fs_type)) 12635372Sbostic continue; 12735372Sbostic /* `/' is special, it's always mounted */ 12835372Sbostic if (!strcmp(fs->fs_file, "/")) 12935372Sbostic fake = 1; 13038445Smckusick #ifdef NFS 13138445Smckusick if (index(fs->fs_spec, '@') != NULL) { 13238445Smckusick if (fs->fs_vfstype != NULL && 13338445Smckusick strcmp(fs->fs_vfstype, "nfs")) 13438445Smckusick continue; 13538445Smckusick if (fs->fs_mntops != NULL) 13638445Smckusick getoptions(fs->fs_mntops, &nfsargs, 13738445Smckusick &opflags, &retrycnt); 13838445Smckusick mnttype = MOUNT_NFS; 13938445Smckusick } else 14038445Smckusick mnttype = MOUNT_UFS; 14138445Smckusick #endif 14235372Sbostic rval |= mountfs(fs->fs_spec, fs->fs_file, 14335372Sbostic type ? type : fs->fs_type); 14435372Sbostic } 14535341Sbostic exit(rval); 14635339Sbostic } 1475073Sroot 14835339Sbostic if (argc == 0) { 14935339Sbostic if (verbose || fake || type) 15035339Sbostic usage(); 151*38632Smckusick if ((mntsize = getfsstat(0, 0)) < 0) { 152*38632Smckusick perror("mount"); 153*38632Smckusick exit(1); 154*38632Smckusick } 155*38632Smckusick mntbuf = 0; 156*38632Smckusick do { 157*38632Smckusick if (mntbuf) 158*38632Smckusick free(mntbuf); 159*38632Smckusick i = (mntsize + 1) * sizeof(struct statfs); 160*38632Smckusick if ((mntbuf = (struct statfs *)malloc(i)) == 0) { 161*38632Smckusick fprintf(stderr, 162*38632Smckusick "no space for mount table buffer\n"); 163*38632Smckusick exit(1); 164*38632Smckusick } 165*38632Smckusick if ((mntsize = getfsstat(mntbuf, i)) < 0) { 166*38632Smckusick perror("df"); 167*38632Smckusick exit(1); 168*38632Smckusick } 169*38632Smckusick } while (i == mntsize * sizeof(struct statfs)); 170*38632Smckusick for (i = 0; i < mntsize; i++) { 171*38632Smckusick if (mntbuf[i].f_flags & M_RDONLY) 172*38632Smckusick type = "ro"; 173*38632Smckusick else 174*38632Smckusick type = "rw"; 175*38632Smckusick prmount(mntbuf[i].f_mntfromname, mntbuf[i].f_mntonname, 176*38632Smckusick type); 177*38632Smckusick } 1784460Sroot exit(0); 1791057Sbill } 18012808Ssam 18135339Sbostic if (all) 18235339Sbostic usage(); 18335339Sbostic 18435339Sbostic if (argc == 1) { 18535339Sbostic if (!(fs = getfsfile(*argv)) && !(fs = getfsspec(*argv))) { 18635339Sbostic fprintf(stderr, 18735339Sbostic "mount: unknown special file or file system %s.\n", 18835339Sbostic *argv); 18935339Sbostic exit(1); 19035339Sbostic } 19135339Sbostic if (BADTYPE(fs->fs_type)) { 19235339Sbostic fprintf(stderr, 19335339Sbostic "mount: %s has unknown file system type.\n", *argv); 19435339Sbostic exit(1); 19535339Sbostic } 19635369Sbostic exit(mountfs(fs->fs_spec, fs->fs_file, 19735369Sbostic type ? type : fs->fs_type)); 19812808Ssam } 1991057Sbill 20035339Sbostic if (argc != 2) 20135339Sbostic usage(); 20212808Ssam 20335369Sbostic exit(mountfs(argv[0], argv[1], type ? type : "rw")); 20412808Ssam } 20512808Ssam 20635339Sbostic static 20712808Ssam mountfs(spec, name, type) 20812808Ssam char *spec, *name, *type; 20912808Ssam { 21035339Sbostic extern int errno; 21135339Sbostic register int cnt; 212*38632Smckusick int flags; 21338070Smckusick struct ufs_args args; 21438445Smckusick char *argp; 2151057Sbill 21612808Ssam if (!fake) { 21738070Smckusick flags = 0; 21838070Smckusick if (!strcmp(type, FSTAB_RO)) 21938070Smckusick flags |= M_RDONLY; 22038445Smckusick switch (mnttype) { 22138445Smckusick case MOUNT_UFS: 22238445Smckusick args.fspec = spec; 22338445Smckusick argp = (caddr_t)&args; 22438445Smckusick break; 225*38632Smckusick 226*38632Smckusick #ifdef NFS 22738445Smckusick case MOUNT_NFS: 228*38632Smckusick if (argp = getnfsargs(spec, name, type)) 229*38632Smckusick break; 230*38632Smckusick return (1); 231*38632Smckusick #endif /* NFS */ 232*38632Smckusick 233*38632Smckusick default: 234*38632Smckusick if (opflags & ISBGRND) 235*38632Smckusick exit(1); 236*38632Smckusick fprintf(stderr, "%d: unknown mount type\n", mnttype); 237*38632Smckusick exit(1); 238*38632Smckusick /* NOTREACHED */ 239*38632Smckusick 24038445Smckusick }; 24138445Smckusick if (mount(mnttype, name, flags, argp)) { 24238445Smckusick if (opflags & ISBGRND) 24338445Smckusick exit(1); 24435339Sbostic fprintf(stderr, "%s on %s: ", spec, name); 24516669Ssam switch (errno) { 24616669Ssam case EMFILE: 24735339Sbostic fprintf(stderr, "Mount table full\n"); 24816669Ssam break; 24916669Ssam case EINVAL: 25035339Sbostic fprintf(stderr, "Bogus super block\n"); 25116669Ssam break; 25216669Ssam default: 25335339Sbostic perror((char *)NULL); 25435339Sbostic break; 25516669Ssam } 25635369Sbostic return(1); 2574460Sroot } 25835339Sbostic 2594460Sroot } 26035339Sbostic 26112808Ssam if (verbose) 262*38632Smckusick prmount(spec, name, type); 26335339Sbostic 26438445Smckusick if (opflags & ISBGRND) 26538445Smckusick exit(); 26638445Smckusick else 26738445Smckusick return(0); 2681057Sbill } 26935339Sbostic 27035339Sbostic static 271*38632Smckusick prmount(spec, name, type) 272*38632Smckusick char *spec, *name, *type; 27335339Sbostic { 274*38632Smckusick register char *root; 275*38632Smckusick 27638445Smckusick if (opflags & ISBGRND) 27738445Smckusick return; 278*38632Smckusick /* 279*38632Smckusick * trim trailing /'s and find last component of name 280*38632Smckusick */ 281*38632Smckusick for (root = index(spec, '\0'); *--root == '/';) 282*38632Smckusick /* void */; 283*38632Smckusick *++root = '\0'; 284*38632Smckusick if (root = rindex(spec, '/')) 285*38632Smckusick spec = root + 1; 286*38632Smckusick printf("%s on %s", spec, name); 287*38632Smckusick if (!strcmp(type, FSTAB_RO)) 28835339Sbostic printf("\t(read-only)"); 289*38632Smckusick else if (!strcmp(type, FSTAB_RQ)) 29035339Sbostic printf("\t(with quotas)"); 29135339Sbostic printf("\n"); 29235339Sbostic } 29335339Sbostic 29435339Sbostic static 295*38632Smckusick usage() 29635339Sbostic { 297*38632Smckusick fprintf(stderr, "usage: mount [-afrw]\nor mount [-frw] special | node\nor mount [-frw] special node\n"); 29835339Sbostic exit(1); 29935339Sbostic } 30035339Sbostic 301*38632Smckusick #ifdef NFS 302*38632Smckusick char * 303*38632Smckusick getnfsargs(spec) 304*38632Smckusick char *spec; 30535339Sbostic { 306*38632Smckusick register CLIENT *clp; 307*38632Smckusick struct hostent *hp; 308*38632Smckusick struct sockaddr_in saddr; 309*38632Smckusick struct timeval pertry, try; 310*38632Smckusick enum clnt_stat clnt_stat; 311*38632Smckusick int so = RPC_ANYSOCK; 312*38632Smckusick char *hostp, *delimp; 313*38632Smckusick u_short tport; 314*38632Smckusick struct nfhret nfhret; 315*38632Smckusick char nam[MNAMELEN + 1]; 316*38632Smckusick 317*38632Smckusick strncpy(nam, spec, MNAMELEN); 318*38632Smckusick nam[MNAMELEN] = '\0'; 319*38632Smckusick if ((delimp = index(spec, '@')) != NULL) { 320*38632Smckusick hostp = delimp + 1; 321*38632Smckusick } else if ((delimp = index(spec, ':')) != NULL) { 322*38632Smckusick hostp = spec; 323*38632Smckusick spec = delimp + 1; 324*38632Smckusick } else { 325*38632Smckusick fprintf(stderr, 326*38632Smckusick "No <host>:<dirpath> or <dirpath>@<host> spec\n"); 327*38632Smckusick return (0); 328*38632Smckusick } 329*38632Smckusick *delimp = '\0'; 330*38632Smckusick if ((hp = gethostbyname(hostp)) == NULL) { 331*38632Smckusick fprintf(stderr, "Can't get net id for host\n"); 332*38632Smckusick return (0); 333*38632Smckusick } 334*38632Smckusick bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length); 335*38632Smckusick nfhret.stat = EACCES; /* Mark not yet successful */ 336*38632Smckusick while (retrycnt > 0) { 337*38632Smckusick saddr.sin_family = AF_INET; 338*38632Smckusick saddr.sin_port = htons(PMAPPORT); 339*38632Smckusick if ((tport = pmap_getport(&saddr, RPCPROG_NFS, 340*38632Smckusick NFS_VER2, IPPROTO_UDP)) == 0) { 341*38632Smckusick if ((opflags & ISBGRND) == 0) 342*38632Smckusick clnt_pcreateerror("NFS Portmap"); 343*38632Smckusick } else { 344*38632Smckusick saddr.sin_port = 0; 345*38632Smckusick pertry.tv_sec = 10; 346*38632Smckusick pertry.tv_usec = 0; 347*38632Smckusick if ((clp = clntudp_create(&saddr, RPCPROG_MNT, 348*38632Smckusick RPCMNT_VER1, pertry, &so)) == NULL) { 349*38632Smckusick if ((opflags & ISBGRND) == 0) 350*38632Smckusick clnt_pcreateerror("Cannot MNT PRC"); 351*38632Smckusick } else { 352*38632Smckusick clp->cl_auth = authunix_create_default(); 353*38632Smckusick try.tv_sec = 10; 354*38632Smckusick try.tv_usec = 0; 355*38632Smckusick clnt_stat = clnt_call(clp, RPCMNT_MOUNT, 356*38632Smckusick xdr_dir, spec, xdr_fh, &nfhret, try); 357*38632Smckusick if (clnt_stat != RPC_SUCCESS) { 358*38632Smckusick if ((opflags & ISBGRND) == 0) 359*38632Smckusick clnt_perror(clp, "Bad MNT RPC"); 360*38632Smckusick } else { 361*38632Smckusick auth_destroy(clp->cl_auth); 362*38632Smckusick clnt_destroy(clp); 363*38632Smckusick retrycnt = 0; 364*38632Smckusick } 365*38632Smckusick } 366*38632Smckusick } 367*38632Smckusick if (--retrycnt > 0) { 368*38632Smckusick if (opflags & BGRND) { 369*38632Smckusick opflags &= ~BGRND; 370*38632Smckusick if (fork()) 371*38632Smckusick return (0); 372*38632Smckusick else 373*38632Smckusick opflags |= ISBGRND; 374*38632Smckusick } 375*38632Smckusick sleep(10); 376*38632Smckusick } 377*38632Smckusick } 378*38632Smckusick if (nfhret.stat) { 379*38632Smckusick if (opflags & ISBGRND) 380*38632Smckusick exit(1); 381*38632Smckusick fprintf(stderr, "Can't access %s, errno=%d\n", spec, 382*38632Smckusick nfhret.stat); 383*38632Smckusick return (0); 384*38632Smckusick } 385*38632Smckusick saddr.sin_port = htons(tport); 386*38632Smckusick nfsargs.addr = &saddr; 387*38632Smckusick nfsargs.fh = &nfhret.nfh; 388*38632Smckusick nfsargs.hostname = nam; 389*38632Smckusick return ((caddr_t)&nfsargs); 39035339Sbostic } 39138445Smckusick 39238445Smckusick /* 39338445Smckusick * xdr routines for mount rpc's 39438445Smckusick */ 39538445Smckusick xdr_dir(xdrsp, dirp) 39638445Smckusick XDR *xdrsp; 39738445Smckusick char *dirp; 39838445Smckusick { 39938445Smckusick return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 40038445Smckusick } 40138445Smckusick 40238445Smckusick xdr_fh(xdrsp, np) 40338445Smckusick XDR *xdrsp; 40438445Smckusick struct nfhret *np; 40538445Smckusick { 40638445Smckusick if (!xdr_u_long(xdrsp, &(np->stat))) 40738445Smckusick return (0); 40838445Smckusick if (np->stat) 40938445Smckusick return (1); 41038445Smckusick return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH)); 41138445Smckusick } 41238445Smckusick 41338445Smckusick /* 41438445Smckusick * Handle the getoption arg. 41538445Smckusick * Essentially update "opflags", "retrycnt" and "nfsargs" 41638445Smckusick */ 41738445Smckusick getoptions(optarg, nfsargsp, opflagsp, retrycntp) 41838445Smckusick char *optarg; 41938445Smckusick struct nfs_args *nfsargsp; 42038445Smckusick int *opflagsp; 42138445Smckusick int *retrycntp; 42238445Smckusick { 42338445Smckusick register char *cp, *nextcp; 42438445Smckusick int num; 42538445Smckusick char *nump; 42638445Smckusick 42738445Smckusick cp = optarg; 42838445Smckusick while (cp != NULL && *cp != '\0') { 42938445Smckusick if ((nextcp = index(cp, ',')) != NULL) 43038445Smckusick *nextcp++ = '\0'; 43138445Smckusick if ((nump = index(cp, '=')) != NULL) { 43238445Smckusick *nump++ = '\0'; 43338445Smckusick num = atoi(nump); 43438445Smckusick } else 43538445Smckusick num = -1; 43638445Smckusick /* 43738445Smckusick * Just test for a string match and do it 43838445Smckusick */ 43938445Smckusick if (!strcmp(cp, "bg")) { 44038445Smckusick *opflagsp |= BGRND; 44138445Smckusick } else if (!strcmp(cp, "soft")) { 44238445Smckusick nfsargsp->flags |= NFSMNT_SOFT; 44338445Smckusick } else if (!strcmp(cp, "intr")) { 44438445Smckusick nfsargsp->flags |= NFSMNT_INT; 44538445Smckusick } else if (!strcmp(cp, "retry") && num > 0) { 44638445Smckusick *retrycntp = num; 44738445Smckusick } else if (!strcmp(cp, "rsize") && num > 0) { 44838445Smckusick nfsargsp->rsize = num; 44938445Smckusick nfsargsp->flags |= NFSMNT_RSIZE; 45038445Smckusick } else if (!strcmp(cp, "wsize") && num > 0) { 45138445Smckusick nfsargsp->wsize = num; 45238445Smckusick nfsargsp->flags |= NFSMNT_WSIZE; 45338445Smckusick } else if (!strcmp(cp, "timeo") && num > 0) { 45438445Smckusick nfsargsp->timeo = num; 45538445Smckusick nfsargsp->flags |= NFSMNT_TIMEO; 45638445Smckusick } else if (!strcmp(cp, "retrans") && num > 0) { 45738445Smckusick nfsargsp->retrans = num; 45838445Smckusick nfsargsp->flags |= NFSMNT_RETRANS; 45938445Smckusick } 46038445Smckusick cp = nextcp; 46138445Smckusick } 46238445Smckusick } 463*38632Smckusick #endif /* NFS */ 464