home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume19 / backup / ilw.c < prev    next >
C/C++ Source or Header  |  1989-06-29  |  3KB  |  135 lines

  1. /*
  2.  * i-list-walker -- apply a specified function to all inodes on a filesystem
  3.  *
  4.  * Based on original routines by Larry Philps.  This reimplementation is
  5.  * Copyright 1988 by Rayan Zachariassen, solely to prevent you from selling
  6.  * it or putting your name on it.  Free (gratis) redistribution is encouraged.
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <sys/param.h>
  11. #include <sys/types.h>
  12. #include <sys/file.h>
  13. #include <sys/time.h>
  14. #include <sys/vnode.h>
  15. #include <ufs/inode.h>
  16. #include <ufs/fs.h>
  17.  
  18. extern char *progname;        /* must be supplied by main program */
  19.  
  20. static char    errmsgbuf[30];
  21. #define    EMSG(x)    (errno < sys_nerr ? sys_errlist[x] : \
  22.            (sprintf(errmsgbuf, "unknown error %d", errno), errmsgbuf))
  23.  
  24. extern int    errno, sys_nerr;
  25. extern char    *sys_errlist[];
  26. extern off_t    lseek();
  27.  
  28. int
  29. bread(fd, bno, buf, cnt)
  30.     daddr_t    bno;
  31.     char    *buf;
  32.     long    cnt;
  33. {
  34.     if (lseek(fd, (off_t) bno * DEV_BSIZE, L_SET) == -1) {
  35.         fprintf(stderr, "%s: bread: lseek: %s\n",
  36.                 progname, EMSG(errno));
  37.         return -2;
  38.     }
  39.     if (read(fd, buf, (int) cnt) != cnt) {
  40.         fprintf(stderr, "%s: read error at block %u: %s\n",
  41.                 progname, bno, EMSG(errno));
  42.         return -1;
  43.     }
  44.     return 0;
  45. }
  46.  
  47. int
  48. bwrite(fd, bno, buf, cnt)
  49.     daddr_t    bno;
  50.     char    *buf;
  51.     long    cnt;
  52. {
  53.     if (lseek(fd, (off_t) bno * DEV_BSIZE, L_SET) == -1) {
  54.         fprintf(stderr, "%s: bwrite: lseek: %s\n",
  55.                 progname, EMSG(errno));
  56.         return -2;
  57.     }
  58.     if (write(fd, buf, (int) cnt) != cnt) {
  59.         fprintf(stderr, "%s: write error at block %u: %s\n",
  60.                 progname, bno, EMSG(errno));
  61.         return -1;
  62.     }
  63.     return 0;
  64. }
  65.  
  66. /*
  67.  * i-list-walker
  68.  *
  69.  * Opens the raw device indicated, and calls the function fn with an inode
  70.  * pointer for every inode on the device.  If the function returns non-zero,
  71.  * the inode on the disk is updated, unless the readonly flag is set.
  72.  *
  73.  * Return -1 in case of error, +ve if inodes were updated, 0 otherwise.
  74.  */
  75.  
  76. ilw(rawdev, fn, readonly)
  77.     char    *rawdev;
  78.     int    (*fn)();
  79.     int    readonly;
  80. {
  81.     register u_int    ino;
  82.     register int    fd, j, nfiles, changed, touched;
  83.     struct   dinode    *ip;
  84.     daddr_t        iblk;
  85.     struct dinode    itab[MAXBSIZE/sizeof(struct dinode)];
  86.     union {
  87.         struct fs u_sblock;
  88.         char dummy[SBSIZE];
  89.     } sb_un;
  90. #define sblock    sb_un.u_sblock
  91.  
  92.     if ((fd = open(rawdev, readonly ? O_RDONLY : O_RDWR, 0)) < 0) {
  93.         fprintf(stderr, "%s: open(%s): %s\n",
  94.                 progname, rawdev, EMSG(errno));
  95.         return -1;
  96.     }
  97.     /*
  98.      * Don't bother stat'ing the device, we might want to do this on
  99.      * real files some day.
  100.      */
  101.     /* printf ("starting filesystem %s\n", rawdev); */
  102.     sync();
  103.     if (bread(fd, SBLOCK, (char *)&sblock, (long) SBSIZE) < 0) {
  104.         close(fd);
  105.         return -1;
  106.     }
  107.     nfiles = sblock.fs_ipg * sblock.fs_ncg;
  108.     touched = 0;
  109.     for (ino = 0; ino < nfiles; touched += changed) {
  110.         iblk = fsbtodb(&sblock, itod(&sblock, ino));
  111.         if (bread(fd, iblk, (char *)itab, sblock.fs_bsize) < 0) {
  112.             (void) close(fd);
  113.             return -1;
  114.         }
  115.         changed = 0;
  116.         for (j = 0; j < INOPB(&sblock) && ino < nfiles; j++, ino++) {
  117.             ip = &itab[j];
  118.             if ((ino < ROOTINO) || ((ip->di_mode&IFMT) == 0))
  119.                 continue;
  120.             if ((*fn)(ip, ino))
  121.                 ++changed;
  122.         }
  123.         if (!changed)
  124.             continue;
  125.         if (readonly)
  126.             printf("replacing block %d with %d changes\n",
  127.                       iblk, changed);
  128.         else if (bwrite(fd, iblk, (char *)itab, sblock.fs_bsize) < 0) {
  129.             (void) close(fd);
  130.             return -1;
  131.         }
  132.     }
  133.     return touched;
  134. }
  135.