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*38445Smckusick static char sccsid[] = "@(#)mount.c 5.9 (Berkeley) 07/11/89"; 1521156Sdist #endif not lint 1621156Sdist 1712808Ssam #include <sys/param.h> 1835339Sbostic #include <sys/file.h> 19*38445Smckusick #include <sys/time.h> 2010811Ssam #include <fstab.h> 2112808Ssam #include <mtab.h> 2216669Ssam #include <errno.h> 2335339Sbostic #include <stdio.h> 24*38445Smckusick #include <strings.h> 25*38445Smckusick #include <sys/dir.h> 26*38445Smckusick #include <sys/uio.h> 27*38445Smckusick #include <sys/namei.h> 28*38445Smckusick #include <sys/mount.h> 29*38445Smckusick #ifdef NFS 30*38445Smckusick #include <sys/socket.h> 31*38445Smckusick #include <sys/socketvar.h> 32*38445Smckusick #include <netdb.h> 33*38445Smckusick #include <rpc/rpc.h> 34*38445Smckusick #include <rpc/pmap_clnt.h> 35*38445Smckusick #include <rpc/pmap_prot.h> 36*38445Smckusick #include <nfs/rpcv2.h> 37*38445Smckusick #include <nfs/nfsv2.h> 38*38445Smckusick #include <nfs/nfs.h> 39*38445Smckusick #endif 401057Sbill 4135339Sbostic #define BADTYPE(type) \ 4235339Sbostic (strcmp(type, FSTAB_RO) && strcmp(type, FSTAB_RW) && \ 4335339Sbostic strcmp(type, FSTAB_RQ)) 4435339Sbostic #define SETTYPE(type) \ 4535339Sbostic (!strcmp(type, FSTAB_RW) || !strcmp(type, FSTAB_RQ)) 461057Sbill 4735339Sbostic #define MTAB "/etc/mtab" 481057Sbill 4935339Sbostic static struct mtab mtab[NMOUNT]; 50*38445Smckusick static int fake, verbose, mnttype; 51*38445Smckusick #ifdef NFS 52*38445Smckusick int xdr_dir(), xdr_fh(); 53*38445Smckusick struct nfs_args nfsargs = { 54*38445Smckusick (struct sockaddr_in *)0, 55*38445Smckusick (nfsv2fh_t *)0, 56*38445Smckusick 0, 57*38445Smckusick NFS_WSIZE, 58*38445Smckusick NFS_RSIZE, 59*38445Smckusick NFS_TIMEO, 60*38445Smckusick NFS_RETRANS, 61*38445Smckusick (char *)0, 62*38445Smckusick }; 635073Sroot 64*38445Smckusick struct nfhret { 65*38445Smckusick u_long stat; 66*38445Smckusick nfsv2fh_t nfh; 67*38445Smckusick }; 68*38445Smckusick int retrycnt = 10000; 69*38445Smckusick #define BGRND 1 70*38445Smckusick #define ISBGRND 2 71*38445Smckusick int opflags = 0; 72*38445Smckusick #endif 73*38445Smckusick 741057Sbill main(argc, argv) 755073Sroot int argc; 765073Sroot char **argv; 771057Sbill { 7835339Sbostic extern char *optarg; 7935339Sbostic extern int optind; 801057Sbill register struct mtab *mp; 8135339Sbostic register struct fstab *fs; 8235339Sbostic register int cnt; 8335372Sbostic int all, ch, fd, rval, sfake; 8435339Sbostic char *type; 851057Sbill 8635339Sbostic all = 0; 8735339Sbostic type = NULL; 88*38445Smckusick mnttype = MOUNT_UFS; 89*38445Smckusick while ((ch = getopt(argc, argv, "afrwvt:o:")) != EOF) 9035339Sbostic switch((char)ch) { 9135339Sbostic case 'a': 9235339Sbostic all = 1; 9335339Sbostic break; 9435339Sbostic case 'f': 9535339Sbostic fake = 1; 9635339Sbostic break; 9735339Sbostic case 'r': 9812808Ssam type = FSTAB_RO; 9935339Sbostic break; 10035339Sbostic case 'v': 10135339Sbostic verbose = 1; 10235339Sbostic break; 10335339Sbostic case 'w': 10435339Sbostic type = FSTAB_RW; 10535339Sbostic break; 106*38445Smckusick #ifdef NFS 107*38445Smckusick case 't': 108*38445Smckusick if (!strcmp(optarg, "nfs")) 109*38445Smckusick mnttype = MOUNT_NFS; 110*38445Smckusick break; 111*38445Smckusick case 'o': 112*38445Smckusick getoptions(optarg,&nfsargs,&opflags,&retrycnt); 113*38445Smckusick break; 114*38445Smckusick #endif 11535339Sbostic case '?': 11635339Sbostic default: 11735339Sbostic usage(); 1185073Sroot } 11935339Sbostic argc -= optind; 12035339Sbostic argv += optind; 12135339Sbostic 12235339Sbostic /* NOSTRICT */ 12335339Sbostic if ((fd = open(MTAB, O_RDONLY, 0)) >= 0) { 12435339Sbostic if (read(fd, (char *)mtab, NMOUNT * sizeof(struct mtab)) < 0) 12535339Sbostic mtaberr(); 12635339Sbostic (void)close(fd); 1271057Sbill } 12835339Sbostic 1294460Sroot if (all) { 13035369Sbostic rval = 0; 13135372Sbostic for (sfake = fake; fs = getfsent(); fake = sfake) { 13235372Sbostic if (BADTYPE(fs->fs_type)) 13335372Sbostic continue; 13435372Sbostic /* `/' is special, it's always mounted */ 13535372Sbostic if (!strcmp(fs->fs_file, "/")) 13635372Sbostic fake = 1; 137*38445Smckusick #ifdef NFS 138*38445Smckusick if (index(fs->fs_spec, '@') != NULL) { 139*38445Smckusick if (fs->fs_vfstype != NULL && 140*38445Smckusick strcmp(fs->fs_vfstype, "nfs")) 141*38445Smckusick continue; 142*38445Smckusick if (fs->fs_mntops != NULL) 143*38445Smckusick getoptions(fs->fs_mntops, &nfsargs, 144*38445Smckusick &opflags, &retrycnt); 145*38445Smckusick mnttype = MOUNT_NFS; 146*38445Smckusick } else 147*38445Smckusick mnttype = MOUNT_UFS; 148*38445Smckusick #endif 14935372Sbostic rval |= mountfs(fs->fs_spec, fs->fs_file, 15035372Sbostic type ? type : fs->fs_type); 15135372Sbostic } 15235341Sbostic exit(rval); 15335339Sbostic } 1545073Sroot 15535339Sbostic if (argc == 0) { 15635339Sbostic if (verbose || fake || type) 15735339Sbostic usage(); 15835339Sbostic for (mp = mtab, cnt = NMOUNT; cnt--; ++mp) 15935339Sbostic if (*mp->m_path) 16035339Sbostic prmtab(mp); 1614460Sroot exit(0); 1621057Sbill } 16312808Ssam 16435339Sbostic if (all) 16535339Sbostic usage(); 16635339Sbostic 16735339Sbostic if (argc == 1) { 16835339Sbostic if (!(fs = getfsfile(*argv)) && !(fs = getfsspec(*argv))) { 16935339Sbostic fprintf(stderr, 17035339Sbostic "mount: unknown special file or file system %s.\n", 17135339Sbostic *argv); 17235339Sbostic exit(1); 17335339Sbostic } 17435339Sbostic if (BADTYPE(fs->fs_type)) { 17535339Sbostic fprintf(stderr, 17635339Sbostic "mount: %s has unknown file system type.\n", *argv); 17735339Sbostic exit(1); 17835339Sbostic } 17935369Sbostic exit(mountfs(fs->fs_spec, fs->fs_file, 18035369Sbostic type ? type : fs->fs_type)); 18112808Ssam } 1821057Sbill 18335339Sbostic if (argc != 2) 18435339Sbostic usage(); 18512808Ssam 18635369Sbostic exit(mountfs(argv[0], argv[1], type ? type : "rw")); 18712808Ssam } 18812808Ssam 18935339Sbostic static 19012808Ssam mountfs(spec, name, type) 19112808Ssam char *spec, *name, *type; 19212808Ssam { 19335339Sbostic extern int errno; 19435339Sbostic register struct mtab *mp, *space; 19535339Sbostic register int cnt; 19635339Sbostic register char *p; 197*38445Smckusick #ifdef NFS 198*38445Smckusick register CLIENT *clp; 199*38445Smckusick struct hostent *hp; 200*38445Smckusick struct sockaddr_in saddr; 201*38445Smckusick struct timeval pertry, try; 202*38445Smckusick enum clnt_stat clnt_stat; 203*38445Smckusick int so = RPC_ANYSOCK; 204*38445Smckusick char *hostp, *delimp; 205*38445Smckusick u_short tport; 206*38445Smckusick struct nfhret nfhret; 207*38445Smckusick char nam[MNAMELEN+1]; 208*38445Smckusick #endif 20938070Smckusick int fd, flags; 21038070Smckusick struct ufs_args args; 211*38445Smckusick char *argp; 2121057Sbill 21312808Ssam if (!fake) { 21438070Smckusick flags = 0; 21538070Smckusick if (!strcmp(type, FSTAB_RO)) 21638070Smckusick flags |= M_RDONLY; 217*38445Smckusick #ifdef NFS 218*38445Smckusick switch (mnttype) { 219*38445Smckusick case MOUNT_UFS: 220*38445Smckusick args.fspec = spec; 221*38445Smckusick argp = (caddr_t)&args; 222*38445Smckusick break; 223*38445Smckusick case MOUNT_NFS: 224*38445Smckusick strncpy(nam, spec, MNAMELEN); 225*38445Smckusick nam[MNAMELEN] = '\0'; 226*38445Smckusick if ((delimp = index(spec, '@')) != NULL) { 227*38445Smckusick hostp = delimp+1; 228*38445Smckusick } else if ((delimp = index(spec, ':')) != NULL) { 229*38445Smckusick hostp = spec; 230*38445Smckusick spec = delimp+1; 231*38445Smckusick } else { 232*38445Smckusick fprintf(stderr, "No <host>:<dirpath> or <dirpath>@<host> spec\n"); 233*38445Smckusick return (1); 234*38445Smckusick } 235*38445Smckusick *delimp = '\0'; 236*38445Smckusick if ((hp = gethostbyname(hostp)) == NULL) { 237*38445Smckusick fprintf(stderr,"Can't get net id for host\n"); 238*38445Smckusick return (1); 239*38445Smckusick } 240*38445Smckusick bcopy(hp->h_addr,(caddr_t)&saddr.sin_addr,hp->h_length); 241*38445Smckusick nfhret.stat = EACCES; /* Mark not yet successful */ 242*38445Smckusick while (retrycnt > 0) { 243*38445Smckusick saddr.sin_family = AF_INET; 244*38445Smckusick saddr.sin_port = htons(PMAPPORT); 245*38445Smckusick if ((tport = pmap_getport(&saddr, RPCPROG_NFS, 246*38445Smckusick NFS_VER2, IPPROTO_UDP)) == 0) { 247*38445Smckusick if ((opflags & ISBGRND) == 0) 248*38445Smckusick clnt_pcreateerror("NFS Portmap"); 249*38445Smckusick } else { 250*38445Smckusick saddr.sin_port = 0; 251*38445Smckusick pertry.tv_sec = 10; 252*38445Smckusick pertry.tv_usec = 0; 253*38445Smckusick if ((clp = clntudp_create(&saddr, RPCPROG_MNT, 254*38445Smckusick RPCMNT_VER1, pertry, &so)) == NULL) { 255*38445Smckusick if ((opflags & ISBGRND) == 0) 256*38445Smckusick clnt_pcreateerror("Cannot MNT PRC"); 257*38445Smckusick } else { 258*38445Smckusick clp->cl_auth = authunix_create_default(); 259*38445Smckusick try.tv_sec = 10; 260*38445Smckusick try.tv_usec = 0; 261*38445Smckusick clnt_stat = clnt_call(clp, RPCMNT_MOUNT, xdr_dir, spec, 262*38445Smckusick xdr_fh, &nfhret, try); 263*38445Smckusick if (clnt_stat != RPC_SUCCESS) { 264*38445Smckusick if ((opflags & ISBGRND) == 0) 265*38445Smckusick clnt_perror(clp, "Bad MNT RPC"); 266*38445Smckusick } else { 267*38445Smckusick auth_destroy(clp->cl_auth); 268*38445Smckusick clnt_destroy(clp); 269*38445Smckusick retrycnt = 0; 270*38445Smckusick } 271*38445Smckusick } 272*38445Smckusick } 273*38445Smckusick if (--retrycnt > 0) { 274*38445Smckusick if (opflags & BGRND) { 275*38445Smckusick opflags &= ~BGRND; 276*38445Smckusick if (fork()) 277*38445Smckusick return (0); 278*38445Smckusick else 279*38445Smckusick opflags |= ISBGRND; 280*38445Smckusick } 281*38445Smckusick sleep(10); 282*38445Smckusick } 283*38445Smckusick } 284*38445Smckusick if (nfhret.stat) { 285*38445Smckusick if (opflags & ISBGRND) 286*38445Smckusick exit(1); 287*38445Smckusick fprintf(stderr, "Can't access %s, errno=%d\n", 288*38445Smckusick spec, nfhret.stat); 289*38445Smckusick return (1); 290*38445Smckusick } 291*38445Smckusick saddr.sin_port = htons(tport); 292*38445Smckusick nfsargs.addr = &saddr; 293*38445Smckusick nfsargs.fh = &nfhret.nfh; 294*38445Smckusick nfsargs.hostname = nam; 295*38445Smckusick argp = (caddr_t)&nfsargs; 296*38445Smckusick break; 297*38445Smckusick }; 298*38445Smckusick #endif 299*38445Smckusick if (mount(mnttype, name, flags, argp)) { 300*38445Smckusick if (opflags & ISBGRND) 301*38445Smckusick exit(1); 30235339Sbostic fprintf(stderr, "%s on %s: ", spec, name); 30316669Ssam switch (errno) { 30416669Ssam case EMFILE: 30535339Sbostic fprintf(stderr, "Mount table full\n"); 30616669Ssam break; 30716669Ssam case EINVAL: 30835339Sbostic fprintf(stderr, "Bogus super block\n"); 30916669Ssam break; 31016669Ssam default: 31135339Sbostic perror((char *)NULL); 31235339Sbostic break; 31316669Ssam } 31435369Sbostic return(1); 3154460Sroot } 31635339Sbostic 31712808Ssam /* we don't do quotas.... */ 31812808Ssam if (strcmp(type, FSTAB_RQ) == 0) 31912808Ssam type = FSTAB_RW; 3204460Sroot } 32135339Sbostic 32235339Sbostic /* trim trailing /'s and find last component of name */ 32335339Sbostic for (p = index(spec, '\0'); *--p == '/';); 32435339Sbostic *++p = '\0'; 32535339Sbostic if (p = rindex(spec, '/')) { 32635339Sbostic *p = '\0'; 32735339Sbostic spec = p + 1; 32812808Ssam } 32935339Sbostic 33035339Sbostic for (mp = mtab, cnt = NMOUNT, space = NULL; cnt--; ++mp) { 33135339Sbostic if (!strcmp(mp->m_dname, spec)) 33235339Sbostic break; 33335339Sbostic if (!space && !*mp->m_path) 33435339Sbostic space = mp; 33535339Sbostic } 33635339Sbostic if (cnt == -1) { 33735339Sbostic if (!space) { 338*38445Smckusick if ((opflags & ISBGRND) == 0) 339*38445Smckusick fprintf(stderr, "mount: no more room in %s.\n", MTAB); 34035339Sbostic exit(1); 34135339Sbostic } 34235339Sbostic mp = space; 34335339Sbostic } 34435339Sbostic 34535339Sbostic #define DNMAX (sizeof(mtab[0].m_dname) - 1) 34635339Sbostic #define PNMAX (sizeof(mtab[0].m_path) - 1) 34735339Sbostic 34835339Sbostic (void)strncpy(mp->m_dname, spec, DNMAX); 34912808Ssam mp->m_dname[DNMAX] = '\0'; 35035339Sbostic (void)strncpy(mp->m_path, name, PNMAX); 35112808Ssam mp->m_path[PNMAX] = '\0'; 35235339Sbostic (void)strcpy(mp->m_type, type); 35335339Sbostic 35412808Ssam if (verbose) 35512808Ssam prmtab(mp); 35635339Sbostic 35735339Sbostic for (mp = mtab + NMOUNT - 1; mp > mtab && !*mp->m_path; --mp); 35835339Sbostic if ((fd = open(MTAB, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) 35935339Sbostic mtaberr(); 36035339Sbostic cnt = (mp - mtab + 1) * sizeof(struct mtab); 36135339Sbostic /* NOSTRICT */ 36235339Sbostic if (write(fd, (char *)mtab, cnt) != cnt) 36335339Sbostic mtaberr(); 36435339Sbostic (void)close(fd); 365*38445Smckusick if (opflags & ISBGRND) 366*38445Smckusick exit(); 367*38445Smckusick else 368*38445Smckusick return(0); 3691057Sbill } 37035339Sbostic 37135339Sbostic static 37235339Sbostic prmtab(mp) 37335339Sbostic register struct mtab *mp; 37435339Sbostic { 375*38445Smckusick if (opflags & ISBGRND) 376*38445Smckusick return; 37735339Sbostic printf("%s on %s", mp->m_dname, mp->m_path); 37835339Sbostic if (!strcmp(mp->m_type, FSTAB_RO)) 37935339Sbostic printf("\t(read-only)"); 38035339Sbostic else if (!strcmp(mp->m_type, FSTAB_RQ)) 38135339Sbostic printf("\t(with quotas)"); 38235339Sbostic printf("\n"); 38335339Sbostic } 38435339Sbostic 38535339Sbostic static 38635339Sbostic mtaberr() 38735339Sbostic { 388*38445Smckusick if (opflags & ISBGRND) 389*38445Smckusick exit(1); 39035339Sbostic fprintf(stderr, "mount: %s: ", MTAB); 39135339Sbostic perror((char *)NULL); 39235339Sbostic exit(1); 39335339Sbostic } 39435339Sbostic 39535339Sbostic static 39635339Sbostic usage() 39735339Sbostic { 39835369Sbostic fprintf(stderr, "usage: mount [-afrw]\nor mount [-frw] special | node\nor mount [-frw] special node\n"); 39935339Sbostic exit(1); 40035339Sbostic } 401*38445Smckusick 402*38445Smckusick #ifdef NFS 403*38445Smckusick /* 404*38445Smckusick * xdr routines for mount rpc's 405*38445Smckusick */ 406*38445Smckusick xdr_dir(xdrsp, dirp) 407*38445Smckusick XDR *xdrsp; 408*38445Smckusick char *dirp; 409*38445Smckusick { 410*38445Smckusick return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 411*38445Smckusick } 412*38445Smckusick 413*38445Smckusick xdr_fh(xdrsp, np) 414*38445Smckusick XDR *xdrsp; 415*38445Smckusick struct nfhret *np; 416*38445Smckusick { 417*38445Smckusick if (!xdr_u_long(xdrsp, &(np->stat))) 418*38445Smckusick return (0); 419*38445Smckusick if (np->stat) 420*38445Smckusick return (1); 421*38445Smckusick return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH)); 422*38445Smckusick } 423*38445Smckusick 424*38445Smckusick /* 425*38445Smckusick * Handle the getoption arg. 426*38445Smckusick * Essentially update "opflags", "retrycnt" and "nfsargs" 427*38445Smckusick */ 428*38445Smckusick getoptions(optarg, nfsargsp, opflagsp, retrycntp) 429*38445Smckusick char *optarg; 430*38445Smckusick struct nfs_args *nfsargsp; 431*38445Smckusick int *opflagsp; 432*38445Smckusick int *retrycntp; 433*38445Smckusick { 434*38445Smckusick register char *cp, *nextcp; 435*38445Smckusick int num; 436*38445Smckusick char *nump; 437*38445Smckusick 438*38445Smckusick cp = optarg; 439*38445Smckusick while (cp != NULL && *cp != '\0') { 440*38445Smckusick if ((nextcp = index(cp, ',')) != NULL) 441*38445Smckusick *nextcp++ = '\0'; 442*38445Smckusick if ((nump = index(cp, '=')) != NULL) { 443*38445Smckusick *nump++ = '\0'; 444*38445Smckusick num = atoi(nump); 445*38445Smckusick } else 446*38445Smckusick num = -1; 447*38445Smckusick /* 448*38445Smckusick * Just test for a string match and do it 449*38445Smckusick */ 450*38445Smckusick if (!strcmp(cp, "bg")) { 451*38445Smckusick *opflagsp |= BGRND; 452*38445Smckusick } else if (!strcmp(cp, "soft")) { 453*38445Smckusick nfsargsp->flags |= NFSMNT_SOFT; 454*38445Smckusick } else if (!strcmp(cp, "intr")) { 455*38445Smckusick nfsargsp->flags |= NFSMNT_INT; 456*38445Smckusick } else if (!strcmp(cp, "retry") && num > 0) { 457*38445Smckusick *retrycntp = num; 458*38445Smckusick } else if (!strcmp(cp, "rsize") && num > 0) { 459*38445Smckusick nfsargsp->rsize = num; 460*38445Smckusick nfsargsp->flags |= NFSMNT_RSIZE; 461*38445Smckusick } else if (!strcmp(cp, "wsize") && num > 0) { 462*38445Smckusick nfsargsp->wsize = num; 463*38445Smckusick nfsargsp->flags |= NFSMNT_WSIZE; 464*38445Smckusick } else if (!strcmp(cp, "timeo") && num > 0) { 465*38445Smckusick nfsargsp->timeo = num; 466*38445Smckusick nfsargsp->flags |= NFSMNT_TIMEO; 467*38445Smckusick } else if (!strcmp(cp, "retrans") && num > 0) { 468*38445Smckusick nfsargsp->retrans = num; 469*38445Smckusick nfsargsp->flags |= NFSMNT_RETRANS; 470*38445Smckusick } 471*38445Smckusick cp = nextcp; 472*38445Smckusick } 473*38445Smckusick } 474*38445Smckusick #endif 475