#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/ioctl.h>
#include <dev/disk.h>
#include <hfs/hfs_mount.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "fsck_hfs.h"
#include "dfalib/CheckHFS.h"
#define CACHE_IOSIZE 32768
#define CACHE_BLOCKS 128
#define CACHE_HASHSIZE 111
const char *cdevname;
char *progname;
char nflag;
char yflag;
char preen;
char force;
char quick;
char debug;
char hotroot;
char guiControl;
int upgrading;
int fsmodified;
int fsreadfd;
int fswritefd;
Cache_t fscache;
static int checkfilesys __P((char * filesys));
static int setup __P((char *dev));
static void usage __P((void));
void
main(argc, argv)
int argc;
char *argv[];
{
int ch;
int ret;
extern int optind;
if (progname = strrchr(*argv, '/'))
++progname;
else
progname = *argv;
while ((ch = getopt(argc, argv, "dfgnpqy")) != EOF) {
switch (ch) {
case 'd':
debug++;
break;
case 'f':
force++;
break;
case 'g':
guiControl++;
break;
case 'n':
nflag++;
yflag = 0;
break;
case 'p':
preen++;
break;
case 'q':
quick++;
break;
case 'y':
yflag++;
nflag = 0;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (guiControl)
debug = 0;
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
(void)signal(SIGINT, catch);
if (argc < 1) {
(void) fprintf(stderr, "%s: missing special-device\n", progname);
usage();
}
ret = 0;
while (argc-- > 0)
ret |= checkfilesys(blockcheck(*argv++));
exit(ret);
}
static int
checkfilesys(char * filesys)
{
int flags;
int result;
int chkLev, repLev, logLev;
flags = 0;
cdevname = filesys;
if (debug && preen)
pwarn("starting\n");
if (setup(filesys) == 0) {
if (preen)
pfatal("CAN'T CHECK FILE SYSTEM.");
return (0);
}
if (preen == 0) {
if (hotroot && !guiControl)
printf("** Root file system\n");
}
chkLev = kAlwaysCheck;
repLev = kMajorRepairs;
logLev = kVerboseLog;
if (yflag)
repLev = kMajorRepairs;
if (quick) {
chkLev = kNeverCheck;
repLev = kNeverRepair;
logLev = kFatalLog;
}
if (preen) {
repLev = kMinorRepairs;
chkLev = force ? kAlwaysCheck : kDirtyCheck;
logLev = kFatalLog;
}
if (debug)
logLev = kDebugLog;
if (nflag)
repLev = kNeverRepair;
result = CheckHFS(fsreadfd, fswritefd, chkLev, repLev, logLev, guiControl, &fsmodified);
if (!hotroot) {
ckfini(1);
if (quick) {
if (result == 0) {
pwarn("QUICKCHECK ONLY; FILESYSTEM CLEAN\n");
return (0);
} else if (result == R_Dirty) {
pwarn("QUICKCHECK ONLY; FILESYSTEM DIRTY\n");
return (DIRTYEXIT);
} else if (result == R_BadSig) {
pwarn("QUICKCHECK ONLY; NO HFS SIGNATURE FOUND\n");
return (DIRTYEXIT);
} else {
return (EEXIT);
}
}
} else {
struct statfs stfs_buf;
if (statfs("/", &stfs_buf) == 0)
flags = stfs_buf.f_flags;
else
flags = 0;
ckfini(flags & MNT_RDONLY);
}
if (!fsmodified)
return ((result == 0) ? 0 : EEXIT);
if (hotroot) {
struct hfs_mount_args args;
if (!preen)
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
if (flags & MNT_RDONLY) {
bzero(&args, sizeof(args));
flags |= MNT_UPDATE | MNT_RELOAD;
if (mount("hfs", "/", flags, &args) == 0)
return (0);
}
if (!preen)
printf("\n***** REBOOT NOW *****\n");
sync();
return (FIXEDROOTEXIT);
}
return (0);
}
static int
setup(char *dev)
{
struct stat statb;
int devBlockSize;
fswritefd = -1;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
return (0);
}
if ((statb.st_mode & S_IFMT) != S_IFCHR) {
pfatal("%s is not a character device", dev);
if (reply("CONTINUE") == 0)
return (0);
}
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
printf("Can't open %s: %s\n", dev, strerror(errno));
return (0);
}
if (preen == 0 && !guiControl)
printf("** %s", dev);
if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) {
fswritefd = -1;
if (preen)
pfatal("NO WRITE ACCESS");
if (!guiControl)
printf(" (NO WRITE)");
}
if (preen == 0 && !guiControl)
printf("\n");
ioctl(fsreadfd, DKIOCBLKSIZE, &devBlockSize);
if (CacheInit (&fscache, fsreadfd, fswritefd, devBlockSize,
CACHE_IOSIZE, CACHE_BLOCKS, CACHE_HASHSIZE) != EOK) {
pfatal("Can't initialize disk cache\n");
return (0);
}
return (1);
}
static void
usage()
{
(void) fprintf(stderr, "usage: %s [-dfnpquy] special-device\n", progname);
exit(1);
}