blob: f5e3e5e9a8c959a58a9eedb105e4b497e3930f3e [file] [log] [blame]
/*
* fsck_ext2fs - wrapper for e2fsck on FreeBSD
* Copyright (C) 2004,2006 Matthias Andree <matthias.andree@gmx.de>
* redistributable in accordance with the
* GNU General Public License v2
*
* $FreeBSD: ports/sysutils/e2fsprogs/files/fsck_ext2fs.c,v 1.5 2006/07/04 15:47:51 leeym Exp $
*
* Upstream: $Id: fsck_ext2fs.c,v 1.6 2006/07/02 11:37:49 emma Exp $
*
* format: gindent -kr
*/
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <errno.h>
__attribute__ ((noreturn))
static int die(const char *tag)
{
perror(tag);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv)
{
int ch, i = 1, force = 0, status, verbose = 0, t;
long block = 0;
enum { normal, preen, yes, no } mode = normal;
char *cmd[256];
pid_t pid;
cmd[0] = "/sbin/e2fsck";
while ((ch = getopt(argc, argv, "BFpfnyb:v")) != -1) {
switch (ch) {
case 'p':
mode = preen;
break;
case 'f':
force = 1;
break;
case 'n':
mode = no;
break;
case 'y':
mode = yes;
break;
case 'b':
block = atol(optarg);
break;
case 'v':
verbose++;
break;
case 'F':
/* e2fsck does not support background checking,
* hence exit with nonzero status to force
* the foreground check. */
exit(1);
case 'B':
default:
fprintf(stderr, "%s: unknown option -%c\n",
argv[0], optopt);
exit(EXIT_FAILURE);
}
}
if (force)
cmd[i++] = "-f";
switch (mode) {
case normal:
/* FreeBSD needs -f to force a check only in context
* with -p -- so map normal to force to match
* expectations */
if (!force)
cmd[i++] = "-f";
break;
case yes:
cmd[i++] = "-y";
break;
case no:
cmd[i++] = "-n";
break;
case preen:
cmd[i++] = "-p";
break;
}
if (block) {
static char b[30];
sprintf(b, "-b %ld", block);
cmd[i++] = b;
}
/* silently limit verbose to 15 so we don't overflow the cmd array */
if (verbose > 15)
verbose = 15;
for (t = verbose; t > 1; t--)
cmd[i++] = "-v";
while (optind < argc) {
cmd[i++] = argv[optind++];
/* sanity check so we don't overflow the cmd buffer */
if (i+1 == sizeof(cmd)/sizeof(cmd[0])) {
errno = E2BIG;
die(argv[0]);
}
}
cmd[i++] = 0;
if (verbose) {
for (i=0; cmd[i]; i++)
fputs(cmd[i], stderr),
fputc(' ', stderr);
fputc('\n', stderr);
}
pid = fork();
switch (pid) {
case -1:
/* error */
die("fork");
break;
case 0:
/* child */
(void) execv(cmd[0], cmd);
perror("execve");
_exit(127);
default:
/* parent */
if (pid != waitpid(pid, &status, 0))
die("waitpid");
if (WIFSIGNALED(status)
|| (WIFEXITED(status) && WEXITSTATUS(status) >= 4))
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}