home *** CD-ROM | disk | FTP | other *** search
- /*
- * i-list-walker -- apply a specified function to all inodes on a filesystem
- *
- * Based on original routines by Larry Philps. This reimplementation is
- * Copyright 1988 by Rayan Zachariassen, solely to prevent you from selling
- * it or putting your name on it. Free (gratis) redistribution is encouraged.
- */
-
- #include <stdio.h>
- #include <sys/param.h>
- #include <sys/types.h>
- #include <sys/file.h>
- #include <sys/time.h>
- #include <sys/vnode.h>
- #include <ufs/inode.h>
- #include <ufs/fs.h>
-
- extern char *progname; /* must be supplied by main program */
-
- static char errmsgbuf[30];
- #define EMSG(x) (errno < sys_nerr ? sys_errlist[x] : \
- (sprintf(errmsgbuf, "unknown error %d", errno), errmsgbuf))
-
- extern int errno, sys_nerr;
- extern char *sys_errlist[];
- extern off_t lseek();
-
- int
- bread(fd, bno, buf, cnt)
- daddr_t bno;
- char *buf;
- long cnt;
- {
- if (lseek(fd, (off_t) bno * DEV_BSIZE, L_SET) == -1) {
- fprintf(stderr, "%s: bread: lseek: %s\n",
- progname, EMSG(errno));
- return -2;
- }
- if (read(fd, buf, (int) cnt) != cnt) {
- fprintf(stderr, "%s: read error at block %u: %s\n",
- progname, bno, EMSG(errno));
- return -1;
- }
- return 0;
- }
-
- int
- bwrite(fd, bno, buf, cnt)
- daddr_t bno;
- char *buf;
- long cnt;
- {
- if (lseek(fd, (off_t) bno * DEV_BSIZE, L_SET) == -1) {
- fprintf(stderr, "%s: bwrite: lseek: %s\n",
- progname, EMSG(errno));
- return -2;
- }
- if (write(fd, buf, (int) cnt) != cnt) {
- fprintf(stderr, "%s: write error at block %u: %s\n",
- progname, bno, EMSG(errno));
- return -1;
- }
- return 0;
- }
-
- /*
- * i-list-walker
- *
- * Opens the raw device indicated, and calls the function fn with an inode
- * pointer for every inode on the device. If the function returns non-zero,
- * the inode on the disk is updated, unless the readonly flag is set.
- *
- * Return -1 in case of error, +ve if inodes were updated, 0 otherwise.
- */
-
- ilw(rawdev, fn, readonly)
- char *rawdev;
- int (*fn)();
- int readonly;
- {
- register u_int ino;
- register int fd, j, nfiles, changed, touched;
- struct dinode *ip;
- daddr_t iblk;
- struct dinode itab[MAXBSIZE/sizeof(struct dinode)];
- union {
- struct fs u_sblock;
- char dummy[SBSIZE];
- } sb_un;
- #define sblock sb_un.u_sblock
-
- if ((fd = open(rawdev, readonly ? O_RDONLY : O_RDWR, 0)) < 0) {
- fprintf(stderr, "%s: open(%s): %s\n",
- progname, rawdev, EMSG(errno));
- return -1;
- }
- /*
- * Don't bother stat'ing the device, we might want to do this on
- * real files some day.
- */
- /* printf ("starting filesystem %s\n", rawdev); */
- sync();
- if (bread(fd, SBLOCK, (char *)&sblock, (long) SBSIZE) < 0) {
- close(fd);
- return -1;
- }
- nfiles = sblock.fs_ipg * sblock.fs_ncg;
- touched = 0;
- for (ino = 0; ino < nfiles; touched += changed) {
- iblk = fsbtodb(&sblock, itod(&sblock, ino));
- if (bread(fd, iblk, (char *)itab, sblock.fs_bsize) < 0) {
- (void) close(fd);
- return -1;
- }
- changed = 0;
- for (j = 0; j < INOPB(&sblock) && ino < nfiles; j++, ino++) {
- ip = &itab[j];
- if ((ino < ROOTINO) || ((ip->di_mode&IFMT) == 0))
- continue;
- if ((*fn)(ip, ino))
- ++changed;
- }
- if (!changed)
- continue;
- if (readonly)
- printf("replacing block %d with %d changes\n",
- iblk, changed);
- else if (bwrite(fd, iblk, (char *)itab, sblock.fs_bsize) < 0) {
- (void) close(fd);
- return -1;
- }
- }
- return touched;
- }
-