home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume22 / mntdisk / part01 / funcs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-21  |  20.9 KB  |  1,023 lines

  1. /* funcs.c -- support functions for mntdisk.c */
  2.  
  3. /* Written by Mike J. Fuller (mikef@sarah.lerc.nasa.gov) 
  4.    for NASA Lewis Research Center */
  5.  
  6. #ifndef lint
  7.     static char ID[] = "@(#)funcs.c 1.00 91/07/02";
  8. #endif
  9.  
  10. #include "mntdisk.h"
  11.  
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <sys/wait.h>
  15. #include <sys/time.h>
  16. #include <sys/vnode.h>
  17. #include <sys/ioctl.h>
  18. #include <ufs/inode.h>
  19. #include <ufs/fs.h>
  20. #include <errno.h>
  21. #include <pwd.h>
  22. #include <malloc.h>
  23. #include <mntent.h>
  24. #include <signal.h>
  25. #include <unistd.h>
  26.  
  27. extern char *prog;
  28. extern int quiet, uid, mask;
  29.  
  30. /*****************************************************************************/
  31.  
  32. #ifdef __STDC__
  33. static int
  34. bread(int fd, daddr_t bno, char *buf, int cnt)
  35. #else
  36. static int bread(fd, bno, buf, cnt)
  37.     int fd, cnt;
  38.     daddr_t bno;
  39.     char *buf;
  40. #endif
  41. {
  42.     if(lseek(fd, bno * DEV_BSIZE, SEEK_SET) != (bno * DEV_BSIZE))
  43.     return(1);
  44.     if(read(fd, buf, cnt) != cnt)
  45.     return(1);
  46.     return(0);
  47. }
  48.  
  49. /*****************************************************************************/
  50.  
  51. #ifdef __STDC__
  52. static int
  53. bwrite(int fd, daddr_t bno, char *buf, int cnt)
  54. #else
  55. static int bwrite(fd, bno, buf, cnt)
  56.     int fd, cnt;
  57.     daddr_t bno;
  58.     char *buf;
  59. #endif
  60. {
  61.     if(lseek(fd, bno * DEV_BSIZE, SEEK_SET) != (bno * DEV_BSIZE))
  62.     return(1);
  63.     if(write(fd, buf, cnt) != cnt)
  64.     return(1);
  65.     return(0);
  66. }
  67.  
  68. /*****************************************************************************/
  69.  
  70. #ifdef __STDC__
  71. static int
  72. has_devices(char *device)
  73. #else
  74. static int has_devices(device)
  75.     char *device;
  76. #endif
  77. {
  78.     register int c, j;
  79.     int fd;
  80.     union {
  81.     struct fs sblock;
  82.     char buf[SBSIZE];
  83.     } sblock;
  84.     union {
  85.     struct dinode *itab;
  86.     char *buf;
  87.     } itab;
  88.  
  89.     if((fd = open(device, O_RDONLY)) == -1) {
  90.     perror(device);
  91.     return(1);
  92.     }
  93.  
  94.     if(bread(fd, SBLOCK, sblock.buf, SBSIZE)) {
  95.     perror(device);
  96.     (void) close(fd);
  97.     return(1);
  98.     }
  99.  
  100.     if(sblock.sblock.fs_magic != FS_MAGIC) {
  101.     (void) fprintf(stderr, "%s: Error: '%s' is not a filesystem.\n",
  102.         prog, device);
  103.     (void) close(fd);
  104.     return(1);
  105.     }
  106.  
  107.     if((itab.buf = (char *) malloc ((unsigned int) (sblock.sblock.fs_ipg *
  108.                     sizeof(struct dinode)))) == (char *) 0) {
  109.     (void) fprintf(stderr, "%s: Error: insufficient memory\n", prog);
  110.     (void) close(fd);
  111.     return(1);
  112.     }
  113.  
  114.     for(c = 0; c < sblock.sblock.fs_ncg; c++) {
  115.     if(bread(fd, fsbtodb(&sblock.sblock, cgimin(&sblock.sblock, c)),
  116.          itab.buf, (int) (sblock.sblock.fs_ipg *
  117.                   sizeof(struct dinode)))) {
  118.         perror(device);
  119.         (void) close(fd);
  120.         free((char *) itab.buf);
  121.         return(1);
  122.     }
  123.     for(j = 0; j < sblock.sblock.fs_ipg; j++)
  124.         if(((itab.itab[j].di_mode & IFMT) == IFCHR) ||
  125.            ((itab.itab[j].di_mode & IFMT) == IFBLK)) {
  126.         (void) close(fd);
  127.         free((char *) itab.buf);
  128.         return(1);
  129.         }
  130.     }
  131.  
  132.     free((char *) itab.buf);
  133.     return(0);
  134. }
  135.  
  136. /*****************************************************************************/
  137.  
  138. #ifdef __STDC__
  139. int
  140. run(char *command)
  141. #else
  142. int run(command)
  143.     char *command;
  144. #endif
  145. {
  146.     int pid;
  147.  
  148.     switch(pid = fork()) {
  149.     case 0: {
  150.     char **argv, *path;
  151.     register int i = 0;
  152.     register char *b = command, *c = command;
  153.     int addflag = 0, word = 0, quote = 0;
  154.  
  155.     if(setreuid(0, -1) == -1) {
  156.         perror("setreuid()");
  157.         _exit(1);
  158.     }
  159.  
  160.     if((argv = (char **) malloc(sizeof(char **))) == (char **) 0) {
  161.         (void) fprintf(stderr, "%s: Error: insufficient memory\n", prog);
  162.         _exit(1);
  163.     }
  164.  
  165.     for(;;) {
  166.         if((*c == '\'') && ! word)
  167.         if(quote) {
  168.             quote = 0;
  169.             addflag = 1;
  170.         }
  171.         else {
  172.             quote = 1;
  173.             b = c + 1;
  174.         }
  175.         else if(*c == '\0')
  176.         if(word && ! quote)
  177.             addflag = 1;
  178.         else
  179.             break;
  180.         else if(isspace(*c)) {
  181.         if(word && ! quote) {
  182.             word = 0;
  183.             addflag = 1;
  184.         }
  185.         }
  186.         else
  187.         if(! word && ! quote) {
  188.             word = 1;
  189.             b = c;
  190.         }
  191.  
  192.         if(addflag) {
  193.         addflag = 0;
  194.         if(! i)
  195.             path = b;
  196.         argv[i++] = b;
  197.         if((argv = (char **)
  198.             realloc((char *) argv, (unsigned int)
  199.                 ((i + 1) * sizeof(char **)))) == (char **) 0) {
  200.             (void) fprintf(stderr, "%s: Error: insufficient memory\n",
  201.                    prog);
  202.             _exit(1);
  203.         }
  204.         if(*c == '\0')
  205.             break;
  206.         *c = '\0';
  207.         if((i == 1) && ((b = strrchr(b, (int) '/')) != (char *) 0))
  208.             argv[0] = b + 1;
  209.         }
  210.         ++c;
  211.     }
  212.     argv[i] = (char *) 0;
  213.  
  214.     if(quote) {
  215.         (void) fprintf(stderr, "%s: run: parse error.\n", prog);
  216.         _exit(1);
  217.     }
  218. #ifdef DEBUG
  219.     else {
  220.         (void) printf("path = '%s'\n", path);
  221.         for(i = 0; argv[i] != (char *) 0; ++i)
  222.         (void) printf("argv[%d] = '%s'\n", i, argv[i]);
  223.     }
  224. #endif
  225.  
  226.     if(quiet)
  227.         (void) close(1);
  228.     (void) execv(path, argv);
  229.     perror(path);
  230.     _exit(1);
  231.     }
  232.  
  233.     case -1:
  234.     perror("fork");
  235.     return(1);
  236.  
  237.     default: {
  238.     int ret, status;
  239.  
  240.     do
  241.         ret = wait(&status);
  242.     while((ret != pid) && (ret != -1));
  243.     if(ret == -1) {
  244.         perror("wait");
  245.         return(-1);
  246.     }
  247.     return(WEXITSTATUS(status));
  248.     }
  249.     }
  250. }
  251.  
  252. /*****************************************************************************/
  253.  
  254. #ifdef __STDC__
  255. char
  256. *username(int uid)
  257. #else
  258. char *username(uid)
  259.     int uid;
  260. #endif
  261. {
  262.     static char buf[BUFSIZ];
  263.     struct passwd *pwp;
  264.     register char *c;
  265.  
  266.     if((pwp = getpwuid(uid)) == (struct passwd *) 0)
  267.     (void) sprintf(buf, "uid %d", uid);
  268.     else {
  269.     for(c = pwp->pw_gecos; *c != '\0'; c++)
  270.         if(*c == ',')
  271.         *c = '\0';
  272.     (void) sprintf(buf, "%s (%s)", pwp->pw_name, pwp->pw_gecos);
  273.     }
  274.     return(buf);
  275. }
  276.  
  277. /*****************************************************************************/
  278.  
  279. #ifdef __STDC__
  280. char
  281. *mounted(char *device)
  282. #else
  283. char *mounted(device)
  284.     char *device;
  285. #endif
  286. {
  287.     static char fsname[MAXPATHLEN];
  288.     FILE *fp;
  289.     struct mntent *mnt;
  290.  
  291.     if((fp = setmntent("/etc/mtab", "r")) == (FILE *) 0) {
  292.     perror("/etc/mtab");
  293.     return((char *) 0);
  294.     }
  295.     while((mnt = getmntent(fp)) != (struct mntent *) 0)
  296.     if(! strcmp(mnt->mnt_fsname, device)) {
  297.         (void) strcpy(fsname, mnt->mnt_dir);
  298.         (void) endmntent(fp);
  299.         return(fsname);
  300.     }
  301.     (void) endmntent(fp);
  302.     return((char *) 0);
  303. }
  304.  
  305. /*****************************************************************************/
  306.  
  307. #ifdef __STDC__
  308. int
  309. dounmount(char *device, char *mountpoint)
  310. #else
  311. int dounmount(device, mountpoint)
  312.     char *device, *mountpoint;
  313. #endif
  314. {
  315.     char tmpmtab[MAXPATHLEN], *mtab = "/etc/mtab";
  316.     FILE *mtabfp, *tmpmtabfp;
  317.     struct mntent *mnt;
  318.  
  319.     if (unmount(mountpoint)) {
  320.     perror(mountpoint);
  321.     return(1);
  322.     }
  323.  
  324.     if((mtabfp = setmntent(mtab, "r+")) == (FILE *) 0) {
  325.     (void) fprintf(stderr, "%s: Warning: couldn't read '%s'.\n",
  326.                prog, mtab);
  327.     return(0);
  328.     }
  329.     if((tmpmtabfp = setmntent(sprintf(tmpmtab, "%s.%d", mtab, getpid()), "w"))
  330.        == (FILE *) 0) {
  331.     (void) fprintf(stderr, "%s: Warning: couldn't create '%s'.\n",
  332.                prog, tmpmtab);
  333.     return(0);
  334.     }
  335.  
  336.     while((mnt = getmntent(mtabfp)) != (struct mntent *) 0)
  337.     if(strcmp(device, mnt->mnt_fsname) && (addmntent(tmpmtabfp, mnt) != 0))
  338.         (void) fprintf(stderr,"%s: Warning: couldn't add '%s' to '%s'.\n",
  339.                prog, mnt->mnt_fsname, tmpmtab);
  340.     (void) endmntent(mtabfp);
  341.     (void) endmntent(tmpmtabfp);
  342.  
  343.     if(unlink(mtab) == -1) {
  344.     (void) fprintf(stderr, "%s: Warning: couldn't delete '%s'.\n",
  345.                prog, mtab);
  346.     return(0);
  347.     }
  348.     if(rename(tmpmtab, mtab) == -1)
  349.     (void) fprintf(stderr, "%s: Warning: couldn't rename '%s' to '%s'.\n",
  350.         prog, tmpmtab, mtab);
  351.  
  352.     return(0);
  353. }
  354.  
  355. /*****************************************************************************/
  356.  
  357. #ifdef EXPORT
  358. #ifdef __STDC__
  359. int
  360. doexport(char *mountpoint, int ro, int unexport)
  361. #else
  362. int doexport(mountpoint, ro, unexport)
  363.     char *mountpoint;
  364.     int ro, unexport;
  365. #endif
  366. {
  367.     char buf[MAXPATHLEN];
  368.  
  369.     if(access("/etc/exports", F_OK) == -1)
  370.     return(0);
  371.  
  372.     if(unexport)
  373.     (void) sprintf(buf, "/usr/etc/exportfs -iu %s", mountpoint);
  374.     else
  375.     (void) sprintf(buf, "/usr/etc/exportfs -i -o %s%s %s", EXPORT,
  376.         ro ? ",ro" : "", mountpoint);
  377.  
  378.     return(run(buf));
  379. }
  380. #endif
  381.  
  382. /*****************************************************************************/
  383.  
  384. #ifdef __STDC__
  385. int
  386. domount(char *device, char *mountpoint, char *mtype, char *moptstr, int mopts)
  387. #else
  388. int domount(device, mountpoint, mtype, moptstr, mopts)
  389.     char *device, *mountpoint, *moptstr, *mtype;
  390.     int mopts;
  391. #endif
  392. {
  393.     FILE *fp;
  394.     struct mntent mnt;
  395.  
  396.     if (mount(mtype, mountpoint, mopts, &device)) {
  397.     perror(device);
  398.     return(1);
  399.     }
  400.  
  401.     if((fp = setmntent("/etc/mtab", "r+")) != (FILE *) 0) {
  402.     mnt.mnt_fsname = device;
  403.     mnt.mnt_dir = mountpoint;
  404.     mnt.mnt_type = mtype;
  405.     mnt.mnt_opts = moptstr;
  406.     mnt.mnt_freq = 0;
  407.     mnt.mnt_passno = 0;
  408.     if (addmntent(fp, &mnt) != 0)
  409.         (void) fprintf(stderr,
  410.             "%s: Warning: couldn't update '/etc/mtab'.\n", prog);
  411.     (void) endmntent(fp);
  412.     }
  413.     else
  414.     (void) fprintf(stderr, "%s: Warning: couldn't update '/etc/mtab'.\n",
  415.                prog);
  416.  
  417.     return(0);
  418. }
  419.  
  420. /*****************************************************************************/
  421.  
  422. #ifdef __STDC__
  423. int
  424. no_fs(char *device)
  425. #else
  426. int no_fs(device)
  427.     char *device;
  428. #endif
  429. {
  430.     int fd;
  431.     union {
  432.     char buf[SBSIZE];
  433.     struct fs sblock;
  434.     } sblock;
  435.  
  436.     if((fd = open(device, O_RDONLY)) == -1) {
  437.     perror(device);
  438.     return(-1);
  439.    }
  440.  
  441.     if(bread(fd, SBLOCK, sblock.buf, SBSIZE)) {
  442.     perror(device);
  443.     (void) close(fd);
  444.     return(-1);
  445.     }
  446.  
  447.     (void) close(fd);
  448.     return(sblock.sblock.fs_magic != FS_MAGIC);
  449. }
  450.  
  451. /*****************************************************************************/
  452.  
  453. #ifdef __STDC__
  454. int
  455. can_overwrite(char *device)
  456. #else
  457. int can_overwrite(device)
  458.     char *device;
  459. #endif
  460. {
  461.     int fd, duid, canwrite = 0;
  462.     union {
  463.     struct fs sblock;
  464.     char buf[SBSIZE];
  465.     } sblock;
  466.     union {
  467.     struct dinode itab[(DEV_BSIZE << 1) / sizeof(struct dinode)];
  468.     char buf[DEV_BSIZE << 1];
  469.     } itab;
  470.  
  471.     if((fd = open(device, O_RDONLY)) == -1) {
  472.     if(errno != EIO)
  473.         perror(device);
  474.     return(errno == EIO);
  475.     }
  476.     if(bread(fd, SBLOCK, sblock.buf, SBSIZE)) {
  477.     (void) close(fd);
  478.     if(errno != EIO)
  479.         perror(device);
  480.     return(errno == EIO);
  481.     }
  482.     if(sblock.sblock.fs_magic != FS_MAGIC) {
  483.     (void) close(fd);
  484.     return(1);
  485.     }
  486.  
  487. #ifndef DEBUG
  488.     {
  489.     struct stat sbuf;
  490.  
  491.     if(fstat(fd, &sbuf) == -1) {
  492.         perror(device);
  493.         (void) close(fd);
  494.         return(0);
  495.     }
  496.     if((sbuf.st_uid == uid) && (sbuf.st_mode & S_IWUSR))
  497.         canwrite = 1;
  498.     else
  499.         if((sbuf.st_gid == (gid_t) getgid()) && (sbuf.st_mode & S_IWGRP))
  500.         canwrite = 1;
  501.         else
  502.         if(sbuf.st_mode & S_IWOTH)
  503.             canwrite = 1;
  504.     }
  505. #endif
  506.  
  507.     if(bread(fd, fsbtodb(&sblock.sblock, cgimin(&sblock.sblock, 0)), itab.buf,
  508.          DEV_BSIZE << 1)) {
  509.     (void) close(fd);
  510.     if(errno != EIO)
  511.         perror(device);
  512.     return(errno == EIO);
  513.     }
  514.  
  515.     (void) close(fd);
  516.     duid = itab.itab[ROOTINO].di_uid;
  517.     if(! canwrite && (duid != uid)) {
  518.     (void) fprintf(stderr,
  519.                "%s: Error: the filesystem on '%s' is owned by %s.\n",
  520.                prog, device, username((int) itab.itab[ROOTINO].di_uid));
  521.     return(0);
  522.     }
  523.  
  524.     if(! quiet)
  525.     (void) printf("%s: Warning: The filesystem on '%s' is owned by %s.\n",
  526.            prog, device, username(duid));
  527.  
  528.     return(1);
  529. }
  530.  
  531. /*****************************************************************************/
  532.  
  533. #ifdef __STDC__
  534. int
  535. mountpoint_ok(char *mp, char *nmp)
  536. #else
  537. int mountpoint_ok(mp, nmp)
  538.     char *mp, *nmp;
  539. #endif
  540. {
  541.     struct stat sbuf;
  542.  
  543.     if(! strcmp(mp, nmp) && (access(mp, F_OK) == -1) &&
  544.        (mkdir(nmp, 0755) == -1)) {
  545.     perror(nmp);
  546.     return(0);
  547.     }
  548.  
  549.     if(stat(nmp, &sbuf) == -1) {
  550.     perror(nmp);
  551.     return(0);
  552.     }
  553.  
  554.     if (! S_ISDIR(sbuf.st_mode)) {
  555.     (void) fprintf(stderr, "%s: Error: '%s' is not a directory.\n",
  556.                prog, nmp);
  557.     return(0);
  558.     }
  559.  
  560.     if(uid && strcmp(mp, nmp) && (sbuf.st_uid != uid)) {
  561.     (void) fprintf(stderr, "%s: Error: not owner of '%s'.\n", prog, nmp);
  562.     return(0);
  563.     }
  564.  
  565.     return(1);
  566. }
  567.  
  568. /*****************************************************************************/
  569.  
  570. #ifdef __STDC__
  571. void
  572. setmodes(char *device, mode_t mode)
  573. #else
  574. void setmodes(device, mode)
  575.     char *device;
  576.     mode_t mode;
  577. #endif
  578. {
  579.     struct dirent *dp;
  580.     DIR *dirp;
  581.     char buf[MAXPATHLEN], prefix[MAXPATHLEN], *c;
  582.     int len;
  583.     register int rlen, blen;
  584.  
  585.     len = strlen(strcpy(prefix, device)) - 1;
  586.     prefix[len] = '\0';
  587.     blen = len + 1;
  588.     rlen = blen + 1;
  589.  
  590.     dirp = opendir("/dev");
  591.     for(dp = readdir(dirp); dp != (struct dirent *) 0; dp = readdir(dirp))
  592.     if((dp->d_namlen == blen) || (dp->d_namlen == rlen)) {
  593.         c = strstr(dp->d_name, prefix);
  594.         if((c == dp->d_name) || ((c == (dp->d_name + 1)) &&
  595.                      (*(dp->d_name) == 'r'))) {
  596.         (void) strcat(strcpy(buf, "/dev/"), dp->d_name);
  597.         if(chmod(buf, (int) mode) == -1)
  598.             perror(buf);
  599. #ifdef DEBUG
  600.         (void) printf("chmod %s %o\n", buf, mode);
  601. #endif
  602.         }
  603.     }
  604.     (void) closedir(dirp);
  605. }
  606.  
  607. /*****************************************************************************/
  608.  
  609. #ifdef __STDC__
  610. int
  611. makeowner(char *device)
  612. #else
  613. int makeowner(device)
  614. char *device;
  615. #endif
  616. {
  617.     int fd;
  618.     daddr_t first_inodes;
  619.     union {
  620.     struct fs sblock;
  621.     char buf[SBSIZE];
  622.     } sblock;
  623.     union {
  624.     struct dinode itab[(DEV_BSIZE << 1) / sizeof(struct dinode)];
  625.     char buf[DEV_BSIZE << 1];
  626.     } itab;
  627.  
  628.     if((fd = open(device, O_RDWR)) == -1) {
  629.     perror(device);
  630.     return(1);
  631.     }
  632.     if(bread(fd, SBLOCK, sblock.buf, SBSIZE)) {
  633.     perror(device);
  634.     (void) close(fd);
  635.     return(1);
  636.     }
  637.     if(sblock.sblock.fs_magic != FS_MAGIC) {
  638.     (void) fprintf(stderr, "%s: '%s' has no filesystem.\n", prog, device);
  639.     return(1);
  640.     }
  641.  
  642.     first_inodes = fsbtodb(&sblock.sblock, cgimin(&sblock.sblock, 0));
  643.     if(bread(fd, first_inodes, itab.buf, DEV_BSIZE << 1)) {
  644.     perror(device);
  645.     (void) close(fd);
  646.     return(1);
  647.     }
  648.     itab.itab[ROOTINO].di_uid = (uid_t) uid;
  649.     itab.itab[ROOTINO].di_gid = (gid_t) getgid();
  650.     itab.itab[ROOTINO].di_mode |= ISGID | (0777 & ~mask);
  651.     if(bwrite(fd, first_inodes, itab.buf, DEV_BSIZE << 1)) {
  652.     perror(device);
  653.     (void) close(fd);
  654.     return(1);
  655.     }
  656.  
  657.     (void) close(fd);
  658.     return(0);
  659. }
  660.  
  661. /*****************************************************************************/
  662.  
  663. #ifdef __STDC__
  664. int
  665. spinup(char *device)
  666. #else
  667. int spinup(device)
  668.     char *device;
  669. #endif
  670. {
  671.     char buf[SBSIZE];
  672.     char rdevice[MAXPATHLEN];
  673.     int fd, rc;
  674.  
  675.     (void) sprintf(rdevice, "/dev/r%s", device);
  676.     if(((fd = open(rdevice, O_RDONLY)) != -1) &&
  677.        ! bread(fd, SBLOCK, buf, SBSIZE)) {
  678.     (void) close(fd);
  679.     return(0);
  680.     }
  681.     else if(errno == EIO) {
  682.     char eoddevice[MAXPATHLEN], command[MAXPATHLEN];
  683.  
  684.     (void) close(fd);
  685.     if(! quiet)
  686.         (void) printf("%s: Spinning up '%s'...\n", prog, device);
  687.     (void) strcpy(eoddevice, device);
  688.     eoddevice[strlen(eoddevice) - 1] = '\0';
  689.     rc = run(sprintf(command, EODSTART, eoddevice));
  690.     if(! rc) sleep(1);
  691.     return(rc);
  692.     }
  693.     else {
  694.     perror(rdevice);
  695.     (void) close(fd);
  696.     return(1);
  697.     }
  698. }
  699.  
  700. /*****************************************************************************/
  701.  
  702. #if TIMEOUT > 0
  703. #ifdef __STDC__
  704. static int
  705. locked(char *device)
  706. #else
  707. static int locked(device)
  708. char *device;
  709. #endif
  710. {
  711.     char disk[MAXPATHLEN], lockfile[MAXPATHLEN];
  712.  
  713.     (void) strcpy(disk, device);
  714.     disk[strlen(disk) - 1] = '\0';
  715.     (void) sprintf(lockfile, "/tmp/%s.lock", disk);
  716.  
  717.     return(access(lockfile, F_OK) != -1);
  718. }
  719. #endif
  720.  
  721. /*****************************************************************************/
  722.  
  723. #if TIMEOUT > 0
  724. #ifdef __STDC__
  725. void
  726. spindown(char *device, int time)
  727. #else
  728. void spindown(device, time)
  729.     char *device;
  730.     int time;
  731. #endif
  732. {
  733.     char disk[MAXPATHLEN], spinfile[MAXPATHLEN];
  734.  
  735.     (void) strcpy(disk, device);
  736.     disk[strlen(disk) - 1] = '\0';
  737.     (void) sprintf(spinfile, "/tmp/%s.spindown", disk);
  738.  
  739.     if(access(spinfile, F_OK) != -1)
  740.     return;
  741.     if(creat(spinfile, 0444) == -1) {
  742.     perror(spinfile);
  743.     return;
  744.     }
  745.     if(chown(spinfile, uid, -1) == -1) {
  746.     perror(spinfile);
  747.     return;
  748.     }
  749.  
  750.     switch(fork()) {
  751.     case 0: {
  752.     char bdevice[MAXPATHLEN], rdevice[MAXPATHLEN], eoddevice[MAXPATHLEN];
  753.     char buf[MAXPATHLEN];
  754.     struct stat asbuf, bsbuf;
  755. #ifndef DEBUG
  756.     int fd;
  757. #endif
  758.  
  759.     (void) strcpy(eoddevice, device);
  760.     eoddevice[strlen(eoddevice) - 1] = '\0';
  761.     (void) sprintf(bdevice, "/dev/%s", device);
  762.     (void) sprintf(rdevice, "/dev/r%s", device);
  763.  
  764. #ifndef DEBUG
  765.     if((fd = open("/dev/tty", O_RDONLY)) != -1) {
  766.         ioctl(fd, TIOCNOTTY, 0);
  767.         (void) close(fd);
  768.     }
  769.     for(fd = (getdtablesize() - 1); fd >= 0; fd--)
  770.     if(isatty(fd) && (close(fd) == -1)) {
  771.         perror("close");
  772.         _exit(1);
  773.     }
  774.     (void) signal(SIGHUP, SIG_IGN);
  775. #endif
  776.  
  777.     do {
  778.         if(stat(rdevice, &bsbuf) == -1) {
  779. #if defined(DEBUG) || ! defined(SYSLOG)
  780.         perror(rdevice);
  781. #else
  782.         syslog(LOG_ERR, "%s: %m", rdevice);
  783. #endif
  784.         if(unlink(spinfile) == -1)
  785. #if defined(DEBUG) || ! defined(SYSLOG)
  786.             perror(spinfile);
  787. #else
  788.             syslog(LOG_ERR, "%s: %m", spinfile);
  789. #endif
  790. #ifdef SYSLOG
  791.         closelog();
  792. #endif
  793.         _exit(1);
  794.         }
  795.  
  796.         sleep(time);
  797.  
  798.         if(access(spinfile, F_OK) == -1)
  799.         _exit(0);
  800.  
  801.         if((mounted(bdevice) != (char *) 0) || locked(device)) {
  802.         if(unlink(spinfile) == -1)
  803. #if defined(DEBUG) || ! defined(SYSLOG)
  804.             perror(spinfile);
  805. #else
  806.             syslog(LOG_ERR, "%s: %m", spinfile);
  807. #endif
  808.         _exit(0);
  809.         }
  810.  
  811.         if(stat(rdevice, &asbuf) == -1) {
  812. #if defined(DEBUG) || ! defined(SYSLOG)
  813.         perror(rdevice);
  814. #else
  815.         syslog(LOG_ERR, "%s: %m", rdevice);
  816. #endif
  817.         if(unlink(spinfile) == -1)
  818. #if defined(DEBUG) || ! defined(SYSLOG)
  819.             perror(spinfile);
  820. #else
  821.             syslog(LOG_ERR, "%s: %m", spinfile);
  822. #endif
  823. #ifdef SYSLOG
  824.         closelog();
  825. #endif
  826.         _exit(1);
  827.         }
  828.         time = asbuf.st_ctime - bsbuf.st_ctime;
  829.     } while(time > 0);
  830.  
  831.     if(unlink(spinfile) == -1)
  832. #if defined(DEBUG) || ! defined(SYSLOG)
  833.         perror(spinfile);
  834. #else
  835.         syslog(LOG_ERR, "%s: %m", spinfile);
  836. #endif
  837.  
  838.     if(run(sprintf(buf, EODSTOP, eoddevice))) {
  839. #ifdef SYSLOG
  840.         closelog();
  841. #endif
  842.         _exit(1);
  843.     }
  844. #ifdef SYSLOG
  845.     syslog(LOG_INFO, "%s spun down '%s'.", username(uid), device);
  846.     closelog();
  847. #endif
  848.     _exit(0);
  849.     }
  850.     case -1:
  851.     perror("fork");
  852.     return;
  853.     default:
  854.     return;
  855.     }
  856. }
  857. #endif
  858.  
  859. /*****************************************************************************/
  860.  
  861. #ifdef __STDC__
  862. int
  863. lock(char *device)
  864. #else
  865. int lock(device)
  866. char *device;
  867. #endif
  868. {
  869.     char disk[MAXPATHLEN], lockfile[MAXPATHLEN];
  870.     struct stat sbuf;
  871.  
  872.     (void) strcpy(disk, device);
  873.     disk[strlen(disk) - 1] = '\0';
  874.     (void) sprintf(lockfile, "/tmp/%s.lock", disk);
  875.  
  876.     if(stat(lockfile, &sbuf) != -1) {
  877.     if(uid == sbuf.st_uid)
  878.         return(0);
  879.     else
  880.         (void) fprintf(stderr,
  881.                "%s: Error: '%s' is currently locked by %s.\n",
  882.                prog, device, username((int) sbuf.st_uid));
  883.     return(1);
  884.     }
  885.  
  886.     if(creat(lockfile, 0444) == -1) {
  887.     perror(lockfile);
  888.     return(1);
  889.     }
  890.     if(chown(lockfile, uid, -1) == -1) {
  891.     perror(lockfile);
  892.     return(1);
  893.     }
  894.     return(0);
  895. }
  896.  
  897. /*****************************************************************************/
  898.  
  899. #ifdef __STDC__
  900. int
  901. unlock(char *device)
  902. #else
  903. int unlock(device)
  904. char *device;
  905. #endif
  906. {
  907.     char disk[MAXPATHLEN], lockfile[MAXPATHLEN];
  908.  
  909.     (void) strcpy(disk, device);
  910.     disk[strlen(disk) - 1] = '\0';
  911.     (void) sprintf(lockfile, "/tmp/%s.lock", disk);
  912.  
  913.     return(unlink(lockfile) != -1);
  914. }
  915.  
  916. /*****************************************************************************/
  917.  
  918. #ifdef __STDC__
  919. int
  920. fsck(char *device)
  921. #else
  922. int fsck(device)
  923. char *device;
  924. #endif
  925. {
  926.     char buf[MAXPATHLEN];
  927.  
  928.     if(! quiet)
  929.     (void) printf("%s: Checking '%s'...\n", prog, device);
  930.  
  931.     if(run(sprintf(buf, "/usr/etc/fsck %s", device))) {
  932.     (void) fprintf(stderr, "%s: Error: fsck failed on '%s'.\n",
  933.                prog, device);
  934.     return(1);
  935.     }
  936.  
  937.     return(0);
  938. }
  939.  
  940. /*****************************************************************************/
  941.  
  942. #ifdef __STDC__
  943. int
  944. ufschecks(char *device, int mode, int skip)
  945. #else
  946. int ufschecks(device, mode, skip)
  947.     char *device;
  948.     int mode, skip;
  949. #endif
  950. {
  951.     char rdevice[MAXPATHLEN];
  952. #ifdef WHEEL
  953.     int gidset[NGROUPS], ngroups;
  954.     register int i;
  955. #endif
  956.  
  957.     (void) sprintf(rdevice, "/dev/r%s", device);
  958.  
  959.     if((mode == EOD) && spinup(device)) {
  960.     (void) fprintf(stderr, "%s: Error: cannot spin up drive '%s'.\n",
  961.         prog, rdevice);
  962.     return(1);
  963.     }
  964.  
  965.     if(no_fs(rdevice)) {
  966.     (void) fprintf(stderr, "%s: Error: '%s' has no filesystem.\n",
  967.                prog, rdevice);
  968.     return(1);
  969.     }
  970.  
  971. #ifdef WHEEL
  972.     if((ngroups = getgroups(NGROUPS, gidset)) == -1) {
  973.     perror("getgroups");
  974.     return(1);
  975.     }
  976.     for(i = (ngroups - 1); i >= 0;  i--)
  977.     if(gidset[i] == 0)
  978.         break;
  979.     if(uid && (i < 0)) {
  980. #else
  981.     if(uid) {
  982. #endif
  983.     if(! quiet)
  984.         (void) printf("%s: Checking '%s' for device special files...\n",
  985.               prog, rdevice);
  986.     if(has_devices(rdevice)) {
  987.         (void) fprintf(stderr,
  988.                "%s: Error: '%s' contains device special files.\n",
  989.                prog, rdevice);
  990. #ifdef SYSLOG
  991.         syslog(LOG_NOTICE,
  992.     "%s attempted to mount a disk in '%s' containing device special files.",
  993.            username(uid), device);
  994. #endif
  995.         return(1);
  996.     }
  997.  
  998.     if(! skip && fsck(rdevice))
  999.         return(1);
  1000.     }
  1001.     return(0);
  1002. }
  1003.  
  1004. /*****************************************************************************/
  1005.  
  1006. #ifdef __STDC__
  1007. int
  1008. device_ok(char *device, char *ndevice)
  1009. #else
  1010. int device_ok(device, ndevice)
  1011.     char *device, *ndevice;
  1012. #endif
  1013. {
  1014.     char buf[MAXPATHLEN];
  1015.     int len;
  1016.  
  1017.     buf[(len = strlen(strcpy(buf, device))) - 2] = '\0';
  1018.     return((strstr(ndevice, buf) == ndevice) && (strlen(ndevice) == len) &&
  1019.        (strchr("01234567", *(ndevice + len - 2)) != (char *) 0) &&
  1020.        (strchr("abcdefgh", *(ndevice + len - 1)) != (char *) 0));
  1021.  
  1022. }
  1023.