Received: from oss.sgi.com (localhost [127.0.0.1]) by oss.sgi.com (8.12.5/8.12.5) with ESMTP id g6ICFrRw028222 for ; Thu, 18 Jul 2002 05:15:53 -0700 Received: (from majordomo@localhost) by oss.sgi.com (8.12.5/8.12.3/Submit) id g6ICFrFZ028221 for linux-xfs-outgoing; Thu, 18 Jul 2002 05:15:53 -0700 X-Authentication-Warning: oss.sgi.com: majordomo set sender to owner-linux-xfs@oss.sgi.com using -f Received: from fruit.eu.org (qmailr@50dyn122.com21.casema.net [213.17.31.122]) by oss.sgi.com (8.12.5/8.12.5) with SMTP id g6ICF7Rw028191 for ; Thu, 18 Jul 2002 05:15:08 -0700 Received: (qmail 24231 invoked by uid 500); 18 Jul 2002 12:15:39 -0000 Date: Thu, 18 Jul 2002 14:15:38 +0200 From: Wessel Dankers To: linux-xfs@oss.sgi.com Subject: mapcheck (more spiffy) Message-ID: <20020718121538.GR5929@fruit.eu.org> Mail-Followup-To: linux-xfs@oss.sgi.com Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="2+K7TauFN1Oc3ugB" Content-Disposition: inline User-Agent: Mutt/1.4i X-oi: oi X-Spam-Status: No, hits=0.0 required=5.0 tests= version=2.20 X-Spam-Level: Sender: owner-linux-xfs@oss.sgi.com Precedence: bulk --2+K7TauFN1Oc3ugB Content-Type: multipart/mixed; boundary="bE2XbrxqIoa/xW9+" Content-Disposition: inline --bE2XbrxqIoa/xW9+ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline oi! I changed mapcheck.c a bit so it's a little less awkward to use. (attached) It now takes options, as follows: Usage: mapcheck [-afhnqvV] [file [...]] [dir [...]] -a, --all Fix all XFS filesystems -f, --force Force application -h, --help Display this message -n, --no-act Scan but don't change any files -q, --quiet Don't output anything except errors -v, --verbose Write verbose info to stdout -V, --version Write version to stdout HTH, HAND! -- Wessel Dankers --bE2XbrxqIoa/xW9+ Content-Type: text/x-csrc; charset=us-ascii Content-Disposition: attachment; filename="mapcheck.c" Content-Transfer-Encoding: quoted-printable /* This fixes up a filesystem which has bad data in the last block * of the file out beyond eof. This confuses some applications. * * Copyright Stephen Lord 2002, All Rights Reserved. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #define SCANDEPTH 42 int numfs =3D 32; char *fs =3D NULL; int verbose =3D 0, readonly =3D 0, quiet =3D 0, force =3D 0; int filecount =3D 0, fixedcount =3D 0, problemcount =3D 0; char *fixedmsg; static struct option options[] =3D { {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, {"verbose", 0, 0, 'v'}, {"quiet", 0, 0, 'q'}, {"force", 0, 0, 'f'}, {"no-act", 0, 0, 'n'}, {"all", 0, 0, 'a'}, {0, 0, 0, 0} }; void *xalloc(void *m, size_t n) { m =3D realloc(m, n); if(!m) { perror("malloc()"); exit(2); } return m; } char *xstrdup(const char *s) { char *m; if(!s) s =3D ""; m =3D strdup(s); if(!m) { perror("malloc()"); exit(2); } return m; } static int checker( const char *file, const struct stat64 *st, int flag, struct FTW *_) { int fd, blk; char *ptr, *ptr2, *ptr3; off64_t off, len; if(flag !=3D FTW_F) return 0; blk =3D st->st_blksize; len =3D st->st_size % blk; off =3D st->st_size - len; filecount++; if(!len) return 0; fd =3D open(file, O_RDWR|O_LARGEFILE); if(fd < 0) { if(verbose) perror(file); return problemcount++, 0; } ptr =3D mmap64(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, off); close(fd); if(ptr =3D=3D MAP_FAILED) { if(verbose) perror(file); return problemcount++, 0; } ptr2 =3D ptr + len; ptr3 =3D ptr + blk; for(; ptr2 < ptr3; ptr2++) { if(*ptr2 !=3D 0) { if(verbose) printf("%s\n", file); if(!readonly) memset(ptr + len, 0, blk - len); fixedcount++; break; } } munmap(ptr, len); return 0; } =20 void catcher(int sig) { printf("\rInterrupted: %d files scanned %d files %s %d errors\n", filecount, fixedcount, fixedmsg, problemcount); exit(128+sig); } void printer(int sig) { printf("\r%d files scanned %d files %s %d errors\033[K\r", filecount, fixedcount, fixedmsg, problemcount); if(!readonly) sync(); alarm(1); } char *isbadfs(struct fstab *fs) { struct stat64 st; if(lstat64(fs->fs_file, &st)) return strerror(errno); if(!strcasecmp(fs->fs_type, "sw")) return "swap partition"; if(strcasecmp(fs->fs_vfstype, "xfs")) return "not an XFS filesystem"; if(!strcasecmp(fs->fs_type, "ro")) return "readonly filesystem"; if(!strcasecmp(fs->fs_type, "xx")) return "to be ignored"; return NULL; } char *isbadfile(char *f) { struct fstab *fs =3D NULL; char *s, *reason =3D NULL; if(!f || !*f) f =3D "."; s =3D xalloc(NULL, PATH_MAX); if(realpath(f, s)) { f =3D xalloc(s, strlen(s)+1); for(;;) { fs =3D getfsfile(f); if(fs) break; s =3D strrchr(f, '/'); if(!s) break; s[s =3D=3D f && s[1]] =3D '\0'; } } else { reason =3D strerror(errno); } free(f); if(reason) return reason; if(!fs) return "can't find the filesystem"; if(force) return NULL; return isbadfs(fs); } int main(int argc, char **argv) { int i, all =3D 0, stop =3D 0; FILE *fh; struct fstab *fs; char *reason; optind =3D 0; while((i =3D getopt_long(argc, argv, "afhnqvV", options, NULL)) !=3D EOF) { switch(i) { case 'a': all =3D 1; break; case 'n': readonly =3D 1; break; case 'q': quiet =3D 1; break; case 'v': verbose =3D 1; break; case 'V': printf("$Id:$\n"); stop =3D 1; break; default: i =3D i !=3D 'h'; fh =3D i ? stderr : stdout; stop =3D i + 1; if(!i) fprintf(fh, "mapcheck: a program to fix a very specific XFS problem.\n= "); fprintf(fh, "Usage: %s [-afhnqvV] [file [...]] [dir [...]]\n", argv[0]); fprintf(fh, " -a, --all Fix all XFS filesystems\n"); fprintf(fh, " -f, --force Force application\n"); fprintf(fh, " -h, --help Display this message\n"); fprintf(fh, " -n, --no-act Scan but don't change any files\n"); fprintf(fh, " -q, --quiet Don't output anything except errors= \n"); fprintf(fh, " -v, --verbose Write verbose info to stdout\n"); fprintf(fh, " -V, --version Write version to stdout\n"); } } if(stop) return stop - 1; setbuf(stdout, NULL); signal(SIGINT, catcher); fixedmsg =3D readonly ? "found" : "fixed"; if(!quiet) { signal(SIGALRM, printer); alarm(1); } if(all) { if(!setfsent()) return perror("reading fstab"), 2; while((fs =3D getfsent())) { if((reason =3D isbadfs(fs))) { if(verbose) fprintf(stderr, "Skipping %s %s: %s\n", fs->fs_spec, fs->fs_file, reason); } else { if(!quiet) fprintf(stderr, "Scanning %s\n", fs->fs_file); nftw64(fs->fs_file, checker, SCANDEPTH, FTW_MOUNT|FTW_PHYS); } } endfsent(); } else if(argc =3D=3D optind) { if((reason =3D isbadfile("."))) return fprintf(stderr, "Can't scan .: %s\n", reason), 1; if(!quiet) fprintf(stderr, "Scanning current directory\n"); nftw64(".", checker, SCANDEPTH, FTW_MOUNT|FTW_PHYS); } for(i =3D optind; i < argc; i++) { if((reason =3D isbadfile(argv[i]))) return fprintf(stderr, "Can't scan %s: %s\n", argv[i], reason), 1; nftw64(argv[i], checker, SCANDEPTH, FTW_MOUNT|FTW_PHYS); } if(!quiet) { alarm(0); printer(0); putchar('\n'); } return 0; } --bE2XbrxqIoa/xW9+-- --2+K7TauFN1Oc3ugB Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQE9NrFqwSIMlSIEfyYRAhLOAJ9EKiO7avPkpMRvXwo7Dq+s0/nypwCdE3YF /fazfj2ydXBhpPEWPSRzsQ8= =oGt7 -----END PGP SIGNATURE----- --2+K7TauFN1Oc3ugB--