Delete sbin directory

This commit is contained in:
Eirikr Hinngart 2025-05-30 23:00:01 -07:00 committed by GitHub
parent 6598721502
commit 2fd6a38d64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 0 additions and 10364 deletions

View File

@ -1,13 +0,0 @@
# $NetBSD: Makefile,v 1.18 2009/06/05 21:52:31 haad Exp $
PROG= fsck
SRCS= fsck.c fsutil.c preen.c
MAN= fsck.8
LDADD+=-lutil
DPADD+=${LIBUTIL}
LDADD+=-lprop
DPADD+=${LIBPROP}
.include <bsd.prog.mk>

View File

@ -1,36 +0,0 @@
/* $NetBSD: exitvalues.h,v 1.3 2015/06/21 03:33:22 dholland Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define FSCK_EXIT_OK 0
#define FSCK_EXIT_USAGE 1
#define FSCK_EXIT_UNRESOLVED 2
#define FSCK_EXIT_ROOT_CHANGED 4
#define FSCK_EXIT_CHECK_FAILED 8
#define FSCK_EXIT_SIGNALLED 12

View File

@ -1,176 +0,0 @@
.\" $NetBSD: fsck.8,v 1.38 2011/04/28 12:16:10 wiz Exp $
.\"
.\" Copyright (c) 1996 Christos Zoulas. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd February 17, 2010
.Dt FSCK 8
.Os
.Sh NAME
.Nm fsck
.Nd file system consistency check and interactive repair
.Sh SYNOPSIS
.Nm
.Op Fl dfnPpqvy
.Op Fl l Ar maxparallel
.Op Fl T Ar fstype:fsoptions
.Op Fl t Ar fstype
.Op Fl x Ar mountpoint
.Op special | node ...
.Sh DESCRIPTION
The
.Nm
command invokes file system-specific programs to check
the special devices listed in the
.Xr fstab 5
file or in the command line for consistency.
.Pp
It is normally used in the script
.Pa /etc/rc
during automatic reboot.
If no file systems are specified, and
.Dq preen
mode is enabled (
.Fl p
option)
.Nm
reads the table
.Pa /etc/fstab
to determine which file systems to check, in what order.
Only partitions in fstab that are mounted ``rw,'' ``rq'' or ``ro''
and that have non-zero pass number are checked.
File systems with pass number 1 (normally just the root file system)
are checked one at a time.
When pass 1 completes, all remaining file systems are checked,
running one process per disk drive.
By default, file systems which are already mounted read-write are not checked.
The disk drive containing each file system is inferred from the longest prefix
of the device name that ends in a digit; the remaining characters are assumed
to be the partition designator.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl d
Debugging mode.
Just print the commands without executing them.
.It Fl f
Force checking of file systems, even when they are marked clean (for file
systems that support this), or when they are mounted read-write.
.It Fl l Ar maxparallel
Limit the number of parallel checks to the number specified in
the following argument.
By default, the limit is the number of disks, running one process per disk.
If a smaller limit is given, the disks are checked round-robin,
one file system at a time.
.It Fl n
Causes
.Nm
to assume no as the answer to all operator questions, except "CONTINUE?".
.It Fl P
Display a progress meter for each file system check.
This option also disables parallel checking.
Note that progress meters are not supported by all file system types.
.It Fl p
Enter preen mode.
In preen mode,
.Nm
will check all file systems listed in
.Pa /etc/fstab
according to their pass number, and will make minor repairs without
human intervention.
.It Fl q
Quiet mode, do not output any messages for clean filesystems.
.It Fl T Ar fstype:fsoptions
List of comma separated file system specific options for the specified
file system type, in the same format as
.Xr mount 8 .
.It Fl t Ar fstype
Invoke
.Nm
only for the comma separated list of file system types.
If the list starts with
.Dq no
then invoke
.Nm
for the file system types that are not specified in the list.
.It Fl v
Print the commands before executing them.
.It Fl x Ar mountpoint
Exclude the filesystem which has a
.Ar mountpoint
the same as in
.Pa /etc/fstab .
Used only in
.Dq preen
mode.
.It Fl y
Causes
.Nm
to assume yes
as the answer to all operator questions.
.El
.Sh FILES
.Bl -tag -width /etc/fstab -compact
.It Pa /etc/fstab
file system table
.El
.Sh EXIT STATUS
.Nm
exits with
.Dv 0
on success.
Any major problems will cause
.Nm
to exit with the following non-zero
.Xr exit 3
codes, so as to alert any invoking program or script that human
intervention is required.
.Bl -tag -width XXXX
.It Dv 1
Usage problem.
.It Dv 2
Unresolved errors while checking the filesystem.
Re-running
.Nm
on the filesystem(s) is required.
.It Dv 4
The root filesystem was changed in the process of checking, and updating the
mount was unsuccessful.
A reboot (without sync) is required.
.It Dv 8
The filesystem check has failed, and a subsequent check is required
that will require human intervention.
.It Dv 12
.Nm
exited because of the result of a signal (usually
.Dv SIGINT
or
.Dv SIGQUIT
from the terminal).
.El
.Sh SEE ALSO
.Xr fstab 5 ,
.Xr fsck_ext2fs 8 ,
.Xr fsck_ffs 8 ,
.Xr fsck_lfs 8 ,
.Xr fsck_msdos 8 ,
.Xr mount 8

View File

@ -1,614 +0,0 @@
/* $NetBSD: fsck.c,v 1.52 2014/10/25 22:00:19 mlelstv Exp $ */
/*
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
* Copyright (c) 1980, 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* From: @(#)mount.c 8.19 (Berkeley) 4/19/94
* From: NetBSD: mount.c,v 1.24 1995/11/18 03:34:29 cgd Exp
*
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: fsck.c,v 1.52 2014/10/25 22:00:19 mlelstv Exp $");
#endif /* not lint */
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/queue.h>
#include <sys/wait.h>
#define FSTYPENAMES
#define FSCKNAMES
#include <sys/disk.h>
#include <sys/disklabel.h>
#include <sys/ioctl.h>
#include <err.h>
#include <errno.h>
#include <fstab.h>
#include <fcntl.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <util.h>
#include "pathnames.h"
#include "fsutil.h"
#include "exitvalues.h"
static enum { IN_LIST, NOT_IN_LIST } which = NOT_IN_LIST;
TAILQ_HEAD(fstypelist, entry) opthead, selhead, omhead;
struct entry {
char *type;
char *options;
TAILQ_ENTRY(entry) entries;
};
static int maxrun = 0;
static char *options = NULL;
static int flags = 0;
static int checkfs(const char *, const char *, const char *, void *, pid_t *);
static int selected(const char *);
static int omitted(const char *);
static void addoption(char *);
static const char *getoptions(const char *);
static void addentry(struct fstypelist *, const char *, const char *);
static void maketypelist(char *);
static void catopt(char **, const char *);
static void mangle(char *, int *, const char ** volatile *, int *);
static const char *getfslab(const char *);
__dead static void usage(void);
static void *isok(struct fstab *);
int
main(int argc, char *argv[])
{
struct fstab *fs;
int i, rval;
const char *vfstype = NULL;
char globopt[3];
int ret = FSCK_EXIT_OK;
char buf[MAXPATHLEN];
globopt[0] = '-';
globopt[2] = '\0';
TAILQ_INIT(&selhead);
TAILQ_INIT(&opthead);
TAILQ_INIT(&omhead);
while ((i = getopt(argc, argv, "dfl:nPpqT:t:vx:y")) != -1) {
switch (i) {
case 'd':
flags |= CHECK_DEBUG;
continue;
case 'f':
flags |= CHECK_FORCE;
break;
case 'n':
flags |= CHECK_NOFIX;
break;
case 'p':
flags |= CHECK_PREEN;
break;
case 'P':
flags |= CHECK_PROGRESS;
break;
case 'q':
break;
case 'l':
maxrun = atoi(optarg);
continue;
case 'T':
if (*optarg)
addoption(optarg);
continue;
case 't':
if (TAILQ_FIRST(&selhead) != NULL)
errx(1, "only one -t option may be specified.");
maketypelist(optarg);
vfstype = optarg;
continue;
case 'v':
flags |= CHECK_VERBOSE;
continue;
case 'x':
addentry(&omhead, optarg, "");
continue;
case 'y':
break;
case '?':
default:
usage();
/* NOTREACHED */
}
/* Pass option to fsck_xxxfs */
globopt[1] = i;
catopt(&options, globopt);
}
/* Don't do progress meters if we're debugging. */
if (flags & CHECK_DEBUG)
flags &= ~CHECK_PROGRESS;
/*
* If progress meters are being used, force max parallel to 1
* so the progress meter outputs don't interfere with one another.
*/
if (flags & CHECK_PROGRESS)
maxrun = 1;
#if defined(__minix)
/* parallel checking heuristic doesn't work for minix currently */
maxrun = 1;
#endif /* !defined(__minix) */
argc -= optind;
argv += optind;
if (argc == 0)
return checkfstab(flags, maxrun, isok, checkfs);
#define BADTYPE(type) \
(strcmp(type, FSTAB_RO) && \
strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))
for (; argc--; argv++) {
const char *spec, *spec2, *mntpt, *type, *cp;
char device[MAXPATHLEN];
spec = mntpt = *argv;
spec2 = getfsspecname(buf, sizeof(buf), spec);
if (spec2 == NULL)
spec2 = spec;
cp = strrchr(spec2, '/');
if (cp == 0) {
(void)snprintf(device, sizeof(device), "%s%s",
_PATH_DEV, spec2);
spec2 = device;
}
fs = getfsfile(spec);
if (fs == NULL)
fs = getfsspec(spec);
if (fs == NULL && spec != spec2) {
fs = getfsspec(spec2);
spec = spec2;
}
if (fs) {
spec = getfsspecname(buf, sizeof(buf), fs->fs_spec);
if (spec == NULL)
err(FSCK_EXIT_CHECK_FAILED, "%s", buf);
type = fs->fs_vfstype;
if (BADTYPE(fs->fs_type))
errx(FSCK_EXIT_CHECK_FAILED,
"%s has unknown file system type.",
spec);
} else {
if (vfstype == NULL)
vfstype = getfslab(spec);
type = vfstype;
}
rval = checkfs(type, blockcheck(spec), *argv, NULL, NULL);
if (rval > ret)
ret = rval;
}
return ret;
}
static void *
isok(struct fstab *fs)
{
if (fs->fs_passno == 0)
return NULL;
if (BADTYPE(fs->fs_type))
return NULL;
if (!selected(fs->fs_vfstype))
return NULL;
if (omitted(fs->fs_file))
return NULL;
return fs;
}
static int
checkfs(const char *vfst, const char *spec, const char *mntpt, void *auxarg,
pid_t *pidp)
{
/* List of directories containing fsck_xxx subcommands. */
static const char *edirs[] = {
#ifdef RESCUEDIR
RESCUEDIR,
#endif
_PATH_SBIN,
_PATH_USRSBIN,
#if defined(__minix)
"/usr/pkg/sbin/",
#endif /* defined(__minix) */
NULL
};
const char ** volatile argv, **edir;
const char * volatile vfstype = vfst;
pid_t pid;
int argc, i, status, maxargc;
char *optb;
char *volatile optbuf;
char execname[MAXPATHLEN + 1], execbase[MAXPATHLEN];
const char *extra = getoptions(vfstype);
if (!strcmp(vfstype, "ufs"))
vfstype = MOUNT_UFS;
optb = NULL;
if (options)
catopt(&optb, options);
if (extra)
catopt(&optb, extra);
optbuf = optb;
maxargc = 64;
argv = emalloc(sizeof(char *) * maxargc);
(void) snprintf(execbase, sizeof(execbase), "fsck_%s", vfstype);
argc = 0;
argv[argc++] = execbase;
if (optbuf)
mangle(optbuf, &argc, &argv, &maxargc);
argv[argc++] = spec;
argv[argc] = NULL;
if (flags & (CHECK_DEBUG|CHECK_VERBOSE)) {
(void)printf("start %s %swait", mntpt,
pidp ? "no" : "");
for (i = 0; i < argc; i++)
(void)printf(" %s", argv[i]);
(void)printf("\n");
}
switch (pid = vfork()) {
case -1: /* Error. */
warn("vfork");
if (optbuf)
free(optbuf);
free(argv);
return FSCK_EXIT_CHECK_FAILED;
case 0: /* Child. */
if ((flags & CHECK_FORCE) == 0) {
struct statvfs sfs;
/*
* if mntpt is a mountpoint of a mounted file
* system and it's mounted read-write, skip it
* unless -f is given.
*/
if ((statvfs(mntpt, &sfs) == 0) &&
(strcmp(mntpt, sfs.f_mntonname) == 0) &&
((sfs.f_flag & MNT_RDONLY) == 0)) {
printf(
"%s: file system is mounted read-write on %s; not checking\n",
spec, mntpt);
if ((flags & CHECK_PREEN) && auxarg != NULL)
_exit(FSCK_EXIT_OK); /* fsck -p */
else
_exit(FSCK_EXIT_CHECK_FAILED); /* fsck [[-p] ...] */
}
}
if (flags & CHECK_DEBUG)
_exit(FSCK_EXIT_OK);
/* Go find an executable. */
edir = edirs;
do {
(void)snprintf(execname,
sizeof(execname), "%s/%s", *edir, execbase);
execv(execname, (char * const *)__UNCONST(argv));
if (errno != ENOENT) {
if (spec)
warn("exec %s for %s", execname, spec);
else
warn("exec %s", execname);
}
} while (*++edir != NULL);
if (errno == ENOENT) {
if (spec)
warn("exec %s for %s", execname, spec);
else
warn("exec %s", execname);
}
_exit(FSCK_EXIT_CHECK_FAILED);
/* NOTREACHED */
default: /* Parent. */
if (optbuf)
free(optbuf);
free(argv);
if (pidp) {
*pidp = pid;
return FSCK_EXIT_OK;
}
if (waitpid(pid, &status, 0) < 0) {
warn("waitpid");
return FSCK_EXIT_CHECK_FAILED;
}
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0)
return WEXITSTATUS(status);
}
else if (WIFSIGNALED(status)) {
warnx("%s: %s", spec, strsignal(WTERMSIG(status)));
return FSCK_EXIT_CHECK_FAILED;
}
break;
}
return FSCK_EXIT_OK;
}
static int
selected(const char *type)
{
struct entry *e;
/* If no type specified, it's always selected. */
TAILQ_FOREACH(e, &selhead, entries)
if (!strcmp(e->type, type))
return which == IN_LIST ? 1 : 0;
return which == IN_LIST ? 0 : 1;
}
static int
omitted(const char *mountedon)
{
struct entry *e;
/* If no type specified, it's always selected. */
TAILQ_FOREACH(e, &omhead, entries)
if (!strcmp(e->type, mountedon))
return 1;
return 0;
}
static const char *
getoptions(const char *type)
{
struct entry *e;
TAILQ_FOREACH(e, &opthead, entries)
if (!strcmp(e->type, type))
return e->options;
return "";
}
static void
addoption(char *optstr)
{
char *newoptions;
struct entry *e;
if ((newoptions = strchr(optstr, ':')) == NULL)
errx(1, "Invalid option string");
*newoptions++ = '\0';
TAILQ_FOREACH(e, &opthead, entries)
if (!strcmp(e->type, optstr)) {
catopt(&e->options, newoptions);
return;
}
addentry(&opthead, optstr, newoptions);
}
static void
addentry(struct fstypelist *list, const char *type, const char *opts)
{
struct entry *e;
e = emalloc(sizeof(struct entry));
e->type = estrdup(type);
e->options = estrdup(opts);
TAILQ_INSERT_TAIL(list, e, entries);
}
static void
maketypelist(char *fslist)
{
char *ptr;
if ((fslist == NULL) || (fslist[0] == '\0'))
errx(1, "empty type list");
if (fslist[0] == 'n' && fslist[1] == 'o') {
fslist += 2;
which = NOT_IN_LIST;
}
else
which = IN_LIST;
while ((ptr = strsep(&fslist, ",")) != NULL)
addentry(&selhead, ptr, "");
}
static void
catopt(char **sp, const char *o)
{
char *s;
size_t i, j;
s = *sp;
if (s) {
i = strlen(s);
j = i + 1 + strlen(o) + 1;
s = erealloc(s, j);
(void)snprintf(s + i, j, ",%s", o);
} else
s = estrdup(o);
*sp = s;
}
static void
mangle(char *opts, int *argcp, const char ** volatile *argvp, int *maxargcp)
{
char *p, *s;
int argc, maxargc;
const char **argv;
argc = *argcp;
argv = *argvp;
maxargc = *maxargcp;
for (s = opts; (p = strsep(&s, ",")) != NULL;) {
/* Always leave space for one more argument and the NULL. */
if (argc >= maxargc - 3) {
maxargc <<= 1;
argv = erealloc(argv, maxargc * sizeof(char *));
}
if (*p != '\0') {
if (*p == '-') {
argv[argc++] = p;
p = strchr(p, '=');
if (p) {
*p = '\0';
argv[argc++] = p+1;
}
} else {
argv[argc++] = "-o";
argv[argc++] = p;
}
}
}
*argcp = argc;
*argvp = argv;
*maxargcp = maxargc;
}
static const char *
getfslab(const char *str)
{
#if defined(__minix)
errx(1, "cannot determine vfstype under minix");
#else
static struct dkwedge_info dkw;
struct disklabel dl;
int fd;
char p;
const char *vfstype;
u_char t;
/* deduce the file system type from the disk label */
if ((fd = open(str, O_RDONLY)) == -1)
err(1, "cannot open `%s'", str);
/* First check to see if it's a wedge. */
if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) {
/* Yup, this is easy. */
(void) close(fd);
return (dkw.dkw_ptype);
}
if (ioctl(fd, DIOCGDINFO, &dl) == -1)
err(1, "cannot get disklabel for `%s'", str);
(void) close(fd);
p = str[strlen(str) - 1];
if ((p - 'a') >= dl.d_npartitions)
errx(1, "partition `%s' is not defined on disk", str);
if ((t = dl.d_partitions[p - 'a'].p_fstype) >= FSMAXTYPES)
errx(1, "partition `%s' is not of a legal vfstype",
str);
if ((vfstype = fscknames[t]) == NULL)
errx(1, "vfstype `%s' on partition `%s' is not supported",
fstypenames[t], str);
return vfstype;
#endif /* defined(__minix) */
}
static void
usage(void)
{
static const char common[] =
"[-dfnPpqvy] [-x excludemount] [-l maxparallel] [-T fstype:fsoptions]\n\t\t[-t fstype]";
(void)fprintf(stderr, "usage: %s %s [special|node]...\n",
getprogname(), common);
exit(FSCK_EXIT_USAGE);
}

View File

@ -1,306 +0,0 @@
/* $NetBSD: fsutil.c,v 1.26 2015/06/21 04:01:40 dholland Exp $ */
/*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: fsutil.c,v 1.26 2015/06/21 04:01:40 dholland Exp $");
#endif /* not lint */
/*
* used by sbin/fsck
* used by sbin/fsck_ext2fs
* used by sbin/fsck_ffs
* used by sbin/fsck_lfs
* used by sbin/fsck_msdos
* used by sbin/fsck_v7fs
* used by sbin/fsdb
* used by usr.sbin/quotacheck
*/
#include <sys/param.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <fstab.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>
#include <util.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "fsutil.h"
#include "exitvalues.h"
volatile sig_atomic_t returntosingle;
static const char *dev = NULL;
static int hot = 0;
static int preen = 0;
int quiet;
#define F_ERROR 0x80000000
void
setcdevname(const char *cd, int pr)
{
dev = cd;
preen = pr;
}
const char *
cdevname(void)
{
return dev;
}
int
hotroot(void)
{
return hot;
}
/*VARARGS*/
void
errexit(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
(void) vfprintf(stderr, fmt, ap);
va_end(ap);
(void)fprintf(stderr, "\n");
exit(FSCK_EXIT_CHECK_FAILED);
}
void
vmsg(int fatal, const char *fmt, va_list ap)
{
int serr = fatal & F_ERROR;
int serrno = errno;
fatal &= ~F_ERROR;
if (!fatal && preen)
(void)printf("%s: ", dev);
if (quiet && !preen) {
(void)printf("** %s (vmsg)\n", dev);
quiet = 0;
}
(void) vprintf(fmt, ap);
if (serr)
printf(" (%s)", strerror(serrno));
if (fatal && preen)
(void) printf("\n");
if (fatal && preen) {
(void) printf(
"%s: UNEXPECTED INCONSISTENCY; RUN %s MANUALLY.\n",
dev, getprogname());
exit(FSCK_EXIT_CHECK_FAILED);
}
}
/*VARARGS*/
void
pfatal(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vmsg(1, fmt, ap);
va_end(ap);
}
/*VARARGS*/
void
pwarn(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vmsg(0, fmt, ap);
va_end(ap);
}
void
perr(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vmsg(1 | F_ERROR, fmt, ap);
va_end(ap);
}
void
panic(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vmsg(1, fmt, ap);
va_end(ap);
exit(FSCK_EXIT_CHECK_FAILED);
}
const char *
blockcheck(const char *origname)
{
#if defined(__minix)
return origname;
#else
struct stat stslash, stblock, stchar;
const char *newname, *raw, *cooked;
struct fstab *fsp;
int retried = 0;
ssize_t len;
char cbuf[MAXPATHLEN];
static char buf[MAXPATHLEN];
hot = 0;
if (stat("/", &stslash) < 0) {
perr("Can't stat `/'");
return (origname);
}
len = readlink(origname, cbuf, sizeof(cbuf)-1);
if (len == -1) {
newname = origname;
} else {
cbuf[len] = '\0';
newname = cbuf;
}
retry:
if (stat(newname, &stblock) < 0) {
perr("Can't stat `%s'", newname);
return origname;
}
if (S_ISBLK(stblock.st_mode)) {
if (stslash.st_dev == stblock.st_rdev)
hot++;
raw = getdiskrawname(buf, sizeof(buf), newname);
if (raw == NULL) {
perr("Can't convert to raw `%s'", newname);
return origname;
}
if (stat(raw, &stchar) < 0) {
perr("Can't stat `%s'", raw);
return origname;
}
if (S_ISCHR(stchar.st_mode)) {
return raw;
} else {
perr("%s is not a character device\n", raw);
return origname;
}
} else if (S_ISCHR(stblock.st_mode) && !retried) {
cooked = getdiskcookedname(cbuf, sizeof(cbuf), newname);
if (cooked == NULL) {
perr("Can't convert to cooked `%s'", newname);
return origname;
} else
newname = cooked;
retried++;
goto retry;
} else if ((fsp = getfsfile(newname)) != 0 && !retried) {
newname = getfsspecname(cbuf, sizeof(cbuf), fsp->fs_spec);
if (newname == NULL)
perr("%s", buf);
retried++;
goto retry;
}
/*
* Not a block or character device, just return name and
* let the user decide whether to use it.
*/
return origname;
#endif /* defined(__minix) */
}
const char *
print_mtime(time_t t)
{
static char b[128];
char *p = ctime(&t);
if (p != NULL)
(void)snprintf(b, sizeof(b), "%12.12s %4.4s ", &p[4], &p[20]);
else
(void)snprintf(b, sizeof(b), "%lld ", (long long)t);
return b;
}
void
catch(int n)
{
if (ckfinish) (*ckfinish)(0);
_exit(FSCK_EXIT_SIGNALLED);
}
/*
* When preening, allow a single quit to signal
* a special exit after filesystem checks complete
* so that reboot sequence may be interrupted.
*/
void
catchquit(int n)
{
static const char msg[] =
"returning to single-user after filesystem check\n";
int serrno = errno;
(void)write(STDOUT_FILENO, msg, sizeof(msg) - 1);
returntosingle = 1;
(void)signal(SIGQUIT, SIG_DFL);
errno = serrno;
}
/*
* Ignore a single quit signal; wait and flush just in case.
* Used by child processes in preen.
*/
void
voidquit(int n)
{
int serrno = errno;
sleep(1);
(void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGQUIT, SIG_DFL);
errno = serrno;
}

View File

@ -1,57 +0,0 @@
/* $NetBSD: fsutil.h,v 1.20 2015/06/21 03:58:36 dholland Exp $ */
/*
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdarg.h>
#include <signal.h>
void errexit(const char *, ...) __printflike(1, 2) __dead;
void pfatal(const char *, ...) __printflike(1, 2);
void pwarn(const char *, ...) __printflike(1, 2);
void perr(const char *, ...) __printflike(1, 2);
void panic(const char *, ...) __printflike(1, 2) __dead;
void vmsg(int, const char *, va_list) __printflike(2, 0);
const char *blockcheck(const char *);
const char *cdevname(void);
void setcdevname(const char *, int);
int hotroot(void);
const char *print_mtime(time_t);
#define CHECK_PREEN 1
#define CHECK_VERBOSE 2
#define CHECK_DEBUG 4
#define CHECK_FORCE 8
#define CHECK_PROGRESS 16
#define CHECK_NOFIX 32
struct fstab;
int checkfstab(int, int, void *(*)(struct fstab *),
int (*) (const char *, const char *, const char *, void *, pid_t *));
void (*ckfinish)(int);
extern volatile sig_atomic_t returntosingle;
void catch(int) __dead;
void catchquit(int);
void voidquit(int);

View File

@ -1,205 +0,0 @@
/* $NetBSD: partutil.c,v 1.15 2015/06/03 17:53:23 martin Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: partutil.c,v 1.15 2015/06/03 17:53:23 martin Exp $");
#include <sys/types.h>
#include <sys/param.h>
#include <sys/disklabel.h>
#include <sys/disk.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <disktab.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <util.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <prop/proplib.h>
#include "partutil.h"
/*
* Convert disklabel geometry info to disk_geom.
*/
static void
label2geom(struct disk_geom *geo, const struct disklabel *lp)
{
geo->dg_secperunit = lp->d_secperunit;
geo->dg_secsize = lp->d_secsize;
geo->dg_nsectors = lp->d_nsectors;
geo->dg_ntracks = lp->d_ntracks;
geo->dg_ncylinders = lp->d_ncylinders;
geo->dg_secpercyl = lp->d_secpercyl;
geo->dg_pcylinders = lp->d_ncylinders;
geo->dg_sparespertrack = lp->d_sparespertrack;
geo->dg_sparespercyl = lp->d_sparespercyl;
geo->dg_acylinders = lp->d_acylinders;
}
/*
* Set what we need to know about disk geometry.
*/
static void
dict2geom(struct disk_geom *geo, prop_dictionary_t dict)
{
(void)memset(geo, 0, sizeof(struct disk_geom));
prop_dictionary_get_int64(dict, "sectors-per-unit",
&geo->dg_secperunit);
prop_dictionary_get_uint32(dict, "sector-size", &geo->dg_secsize);
prop_dictionary_get_uint32(dict, "sectors-per-track",
&geo->dg_nsectors);
prop_dictionary_get_uint32(dict, "tracks-per-cylinder",
&geo->dg_ntracks);
prop_dictionary_get_uint32(dict, "cylinders-per-unit",
&geo->dg_ncylinders);
}
int
getdiskinfo(const char *s, int fd, const char *dt, struct disk_geom *geo,
struct dkwedge_info *dkw)
{
struct disklabel lab;
struct disklabel *lp = &lab;
prop_dictionary_t disk_dict, geom_dict;
#if !defined(__minix)
struct stat sb;
const struct partition *pp;
int ptn, error;
#endif /* defined(__minix) */
if (dt) {
#if defined(__minix)
errx(1, "minix doesn't know about disk types (%s)", dt);
#else
lp = getdiskbyname(dt);
if (lp == NULL)
errx(1, "unknown disk type `%s'", dt);
#endif /* defined(__minix) */
}
/* Get disk description dictionary */
#if !defined(__minix)
error = prop_dictionary_recv_ioctl(fd, DIOCGDISKINFO, &disk_dict);
/* fail quickly if the device does not exist at all */
if (error == ENXIO)
return -1;
if (error) {
#else
if (1) {
#endif /* !defined(__minix) */
/*
* Ask for disklabel if DIOCGDISKINFO failed. This is
* compatibility call and can be removed when all devices
* will support DIOCGDISKINFO.
* cgd, ccd pseudo disk drives doesn't support DIOCGDDISKINFO
*/
if (ioctl(fd, DIOCGDINFO, lp) == -1) {
if (errno != ENXIO)
warn("DIOCGDINFO on %s failed", s);
return -1;
}
label2geom(geo, lp);
} else {
geom_dict = prop_dictionary_get(disk_dict, "geometry");
dict2geom(geo, geom_dict);
}
if (dkw == NULL)
return 0;
/* Get info about partition/wedge */
if (ioctl(fd, DIOCGWEDGEINFO, dkw) != -1) {
/* DIOCGWEDGEINFO didn't fail, we're done */
return 0;
}
if (ioctl(fd, DIOCGDINFO, lp) == -1) {
err(1, "Please implement DIOCGWEDGEINFO or "
"DIOCGDINFO for disk device %s", s);
}
#if !defined(__minix)
/* DIOCGDINFO didn't fail */
(void)memset(dkw, 0, sizeof(*dkw));
if (stat(s, &sb) == -1)
return 0;
ptn = strchr(s, '\0')[-1] - 'a';
if ((unsigned)ptn >= lp->d_npartitions ||
(devminor_t)ptn != DISKPART(sb.st_rdev))
return 0;
pp = &lp->d_partitions[ptn];
if (ptn != getrawpartition()) {
dkw->dkw_offset = pp->p_offset;
dkw->dkw_size = pp->p_size;
} else {
dkw->dkw_offset = 0;
dkw->dkw_size = geo->dg_secperunit;
}
dkw->dkw_parent[0] = '*';
strlcpy(dkw->dkw_ptype, getfstypename(pp->p_fstype),
sizeof(dkw->dkw_ptype));
#endif /* !defined(__minix) */
return 0;
}
int
getdisksize(const char *name, u_int *secsize, off_t *mediasize)
{
char buf[MAXPATHLEN];
struct disk_geom geo;
int fd, error;
if ((fd = opendisk(name, O_RDONLY, buf, sizeof(buf), 0)) == -1)
return -1;
error = getdiskinfo(name, fd, NULL, &geo, NULL);
close(fd);
if (error)
return error;
*secsize = geo.dg_secsize;
*mediasize = geo.dg_secsize * geo.dg_secperunit;
return 0;
}

View File

@ -1,42 +0,0 @@
/* $NetBSD: partutil.h,v 1.3 2014/12/29 16:27:43 christos Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PARTUTIL_H_
#define _PARTUTIL_H_
__BEGIN_DECLS
struct dkwedge_info;
struct disk_geom;
int getdiskinfo(const char *, int, const char *,
struct disk_geom *, struct dkwedge_info *);
int getdisksize(const char *, u_int *, off_t *);
__END_DECLS
#endif /* _PARTUTIL_H_ */

View File

@ -1,28 +0,0 @@
/* $NetBSD: pathnames.h,v 1.2 2009/10/21 01:07:46 snj Exp $ */
/*
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _PATH_SBIN "/sbin"
#define _PATH_USRSBIN "/usr/sbin"

View File

@ -1,374 +0,0 @@
/* $NetBSD: preen.c,v 1.32 2015/06/21 04:01:40 dholland Exp $ */
/*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: preen.c,v 1.32 2015/06/21 04:01:40 dholland Exp $");
#endif
#endif /* not lint */
/*
* used by sbin/fsck
* used by usr.sbin/quotacheck
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/queue.h>
#include <sys/disk.h>
#include <sys/ioctl.h>
#include <err.h>
#include <ctype.h>
#include <fstab.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <util.h>
#include "fsutil.h"
#include "exitvalues.h"
struct partentry {
TAILQ_ENTRY(partentry) p_entries;
char *p_devname; /* device name */
char *p_mntpt; /* mount point */
char *p_type; /* file system type */
void *p_auxarg; /* auxiliary argument */
};
TAILQ_HEAD(part, partentry) badh;
struct diskentry {
TAILQ_ENTRY(diskentry) d_entries;
char *d_name; /* disk base name */
TAILQ_HEAD(prt, partentry) d_part; /* list of partitions on disk */
int d_pid; /* 0 or pid of fsck proc */
};
TAILQ_HEAD(diskinfo, diskentry) diskh;
static int nrun = 0, ndisks = 0;
static struct diskentry *finddisk(const char *);
static void addpart(const char *, const char *, const char *, void *);
static int startdisk(struct diskentry *,
int (*)(const char *, const char *, const char *, void *, pid_t *));
static void printpart(void);
int
checkfstab(int flags, int maxrun, void *(*docheck)(struct fstab *),
int (*checkit)(const char *, const char *, const char *, void *, pid_t *))
{
struct fstab *fs;
struct diskentry *d, *nextdisk;
struct partentry *p;
int ret, pid, retcode, passno, sumstatus, status;
void *auxarg;
const char *name;
int error = FSCK_EXIT_OK;
TAILQ_INIT(&badh);
TAILQ_INIT(&diskh);
sumstatus = FSCK_EXIT_OK;
for (passno = 1; passno <= 2; passno++) {
if (setfsent() == 0) {
warnx("Can't open checklist file: %s", _PATH_FSTAB);
return FSCK_EXIT_CHECK_FAILED;
}
while ((fs = getfsent()) != 0) {
char buf[MAXPATHLEN];
const char *fsspec;
if ((auxarg = (*docheck)(fs)) == NULL)
continue;
fsspec = getfsspecname(buf, sizeof(buf), fs->fs_spec);
if (fsspec == NULL) {
warn("%s", buf);
return FSCK_EXIT_CHECK_FAILED;
}
name = blockcheck(fsspec);
if (flags & CHECK_DEBUG)
printf("pass %d, name %s\n", passno, name);
if ((flags & CHECK_PREEN) == 0 ||
(passno == 1 && fs->fs_passno == 1)) {
if (name == NULL) {
if (flags & CHECK_PREEN)
return FSCK_EXIT_CHECK_FAILED;
else
continue;
}
sumstatus = (*checkit)(fs->fs_vfstype,
name, fs->fs_file, auxarg, NULL);
if (sumstatus) {
if ((flags & CHECK_NOFIX) == 0)
return sumstatus;
else if (error < sumstatus)
error = sumstatus;
}
} else if (passno == 2 && fs->fs_passno > 1) {
if (name == NULL) {
(void) fprintf(stderr,
"BAD DISK NAME %s\n", fsspec);
sumstatus = FSCK_EXIT_CHECK_FAILED;
continue;
}
addpart(fs->fs_vfstype, name, fs->fs_file,
auxarg);
}
}
if ((flags & CHECK_PREEN) == 0)
return error;
}
if (flags & CHECK_DEBUG)
printpart();
if (flags & CHECK_PREEN) {
if (maxrun == 0)
maxrun = ndisks;
if (maxrun > ndisks)
maxrun = ndisks;
nextdisk = TAILQ_FIRST(&diskh);
for (passno = 0; passno < maxrun; ++passno) {
if ((ret = startdisk(nextdisk, checkit)) != 0) {
if ((flags & CHECK_NOFIX) == 0)
return ret;
else if (error < ret)
error = ret;
}
nextdisk = TAILQ_NEXT(nextdisk, d_entries);
}
while ((pid = wait(&status)) != -1) {
TAILQ_FOREACH(d, &diskh, d_entries)
if (d->d_pid == pid)
break;
if (d == NULL) {
warnx("Unknown pid %d", pid);
continue;
}
if (WIFEXITED(status))
retcode = WEXITSTATUS(status);
else
retcode = 0;
p = TAILQ_FIRST(&d->d_part);
if (flags & (CHECK_DEBUG|CHECK_VERBOSE))
(void) printf("done %s: %s (%s) = 0x%x\n",
p->p_type, p->p_devname, p->p_mntpt,
status);
if (WIFSIGNALED(status)) {
(void) fprintf(stderr,
"%s: %s (%s): EXITED WITH SIGNAL %d\n",
p->p_type, p->p_devname, p->p_mntpt,
WTERMSIG(status));
retcode = FSCK_EXIT_SIGNALLED;
}
TAILQ_REMOVE(&d->d_part, p, p_entries);
if (retcode != 0) {
TAILQ_INSERT_TAIL(&badh, p, p_entries);
sumstatus |= retcode;
} else {
free(p->p_type);
free(p->p_devname);
free(p);
}
d->d_pid = 0;
nrun--;
if (TAILQ_FIRST(&d->d_part) == NULL)
ndisks--;
if (nextdisk == NULL) {
if (TAILQ_FIRST(&d->d_part) != NULL) {
if ((ret = startdisk(d, checkit)) != 0)
{
if ((flags & CHECK_NOFIX) == 0)
return ret;
else if (error < ret)
error = ret;
}
}
} else if (nrun < maxrun && nrun < ndisks) {
for ( ;; ) {
nextdisk = TAILQ_NEXT(nextdisk,
d_entries);
if (nextdisk == NULL)
nextdisk = TAILQ_FIRST(&diskh);
if (TAILQ_FIRST(&nextdisk->d_part)
!= NULL && nextdisk->d_pid == 0)
break;
}
if ((ret = startdisk(nextdisk, checkit)) != 0)
{
if ((flags & CHECK_NOFIX) == 0)
return ret;
else if (error < ret)
error = ret;
}
}
}
}
if (sumstatus) {
p = TAILQ_FIRST(&badh);
if (p == NULL)
return sumstatus;
(void) fprintf(stderr,
"THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
TAILQ_NEXT(p, p_entries) ? "S" : "",
"UNEXPECTED INCONSISTENCY:");
TAILQ_FOREACH(p, &badh, p_entries)
(void) fprintf(stderr,
"%s: %s (%s)%s", p->p_type, p->p_devname,
p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n");
return sumstatus;
}
(void) endfsent();
return error;
}
static struct diskentry *
finddisk(const char *name)
{
const char *p;
size_t len, dlen;
struct diskentry *d;
#if !defined(__minix)
char buf[MAXPATHLEN];
struct dkwedge_info dkw;
int fd;
if ((fd = opendisk(name, O_RDONLY, buf, sizeof(buf), 0)) != -1) {
if (ioctl(fd, DIOCGWEDGEINFO, &dkw) != -1)
name = dkw.dkw_parent;
(void)close(fd);
}
#endif /* !defined(__minix) */
for (dlen = len = strlen(name), p = name + len - 1; p >= name; --p)
if (isdigit((unsigned char)*p)) {
len = p - name + 1;
break;
}
if (p < name)
len = dlen;
TAILQ_FOREACH(d, &diskh, d_entries)
if (strncmp(d->d_name, name, len) == 0 && d->d_name[len] == 0)
return d;
d = emalloc(sizeof(*d));
d->d_name = estrdup(name);
d->d_name[len] = '\0';
TAILQ_INIT(&d->d_part);
d->d_pid = 0;
TAILQ_INSERT_TAIL(&diskh, d, d_entries);
ndisks++;
return d;
}
static void
printpart(void)
{
struct diskentry *d;
struct partentry *p;
TAILQ_FOREACH(d, &diskh, d_entries) {
(void) printf("disk %s:", d->d_name);
TAILQ_FOREACH(p, &d->d_part, p_entries)
(void) printf(" %s", p->p_devname);
(void) printf("\n");
}
}
static void
addpart(const char *type, const char *dev, const char *mntpt, void *auxarg)
{
struct diskentry *d = finddisk(dev);
struct partentry *p;
TAILQ_FOREACH(p, &d->d_part, p_entries)
if (strcmp(p->p_devname, dev) == 0) {
warnx("%s in fstab more than once!", dev);
return;
}
p = emalloc(sizeof(*p));
p->p_devname = estrdup(dev);
p->p_mntpt = estrdup(mntpt);
p->p_type = estrdup(type);
p->p_auxarg = auxarg;
TAILQ_INSERT_TAIL(&d->d_part, p, p_entries);
}
static int
startdisk(struct diskentry *d,
int (*checkit)(const char *, const char *, const char *, void *, pid_t *))
{
struct partentry *p = TAILQ_FIRST(&d->d_part);
int rv;
while ((rv = (*checkit)(p->p_type, p->p_devname, p->p_mntpt,
p->p_auxarg, &d->d_pid)) != 0 && nrun > 0)
sleep(10);
if (rv == 0)
nrun++;
return rv;
}

View File

@ -1,168 +0,0 @@
/* $NetBSD: progress.c,v 1.5 2009/04/11 06:48:36 lukem Exp $ */
/*-
* Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Luke Mewburn; by Chris Gilbert; and by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SMALL
#include <sys/cdefs.h>
__RCSID("$NetBSD: progress.c,v 1.5 2009/04/11 06:48:36 lukem Exp $");
/*
* File system independent fsck progress bar routines.
*/
#include <sys/param.h>
#include <sys/tty.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "progress.h"
static size_t ttywidth = 80;
static int progress_onoff;
static int progress_lowlim;
static int progress_highlim;
#define BUFLEFT (sizeof(buf) - len)
void
progress_switch(int onoff)
{
progress_onoff = onoff;
}
void
progress_init(void)
{
progress_setrange(0, 100);
}
/* Set both low and high limit. */
void
progress_setrange(int lowlim, int highlim)
{
progress_lowlim = lowlim;
progress_highlim = highlim;
}
/* Previous high limit becomes new low limit; set new high limit. */
void
progress_sethighlim(int highlim)
{
progress_setrange(progress_highlim, highlim);
}
/*
* Display a progress bar, assuming that current/total represents a
* percentage in the range [progress_lowlim .. progress_highlim].
*/
void
progress_bar(const char *dev, const char *label, off_t current, off_t total)
{
static int lastpercentage = -1;
char buf[256];
int len, percentage;
int barlength;
int i;
int lengthextras;
#define BAROVERHEAD 10 /* non-* portion of progress bar */
/*
* stars should contain at least sizeof(buf) - BAROVERHEAD
* entries.
*/
static const char stars[] =
"*****************************************************************************"
"*****************************************************************************"
"*****************************************************************************";
if (progress_onoff == 0)
return;
len = 0;
lengthextras = strlen(dev) + (label != NULL ? strlen(label) : 0);
percentage = progress_lowlim +
(current * (progress_highlim - progress_lowlim)) / total;
percentage = MAX(percentage, 0);
percentage = MIN(percentage, 100);
if (percentage == lastpercentage)
return;
lastpercentage = percentage;
len += snprintf(buf + len, BUFLEFT, "%s: ", dev);
if (label != NULL)
len += snprintf(buf + len, BUFLEFT, "%s ", label);
barlength = MIN(sizeof(buf) - 1, ttywidth) - BAROVERHEAD - lengthextras;
if (barlength > 0) {
i = barlength * percentage / 100;
len += snprintf(buf + len, BUFLEFT,
"|%.*s%*s| ", i, stars, barlength - i, "");
}
len += snprintf(buf + len, BUFLEFT, "%3d%%\r", percentage);
write(fileno(stdout), buf, len);
}
void
progress_done(void)
{
char buf[256];
int len;
if (progress_onoff == 0)
return;
len = MIN(sizeof(buf) - 2, ttywidth);
memset(buf, ' ', len);
buf[len] = '\r';
buf[len + 1] = '\0';
write(fileno(stdout), buf, len + 1);
}
void
progress_ttywidth(int a)
{
struct winsize winsize;
int oerrno = errno;
if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1 &&
winsize.ws_col != 0)
ttywidth = winsize.ws_col;
else
ttywidth = 80;
errno = oerrno;
}
#endif /* ! SMALL */

View File

@ -1,42 +0,0 @@
/* $NetBSD: progress.h,v 1.3 2008/04/28 20:23:08 martin Exp $ */
/*-
* Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Luke Mewburn; by Chris Gilbert; and by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* File system independent fsck progress bar routines.
*/
void progress_init(void);
void progress_setrange(int, int);
void progress_sethighlim(int);
void progress_switch(int);
void progress_ttywidth(int);
void progress_bar(const char *, const char *, off_t, off_t);
void progress_done(void);

View File

@ -1,24 +0,0 @@
# $NetBSD: Makefile,v 1.17 2014/03/04 21:07:22 joerg Exp $
# @(#)Makefile 8.1 (Berkeley) 6/5/93
.include <bsd.own.mk>
PROG= fsck_ext2fs
MAN= fsck_ext2fs.8
SRCS= dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \
pass5.c fsutil.c setup.c utilities.c ext2fs_bswap.c
FSCK= ${NETBSDSRCDIR}/sbin/fsck
CPPFLAGS+= -I${FSCK}
.PATH: ${NETBSDSRCDIR}/sys/ufs/ext2fs ${FSCK}
CWARNFLAGS.clang+= -Wno-error=tautological-pointer-compare
.if defined(__MINIX)
# To compile with clang 3.4
NOCLANGERROR= yes
.endif # defined(__MINIX)
.include <bsd.prog.mk>
LDADD+=-lutil
DPADD+=${LIBUTIL}

View File

@ -1,723 +0,0 @@
/* $NetBSD: dir.c,v 1.28 2013/06/23 07:28:36 dholland Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)dir.c 8.5 (Berkeley) 12/8/94";
#else
__RCSID("$NetBSD: dir.c,v 1.28 2013/06/23 07:28:36 dholland Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ufs/dir.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs_dir.h>
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include "fsck.h"
#include "fsutil.h"
#include "extern.h"
const char *lfname = "lost+found";
int lfmode = 01700;
struct ext2fs_dirtemplate emptydir = {
.dot_ino = 0,
.dot_reclen = UFS_DIRBLKSIZ,
};
struct ext2fs_dirtemplate dirhead = {
.dot_ino = 0,
.dot_reclen = 12,
.dot_namlen = 1,
.dot_type = EXT2_FT_DIR,
.dot_name = ".",
.dotdot_ino = 0,
.dotdot_reclen = UFS_DIRBLKSIZ - 12,
.dotdot_namlen = 2,
.dotdot_type = EXT2_FT_DIR,
.dotdot_name = "..",
};
#undef UFS_DIRBLKSIZ
static int expanddir(struct ext2fs_dinode *, char *);
static void freedir(ino_t, ino_t);
static struct ext2fs_direct *fsck_readdir(struct inodesc *);
static struct bufarea *getdirblk(daddr_t, long);
static int lftempname(char *, ino_t);
static int mkentry(struct inodesc *);
static int chgino(struct inodesc *);
/*
* Propagate connected state through the tree.
*/
void
propagate(void)
{
struct inoinfo **inpp, *inp, *pinp;
struct inoinfo **inpend;
/*
* Create a list of children for each directory.
*/
inpend = &inpsort[inplast];
for (inpp = inpsort; inpp < inpend; inpp++) {
inp = *inpp;
if (inp->i_parent == 0 ||
inp->i_number == EXT2_ROOTINO)
continue;
pinp = getinoinfo(inp->i_parent);
inp->i_parentp = pinp;
inp->i_sibling = pinp->i_child;
pinp->i_child = inp;
}
inp = getinoinfo(EXT2_ROOTINO);
while (inp) {
statemap[inp->i_number] = DFOUND;
if (inp->i_child &&
statemap[inp->i_child->i_number] == DSTATE)
inp = inp->i_child;
else if (inp->i_sibling)
inp = inp->i_sibling;
else
inp = inp->i_parentp;
}
}
/*
* Scan each entry in a directory block.
*/
int
dirscan(struct inodesc *idesc)
{
struct ext2fs_direct *dp;
struct bufarea *bp;
int dsize, n;
long blksiz;
char *dbuf = NULL;
if ((dbuf = malloc(sblock.e2fs_bsize)) == NULL)
err(8, "Can't allocate directory block");
if (idesc->id_type != DATA)
errexit("wrong type to dirscan %d", idesc->id_type);
if (idesc->id_entryno == 0 &&
(idesc->id_filesize & (sblock.e2fs_bsize - 1)) != 0)
idesc->id_filesize = roundup(idesc->id_filesize, sblock.e2fs_bsize);
blksiz = idesc->id_numfrags * sblock.e2fs_bsize;
if (chkrange(idesc->id_blkno, idesc->id_numfrags)) {
idesc->id_filesize -= blksiz;
free(dbuf);
return (SKIP);
}
idesc->id_loc = 0;
for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
dsize = fs2h16(dp->e2d_reclen);
memcpy(dbuf, dp, (size_t)dsize);
idesc->id_dirp = (struct ext2fs_direct *)dbuf;
if ((n = (*idesc->id_func)(idesc)) & ALTERED) {
bp = getdirblk(idesc->id_blkno, blksiz);
memcpy(bp->b_un.b_buf + idesc->id_loc - dsize, dbuf,
(size_t)dsize);
dirty(bp);
sbdirty();
}
if (n & STOP) {
free(dbuf);
return (n);
}
}
free(dbuf);
return (idesc->id_filesize > 0 ? KEEPON : STOP);
}
/*
* get next entry in a directory.
*/
static struct ext2fs_direct *
fsck_readdir(struct inodesc *idesc)
{
struct ext2fs_direct *dp, *ndp;
struct bufarea *bp;
long size, blksiz, fix, dploc;
blksiz = idesc->id_numfrags * sblock.e2fs_bsize;
bp = getdirblk(idesc->id_blkno, blksiz);
if (idesc->id_loc % sblock.e2fs_bsize == 0 && idesc->id_filesize > 0 &&
idesc->id_loc < blksiz) {
dp = (struct ext2fs_direct *)(bp->b_un.b_buf + idesc->id_loc);
if (dircheck(idesc, dp))
goto dpok;
if (idesc->id_fix == IGNORE)
return (0);
fix = dofix(idesc, "DIRECTORY CORRUPTED");
bp = getdirblk(idesc->id_blkno, blksiz);
dp = (struct ext2fs_direct *)(bp->b_un.b_buf + idesc->id_loc);
dp->e2d_reclen = h2fs16(sblock.e2fs_bsize);
dp->e2d_ino = 0;
dp->e2d_namlen = 0;
dp->e2d_type = 0;
dp->e2d_name[0] = '\0';
if (fix)
dirty(bp);
idesc->id_loc += sblock.e2fs_bsize;
idesc->id_filesize -= sblock.e2fs_bsize;
return (dp);
}
dpok:
if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz)
return NULL;
dploc = idesc->id_loc;
dp = (struct ext2fs_direct *)(bp->b_un.b_buf + dploc);
idesc->id_loc += fs2h16(dp->e2d_reclen);
idesc->id_filesize -= fs2h16(dp->e2d_reclen);
if ((idesc->id_loc % sblock.e2fs_bsize) == 0)
return (dp);
ndp = (struct ext2fs_direct *)(bp->b_un.b_buf + idesc->id_loc);
if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
dircheck(idesc, ndp) == 0) {
size = sblock.e2fs_bsize - (idesc->id_loc % sblock.e2fs_bsize);
idesc->id_loc += size;
idesc->id_filesize -= size;
if (idesc->id_fix == IGNORE)
return (0);
fix = dofix(idesc, "DIRECTORY CORRUPTED");
bp = getdirblk(idesc->id_blkno, blksiz);
dp = (struct ext2fs_direct *)(bp->b_un.b_buf + dploc);
dp->e2d_reclen = h2fs16(fs2h16(dp->e2d_reclen) + size);
if (fix)
dirty(bp);
}
return (dp);
}
/*
* Verify that a directory entry is valid.
* This is a superset of the checks made in the kernel.
*/
int
dircheck(struct inodesc *idesc, struct ext2fs_direct *dp)
{
int size;
char *cp;
int spaceleft;
u_int16_t reclen = fs2h16(dp->e2d_reclen);
spaceleft = sblock.e2fs_bsize - (idesc->id_loc % sblock.e2fs_bsize);
if (fs2h32(dp->e2d_ino) > maxino ||
reclen == 0 ||
reclen > spaceleft ||
(reclen & 0x3) != 0)
return (0);
if (dp->e2d_ino == 0)
return (1);
if (sblock.e2fs.e2fs_rev < E2FS_REV1 ||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) == 0)
if (dp->e2d_type != 0)
return (1);
size = EXT2FS_DIRSIZ(dp->e2d_namlen);
if (reclen < size ||
idesc->id_filesize < size /* ||
dp->e2d_namlen > EXT2FS_MAXNAMLEN */)
return (0);
for (cp = dp->e2d_name, size = 0; size < dp->e2d_namlen; size++)
if (*cp == '\0' || (*cp++ == '/'))
return (0);
return (1);
}
void
direrror(ino_t ino, const char *errmesg)
{
fileerror(ino, ino, errmesg);
}
void
fileerror(ino_t cwd, ino_t ino, const char *errmesg)
{
struct ext2fs_dinode *dp;
char pathbuf[MAXPATHLEN + 1];
pwarn("%s ", errmesg);
pinode(ino);
printf("\n");
getpathname(pathbuf, sizeof(pathbuf), cwd, ino);
if ((ino < EXT2_FIRSTINO && ino != EXT2_ROOTINO) || ino > maxino) {
pfatal("NAME=%s\n", pathbuf);
return;
}
dp = ginode(ino);
if (ftypeok(dp))
pfatal("%s=%s\n",
(fs2h16(dp->e2di_mode) & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf);
else
pfatal("NAME=%s\n", pathbuf);
}
void
adjust(struct inodesc *idesc, short lcnt)
{
struct ext2fs_dinode *dp;
dp = ginode(idesc->id_number);
if (fs2h16(dp->e2di_nlink) == lcnt) {
if (linkup(idesc->id_number, (ino_t)0) == 0)
clri(idesc, "UNREF", 0);
} else {
pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname :
((fs2h16(dp->e2di_mode) & IFMT) == IFDIR ? "DIR" : "FILE"));
pinode(idesc->id_number);
printf(" COUNT %d SHOULD BE %d",
fs2h16(dp->e2di_nlink), fs2h16(dp->e2di_nlink) - lcnt);
if (preen) {
if (lcnt < 0) {
printf("\n");
pfatal("LINK COUNT INCREASING");
}
printf(" (ADJUSTED)\n");
}
if (preen || reply("ADJUST") == 1) {
dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) - lcnt);
inodirty();
}
}
}
static int
mkentry(struct inodesc *idesc)
{
struct ext2fs_direct *dirp = idesc->id_dirp;
struct ext2fs_direct newent;
int newlen, oldlen;
newent.e2d_type = 0; /* XXX gcc */
newent.e2d_namlen = strlen(idesc->id_name);
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
newent.e2d_type = inot2ext2dt(typemap[idesc->id_parent]);
newlen = EXT2FS_DIRSIZ(newent.e2d_namlen);
if (dirp->e2d_ino != 0)
oldlen = EXT2FS_DIRSIZ(dirp->e2d_namlen);
else
oldlen = 0;
if (fs2h16(dirp->e2d_reclen) - oldlen < newlen)
return (KEEPON);
newent.e2d_reclen = h2fs16(fs2h16(dirp->e2d_reclen) - oldlen);
dirp->e2d_reclen = h2fs16(oldlen);
dirp = (struct ext2fs_direct *)(((char *)dirp) + oldlen);
dirp->e2d_ino = h2fs32(idesc->id_parent); /* ino to be entered is in id_parent */
dirp->e2d_reclen = newent.e2d_reclen;
dirp->e2d_namlen = newent.e2d_namlen;
dirp->e2d_type = newent.e2d_type;
memcpy(dirp->e2d_name, idesc->id_name, (size_t)(dirp->e2d_namlen));
return (ALTERED|STOP);
}
static int
chgino(struct inodesc *idesc)
{
struct ext2fs_direct *dirp = idesc->id_dirp;
u_int16_t namlen = dirp->e2d_namlen;
if (strlen(idesc->id_name) != namlen ||
strncmp(dirp->e2d_name, idesc->id_name, (int)namlen))
return (KEEPON);
dirp->e2d_ino = h2fs32(idesc->id_parent);
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
dirp->e2d_type = inot2ext2dt(typemap[idesc->id_parent]);
else
dirp->e2d_type = 0;
return (ALTERED|STOP);
}
int
linkup(ino_t orphan, ino_t parentdir)
{
struct ext2fs_dinode *dp;
int lostdir;
ino_t oldlfdir;
struct inodesc idesc;
char tempname[BUFSIZ];
memset(&idesc, 0, sizeof(struct inodesc));
dp = ginode(orphan);
lostdir = (fs2h16(dp->e2di_mode) & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
if (preen && inosize(dp) == 0)
return (0);
if (preen)
printf(" (RECONNECTED)\n");
else
if (reply("RECONNECT") == 0)
return (0);
if (lfdir == 0) {
dp = ginode(EXT2_ROOTINO);
idesc.id_name = lfname;
idesc.id_type = DATA;
idesc.id_func = findino;
idesc.id_number = EXT2_ROOTINO;
if ((ckinode(dp, &idesc) & FOUND) != 0) {
lfdir = idesc.id_parent;
} else {
pwarn("NO lost+found DIRECTORY");
if (preen || reply("CREATE")) {
lfdir = allocdir(EXT2_ROOTINO, (ino_t)0, lfmode);
if (lfdir != 0) {
if (makeentry(EXT2_ROOTINO, lfdir, lfname) != 0) {
if (preen)
printf(" (CREATED)\n");
} else {
freedir(lfdir, EXT2_ROOTINO);
lfdir = 0;
if (preen)
printf("\n");
}
}
}
}
if (lfdir == 0) {
pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY");
printf("\n\n");
return (0);
}
}
dp = ginode(lfdir);
if ((fs2h16(dp->e2di_mode) & IFMT) != IFDIR) {
pfatal("lost+found IS NOT A DIRECTORY");
if (reply("REALLOCATE") == 0)
return (0);
oldlfdir = lfdir;
if ((lfdir = allocdir(EXT2_ROOTINO, (ino_t)0, lfmode)) == 0) {
pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
return (0);
}
if ((changeino(EXT2_ROOTINO, lfname, lfdir) & ALTERED) == 0) {
pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
return (0);
}
inodirty();
idesc.id_type = ADDR;
idesc.id_func = pass4check;
idesc.id_number = oldlfdir;
adjust(&idesc, lncntp[oldlfdir] + 1);
lncntp[oldlfdir] = 0;
dp = ginode(lfdir);
}
if (statemap[lfdir] != DFOUND) {
pfatal("SORRY. NO lost+found DIRECTORY\n\n");
return (0);
}
(void)lftempname(tempname, orphan);
if (makeentry(lfdir, orphan, tempname) == 0) {
pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
printf("\n\n");
return (0);
}
lncntp[orphan]--;
if (lostdir) {
if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 &&
parentdir != (ino_t)-1)
(void)makeentry(orphan, lfdir, "..");
dp = ginode(lfdir);
dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) +1);
inodirty();
lncntp[lfdir]++;
pwarn("DIR I=%llu CONNECTED. ", (unsigned long long)orphan);
if (parentdir != (ino_t)-1)
printf("PARENT WAS I=%llu\n",
(unsigned long long)parentdir);
if (preen == 0)
printf("\n");
}
return (1);
}
/*
* fix an entry in a directory.
*/
int
changeino(ino_t dir, const char *name, ino_t newnum)
{
struct inodesc idesc;
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = DATA;
idesc.id_func = chgino;
idesc.id_number = dir;
idesc.id_fix = DONTKNOW;
idesc.id_name = name;
idesc.id_parent = newnum; /* new value for name */
return (ckinode(ginode(dir), &idesc));
}
/*
* make an entry in a directory
*/
int
makeentry(ino_t parent, ino_t ino, const char *name)
{
struct ext2fs_dinode *dp;
struct inodesc idesc;
char pathbuf[MAXPATHLEN + 1];
if ((parent < EXT2_FIRSTINO && parent != EXT2_ROOTINO)
|| parent >= maxino ||
(ino < EXT2_FIRSTINO && ino < EXT2_ROOTINO) || ino >= maxino)
return (0);
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = DATA;
idesc.id_func = mkentry;
idesc.id_number = parent;
idesc.id_parent = ino; /* this is the inode to enter */
idesc.id_fix = DONTKNOW;
idesc.id_name = name;
dp = ginode(parent);
if (inosize(dp) % sblock.e2fs_bsize) {
inossize(dp, roundup(inosize(dp), sblock.e2fs_bsize));
inodirty();
}
if ((ckinode(dp, &idesc) & ALTERED) != 0)
return (1);
getpathname(pathbuf, sizeof(pathbuf), parent, parent);
dp = ginode(parent);
if (expanddir(dp, pathbuf) == 0)
return (0);
return (ckinode(dp, &idesc) & ALTERED);
}
/*
* Attempt to expand the size of a directory
*/
static int
expanddir(struct ext2fs_dinode *dp, char *name)
{
daddr_t lastbn, newblk;
struct bufarea *bp;
char *firstblk;
lastbn = ext2_lblkno(&sblock, inosize(dp));
if (lastbn >= EXT2FS_NDADDR - 1 || fs2h32(dp->e2di_blocks[lastbn]) == 0 ||
inosize(dp) == 0) {
return (0);
}
if ((newblk = allocblk()) == 0) {
return (0);
}
dp->e2di_blocks[lastbn + 1] = dp->e2di_blocks[lastbn];
dp->e2di_blocks[lastbn] = h2fs32(newblk);
inossize(dp, inosize(dp) + sblock.e2fs_bsize);
inosnblock(dp, inonblock(dp) + btodb(sblock.e2fs_bsize));
bp = getdirblk(fs2h32(dp->e2di_blocks[lastbn + 1]),
sblock.e2fs_bsize);
if (bp->b_errs)
goto bad;
if ((firstblk = malloc(sblock.e2fs_bsize)) == NULL)
err(8, "cannot allocate first block");
memcpy(firstblk, bp->b_un.b_buf, sblock.e2fs_bsize);
bp = getdirblk(newblk, sblock.e2fs_bsize);
if (bp->b_errs) {
free(firstblk);
goto bad;
}
memcpy(bp->b_un.b_buf, firstblk, sblock.e2fs_bsize);
free(firstblk);
dirty(bp);
bp = getdirblk(fs2h32(dp->e2di_blocks[lastbn + 1]),
sblock.e2fs_bsize);
if (bp->b_errs)
goto bad;
emptydir.dot_reclen = h2fs16(sblock.e2fs_bsize);
memcpy(bp->b_un.b_buf, &emptydir, sizeof emptydir);
pwarn("NO SPACE LEFT IN %s", name);
if (preen)
printf(" (EXPANDED)\n");
else if (reply("EXPAND") == 0)
goto bad;
dirty(bp);
inodirty();
return (1);
bad:
dp->e2di_blocks[lastbn] = dp->e2di_blocks[lastbn + 1];
dp->e2di_blocks[lastbn + 1] = 0;
inossize(dp, inosize(dp) - sblock.e2fs_bsize);
inosnblock(dp, inonblock(dp) - btodb(sblock.e2fs_bsize));
freeblk(newblk);
return (0);
}
/*
* allocate a new directory
*/
int
allocdir(ino_t parent, ino_t request, int mode)
{
ino_t ino;
struct ext2fs_dinode *dp;
struct bufarea *bp;
struct ext2fs_dirtemplate *dirp;
ino = allocino(request, IFDIR|mode);
dirhead.dot_reclen = h2fs16(12); /* XXX */
dirhead.dotdot_reclen = h2fs16(sblock.e2fs_bsize - 12); /* XXX */
dirhead.dot_namlen = 1;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
dirhead.dot_type = EXT2_FT_DIR;
else
dirhead.dot_type = 0;
dirhead.dotdot_namlen = 2;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
dirhead.dotdot_type = EXT2_FT_DIR;
else
dirhead.dotdot_type = 0;
dirp = &dirhead;
dirp->dot_ino = h2fs32(ino);
dirp->dotdot_ino = h2fs32(parent);
dp = ginode(ino);
bp = getdirblk(fs2h32(dp->e2di_blocks[0]), sblock.e2fs_bsize);
if (bp->b_errs) {
freeino(ino);
return (0);
}
memcpy(bp->b_un.b_buf, dirp, sizeof(struct ext2fs_dirtemplate));
dirty(bp);
dp->e2di_nlink = h2fs16(2);
inodirty();
if (ino == EXT2_ROOTINO) {
lncntp[ino] = fs2h16(dp->e2di_nlink);
cacheino(dp, ino);
return(ino);
}
if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) {
freeino(ino);
return (0);
}
cacheino(dp, ino);
statemap[ino] = statemap[parent];
if (statemap[ino] == DSTATE) {
lncntp[ino] = fs2h16(dp->e2di_nlink);
lncntp[parent]++;
}
dp = ginode(parent);
dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) + 1);
inodirty();
return (ino);
}
/*
* free a directory inode
*/
static void
freedir(ino_t ino, ino_t parent)
{
struct ext2fs_dinode *dp;
if (ino != parent) {
dp = ginode(parent);
dp->e2di_nlink = h2fs16(fs2h16(dp->e2di_nlink) - 1);
inodirty();
}
freeino(ino);
}
/*
* generate a temporary name for the lost+found directory.
*/
static int
lftempname(char *bufp, ino_t ino)
{
ino_t in;
char *cp;
int namlen;
cp = bufp + 2;
for (in = maxino; in > 0; in /= 10)
cp++;
*--cp = 0;
namlen = cp - bufp;
in = ino;
while (cp > bufp) {
*--cp = (in % 10) + '0';
in /= 10;
}
*cp = '#';
return (namlen);
}
/*
* Get a directory block.
* Insure that it is held until another is requested.
*/
static struct bufarea *
getdirblk(daddr_t blkno, long size)
{
if (pdirbp != 0)
pdirbp->b_flags &= ~B_INUSE;
pdirbp = getdatablk(blkno, size);
return (pdirbp);
}

View File

@ -1,75 +0,0 @@
/* $NetBSD: extern.h,v 1.8 2012/11/25 19:42:14 jakllsch Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
* Copyright (c) 1994 James A. Jegers
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
void adjust(struct inodesc *, short);
int allocblk(void);
int allocdir(ino_t, ino_t, int);
void blkerror(ino_t, const char *, daddr_t);
int bread(int, char *, daddr_t, long);
void bufinit(void);
void bwrite(int, char *, daddr_t, long);
void cacheino(struct ext2fs_dinode *, ino_t);
int changeino(ino_t, const char *, ino_t);
int chkrange(daddr_t, int);
void ckfini(int);
int ckinode(struct ext2fs_dinode *, struct inodesc *);
void clri(struct inodesc *, const char *, int);
int dircheck(struct inodesc *, struct ext2fs_direct *);
void direrror(ino_t, const char *);
int dirscan(struct inodesc *);
int dofix(struct inodesc *, const char *);
void fileerror(ino_t, ino_t, const char *);
int findino(struct inodesc *);
int findname(struct inodesc *);
void flush(int, struct bufarea *);
void freeblk(daddr_t);
void freeino(ino_t);
void freeinodebuf(void);
int ftypeok(struct ext2fs_dinode *);
void getpathname(char *, size_t, ino_t, ino_t);
void inocleanup(void);
void inodirty(void);
u_int64_t inosize(struct ext2fs_dinode *);
void inossize(struct ext2fs_dinode *, u_int64_t);
int linkup(ino_t, ino_t);
int makeentry(ino_t, ino_t, const char *);
void pass1(void);
void pass1b(void);
void pass2(void);
void pass3(void);
void pass4(void);
int pass1check(struct inodesc *);
int pass4check(struct inodesc *);
void pass5(void);
void pinode(ino_t);
void propagate(void);
int reply(const char *);
void resetinodebuf(void);
int setup(const char *);
struct ext2fs_dinode * getnextinode(ino_t);
uint64_t inonblock(struct ext2fs_dinode *);
void inosnblock(struct ext2fs_dinode *, uint64_t);

View File

@ -1,238 +0,0 @@
/* $NetBSD: fsck.h,v 1.15 2009/10/19 18:41:08 bouyer Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)fsck.h 8.1 (Berkeley) 6/5/93
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @(#)fsck.h 8.1 (Berkeley) 6/5/93
*/
#define MAXDUP 10 /* limit on dup blks (per inode) */
#define MAXBAD 10 /* limit on bad blks (per inode) */
#define MAXBUFSPACE 80*1024 /* maximum space to allocate to buffers */
#define INOBUFSIZE 128*1024 /* size of buffer to read inodes in pass1 */
#ifndef BUFSIZ
#define BUFSIZ 1024
#endif
#define USTATE 01 /* inode not allocated */
#define FSTATE 02 /* inode is file */
#define DSTATE 03 /* inode is directory */
#define DFOUND 04 /* directory found during descent */
#define DCLEAR 05 /* directory is to be cleared */
#define FCLEAR 06 /* file is to be cleared */
/*
* buffer cache structure.
*/
struct bufarea {
struct bufarea *b_next; /* free list queue */
struct bufarea *b_prev; /* free list queue */
daddr_t b_bno;
int b_size;
int b_errs;
int b_flags;
union {
char *b_buf; /* buffer space */
/* XXX ondisk32 */
int32_t *b_indir; /* indirect block */
struct ext2fs *b_fs; /* super block */
struct ext2_gd *b_cgd; /* cylinder group descriptor */
struct ext2fs_dinode *b_dinode; /* inode block */
} b_un;
char b_dirty;
};
#define B_INUSE 1
#define MINBUFS 5 /* minimum number of buffers required */
struct bufarea bufhead; /* head of list of other blks in filesys */
struct bufarea sblk; /* file system superblock */
struct bufarea asblk; /* first alternate superblock */
struct bufarea *pdirbp; /* current directory contents */
struct bufarea *pbp; /* current inode block */
struct bufarea *getdatablk(daddr_t, long);
struct m_ext2fs sblock;
#define dirty(bp) (bp)->b_dirty = 1
#define initbarea(bp) \
(bp)->b_dirty = 0; \
(bp)->b_bno = (daddr_t)-1; \
(bp)->b_flags = 0;
#define sbdirty() copyback_sb(&sblk); sblk.b_dirty = 1
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
struct inodesc {
enum fixstate id_fix; /* policy on fixing errors */
int (*id_func) /* function to be applied to blocks of inode */
(struct inodesc *);
ino_t id_number; /* inode number described */
ino_t id_parent; /* for DATA nodes, their parent */
daddr_t id_blkno; /* current block number being examined */
int id_numfrags; /* number of frags contained in block */
quad_t id_filesize; /* for DATA nodes, the size of the directory */
int id_loc; /* for DATA nodes, current location in dir */
int id_entryno; /* for DATA nodes, current entry number */
struct ext2fs_direct *id_dirp; /* for DATA nodes, ptr to current entry */
const char *id_name; /* for DATA nodes, name to find or enter */
char id_type; /* type of descriptor, DATA or ADDR */
};
/* file types */
#define DATA 1
#define ADDR 2
/*
* Linked list of duplicate blocks.
*
* The list is composed of two parts. The first part of the
* list (from duplist through the node pointed to by muldup)
* contains a single copy of each duplicate block that has been
* found. The second part of the list (from muldup to the end)
* contains duplicate blocks that have been found more than once.
* To check if a block has been found as a duplicate it is only
* necessary to search from duplist through muldup. To find the
* total number of times that a block has been found as a duplicate
* the entire list must be searched for occurrences of the block
* in question. The following diagram shows a sample list where
* w (found twice), x (found once), y (found three times), and z
* (found once) are duplicate block numbers:
*
* w -> y -> x -> z -> y -> w -> y
* ^ ^
* | |
* duplist muldup
*/
struct dups {
struct dups *next;
daddr_t dup;
};
struct dups *duplist; /* head of dup list */
struct dups *muldup; /* end of unique duplicate dup block numbers */
/*
* Linked list of inodes with zero link counts.
*/
struct zlncnt {
struct zlncnt *next;
ino_t zlncnt;
};
struct zlncnt *zlnhead; /* head of zero link count list */
/*
* Inode cache data structures.
*/
struct inoinfo {
struct inoinfo *i_nexthash; /* next entry in hash chain */
struct inoinfo *i_child, *i_sibling, *i_parentp;
ino_t i_number; /* inode number of this entry */
ino_t i_parent; /* inode number of parent */
ino_t i_dotdot; /* inode number of `..' */
u_int64_t i_isize; /* size of inode */
u_int i_numblks; /* size of block array in bytes */
/* XXX ondisk32 */
int32_t i_blks[1]; /* actually longer */
} **inphead, **inpsort;
long numdirs, listmax, inplast;
long dev_bsize; /* computed value of DEV_BSIZE */
long secsize; /* actual disk sector size */
char nflag; /* assume a no response */
char yflag; /* assume a yes response */
int bflag; /* location of alternate super block */
int Uflag; /* resolve user names */
int debug; /* output debugging info */
int preen; /* just fix normal inconsistencies */
char havesb; /* superblock has been read */
char skipclean; /* skip clean file systems if preening */
int fsmodified; /* 1 => write done to file system */
int fsreadfd; /* file descriptor for reading file system */
int fswritefd; /* file descriptor for writing file system */
int rerun; /* rerun fsck. Only used in non-preen mode */
daddr_t maxfsblock; /* number of blocks in the file system */
char *blockmap; /* ptr to primary blk allocation map */
ino_t maxino; /* number of inodes in file system */
ino_t lastino; /* last inode in use */
char *statemap; /* ptr to inode state table */
u_char *typemap; /* ptr to inode type table */
int16_t *lncntp; /* ptr to link count table */
ino_t lfdir; /* lost & found directory inode number */
extern const char *lfname; /* lost & found directory name */
extern int lfmode; /* lost & found directory creation mode */
daddr_t n_blks; /* number of blocks in use */
daddr_t n_files; /* number of files in use */
#define clearinode(dp) (*(dp) = zino)
struct ext2fs_dinode zino;
#define setbmap(blkno) setbit(blockmap, blkno)
#define testbmap(blkno) isset(blockmap, blkno)
#define clrbmap(blkno) clrbit(blockmap, blkno)
#define STOP 0x01
#define SKIP 0x02
#define KEEPON 0x04
#define ALTERED 0x08
#define FOUND 0x10
struct ext2fs_dinode *ginode(ino_t);
struct inoinfo *getinoinfo(ino_t);
void getblk(struct bufarea *, daddr_t, long);
ino_t allocino(ino_t, int);
void copyback_sb(struct bufarea*);
daddr_t cgoverhead(int); /* overhead per cg */

View File

@ -1,253 +0,0 @@
.\" $NetBSD: fsck_ext2fs.8,v 1.19 2010/02/21 13:26:45 wiz Exp $
.\"
.\" Copyright (c) 1980, 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" Copyright (c) 1997 Manuel Bouyer.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" @(#)fsck.8 8.3 (Berkeley) 11/29/94
.\"
.Dd October 9, 2008
.Dt FSCK_EXT2FS 8
.Os
.Sh NAME
.Nm fsck_ext2fs
.Nd ext2 File System consistency check and interactive repair
.Sh SYNOPSIS
.Nm
.Op Fl dfnpUy
.Op Fl b Ar block#
.Op Fl c Ar level
.Op Fl m Ar mode
.Ar filesystem ...
.Sh DESCRIPTION
.Nm
performs interactive filesystem consistency checks and repair for each of
the filesystems specified on the command line.
It is normally invoked from
.Xr fsck 8 .
.Pp
The kernel takes care that only a restricted class of innocuous filesystem
inconsistencies can happen unless hardware or software failures intervene.
These are limited to the following:
.Pp
.Bl -item -compact
.It
Unreferenced inodes
.It
Link counts in inodes too large
.It
Missing blocks in the free map
.It
Blocks in the free map also in files
.It
Counts in the super-block wrong
.El
.Pp
These are the only inconsistencies that
.Nm
in
.Dq preen
mode (with the
.Fl p
option) will correct; if it encounters other inconsistencies, it exits
with an abnormal return status.
For each corrected inconsistency one or more lines will be printed
identifying the filesystem on which the correction will take place,
and the nature of the correction.
After successfully correcting a filesystem,
.Nm
will print the number of files on that filesystem
and the number of used and free blocks.
.Pp
If sent a
.Dv QUIT
signal,
.Nm
will finish the filesystem checks, then exit with an abnormal return status.
.Pp
Without the
.Fl p
option,
.Nm
audits and interactively repairs inconsistent conditions for filesystems.
If the filesystem is inconsistent the operator is prompted for concurrence
before each correction is attempted.
It should be noted that some of the corrective actions which are not
correctable under the
.Fl p
option will result in some loss of data.
The amount and severity of data lost may be determined from the diagnostic
output.
The default action for each consistency correction
is to wait for the operator to respond
.Li yes
or
.Li no .
If the operator does not have write permission on the filesystem
.Nm
will default to a
.Fl n
action.
.Pp
The following flags are interpreted by
.Nm .
.Bl -tag -width indent
.It Fl b
Use the block specified immediately after the flag as
the super block for the filesystem.
Block 8193 is usually an alternate super block.
.It Fl d
Print debugging output.
.It Fl f
Force checking of file systems.
Normally, if a file system is cleanly unmounted, the kernel will set a
.Dq clean flag
in the file system superblock, and
.Nm
will not check the file system.
This option forces
.Nm
to check the file system, regardless of the state of the clean flag.
.It Fl m
Use the mode specified in octal immediately after the flag as the
permission bits to use when creating the
.Pa lost+found
directory rather than the default 1777.
In particular, systems that do not wish to have lost files accessible
by all users on the system should use a more restrictive
set of permissions such as 700.
.It Fl n
Assume a no response to all questions asked by
.Nm
except for
.Ql CONTINUE? ,
which is assumed to be affirmative;
do not open the filesystem for writing.
.It Fl p
Specify
.Dq preen
mode, described above.
.It Fl U
Resolve numeric userids to usernames.
.It Fl y
Assume a yes response to all questions asked by
.Nm ;
this should be used with great caution as this is a free license
to continue after essentially unlimited trouble has been encountered.
.El
.Pp
Inconsistencies checked are as follows:
.Bl -enum -offset indent -compact
.It
Blocks claimed by more than one inode or the free map.
.It
Blocks claimed by an inode outside the range of the filesystem.
.It
Incorrect link counts.
.It
Size checks:
.Bl -item -offset indent -compact
.It
Directory size not a multiple of filesystem block size.
.It
Partially truncated file.
.El
.It
Bad inode format.
.It
Blocks not accounted for anywhere.
.It
Directory checks:
.Bl -item -offset indent -compact
.It
File pointing to unallocated inode.
.It
Inode number out of range.
.It
Dot or dot-dot not the first two entries of a directory
or having the wrong inode number.
.El
.It
Super Block checks:
.Bl -item -offset indent -compact
.It
More blocks for inodes than there are in the filesystem.
.It
Bad free block map format.
.It
Total free block and/or free inode count incorrect.
.El
.El
.Pp
Orphaned files and directories (allocated but unreferenced) are,
with the operator's concurrence, reconnected by
placing them in the
.Pa lost+found
directory.
The name assigned is the inode number.
If the
.Pa lost+found
directory does not exist, it is created.
If there is insufficient space its size is increased.
.Pp
Because of inconsistencies between the block device and the buffer cache,
the raw device should always be used.
.Sh DIAGNOSTICS
The diagnostics produced by
.Nm
are fully enumerated and explained in Appendix A of
.Rs
.%T "Fsck \- The UNIX File System Check Program"
.Re
.Sh SEE ALSO
.Xr fs 5 ,
.Xr fstab 5 ,
.Xr fsck 8 ,
.Xr fsdb 8 ,
.Xr newfs 8 ,
.Xr reboot 8

View File

@ -1,812 +0,0 @@
/* $NetBSD: inode.c,v 1.36 2013/06/23 07:28:36 dholland Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)inode.c 8.5 (Berkeley) 2/8/95";
#else
__RCSID("$NetBSD: inode.c,v 1.36 2013/06/23 07:28:36 dholland Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs_dir.h>
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
#ifndef SMALL
#include <pwd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "fsck.h"
#include "fsutil.h"
#include "extern.h"
/*
* CG is stored in fs byte order in memory, so we can't use ino_to_fsba
* here.
*/
#define fsck_ino_to_fsba(fs, x) \
(fs2h32((fs)->e2fs_gd[ino_to_cg(fs, x)].ext2bgd_i_tables) + \
(((x)-1) % (fs)->e2fs.e2fs_ipg)/(fs)->e2fs_ipb)
static ino_t startinum;
static int iblock(struct inodesc *, long, u_int64_t);
static int setlarge(void);
static int sethuge(void);
static int
setlarge(void)
{
if (sblock.e2fs.e2fs_rev < E2FS_REV1) {
pfatal("LARGE FILES UNSUPPORTED ON REVISION 0 FILESYSTEMS");
return 0;
}
if (!(sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE)) {
if (preen)
pwarn("SETTING LARGE FILE INDICATOR\n");
else if (!reply("SET LARGE FILE INDICATOR"))
return 0;
sblock.e2fs.e2fs_features_rocompat |= EXT2F_ROCOMPAT_LARGEFILE;
sbdirty();
}
return 1;
}
static int
sethuge(void)
{
if (sblock.e2fs.e2fs_rev < E2FS_REV1) {
pfatal("HUGE FILES UNSUPPORTED ON REVISION 0 FILESYSTEMS");
return 0;
}
if (!(sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_HUGE_FILE)) {
if (preen)
pwarn("SETTING HUGE FILE FEATURE\n");
else if (!reply("SET HUGE FILE FEATURE"))
return 0;
sblock.e2fs.e2fs_features_rocompat |= EXT2F_ROCOMPAT_HUGE_FILE;
sbdirty();
}
return 1;
}
u_int64_t
inosize(struct ext2fs_dinode *dp)
{
u_int64_t size = fs2h32(dp->e2di_size);
if ((fs2h16(dp->e2di_mode) & IFMT) == IFREG)
size |= (u_int64_t)fs2h32(dp->e2di_dacl) << 32;
if (size > INT32_MAX)
(void)setlarge();
return size;
}
void
inossize(struct ext2fs_dinode *dp, u_int64_t size)
{
if ((fs2h16(dp->e2di_mode) & IFMT) == IFREG) {
dp->e2di_dacl = h2fs32(size >> 32);
if (size > INT32_MAX)
if (!setlarge())
return;
} else if (size > INT32_MAX) {
pfatal("TRYING TO SET FILESIZE TO %llu ON MODE %x FILE\n",
(unsigned long long)size, fs2h16(dp->e2di_mode) & IFMT);
return;
}
dp->e2di_size = h2fs32(size);
}
int
ckinode(struct ext2fs_dinode *dp, struct inodesc *idesc)
{
u_int32_t *ap;
long ret, n, ndb;
struct ext2fs_dinode dino;
u_int64_t remsize, sizepb;
mode_t mode;
char pathbuf[MAXPATHLEN + 1];
if (idesc->id_fix != IGNORE)
idesc->id_fix = DONTKNOW;
idesc->id_entryno = 0;
idesc->id_filesize = inosize(dp);
mode = fs2h16(dp->e2di_mode) & IFMT;
if (mode == IFBLK || mode == IFCHR || mode == IFIFO ||
(mode == IFLNK && (inosize(dp) < EXT2_MAXSYMLINKLEN)))
return (KEEPON);
dino = *dp;
ndb = howmany(inosize(&dino), sblock.e2fs_bsize);
for (ap = &dino.e2di_blocks[0]; ap < &dino.e2di_blocks[EXT2FS_NDADDR];
ap++,ndb--) {
idesc->id_numfrags = 1;
if (*ap == 0) {
if (idesc->id_type == DATA && ndb > 0) {
/* An empty block in a directory XXX */
getpathname(pathbuf, sizeof(pathbuf),
idesc->id_number, idesc->id_number);
pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
inossize(dp,
(ap - &dino.e2di_blocks[0]) *
sblock.e2fs_bsize);
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
rerun = 1;
inodirty();
}
}
continue;
}
idesc->id_blkno = fs2h32(*ap);
if (idesc->id_type == ADDR)
ret = (*idesc->id_func)(idesc);
else
ret = dirscan(idesc);
if (ret & STOP)
return (ret);
}
idesc->id_numfrags = 1;
remsize = inosize(&dino) - sblock.e2fs_bsize * EXT2FS_NDADDR;
sizepb = sblock.e2fs_bsize;
for (ap = &dino.e2di_blocks[EXT2FS_NDADDR], n = 1; n <= EXT2FS_NIADDR; ap++, n++) {
if (*ap) {
idesc->id_blkno = fs2h32(*ap);
ret = iblock(idesc, n, remsize);
if (ret & STOP)
return (ret);
} else {
if (idesc->id_type == DATA && remsize > 0) {
/* An empty block in a directory XXX */
getpathname(pathbuf, sizeof(pathbuf),
idesc->id_number, idesc->id_number);
pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
inossize(dp, inosize(dp) - remsize);
remsize = 0;
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
rerun = 1;
inodirty();
break;
}
}
}
sizepb *= EXT2_NINDIR(&sblock);
remsize -= sizepb;
}
return (KEEPON);
}
static int
iblock(struct inodesc *idesc, long ilevel, u_int64_t isize)
{
/* XXX ondisk32 */
int32_t *ap;
int32_t *aplim;
struct bufarea *bp;
int i, n, (*func)(struct inodesc *);
size_t nif;
u_int64_t sizepb;
char buf[BUFSIZ];
char pathbuf[MAXPATHLEN + 1];
struct ext2fs_dinode *dp;
if (idesc->id_type == ADDR) {
func = idesc->id_func;
if (((n = (*func)(idesc)) & KEEPON) == 0)
return (n);
} else
func = dirscan;
if (chkrange(idesc->id_blkno, idesc->id_numfrags))
return (SKIP);
bp = getdatablk(idesc->id_blkno, sblock.e2fs_bsize);
ilevel--;
for (sizepb = sblock.e2fs_bsize, i = 0; i < ilevel; i++)
sizepb *= EXT2_NINDIR(&sblock);
if (isize > sizepb * EXT2_NINDIR(&sblock))
nif = EXT2_NINDIR(&sblock);
else
nif = howmany(isize, sizepb);
if (idesc->id_func == pass1check &&
nif < EXT2_NINDIR(&sblock)) {
aplim = &bp->b_un.b_indir[EXT2_NINDIR(&sblock)];
for (ap = &bp->b_un.b_indir[nif]; ap < aplim; ap++) {
if (*ap == 0)
continue;
(void)snprintf(buf, sizeof(buf),
"PARTIALLY TRUNCATED INODE I=%llu",
(unsigned long long)idesc->id_number);
if (dofix(idesc, buf)) {
*ap = 0;
dirty(bp);
}
}
flush(fswritefd, bp);
}
aplim = &bp->b_un.b_indir[nif];
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
if (*ap) {
idesc->id_blkno = fs2h32(*ap);
if (ilevel == 0)
n = (*func)(idesc);
else
n = iblock(idesc, ilevel, isize);
if (n & STOP) {
bp->b_flags &= ~B_INUSE;
return (n);
}
} else {
if (idesc->id_type == DATA && isize > 0) {
/* An empty block in a directory XXX */
getpathname(pathbuf, sizeof(pathbuf),
idesc->id_number, idesc->id_number);
pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS",
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
inossize(dp, inosize(dp) - isize);
isize = 0;
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
rerun = 1;
inodirty();
bp->b_flags &= ~B_INUSE;
return(STOP);
}
}
}
isize -= sizepb;
}
bp->b_flags &= ~B_INUSE;
return (KEEPON);
}
/*
* Check that a block in a legal block number.
* Return 0 if in range, 1 if out of range.
*/
int
chkrange(daddr_t blk, int cnt)
{
int c, overh;
if ((unsigned int)(blk + cnt) > maxfsblock)
return (1);
c = dtog(&sblock, blk);
overh = cgoverhead(c);
if (blk < sblock.e2fs.e2fs_bpg * c + overh +
sblock.e2fs.e2fs_first_dblock) {
if ((blk + cnt) > sblock.e2fs.e2fs_bpg * c + overh +
sblock.e2fs.e2fs_first_dblock) {
if (debug) {
printf("blk %lld < cgdmin %d;",
(long long)blk,
sblock.e2fs.e2fs_bpg * c + overh +
sblock.e2fs.e2fs_first_dblock);
printf(" blk + cnt %lld > cgsbase %d\n",
(long long)(blk + cnt),
sblock.e2fs.e2fs_bpg * c +
overh + sblock.e2fs.e2fs_first_dblock);
}
return (1);
}
} else {
if ((blk + cnt) > sblock.e2fs.e2fs_bpg * (c + 1) + overh +
sblock.e2fs.e2fs_first_dblock) {
if (debug) {
printf("blk %lld >= cgdmin %d;",
(long long)blk,
sblock.e2fs.e2fs_bpg * c + overh +
sblock.e2fs.e2fs_first_dblock);
printf(" blk + cnt %lld > cgdmax %d\n",
(long long)(blk+cnt),
sblock.e2fs.e2fs_bpg * (c + 1) +
overh + sblock.e2fs.e2fs_first_dblock);
}
return (1);
}
}
return (0);
}
/*
* General purpose interface for reading inodes.
*/
struct ext2fs_dinode *
ginode(ino_t inumber)
{
daddr_t iblk;
struct ext2fs_dinode *dp;
if ((inumber < EXT2_FIRSTINO &&
inumber != EXT2_ROOTINO &&
!(inumber == EXT2_RESIZEINO &&
(sblock.e2fs.e2fs_features_compat & EXT2F_COMPAT_RESIZE) != 0))
|| inumber > maxino)
errexit("bad inode number %llu to ginode",
(unsigned long long)inumber);
if (startinum == 0 ||
inumber < startinum || inumber >= startinum + sblock.e2fs_ipb) {
iblk = fsck_ino_to_fsba(&sblock, inumber);
if (pbp != 0)
pbp->b_flags &= ~B_INUSE;
pbp = getdatablk(iblk, sblock.e2fs_bsize);
startinum =
((inumber - 1) / sblock.e2fs_ipb) * sblock.e2fs_ipb + 1;
}
dp = (struct ext2fs_dinode *)(pbp->b_un.b_buf +
EXT2_DINODE_SIZE(&sblock) * ino_to_fsbo(&sblock, inumber));
return dp;
}
/*
* Special purpose version of ginode used to optimize first pass
* over all the inodes in numerical order.
*/
ino_t nextino, lastinum;
long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
char *inodebuf;
struct ext2fs_dinode *
getnextinode(ino_t inumber)
{
long size;
daddr_t dblk;
struct ext2fs_dinode *dp;
static char *bp;
if (inumber != nextino++ || inumber > maxino)
errexit("bad inode number %llu to nextinode",
(unsigned long long)inumber);
if (inumber >= lastinum) {
readcnt++;
dblk = EXT2_FSBTODB(&sblock, fsck_ino_to_fsba(&sblock, lastinum));
if (readcnt % readpercg == 0) {
size = partialsize;
lastinum += partialcnt;
} else {
size = inobufsize;
lastinum += fullcnt;
}
(void)bread(fsreadfd, inodebuf, dblk, size);
bp = inodebuf;
}
dp = (struct ext2fs_dinode *)bp;
bp += EXT2_DINODE_SIZE(&sblock);
return dp;
}
void
resetinodebuf(void)
{
startinum = 0;
nextino = 1;
lastinum = 1;
readcnt = 0;
inobufsize = ext2_blkroundup(&sblock, INOBUFSIZE);
fullcnt = inobufsize / EXT2_DINODE_SIZE(&sblock);
readpercg = sblock.e2fs.e2fs_ipg / fullcnt;
partialcnt = sblock.e2fs.e2fs_ipg % fullcnt;
partialsize = partialcnt * EXT2_DINODE_SIZE(&sblock);
if (partialcnt != 0) {
readpercg++;
} else {
partialcnt = fullcnt;
partialsize = inobufsize;
}
if (inodebuf == NULL &&
(inodebuf = malloc((unsigned int)inobufsize)) == NULL)
errexit("Cannot allocate space for inode buffer");
while (nextino < EXT2_ROOTINO)
(void)getnextinode(nextino);
}
void
freeinodebuf(void)
{
if (inodebuf != NULL)
free(inodebuf);
inodebuf = NULL;
}
/*
* Routines to maintain information about directory inodes.
* This is built during the first pass and used during the
* second and third passes.
*
* Enter inodes into the cache.
*/
void
cacheino(struct ext2fs_dinode *dp, ino_t inumber)
{
struct inoinfo *inp;
struct inoinfo **inpp;
unsigned int blks;
blks = howmany(inosize(dp), sblock.e2fs_bsize);
if (blks > EXT2FS_NDADDR)
blks = EXT2FS_NDADDR + EXT2FS_NIADDR;
/* XXX ondisk32 */
inp = malloc(sizeof(*inp) + (blks - 1) * sizeof(int32_t));
if (inp == NULL)
return;
inpp = &inphead[inumber % numdirs];
inp->i_nexthash = *inpp;
*inpp = inp;
inp->i_child = inp->i_sibling = inp->i_parentp = 0;
if (inumber == EXT2_ROOTINO)
inp->i_parent = EXT2_ROOTINO;
else
inp->i_parent = (ino_t)0;
inp->i_dotdot = (ino_t)0;
inp->i_number = inumber;
inp->i_isize = inosize(dp);
/* XXX ondisk32 */
inp->i_numblks = blks * sizeof(int32_t);
memcpy(&inp->i_blks[0], &dp->e2di_blocks[0], (size_t)inp->i_numblks);
if (inplast == listmax) {
listmax += 100;
inpsort = (struct inoinfo **)realloc((char *)inpsort,
(unsigned int)listmax * sizeof(struct inoinfo *));
if (inpsort == NULL)
errexit("cannot increase directory list");
}
inpsort[inplast++] = inp;
}
/*
* Look up an inode cache structure.
*/
struct inoinfo *
getinoinfo(ino_t inumber)
{
struct inoinfo *inp;
for (inp = inphead[inumber % numdirs]; inp; inp = inp->i_nexthash) {
if (inp->i_number != inumber)
continue;
return (inp);
}
errexit("cannot find inode %llu", (unsigned long long)inumber);
return ((struct inoinfo *)0);
}
/*
* Clean up all the inode cache structure.
*/
void
inocleanup(void)
{
struct inoinfo **inpp;
if (inphead == NULL)
return;
for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
free(*inpp);
free(inphead);
free(inpsort);
inphead = inpsort = NULL;
}
void
inodirty(void)
{
dirty(pbp);
}
void
clri(struct inodesc *idesc, const char *type, int flag)
{
struct ext2fs_dinode *dp;
dp = ginode(idesc->id_number);
if (flag == 1) {
pwarn("%s %s", type,
(fs2h16(dp->e2di_mode) & IFMT) == IFDIR ? "DIR" : "FILE");
pinode(idesc->id_number);
}
if (preen || reply("CLEAR") == 1) {
if (preen)
printf(" (CLEARED)\n");
n_files--;
(void)ckinode(dp, idesc);
clearinode(dp);
statemap[idesc->id_number] = USTATE;
inodirty();
}
}
int
findname(struct inodesc *idesc)
{
struct ext2fs_direct *dirp = idesc->id_dirp;
u_int16_t namlen = dirp->e2d_namlen;
/* from utilities.c namebuf[] variable */
char *buf = __UNCONST(idesc->id_name);
if (namlen > MAXPATHLEN) {
/* XXX: Prevent overflow but don't fix */
namlen = MAXPATHLEN;
}
if (fs2h32(dirp->e2d_ino) != idesc->id_parent)
return (KEEPON);
(void)memcpy(buf, dirp->e2d_name, (size_t)namlen);
buf[namlen] = '\0';
return (STOP|FOUND);
}
int
findino(struct inodesc *idesc)
{
struct ext2fs_direct *dirp = idesc->id_dirp;
u_int32_t ino = fs2h32(dirp->e2d_ino);
if (ino == 0)
return (KEEPON);
if (strcmp(dirp->e2d_name, idesc->id_name) == 0 &&
(ino == EXT2_ROOTINO || ino >= EXT2_FIRSTINO)
&& ino <= maxino) {
idesc->id_parent = ino;
return (STOP|FOUND);
}
return (KEEPON);
}
void
pinode(ino_t ino)
{
struct ext2fs_dinode *dp;
struct passwd *pw;
uid_t uid;
printf(" I=%llu ", (unsigned long long)ino);
if ((ino < EXT2_FIRSTINO && ino != EXT2_ROOTINO) || ino > maxino)
return;
dp = ginode(ino);
uid = fs2h16(dp->e2di_uid);
if (sblock.e2fs.e2fs_rev > E2FS_REV0)
uid |= fs2h16(dp->e2di_uid_high) << 16;
printf(" OWNER=");
#ifndef SMALL
if (Uflag && (pw = getpwuid(uid)) != 0)
printf("%s ", pw->pw_name);
else
#endif
printf("%u ", (unsigned int)uid);
printf("MODE=%o\n", fs2h16(dp->e2di_mode));
if (preen)
printf("%s: ", cdevname());
printf("SIZE=%llu ", (long long)inosize(dp));
printf("MTIME=%s ", print_mtime(fs2h32(dp->e2di_mtime)));
}
void
blkerror(ino_t ino, const char *type, daddr_t blk)
{
pfatal("%lld %s I=%llu", (long long)blk, type, (unsigned long long)ino);
printf("\n");
switch (statemap[ino]) {
case FSTATE:
statemap[ino] = FCLEAR;
return;
case DSTATE:
statemap[ino] = DCLEAR;
return;
case FCLEAR:
case DCLEAR:
return;
default:
errexit("BAD STATE %d TO BLKERR", statemap[ino]);
/* NOTREACHED */
}
}
/*
* allocate an unused inode
*/
ino_t
allocino(ino_t request, int type)
{
ino_t ino;
struct ext2fs_dinode *dp;
time_t t;
if (request == 0)
request = EXT2_ROOTINO;
else if (statemap[request] != USTATE)
return (0);
for (ino = request; ino < maxino; ino++) {
if ((ino > EXT2_ROOTINO) && (ino < EXT2_FIRSTINO))
continue;
if (statemap[ino] == USTATE)
break;
}
if (ino == maxino)
return (0);
switch (type & IFMT) {
case IFDIR:
statemap[ino] = DSTATE;
break;
case IFREG:
case IFLNK:
statemap[ino] = FSTATE;
break;
default:
return (0);
}
dp = ginode(ino);
dp->e2di_blocks[0] = h2fs32(allocblk());
if (dp->e2di_blocks[0] == 0) {
statemap[ino] = USTATE;
return (0);
}
dp->e2di_mode = h2fs16(type);
(void)time(&t);
dp->e2di_atime = h2fs32(t);
dp->e2di_mtime = dp->e2di_ctime = dp->e2di_atime;
dp->e2di_dtime = 0;
inossize(dp, sblock.e2fs_bsize);
inosnblock(dp, btodb(sblock.e2fs_bsize));
n_files++;
inodirty();
typemap[ino] = E2IFTODT(type);
return (ino);
}
/*
* deallocate an inode
*/
void
freeino(ino_t ino)
{
struct inodesc idesc;
struct ext2fs_dinode *dp;
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass4check;
idesc.id_number = ino;
dp = ginode(ino);
(void)ckinode(dp, &idesc);
clearinode(dp);
inodirty();
statemap[ino] = USTATE;
n_files--;
}
uint64_t
inonblock(struct ext2fs_dinode *dp)
{
uint64_t nblock;
/* XXX check for EXT2_HUGE_FILE without EXT2F_ROCOMPAT_HUGE_FILE? */
nblock = fs2h32(dp->e2di_nblock);
if ((sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_HUGE_FILE)) {
nblock |= (uint64_t)fs2h16(dp->e2di_nblock_high) << 32;
if (fs2h32(dp->e2di_flags) & EXT2_HUGE_FILE) {
nblock = EXT2_FSBTODB(&sblock, nblock);
}
}
return nblock;
}
void
inosnblock(struct ext2fs_dinode *dp, uint64_t nblock)
{
uint32_t flags;
flags = fs2h32(dp->e2di_flags);
if (nblock <= 0xffffffffULL) {
flags &= ~EXT2_HUGE_FILE;
dp->e2di_flags = h2fs32(flags);
dp->e2di_nblock = h2fs32(nblock);
return;
}
sethuge();
if (nblock <= 0xffffffffffffULL) {
flags &= ~EXT2_HUGE_FILE;
dp->e2di_flags = h2fs32(flags);
dp->e2di_nblock = h2fs32(nblock);
dp->e2di_nblock_high = h2fs16((nblock >> 32));
return;
}
if (EXT2_DBTOFSB(&sblock, nblock) <= 0xffffffffffffULL) {
flags |= EXT2_HUGE_FILE;
dp->e2di_flags = h2fs32(flags);
dp->e2di_nblock = h2fs32(EXT2_DBTOFSB(&sblock, nblock));
dp->e2di_nblock_high = h2fs16((EXT2_DBTOFSB(&sblock, nblock) >> 32));
return;
}
pfatal("trying to set nblocks higher than representable");
return;
}

View File

@ -1,358 +0,0 @@
/* $NetBSD: main.c,v 1.37 2011/06/09 19:57:51 christos Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/23/94";
#else
__RCSID("$NetBSD: main.c,v 1.37 2011/06/09 19:57:51 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <sys/mount.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs.h>
#include <fstab.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include "fsck.h"
#include "extern.h"
#include "fsutil.h"
#include "exitvalues.h"
volatile sig_atomic_t returntosingle = 0;
static int argtoi(int, const char *, const char *, int);
static int checkfilesys(const char *, char *, long, int);
static void usage(void) __dead;
int
main(int argc, char *argv[])
{
int ch;
int ret = FSCK_EXIT_OK;
ckfinish = ckfini;
sync();
skipclean = 1;
while ((ch = getopt(argc, argv, "b:dfm:npPqUy")) != -1) {
switch (ch) {
case 'b':
skipclean = 0;
bflag = argtoi('b', "number", optarg, 10);
printf("Alternate super block location: %d\n", bflag);
break;
case 'd':
debug++;
break;
case 'f':
skipclean = 0;
break;
case 'm':
lfmode = argtoi('m', "mode", optarg, 8);
if (lfmode &~ 07777)
errexit("bad mode to -m: %o", lfmode);
printf("** lost+found creation mode %o\n", lfmode);
break;
case 'n':
nflag++;
yflag = 0;
break;
case 'p':
preen++;
break;
case 'P':
/* Progress meter not implemented. */
break;
case 'q': /* Quiet not implemented */
break;
#ifndef SMALL
case 'U':
Uflag++;
break;
#endif
case 'y':
yflag++;
nflag = 0;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (!argc)
usage();
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
(void)signal(SIGINT, catch);
if (preen)
(void)signal(SIGQUIT, catchquit);
while (argc-- > 0) {
int nret = checkfilesys(blockcheck(*argv++), 0, 0L, 0);
if (ret < nret)
ret = nret;
}
return returntosingle ? FSCK_EXIT_UNRESOLVED : ret;
}
static int
argtoi(int flag, const char *req, const char *str, int base)
{
char *cp;
int ret;
ret = (int)strtol(str, &cp, base);
if (cp == str || *cp)
errexit("-%c flag requires a %s", flag, req);
return (ret);
}
/*
* Check the specified filesystem.
*/
/* ARGSUSED */
static int
checkfilesys(const char *filesys, char *mntpt, long auxdata, int child)
{
daddr_t n_bfree;
struct dups *dp;
struct zlncnt *zlnp;
int i;
if (preen && child)
(void)signal(SIGQUIT, voidquit);
setcdevname(filesys, preen);
if (debug && preen)
pwarn("starting\n");
switch (setup(filesys)) {
case 0:
if (preen)
pfatal("CAN'T CHECK FILE SYSTEM.");
case -1:
return FSCK_EXIT_OK;
}
/*
* 1: scan inodes tallying blocks used
*/
if (preen == 0) {
if (sblock.e2fs.e2fs_rev > E2FS_REV0) {
printf("** Last Mounted on %s\n",
sblock.e2fs.e2fs_fsmnt);
}
if (hotroot())
printf("** Root file system\n");
printf("** Phase 1 - Check Blocks and Sizes\n");
}
pass1();
/*
* 1b: locate first references to duplicates, if any
*/
if (duplist) {
if (preen)
pfatal("INTERNAL ERROR: dups with -p");
printf("** Phase 1b - Rescan For More DUPS\n");
pass1b();
}
/*
* 2: traverse directories from root to mark all connected directories
*/
if (preen == 0)
printf("** Phase 2 - Check Pathnames\n");
pass2();
/*
* 3: scan inodes looking for disconnected directories
*/
if (preen == 0)
printf("** Phase 3 - Check Connectivity\n");
pass3();
/*
* 4: scan inodes looking for disconnected files; check reference counts
*/
if (preen == 0)
printf("** Phase 4 - Check Reference Counts\n");
pass4();
/*
* 5: check and repair resource counts in cylinder groups
*/
if (preen == 0)
printf("** Phase 5 - Check Cyl groups\n");
pass5();
/*
* print out summary statistics
*/
n_bfree = sblock.e2fs.e2fs_fbcount;
pwarn("%lld files, %lld used, %lld free\n",
(long long)n_files, (long long)n_blks, (long long)n_bfree);
if (debug &&
/* 9 reserved and unused inodes in FS */
(n_files -= maxino - 9 - sblock.e2fs.e2fs_ficount))
printf("%lld files missing\n", (long long)n_files);
if (debug) {
for (i = 0; i < sblock.e2fs_ncg; i++)
n_blks += cgoverhead(i);
n_blks += sblock.e2fs.e2fs_first_dblock;
if (n_blks -= maxfsblock - n_bfree)
printf("%lld blocks missing\n", (long long)n_blks);
if (duplist != NULL) {
printf("The following duplicate blocks remain:");
for (dp = duplist; dp; dp = dp->next)
printf(" %lld,", (long long)dp->dup);
printf("\n");
}
if (zlnhead != NULL) {
printf("The following zero link count inodes remain:");
for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
printf(" %llu,",
(unsigned long long)zlnp->zlncnt);
printf("\n");
}
}
zlnhead = (struct zlncnt *)0;
duplist = (struct dups *)0;
muldup = (struct dups *)0;
inocleanup();
if (fsmodified) {
time_t t;
(void)time(&t);
sblock.e2fs.e2fs_wtime = t;
sblock.e2fs.e2fs_lastfsck = t;
sbdirty();
}
ckfini(1);
free(blockmap);
free(statemap);
free((char *)lncntp);
if (!fsmodified)
return FSCK_EXIT_OK;
if (!preen)
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
if (rerun)
printf("\n***** PLEASE RERUN FSCK *****\n");
#if !defined(__minix)
if (hotroot()) {
struct statvfs stfs_buf;
/*
* We modified the root. Do a mount update on
* it, unless it is read-write, so we can continue.
*/
if (statvfs("/", &stfs_buf) == 0) {
long flags = stfs_buf.f_flag;
struct ufs_args args;
if (flags & MNT_RDONLY) {
args.fspec = 0;
flags |= MNT_UPDATE | MNT_RELOAD;
if (mount(MOUNT_EXT2FS, "/", flags,
&args, sizeof args) == 0)
return FSCK_EXIT_OK;
}
}
if (!preen)
printf("\n***** REBOOT NOW *****\n");
sync();
return FSCK_EXIT_ROOT_CHANGED;
}
#endif /* !defined(__minix) */
return FSCK_EXIT_OK;
}
static void
usage(void)
{
(void) fprintf(stderr,
"usage: %s [-dfnpUy] [-b block] [-c level] [-m mode] filesystem ...\n",
getprogname());
exit(FSCK_EXIT_USAGE);
}

View File

@ -1,395 +0,0 @@
/* $NetBSD: pass1.c,v 1.24 2013/06/19 17:51:25 dholland Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)pass1.c 8.1 (Berkeley) 6/5/93";
#else
__RCSID("$NetBSD: pass1.c,v 1.24 2013/06/19 17:51:25 dholland Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs_dir.h>
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "fsck.h"
#include "extern.h"
#include "fsutil.h"
#include "exitvalues.h"
static daddr_t badblk;
static daddr_t dupblk;
static void checkinode(ino_t, struct inodesc *);
void
pass1(void)
{
ino_t inumber;
int c, i;
size_t j;
daddr_t dbase;
struct inodesc idesc;
/*
* Set file system reserved blocks in used block map.
*/
for (c = 0; c < sblock.e2fs_ncg; c++) {
dbase = c * sblock.e2fs.e2fs_bpg +
sblock.e2fs.e2fs_first_dblock;
/* Mark the blocks used for the inode table */
if (fs2h32(sblock.e2fs_gd[c].ext2bgd_i_tables) >= dbase) {
for (i = 0; i < sblock.e2fs_itpg; i++)
setbmap(
fs2h32(sblock.e2fs_gd[c].ext2bgd_i_tables)
+ i);
}
/* Mark the blocks used for the block bitmap */
if (fs2h32(sblock.e2fs_gd[c].ext2bgd_b_bitmap) >= dbase)
setbmap(fs2h32(sblock.e2fs_gd[c].ext2bgd_b_bitmap));
/* Mark the blocks used for the inode bitmap */
if (fs2h32(sblock.e2fs_gd[c].ext2bgd_i_bitmap) >= dbase)
setbmap(fs2h32(sblock.e2fs_gd[c].ext2bgd_i_bitmap));
if (sblock.e2fs.e2fs_rev == E2FS_REV0 ||
(sblock.e2fs.e2fs_features_rocompat &
EXT2F_ROCOMPAT_SPARSESUPER) == 0 ||
cg_has_sb(c)) {
/* Mark copuy of SB and descriptors */
setbmap(dbase);
for (i = 1; i <= sblock.e2fs_ngdb; i++)
setbmap(dbase+i);
}
if (c == 0) {
for(i = 0; i < dbase; i++)
setbmap(i);
}
}
/*
* Find all allocated blocks.
*/
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass1check;
inumber = 1;
n_files = n_blks = 0;
resetinodebuf();
for (c = 0; c < sblock.e2fs_ncg; c++) {
for (j = 0;
j < sblock.e2fs.e2fs_ipg && inumber <= sblock.e2fs.e2fs_icount;
j++, inumber++) {
if (inumber < EXT2_ROOTINO) /* XXX */
continue;
checkinode(inumber, &idesc);
}
}
freeinodebuf();
}
static void
checkinode(ino_t inumber, struct inodesc *idesc)
{
struct ext2fs_dinode *dp;
struct zlncnt *zlnp;
int ndb, j;
mode_t mode;
dp = getnextinode(inumber);
if (inumber < EXT2_FIRSTINO &&
inumber != EXT2_ROOTINO &&
!(inumber == EXT2_RESIZEINO &&
(sblock.e2fs.e2fs_features_compat & EXT2F_COMPAT_RESIZE) != 0))
return;
mode = fs2h16(dp->e2di_mode) & IFMT;
if (mode == 0 || (dp->e2di_dtime != 0 && dp->e2di_nlink == 0)) {
if (mode == 0 && (
memcmp(dp->e2di_blocks, zino.e2di_blocks,
(EXT2FS_NDADDR + EXT2FS_NIADDR) * sizeof(u_int32_t)) ||
dp->e2di_mode || inosize(dp))) {
pfatal("PARTIALLY ALLOCATED INODE I=%llu",
(unsigned long long)inumber);
if (reply("CLEAR") == 1) {
dp = ginode(inumber);
clearinode(dp);
inodirty();
}
}
#ifdef notyet /* it seems that dtime == 0 is valid for a unallocated inode */
if (dp->e2di_dtime == 0) {
pwarn("DELETED INODE I=%llu HAS A NULL DTIME",
(unsigned long long)inumber);
if (preen) {
printf(" (CORRECTED)\n");
}
if (preen || reply("CORRECT")) {
time_t t;
time(&t);
dp->e2di_dtime = h2fs32(t);
dp = ginode(inumber);
inodirty();
}
}
#endif
statemap[inumber] = USTATE;
return;
}
lastino = inumber;
if (dp->e2di_dtime != 0) {
pwarn("INODE I=%llu HAS DTIME=%s",
(unsigned long long)inumber,
print_mtime(fs2h32(dp->e2di_dtime)));
if (preen) {
printf(" (CORRECTED)\n");
}
if (preen || reply("CORRECT")) {
dp = ginode(inumber);
dp->e2di_dtime = 0;
inodirty();
}
}
if (inosize(dp) + sblock.e2fs_bsize - 1 < inosize(dp)) {
if (debug)
printf("bad size %llu:", (unsigned long long)inosize(dp));
goto unknown;
}
if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
dp = ginode(inumber);
dp->e2di_mode = h2fs16(IFREG|0600);
inossize(dp, sblock.e2fs_bsize);
inodirty();
}
ndb = howmany(inosize(dp), sblock.e2fs_bsize);
if (ndb < 0) {
if (debug)
printf("bad size %llu ndb %d:",
(unsigned long long)inosize(dp), ndb);
goto unknown;
}
if (mode == IFBLK || mode == IFCHR)
ndb++;
if (mode == IFLNK) {
/*
* Fake ndb value so direct/indirect block checks below
* will detect any garbage after symlink string.
*/
if (inosize(dp) < EXT2_MAXSYMLINKLEN ||
(EXT2_MAXSYMLINKLEN == 0 && dp->e2di_blocks == 0)) {
ndb = howmany(inosize(dp), sizeof(u_int32_t));
if (ndb > EXT2FS_NDADDR) {
j = ndb - EXT2FS_NDADDR;
for (ndb = 1; j > 1; j--)
ndb *= EXT2_NINDIR(&sblock);
ndb += EXT2FS_NDADDR;
}
}
}
/* Linux puts things in blocks for FIFO, so skip this check */
if (mode != IFIFO) {
for (j = ndb; j < EXT2FS_NDADDR; j++)
if (dp->e2di_blocks[j] != 0) {
if (debug)
printf("bad direct addr: %d\n",
fs2h32(dp->e2di_blocks[j]));
goto unknown;
}
for (j = 0, ndb -= EXT2FS_NDADDR; ndb > 0; j++)
ndb /= EXT2_NINDIR(&sblock);
for (; j < EXT2FS_NIADDR; j++) {
if (dp->e2di_blocks[j+EXT2FS_NDADDR] != 0) {
if (debug)
printf("bad indirect addr: %d\n",
fs2h32(dp->e2di_blocks[j+EXT2FS_NDADDR]));
goto unknown;
}
}
}
if (ftypeok(dp) == 0)
goto unknown;
if (inumber >= EXT2_FIRSTINO || inumber == EXT2_ROOTINO) {
/* Don't count reserved inodes except root */
n_files++;
}
lncntp[inumber] = fs2h16(dp->e2di_nlink);
if (dp->e2di_nlink == 0) {
zlnp = malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0)
exit(FSCK_EXIT_CHECK_FAILED);
} else {
zlnp->zlncnt = inumber;
zlnp->next = zlnhead;
zlnhead = zlnp;
}
}
if (mode == IFDIR) {
if (inosize(dp) == 0)
statemap[inumber] = DCLEAR;
else
statemap[inumber] = DSTATE;
cacheino(dp, inumber);
} else {
statemap[inumber] = FSTATE;
}
typemap[inumber] = E2IFTODT(mode);
badblk = dupblk = 0;
idesc->id_number = inumber;
(void)ckinode(dp, idesc);
idesc->id_entryno *= btodb(sblock.e2fs_bsize);
if (inonblock(dp) != (uint32_t)idesc->id_entryno) {
pwarn("INCORRECT BLOCK COUNT I=%llu (%llu should be %d)",
(unsigned long long)inumber,
(unsigned long long)inonblock(dp),
idesc->id_entryno);
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
return;
dp = ginode(inumber);
inosnblock(dp, idesc->id_entryno);
inodirty();
}
return;
unknown:
pfatal("UNKNOWN FILE TYPE I=%llu", (unsigned long long)inumber);
statemap[inumber] = FCLEAR;
if (reply("CLEAR") == 1) {
statemap[inumber] = USTATE;
dp = ginode(inumber);
clearinode(dp);
inodirty();
}
}
int
pass1check(struct inodesc *idesc)
{
int res = KEEPON;
int anyout, nfrags;
daddr_t blkno = idesc->id_blkno;
struct dups *dlp;
struct dups *new;
if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) {
blkerror(idesc->id_number, "BAD", blkno);
if (badblk++ >= MAXBAD) {
pwarn("EXCESSIVE BAD BLKS I=%llu",
(unsigned long long)idesc->id_number);
if (preen)
printf(" (SKIPPING)\n");
else if (reply("CONTINUE") == 0)
exit(FSCK_EXIT_CHECK_FAILED);
return (STOP);
}
}
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
if (anyout && chkrange(blkno, 1)) {
res = SKIP;
} else if (!testbmap(blkno)) {
n_blks++;
setbmap(blkno);
} else {
blkerror(idesc->id_number, "DUP", blkno);
if (dupblk++ >= MAXDUP) {
pwarn("EXCESSIVE DUP BLKS I=%llu",
(unsigned long long)idesc->id_number);
if (preen)
printf(" (SKIPPING)\n");
else if (reply("CONTINUE") == 0)
exit(FSCK_EXIT_CHECK_FAILED);
return (STOP);
}
new = malloc(sizeof(struct dups));
if (new == NULL) {
pfatal("DUP TABLE OVERFLOW.");
if (reply("CONTINUE") == 0)
exit(FSCK_EXIT_CHECK_FAILED);
return (STOP);
}
new->dup = blkno;
if (muldup == 0) {
duplist = muldup = new;
new->next = 0;
} else {
new->next = muldup->next;
muldup->next = new;
}
for (dlp = duplist; dlp != muldup; dlp = dlp->next)
if (dlp->dup == blkno)
break;
if (dlp == muldup && dlp->dup != blkno)
muldup = new;
}
/*
* count the number of blocks found in id_entryno
*/
idesc->id_entryno++;
}
return (res);
}

View File

@ -1,130 +0,0 @@
/* $NetBSD: pass1b.c,v 1.8 2009/10/19 18:41:08 bouyer Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)pass1b.c 8.1 (Berkeley) 6/5/93";
#else
__RCSID("$NetBSD: pass1b.c,v 1.8 2009/10/19 18:41:08 bouyer Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs.h>
#include <string.h>
#include "fsck.h"
#include "extern.h"
static int pass1bcheck(struct inodesc *);
static struct dups *duphead;
void
pass1b(void)
{
int c;
uint32_t i;
struct ext2fs_dinode *dp;
struct inodesc idesc;
ino_t inumber;
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass1bcheck;
duphead = duplist;
inumber = 0;
for (c = 0; c < sblock.e2fs_ncg; c++) {
for (i = 0; i < sblock.e2fs.e2fs_ipg; i++, inumber++) {
if ((inumber < EXT2_FIRSTINO) && (inumber != EXT2_ROOTINO))
continue;
dp = ginode(inumber);
if (dp == NULL)
continue;
idesc.id_number = inumber;
if (statemap[inumber] != USTATE &&
(ckinode(dp, &idesc) & STOP))
return;
}
}
}
static int
pass1bcheck(struct inodesc *idesc)
{
struct dups *dlp;
int nfrags, res = KEEPON;
daddr_t blkno = idesc->id_blkno;
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
if (chkrange(blkno, 1))
res = SKIP;
for (dlp = duphead; dlp; dlp = dlp->next) {
if (dlp->dup == blkno) {
blkerror(idesc->id_number, "DUP", blkno);
dlp->dup = duphead->dup;
duphead->dup = blkno;
duphead = duphead->next;
}
if (dlp == muldup)
break;
}
if (muldup == 0 || duphead == muldup->next)
return (STOP);
}
return (res);
}

View File

@ -1,470 +0,0 @@
/* $NetBSD: pass2.c,v 1.15 2009/10/19 18:41:08 bouyer Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)pass2.c 8.6 (Berkeley) 10/27/94";
#else
__RCSID("$NetBSD: pass2.c,v 1.15 2009/10/19 18:41:08 bouyer Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs_dir.h>
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fsck.h"
#include "fsutil.h"
#include "extern.h"
#include "exitvalues.h"
#define MINDIRSIZE (sizeof (struct ext2fs_dirtemplate))
static int pass2check(struct inodesc *);
static int blksort(const void *, const void *);
void
pass2(void)
{
struct ext2fs_dinode *dp;
struct inoinfo **inpp, *inp;
struct inoinfo **inpend;
struct inodesc curino;
struct ext2fs_dinode dino;
char pathbuf[MAXPATHLEN + 1];
switch (statemap[EXT2_ROOTINO]) {
case USTATE:
pfatal("ROOT INODE UNALLOCATED");
if (reply("ALLOCATE") == 0)
exit(FSCK_EXIT_CHECK_FAILED);
if (allocdir(EXT2_ROOTINO, EXT2_ROOTINO, 0755) != EXT2_ROOTINO)
errexit("CANNOT ALLOCATE ROOT INODE");
break;
case DCLEAR:
pfatal("DUPS/BAD IN ROOT INODE");
if (reply("REALLOCATE")) {
freeino(EXT2_ROOTINO);
if (allocdir(EXT2_ROOTINO, EXT2_ROOTINO, 0755) != EXT2_ROOTINO)
errexit("CANNOT ALLOCATE ROOT INODE");
break;
}
if (reply("CONTINUE") == 0)
exit(FSCK_EXIT_CHECK_FAILED);
break;
case FSTATE:
case FCLEAR:
pfatal("ROOT INODE NOT DIRECTORY");
if (reply("REALLOCATE")) {
freeino(EXT2_ROOTINO);
if (allocdir(EXT2_ROOTINO, EXT2_ROOTINO, 0755) != EXT2_ROOTINO)
errexit("CANNOT ALLOCATE ROOT INODE");
break;
}
if (reply("FIX") == 0)
exit(FSCK_EXIT_CHECK_FAILED);
dp = ginode(EXT2_ROOTINO);
dp->e2di_mode = h2fs16((fs2h16(dp->e2di_mode) & ~IFMT) | IFDIR);
inodirty();
break;
case DSTATE:
break;
default:
errexit("BAD STATE %d FOR ROOT INODE", statemap[EXT2_ROOTINO]);
}
/*
* Sort the directory list into disk block order.
*/
qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort);
/*
* Check the integrity of each directory.
*/
memset(&curino, 0, sizeof(struct inodesc));
curino.id_type = DATA;
curino.id_func = pass2check;
inpend = &inpsort[inplast];
for (inpp = inpsort; inpp < inpend; inpp++) {
inp = *inpp;
if (inp->i_isize == 0)
continue;
if (inp->i_isize < MINDIRSIZE) {
direrror(inp->i_number, "DIRECTORY TOO SHORT");
inp->i_isize = roundup(MINDIRSIZE, sblock.e2fs_bsize);
if (reply("FIX") == 1) {
dp = ginode(inp->i_number);
inossize(dp, inp->i_isize);
inodirty();
}
} else if ((inp->i_isize & (sblock.e2fs_bsize - 1)) != 0) {
getpathname(pathbuf, sizeof(pathbuf), inp->i_number,
inp->i_number);
pwarn("DIRECTORY %s: LENGTH %lu NOT MULTIPLE OF %d",
pathbuf, (u_long)inp->i_isize, sblock.e2fs_bsize);
if (preen)
printf(" (ADJUSTED)\n");
inp->i_isize = roundup(inp->i_isize, sblock.e2fs_bsize);
if (preen || reply("ADJUST") == 1) {
dp = ginode(inp->i_number);
inossize(dp, inp->i_isize);
inodirty();
}
}
memset(&dino, 0, sizeof(struct ext2fs_dinode));
dino.e2di_mode = h2fs16(IFDIR);
inossize(&dino, inp->i_isize);
memcpy(&dino.e2di_blocks[0], &inp->i_blks[0], (size_t)inp->i_numblks);
curino.id_number = inp->i_number;
curino.id_parent = inp->i_parent;
(void)ckinode(&dino, &curino);
}
/*
* Now that the parents of all directories have been found,
* make another pass to verify the value of `..'
*/
for (inpp = inpsort; inpp < inpend; inpp++) {
inp = *inpp;
if (inp->i_parent == 0 || inp->i_isize == 0)
continue;
if (inp->i_dotdot == inp->i_parent ||
inp->i_dotdot == (ino_t)-1)
continue;
if (inp->i_dotdot == 0) {
inp->i_dotdot = inp->i_parent;
fileerror(inp->i_parent, inp->i_number, "MISSING '..'");
if (reply("FIX") == 0)
continue;
(void)makeentry(inp->i_number, inp->i_parent, "..");
lncntp[inp->i_parent]--;
continue;
}
fileerror(inp->i_parent, inp->i_number,
"BAD INODE NUMBER FOR '..'");
if (reply("FIX") == 0)
continue;
lncntp[inp->i_dotdot]++;
lncntp[inp->i_parent]--;
inp->i_dotdot = inp->i_parent;
(void)changeino(inp->i_number, "..", inp->i_parent);
}
/*
* Mark all the directories that can be found from the root.
*/
propagate();
}
static int
pass2check(struct inodesc *idesc)
{
struct ext2fs_direct *dirp = idesc->id_dirp;
struct inoinfo *inp;
int n, entrysize, ret = 0;
struct ext2fs_dinode *dp;
const char *errmsg;
struct ext2fs_direct proto;
char namebuf[MAXPATHLEN + 1];
char pathbuf[MAXPATHLEN + 1];
/*
* check for "."
*/
if (idesc->id_entryno != 0)
goto chk1;
if (fs2h32(dirp->e2d_ino) != 0 && dirp->e2d_namlen == 1 &&
dirp->e2d_name[0] == '.') {
if (fs2h32(dirp->e2d_ino) != idesc->id_number) {
direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'");
dirp->e2d_ino = h2fs32(idesc->id_number);
if (reply("FIX") == 1)
ret |= ALTERED;
}
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)
&& (dirp->e2d_type != EXT2_FT_DIR)) {
direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'");
dirp->e2d_type = EXT2_FT_DIR;
if (reply("FIX") == 1)
ret |= ALTERED;
}
goto chk1;
}
direrror(idesc->id_number, "MISSING '.'");
proto.e2d_ino = h2fs32(idesc->id_number);
proto.e2d_namlen = 1;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
proto.e2d_type = EXT2_FT_DIR;
else
proto.e2d_type = 0;
(void)strlcpy(proto.e2d_name, ".", sizeof(proto.e2d_name));
entrysize = EXT2FS_DIRSIZ(proto.e2d_namlen);
if (fs2h32(dirp->e2d_ino) != 0 && strcmp(dirp->e2d_name, "..") != 0) {
pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
dirp->e2d_name);
} else if (fs2h16(dirp->e2d_reclen) < entrysize) {
pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
} else if (fs2h16(dirp->e2d_reclen) < 2 * entrysize) {
proto.e2d_reclen = dirp->e2d_reclen;
memcpy(dirp, &proto, (size_t)entrysize);
if (reply("FIX") == 1)
ret |= ALTERED;
} else {
n = fs2h16(dirp->e2d_reclen) - entrysize;
proto.e2d_reclen = h2fs16(entrysize);
memcpy(dirp, &proto, (size_t)entrysize);
idesc->id_entryno++;
lncntp[fs2h32(dirp->e2d_ino)]--;
dirp = (struct ext2fs_direct *)((char *)(dirp) + entrysize);
memset(dirp, 0, (size_t)n);
dirp->e2d_reclen = h2fs16(n);
if (reply("FIX") == 1)
ret |= ALTERED;
}
chk1:
if (idesc->id_entryno > 1)
goto chk2;
inp = getinoinfo(idesc->id_number);
proto.e2d_ino = h2fs32(inp->i_parent);
proto.e2d_namlen = 2;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
proto.e2d_type = EXT2_FT_DIR;
else
proto.e2d_type = 0;
(void)strlcpy(proto.e2d_name, "..", sizeof(proto.e2d_name));
entrysize = EXT2FS_DIRSIZ(2);
if (idesc->id_entryno == 0) {
n = EXT2FS_DIRSIZ(dirp->e2d_namlen);
if (fs2h16(dirp->e2d_reclen) < n + entrysize)
goto chk2;
proto.e2d_reclen = h2fs16(fs2h16(dirp->e2d_reclen) - n);
dirp->e2d_reclen = h2fs16(n);
idesc->id_entryno++;
lncntp[fs2h32(dirp->e2d_ino)]--;
dirp = (struct ext2fs_direct *)((char *)(dirp) + n);
memset(dirp, 0, (size_t)fs2h16(proto.e2d_reclen));
dirp->e2d_reclen = proto.e2d_reclen;
}
if (fs2h32(dirp->e2d_ino) != 0 &&
dirp->e2d_namlen == 2 &&
strncmp(dirp->e2d_name, "..", 2) == 0) {
inp->i_dotdot = fs2h32(dirp->e2d_ino);
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)
&& dirp->e2d_type != EXT2_FT_DIR) {
direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'");
dirp->e2d_type = EXT2_FT_DIR;
if (reply("FIX") == 1)
ret |= ALTERED;
}
goto chk2;
}
if (fs2h32(dirp->e2d_ino) != 0 &&
dirp->e2d_namlen == 1 &&
strncmp(dirp->e2d_name, ".", 1) != 0) {
fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
dirp->e2d_name);
inp->i_dotdot = (ino_t)-1;
} else if (fs2h16(dirp->e2d_reclen) < entrysize) {
fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
inp->i_dotdot = (ino_t)-1;
} else if (inp->i_parent != 0) {
/*
* We know the parent, so fix now.
*/
inp->i_dotdot = inp->i_parent;
fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
proto.e2d_reclen = dirp->e2d_reclen;
memcpy(dirp, &proto, (size_t)entrysize);
if (reply("FIX") == 1)
ret |= ALTERED;
}
idesc->id_entryno++;
if (fs2h32(dirp->e2d_ino) != 0)
lncntp[fs2h32(dirp->e2d_ino)]--;
return (ret|KEEPON);
chk2:
if (fs2h32(dirp->e2d_ino) == 0)
return (ret|KEEPON);
if (dirp->e2d_namlen <= 2 &&
dirp->e2d_name[0] == '.' &&
idesc->id_entryno >= 2) {
if (dirp->e2d_namlen == 1) {
direrror(idesc->id_number, "EXTRA '.' ENTRY");
dirp->e2d_ino = 0;
if (reply("FIX") == 1)
ret |= ALTERED;
return (KEEPON | ret);
}
if (dirp->e2d_name[1] == '.') {
direrror(idesc->id_number, "EXTRA '..' ENTRY");
dirp->e2d_ino = 0;
if (reply("FIX") == 1)
ret |= ALTERED;
return (KEEPON | ret);
}
}
idesc->id_entryno++;
n = 0;
if (fs2h32(dirp->e2d_ino) > maxino ||
(fs2h32(dirp->e2d_ino) < EXT2_FIRSTINO &&
fs2h32(dirp->e2d_ino) != EXT2_ROOTINO)) {
fileerror(idesc->id_number, fs2h32(dirp->e2d_ino), "I OUT OF RANGE");
n = reply("REMOVE");
} else {
again:
switch (statemap[fs2h32(dirp->e2d_ino)]) {
case USTATE:
if (idesc->id_entryno <= 2)
break;
fileerror(idesc->id_number, fs2h32(dirp->e2d_ino), "UNALLOCATED");
n = reply("REMOVE");
break;
case DCLEAR:
case FCLEAR:
if (idesc->id_entryno <= 2)
break;
if (statemap[fs2h32(dirp->e2d_ino)] == FCLEAR)
errmsg = "DUP/BAD";
else if (!preen)
errmsg = "ZERO LENGTH DIRECTORY";
else {
n = 1;
break;
}
fileerror(idesc->id_number, fs2h32(dirp->e2d_ino), errmsg);
if ((n = reply("REMOVE")) == 1)
break;
dp = ginode(fs2h32(dirp->e2d_ino));
statemap[fs2h32(dirp->e2d_ino)] =
(fs2h16(dp->e2di_mode) & IFMT) == IFDIR ? DSTATE : FSTATE;
lncntp[fs2h32(dirp->e2d_ino)] = fs2h16(dp->e2di_nlink);
goto again;
case DSTATE:
case DFOUND:
inp = getinoinfo(fs2h32(dirp->e2d_ino));
if (inp->i_parent != 0 && idesc->id_entryno > 2) {
getpathname(pathbuf, sizeof(pathbuf),
idesc->id_number, idesc->id_number);
getpathname(namebuf, sizeof(namebuf),
fs2h32(dirp->e2d_ino),
fs2h32(dirp->e2d_ino));
pwarn("%s %s %s\n", pathbuf,
"IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
namebuf);
if (preen)
printf(" (IGNORED)\n");
else if ((n = reply("REMOVE")) == 1)
break;
}
if (idesc->id_entryno > 2)
inp->i_parent = idesc->id_number;
/* fall through */
case FSTATE:
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat &
EXT2F_INCOMPAT_FTYPE) &&
dirp->e2d_type !=
inot2ext2dt(typemap[fs2h32(dirp->e2d_ino)])) {
dirp->e2d_type =
inot2ext2dt(typemap[fs2h32(dirp->e2d_ino)]);
fileerror(idesc->id_number,
fs2h32(dirp->e2d_ino),
"BAD TYPE VALUE");
if (reply("FIX") == 1)
ret |= ALTERED;
}
lncntp[fs2h32(dirp->e2d_ino)]--;
break;
default:
errexit("BAD STATE %d FOR INODE I=%d",
statemap[fs2h32(dirp->e2d_ino)], fs2h32(dirp->e2d_ino));
}
}
if (n == 0)
return (ret|KEEPON);
dirp->e2d_ino = 0;
return (ret|KEEPON|ALTERED);
}
/*
* Routine to sort disk blocks.
*/
static int
blksort(const void *inpp1, const void *inpp2)
{
return ((* (const struct inoinfo * const*) inpp1)->i_blks[0] -
(* (const struct inoinfo * const*) inpp2)->i_blks[0]);
}

View File

@ -1,100 +0,0 @@
/* $NetBSD: pass3.c,v 1.7 2009/10/19 18:41:08 bouyer Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)pass3.c 8.1 (Berkeley) 6/5/93";
#else
__RCSID("$NetBSD: pass3.c,v 1.7 2009/10/19 18:41:08 bouyer Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs.h>
#include "fsck.h"
#include "extern.h"
void
pass3(void)
{
struct inoinfo **inpp, *inp;
ino_t orphan;
int loopcnt;
for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
inp = *inpp;
if (inp->i_number == EXT2_ROOTINO ||
!(inp->i_parent == 0 || statemap[inp->i_number] == DSTATE))
continue;
if (statemap[inp->i_number] == DCLEAR)
continue;
for (loopcnt = 0; ; loopcnt++) {
orphan = inp->i_number;
if (inp->i_parent == 0 ||
statemap[inp->i_parent] != DSTATE ||
loopcnt > numdirs)
break;
inp = getinoinfo(inp->i_parent);
}
(void)linkup(orphan, inp->i_dotdot);
inp->i_parent = inp->i_dotdot = lfdir;
lncntp[lfdir]--;
statemap[orphan] = DFOUND;
propagate();
}
}

View File

@ -1,164 +0,0 @@
/* $NetBSD: pass4.c,v 1.10 2009/10/19 18:41:08 bouyer Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)pass4.c 8.1 (Berkeley) 6/5/93";
#else
__RCSID("$NetBSD: pass4.c,v 1.10 2009/10/19 18:41:08 bouyer Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs.h>
#include <stdlib.h>
#include <string.h>
#include "fsutil.h"
#include "fsck.h"
#include "extern.h"
void
pass4(void)
{
ino_t inumber;
struct zlncnt *zlnp;
struct ext2fs_dinode *dp;
struct inodesc idesc;
int n;
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = pass4check;
for (inumber = EXT2_ROOTINO; inumber <= lastino; inumber++) {
if (inumber < EXT2_FIRSTINO && inumber > EXT2_ROOTINO)
continue;
idesc.id_number = inumber;
switch (statemap[inumber]) {
case FSTATE:
case DFOUND:
n = lncntp[inumber];
if (n)
adjust(&idesc, (short)n);
else {
for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
if (zlnp->zlncnt == inumber) {
zlnp->zlncnt = zlnhead->zlncnt;
zlnp = zlnhead;
zlnhead = zlnhead->next;
free((char *)zlnp);
clri(&idesc, "UNREF", 1);
break;
}
}
break;
case DSTATE:
clri(&idesc, "UNREF", 1);
break;
case DCLEAR:
dp = ginode(inumber);
if (inosize(dp) == 0) {
clri(&idesc, "ZERO LENGTH", 1);
break;
}
/* fall through */
case FCLEAR:
clri(&idesc, "BAD/DUP", 1);
break;
case USTATE:
break;
default:
errexit("BAD STATE %d FOR INODE I=%llu",
statemap[inumber], (unsigned long long)inumber);
}
}
}
int
pass4check(struct inodesc *idesc)
{
struct dups *dlp;
int nfrags, res = KEEPON;
daddr_t blkno = idesc->id_blkno;
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
if (chkrange(blkno, 1)) {
res = SKIP;
} else if (testbmap(blkno)) {
for (dlp = duplist; dlp; dlp = dlp->next) {
if (dlp->dup != blkno)
continue;
dlp->dup = duplist->dup;
dlp = duplist;
duplist = duplist->next;
free((char *)dlp);
break;
}
if (dlp == 0) {
clrbmap(blkno);
n_blks--;
}
}
}
return (res);
}

View File

@ -1,277 +0,0 @@
/* $NetBSD: pass5.c,v 1.20 2012/08/26 09:33:18 dholland Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)pass5.c 8.6 (Berkeley) 11/30/94";
#else
__RCSID("$NetBSD: pass5.c,v 1.20 2012/08/26 09:33:18 dholland Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "fsutil.h"
#include "fsck.h"
#include "extern.h"
static void print_bmap(char *, uint32_t);
void
pass5(void)
{
int c;
struct m_ext2fs *fs = &sblock;
daddr_t dbase, dmax;
daddr_t d;
uint32_t i, j;
struct inodesc idesc[3];
struct bufarea *ino_bitmap = NULL, *blk_bitmap = NULL;
char *ibmap, *bbmap;
u_int32_t cs_ndir, cs_nbfree, cs_nifree;
char msg[255];
cs_ndir = 0;
cs_nbfree = 0;
cs_nifree = 0;
ibmap = malloc(fs->e2fs_bsize);
bbmap = malloc(fs->e2fs_bsize);
if (ibmap == NULL || bbmap == NULL) {
errexit("out of memory");
}
for (c = 0; c < fs->e2fs_ncg; c++) {
u_int32_t nbfree = 0;
u_int32_t nifree = 0;
u_int32_t ndirs = 0;
nbfree = 0;
nifree = fs->e2fs.e2fs_ipg;
ndirs = 0;
if (blk_bitmap == NULL) {
blk_bitmap = getdatablk(fs2h32(fs->e2fs_gd[c].ext2bgd_b_bitmap),
fs->e2fs_bsize);
} else {
getblk(blk_bitmap, fs2h32(fs->e2fs_gd[c].ext2bgd_b_bitmap),
fs->e2fs_bsize);
}
if (ino_bitmap == NULL) {
ino_bitmap = getdatablk(fs2h32(fs->e2fs_gd[c].ext2bgd_i_bitmap),
fs->e2fs_bsize);
} else {
getblk(ino_bitmap, fs2h32(fs->e2fs_gd[c].ext2bgd_i_bitmap),
fs->e2fs_bsize);
}
memset(bbmap, 0, fs->e2fs_bsize);
memset(ibmap, 0, fs->e2fs_bsize);
memset(&idesc[0], 0, sizeof idesc);
for (i = 0; i < 3; i++) {
idesc[i].id_type = ADDR;
}
j = fs->e2fs.e2fs_ipg * c + 1;
for (i = 0; i < fs->e2fs.e2fs_ipg; j++, i++) {
if ((j < EXT2_FIRSTINO) && (j != EXT2_ROOTINO)) {
setbit(ibmap, i);
nifree--;
continue;
}
if (j > fs->e2fs.e2fs_icount) {
setbit(ibmap, i);
continue;
}
switch (statemap[j]) {
case USTATE:
break;
case DSTATE:
case DCLEAR:
case DFOUND:
ndirs++;
/* fall through */
case FSTATE:
case FCLEAR:
nifree--;
setbit(ibmap, i);
break;
default:
errexit("BAD STATE %d FOR INODE I=%"PRIu32,
statemap[j], j);
}
}
/* fill in unused par of the inode map */
for (i = fs->e2fs.e2fs_ipg / NBBY; i < (uint32_t)fs->e2fs_bsize; i++)
ibmap[i] = 0xff;
dbase = c * sblock.e2fs.e2fs_bpg +
sblock.e2fs.e2fs_first_dblock;
dmax = (c+1) * sblock.e2fs.e2fs_bpg +
sblock.e2fs.e2fs_first_dblock;
for (i = 0, d = dbase;
d < dmax;
d ++, i ++) {
if (testbmap(d) || d >= sblock.e2fs.e2fs_bcount) {
setbit(bbmap, i);
continue;
} else {
nbfree++;
}
}
cs_nbfree += nbfree;
cs_nifree += nifree;
cs_ndir += ndirs;
if (debug && (fs2h16(fs->e2fs_gd[c].ext2bgd_nbfree) != nbfree ||
fs2h16(fs->e2fs_gd[c].ext2bgd_nifree) != nifree ||
fs2h16(fs->e2fs_gd[c].ext2bgd_ndirs) != ndirs)) {
printf("summary info for cg %d is %d, %d, %d,"
"should be %d, %d, %d\n", c,
fs2h16(fs->e2fs_gd[c].ext2bgd_nbfree),
fs2h16(fs->e2fs_gd[c].ext2bgd_nifree),
fs2h16(fs->e2fs_gd[c].ext2bgd_ndirs),
nbfree,
nifree,
ndirs);
}
(void)snprintf(msg, sizeof(msg),
"SUMMARY INFORMATIONS WRONG FOR CG #%d", c);
if ((fs2h16(fs->e2fs_gd[c].ext2bgd_nbfree) != nbfree ||
fs2h16(fs->e2fs_gd[c].ext2bgd_nifree) != nifree ||
fs2h16(fs->e2fs_gd[c].ext2bgd_ndirs) != ndirs) &&
dofix(&idesc[0], msg)) {
fs->e2fs_gd[c].ext2bgd_nbfree = h2fs16(nbfree);
fs->e2fs_gd[c].ext2bgd_nifree = h2fs16(nifree);
fs->e2fs_gd[c].ext2bgd_ndirs = h2fs16(ndirs);
sbdirty();
}
if (debug && memcmp(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize)) {
printf("blk_bitmap:\n");
print_bmap(blk_bitmap->b_un.b_buf, fs->e2fs_bsize);
printf("bbmap:\n");
print_bmap(bbmap, fs->e2fs_bsize);
}
(void)snprintf(msg, sizeof(msg),
"BLK(S) MISSING IN BIT MAPS #%d", c);
if (memcmp(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize) &&
dofix(&idesc[1], msg)) {
memcpy(blk_bitmap->b_un.b_buf, bbmap, fs->e2fs_bsize);
dirty(blk_bitmap);
}
if (debug && memcmp(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize)) {
printf("ino_bitmap:\n");
print_bmap(ino_bitmap->b_un.b_buf, fs->e2fs_bsize);
printf("ibmap:\n");
print_bmap(ibmap, fs->e2fs_bsize);
}
(void)snprintf(msg, sizeof(msg),
"INODE(S) MISSING IN BIT MAPS #%d", c);
if (memcmp(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize) &&
dofix(&idesc[1], msg)) {
memcpy(ino_bitmap->b_un.b_buf, ibmap, fs->e2fs_bsize);
dirty(ino_bitmap);
}
}
if (debug && (fs->e2fs.e2fs_fbcount != cs_nbfree ||
fs->e2fs.e2fs_ficount != cs_nifree)) {
printf("summary info bad in superblock: %d, %d should be %d, %d\n",
fs->e2fs.e2fs_fbcount, fs->e2fs.e2fs_ficount,
cs_nbfree, cs_nifree);
}
if ((fs->e2fs.e2fs_fbcount != cs_nbfree ||
fs->e2fs.e2fs_ficount != cs_nifree)
&& dofix(&idesc[0], "SUPERBLK SUMMARY INFORMATION BAD")) {
fs->e2fs.e2fs_fbcount = cs_nbfree;
fs->e2fs.e2fs_ficount = cs_nifree;
sbdirty();
}
free(ibmap);
free(bbmap);
}
static void
print_bmap(char *map, uint32_t size)
{
uint32_t i, j;
i = 0;
while (i < size) {
printf("%04x: ",i);
for (j = 0; j < 16; j++, i++)
printf("%02x ", (unsigned char)map[i] & 0xff);
printf("\n");
}
}

View File

@ -1,557 +0,0 @@
/* $NetBSD: setup.c,v 1.32 2014/12/04 01:41:37 christos Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)setup.c 8.5 (Berkeley) 11/23/94";
#else
__RCSID("$NetBSD: setup.c,v 1.32 2014/12/04 01:41:37 christos Exp $");
#endif
#endif /* not lint */
#define FSTYPENAMES
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/disklabel.h>
#include <sys/file.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "fsck.h"
#include "extern.h"
#include "fsutil.h"
#include "exitvalues.h"
void badsb(int, const char *);
int calcsb(const char *, int, struct m_ext2fs *);
static struct disklabel *getdisklabel(const char *, int);
static int readsb(int);
int
setup(const char *dev)
{
long cg, asked, i;
long bmapsize;
struct disklabel *lp;
off_t sizepb;
struct stat statb;
struct m_ext2fs proto;
int doskipclean;
u_int64_t maxfilesize;
havesb = 0;
fswritefd = -1;
doskipclean = skipclean;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
return 0;
}
#if !defined(__minix)
if (!S_ISCHR(statb.st_mode)) {
pfatal("%s is not a character device", dev);
if (reply("CONTINUE") == 0)
return 0;
}
#endif /* !defined(__minix) */
if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
printf("Can't open %s: %s\n", dev, strerror(errno));
return 0;
}
if (preen == 0)
printf("** %s", dev);
if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) {
fswritefd = -1;
if (preen)
pfatal("NO WRITE ACCESS");
printf(" (NO WRITE)");
}
if (preen == 0)
printf("\n");
fsmodified = 0;
lfdir = 0;
initbarea(&sblk);
initbarea(&asblk);
sblk.b_un.b_buf = malloc(SBSIZE);
asblk.b_un.b_buf = malloc(SBSIZE);
if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
errexit("cannot allocate space for superblock");
if ((lp = getdisklabel(NULL, fsreadfd)) != NULL)
dev_bsize = secsize = lp->d_secsize;
else
dev_bsize = secsize = DEV_BSIZE;
/*
* Read in the superblock, looking for alternates if necessary
*/
if (readsb(1) == 0) {
if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0)
return 0;
if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
return 0;
for (cg = 1; cg < proto.e2fs_ncg; cg++) {
bflag = EXT2_FSBTODB(&proto,
cg * proto.e2fs.e2fs_bpg +
proto.e2fs.e2fs_first_dblock);
if (readsb(0) != 0)
break;
}
if (cg >= proto.e2fs_ncg) {
printf("%s %s\n%s %s\n%s %s\n",
"SEARCH FOR ALTERNATE SUPER-BLOCK",
"FAILED. YOU MUST USE THE",
"-b OPTION TO FSCK_FFS TO SPECIFY THE",
"LOCATION OF AN ALTERNATE",
"SUPER-BLOCK TO SUPPLY NEEDED",
"INFORMATION; SEE fsck_ext2fs(8).");
return 0;
}
doskipclean = 0;
pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag);
}
if (debug)
printf("state = %d\n", sblock.e2fs.e2fs_state);
if (sblock.e2fs.e2fs_state == E2FS_ISCLEAN) {
if (doskipclean) {
pwarn("%sile system is clean; not checking\n",
preen ? "f" : "** F");
return -1;
}
if (!preen)
pwarn("** File system is already clean\n");
}
maxfsblock = sblock.e2fs.e2fs_bcount;
maxino = sblock.e2fs_ncg * sblock.e2fs.e2fs_ipg;
sizepb = sblock.e2fs_bsize;
maxfilesize = sblock.e2fs_bsize * EXT2FS_NDADDR - 1;
for (i = 0; i < EXT2FS_NIADDR; i++) {
sizepb *= EXT2_NINDIR(&sblock);
maxfilesize += sizepb;
}
/*
* Check and potentially fix certain fields in the super block.
*/
if (/* (sblock.e2fs.e2fs_rbcount < 0) || */
(sblock.e2fs.e2fs_rbcount > sblock.e2fs.e2fs_bcount)) {
pfatal("IMPOSSIBLE RESERVED BLOCK COUNT=%d IN SUPERBLOCK",
sblock.e2fs.e2fs_rbcount);
if (reply("SET TO DEFAULT") == 1) {
sblock.e2fs.e2fs_rbcount =
sblock.e2fs.e2fs_bcount * MINFREE / 100;
sbdirty();
dirty(&asblk);
}
}
if (sblock.e2fs.e2fs_bpg != sblock.e2fs.e2fs_fpg) {
pfatal("WRONG FPG=%d (BPG=%d) IN SUPERBLOCK",
sblock.e2fs.e2fs_fpg, sblock.e2fs.e2fs_bpg);
return 0;
}
if (asblk.b_dirty && !bflag) {
copyback_sb(&asblk);
flush(fswritefd, &asblk);
}
/*
* read in the summary info.
*/
sblock.e2fs_gd = malloc(sblock.e2fs_ngdb * sblock.e2fs_bsize);
if (sblock.e2fs_gd == NULL)
errexit("out of memory");
asked = 0;
for (i = 0; i < sblock.e2fs_ngdb; i++) {
if (bread(fsreadfd,
(char *)&sblock.e2fs_gd[i * sblock.e2fs_bsize /
sizeof(struct ext2_gd)],
EXT2_FSBTODB(&sblock, ((sblock.e2fs_bsize > 1024) ? 0 : 1) +
i + 1),
sblock.e2fs_bsize) != 0 && !asked) {
pfatal("BAD SUMMARY INFORMATION");
if (reply("CONTINUE") == 0)
exit(FSCK_EXIT_CHECK_FAILED);
asked++;
}
}
/*
* allocate and initialize the necessary maps
*/
bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t));
blockmap = calloc((unsigned int)bmapsize, sizeof(char));
if (blockmap == NULL) {
printf("cannot alloc %u bytes for blockmap\n",
(unsigned int)bmapsize);
goto badsblabel;
}
statemap = calloc((unsigned int)(maxino + 2), sizeof(char));
if (statemap == NULL) {
printf("cannot alloc %u bytes for statemap\n",
(unsigned int)(maxino + 1));
goto badsblabel;
}
typemap = calloc((unsigned int)(maxino + 1), sizeof(char));
if (typemap == NULL) {
printf("cannot alloc %u bytes for typemap\n",
(unsigned int)(maxino + 1));
goto badsblabel;
}
lncntp = calloc((unsigned)(maxino + 1), sizeof(int16_t));
if (lncntp == NULL) {
printf("cannot alloc %u bytes for lncntp\n",
(unsigned int)((maxino + 1) * sizeof(int16_t)));
goto badsblabel;
}
for (numdirs = 0, cg = 0; cg < sblock.e2fs_ncg; cg++) {
numdirs += fs2h16(sblock.e2fs_gd[cg].ext2bgd_ndirs);
}
inplast = 0;
listmax = numdirs + 10;
inpsort = calloc((unsigned int)listmax, sizeof(struct inoinfo *));
inphead = calloc((unsigned int)numdirs, sizeof(struct inoinfo *));
if (inpsort == NULL || inphead == NULL) {
printf("cannot alloc %u bytes for inphead\n",
(unsigned int)(numdirs * sizeof(struct inoinfo *)));
goto badsblabel;
}
bufinit();
return 1;
badsblabel:
ckfini(0);
return 0;
}
/*
* Read in the super block and its summary info, convert to host byte order.
*/
static int
readsb(int listerr)
{
daddr_t super = bflag ? bflag : SBOFF / dev_bsize;
if (bread(fsreadfd, (char *)sblk.b_un.b_fs, super, (long)SBSIZE) != 0)
return 0;
sblk.b_bno = super;
sblk.b_size = SBSIZE;
/* Copy the superblock in memory */
e2fs_sbload(sblk.b_un.b_fs, &sblock.e2fs);
/*
* run a few consistency checks of the super block
*/
if (sblock.e2fs.e2fs_magic != E2FS_MAGIC) {
badsb(listerr, "MAGIC NUMBER WRONG");
return 0;
}
if (sblock.e2fs.e2fs_log_bsize > 2) {
badsb(listerr, "BAD LOG_BSIZE");
return 0;
}
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(!powerof2(sblock.e2fs.e2fs_inode_size) ||
sblock.e2fs.e2fs_inode_size < sizeof(struct ext2fs_dinode) ||
sblock.e2fs.e2fs_inode_size >
(1024 << sblock.e2fs.e2fs_log_bsize))) {
badsb(listerr, "BAD INODE_SIZE");
return 0;
}
/* compute the dynamic fields of the in-memory sb */
/* compute dynamic sb infos */
sblock.e2fs_ncg =
howmany(sblock.e2fs.e2fs_bcount - sblock.e2fs.e2fs_first_dblock,
sblock.e2fs.e2fs_bpg);
/* XXX assume hw bsize = 512 */
sblock.e2fs_fsbtodb = sblock.e2fs.e2fs_log_bsize + 1;
sblock.e2fs_bsize = 1024 << sblock.e2fs.e2fs_log_bsize;
sblock.e2fs_bshift = LOG_MINBSIZE + sblock.e2fs.e2fs_log_bsize;
sblock.e2fs_qbmask = sblock.e2fs_bsize - 1;
sblock.e2fs_bmask = ~sblock.e2fs_qbmask;
sblock.e2fs_ngdb = howmany(sblock.e2fs_ncg,
sblock.e2fs_bsize / sizeof(struct ext2_gd));
sblock.e2fs_ipb = sblock.e2fs_bsize / EXT2_DINODE_SIZE(&sblock);
sblock.e2fs_itpg = howmany(sblock.e2fs.e2fs_ipg, sblock.e2fs_ipb);
/*
* Compute block size that the filesystem is based on,
* according to fsbtodb, and adjust superblock block number
* so we can tell if this is an alternate later.
*/
super *= dev_bsize;
dev_bsize = sblock.e2fs_bsize / EXT2_FSBTODB(&sblock, 1);
sblk.b_bno = super / dev_bsize;
if (sblock.e2fs_ncg == 1) {
/* no alternate superblock; assume it's okay */
havesb = 1;
return 1;
}
getblk(&asblk, 1 * sblock.e2fs.e2fs_bpg + sblock.e2fs.e2fs_first_dblock,
(long)SBSIZE);
if (asblk.b_errs)
return 0;
if (bflag) {
havesb = 1;
return 1;
}
/*
* Set all possible fields that could differ, then do check
* of whole super block against an alternate super block.
* When an alternate super-block is specified this check is skipped.
*/
asblk.b_un.b_fs->e2fs_rbcount = sblk.b_un.b_fs->e2fs_rbcount;
asblk.b_un.b_fs->e2fs_fbcount = sblk.b_un.b_fs->e2fs_fbcount;
asblk.b_un.b_fs->e2fs_ficount = sblk.b_un.b_fs->e2fs_ficount;
asblk.b_un.b_fs->e2fs_mtime = sblk.b_un.b_fs->e2fs_mtime;
asblk.b_un.b_fs->e2fs_wtime = sblk.b_un.b_fs->e2fs_wtime;
asblk.b_un.b_fs->e2fs_mnt_count = sblk.b_un.b_fs->e2fs_mnt_count;
asblk.b_un.b_fs->e2fs_max_mnt_count =
sblk.b_un.b_fs->e2fs_max_mnt_count;
asblk.b_un.b_fs->e2fs_state = sblk.b_un.b_fs->e2fs_state;
asblk.b_un.b_fs->e2fs_beh = sblk.b_un.b_fs->e2fs_beh;
asblk.b_un.b_fs->e2fs_lastfsck = sblk.b_un.b_fs->e2fs_lastfsck;
asblk.b_un.b_fs->e2fs_fsckintv = sblk.b_un.b_fs->e2fs_fsckintv;
asblk.b_un.b_fs->e2fs_ruid = sblk.b_un.b_fs->e2fs_ruid;
asblk.b_un.b_fs->e2fs_rgid = sblk.b_un.b_fs->e2fs_rgid;
asblk.b_un.b_fs->e2fs_block_group_nr =
sblk.b_un.b_fs->e2fs_block_group_nr;
asblk.b_un.b_fs->e2fs_features_rocompat &= ~EXT2F_ROCOMPAT_LARGEFILE;
asblk.b_un.b_fs->e2fs_features_rocompat |=
sblk.b_un.b_fs->e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
((sblock.e2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) ||
(sblock.e2fs.e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP))) {
if (debug) {
printf("compat 0x%08x, incompat 0x%08x, compat_ro "
"0x%08x\n",
sblock.e2fs.e2fs_features_compat,
sblock.e2fs.e2fs_features_incompat,
sblock.e2fs.e2fs_features_rocompat);
}
badsb(listerr, "INCOMPATIBLE FEATURE BITS IN SUPER BLOCK");
return 0;
}
if (memcmp(sblk.b_un.b_fs, asblk.b_un.b_fs, SBSIZE)) {
if (debug) {
u_int32_t *nlp, *olp, *endlp;
printf("superblock mismatches\n");
nlp = (u_int32_t *)asblk.b_un.b_fs;
olp = (u_int32_t *)sblk.b_un.b_fs;
endlp = olp + (SBSIZE / sizeof(*olp));
for ( ; olp < endlp; olp++, nlp++) {
if (*olp == *nlp)
continue;
printf("offset %ld, original %ld, "
"alternate %ld\n",
(long)(olp - (u_int32_t *)sblk.b_un.b_fs),
(long)fs2h32(*olp),
(long)fs2h32(*nlp));
}
}
badsb(listerr,
"VALUES IN SUPER BLOCK DISAGREE WITH "
"THOSE IN FIRST ALTERNATE");
return 0;
}
havesb = 1;
return 1;
}
void
copyback_sb(struct bufarea *bp)
{
/* Copy the in-memory superblock back to buffer */
bp->b_un.b_fs->e2fs_icount = h2fs32(sblock.e2fs.e2fs_icount);
bp->b_un.b_fs->e2fs_bcount = h2fs32(sblock.e2fs.e2fs_bcount);
bp->b_un.b_fs->e2fs_rbcount = h2fs32(sblock.e2fs.e2fs_rbcount);
bp->b_un.b_fs->e2fs_fbcount = h2fs32(sblock.e2fs.e2fs_fbcount);
bp->b_un.b_fs->e2fs_ficount = h2fs32(sblock.e2fs.e2fs_ficount);
bp->b_un.b_fs->e2fs_first_dblock =
h2fs32(sblock.e2fs.e2fs_first_dblock);
bp->b_un.b_fs->e2fs_log_bsize = h2fs32(sblock.e2fs.e2fs_log_bsize);
bp->b_un.b_fs->e2fs_fsize = h2fs32(sblock.e2fs.e2fs_fsize);
bp->b_un.b_fs->e2fs_bpg = h2fs32(sblock.e2fs.e2fs_bpg);
bp->b_un.b_fs->e2fs_fpg = h2fs32(sblock.e2fs.e2fs_fpg);
bp->b_un.b_fs->e2fs_ipg = h2fs32(sblock.e2fs.e2fs_ipg);
bp->b_un.b_fs->e2fs_mtime = h2fs32(sblock.e2fs.e2fs_mtime);
bp->b_un.b_fs->e2fs_wtime = h2fs32(sblock.e2fs.e2fs_wtime);
bp->b_un.b_fs->e2fs_lastfsck = h2fs32(sblock.e2fs.e2fs_lastfsck);
bp->b_un.b_fs->e2fs_fsckintv = h2fs32(sblock.e2fs.e2fs_fsckintv);
bp->b_un.b_fs->e2fs_creator = h2fs32(sblock.e2fs.e2fs_creator);
bp->b_un.b_fs->e2fs_rev = h2fs32(sblock.e2fs.e2fs_rev);
bp->b_un.b_fs->e2fs_mnt_count = h2fs16(sblock.e2fs.e2fs_mnt_count);
bp->b_un.b_fs->e2fs_max_mnt_count =
h2fs16(sblock.e2fs.e2fs_max_mnt_count);
bp->b_un.b_fs->e2fs_magic = h2fs16(sblock.e2fs.e2fs_magic);
bp->b_un.b_fs->e2fs_state = h2fs16(sblock.e2fs.e2fs_state);
bp->b_un.b_fs->e2fs_beh = h2fs16(sblock.e2fs.e2fs_beh);
bp->b_un.b_fs->e2fs_ruid = h2fs16(sblock.e2fs.e2fs_ruid);
bp->b_un.b_fs->e2fs_rgid = h2fs16(sblock.e2fs.e2fs_rgid);
}
void
badsb(int listerr, const char *s)
{
if (!listerr)
return;
if (preen)
printf("%s: ", cdevname());
pfatal("BAD SUPER BLOCK: %s\n", s);
}
/*
* Calculate a prototype superblock based on information in the disk label.
* When done the cgsblock macro can be calculated and the fs_ncg field
* can be used. Do NOT attempt to use other macros without verifying that
* their needed information is available!
*/
int
calcsb(const char *dev, int devfd, struct m_ext2fs *fs)
{
#if defined(__minix)
errexit("%s: calcsb: can't read disk label under minix", dev);
#else
struct disklabel *lp;
struct partition *pp;
char *cp;
cp = strchr(dev, '\0');
if (cp-- == dev ||
((*cp < 'a' || *cp > 'h') && !isdigit((unsigned char)*cp))) {
pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev);
return 0;
}
lp = getdisklabel(dev, devfd);
if (isdigit((unsigned char)*cp))
pp = &lp->d_partitions[0];
else
pp = &lp->d_partitions[*cp - 'a'];
if (pp->p_fstype != FS_EX2FS) {
pfatal("%s: NOT LABELED AS A EXT2 FILE SYSTEM (%s)\n",
dev, pp->p_fstype < FSMAXTYPES ?
fstypenames[pp->p_fstype] : "unknown");
return 0;
}
if (pp->p_fsize == 0) {
pfatal("%s: PARTITION SIZE IS 0\n", dev);
return 0;
}
memset(fs, 0, sizeof(struct m_ext2fs));
fs->e2fs_bsize = pp->p_fsize;
fs->e2fs.e2fs_log_bsize = pp->p_fsize / 1024;
fs->e2fs.e2fs_bcount = (pp->p_size * DEV_BSIZE) / fs->e2fs_bsize;
fs->e2fs.e2fs_first_dblock = (fs->e2fs.e2fs_log_bsize == 0) ? 1 : 0;
fs->e2fs.e2fs_bpg = fs->e2fs_bsize * NBBY;
fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize;
fs->e2fs_qbmask = fs->e2fs_bsize - 1;
fs->e2fs_bmask = ~fs->e2fs_qbmask;
fs->e2fs_ncg =
howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
fs->e2fs.e2fs_bpg);
fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1;
fs->e2fs_ngdb = howmany(fs->e2fs_ncg,
fs->e2fs_bsize / sizeof(struct ext2_gd));
return 1;
#endif /* defined(__minix) */
}
static struct disklabel *
getdisklabel(const char *s, int fd)
{
static struct disklabel lab;
#if defined(__minix)
if (s == NULL)
return NULL;
errexit("%s: can't read disk label under minix", s);
#else
if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
if (s == NULL)
return NULL;
pwarn("ioctl (GCINFO): %s\n", strerror(errno));
errexit("%s: can't read disk label", s);
}
#endif /* defined(__minix) */
return &lab;
}
daddr_t
cgoverhead(int c)
{
int overh;
overh =
1 /* block bitmap */ +
1 /* inode bitmap */ +
sblock.e2fs_itpg;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) {
if (cg_has_sb(c) == 0)
return overh;
}
overh += 1 /* superblock */ + sblock.e2fs_ngdb;
return overh;
}

View File

@ -1,499 +0,0 @@
/* $NetBSD: utilities.c,v 1.23 2013/06/23 02:06:04 dholland Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)utilities.c 8.1 (Berkeley) 6/5/93";
#else
__RCSID("$NetBSD: utilities.c,v 1.23 2013/06/23 02:06:04 dholland Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs_dir.h>
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include "fsutil.h"
#include "fsck.h"
#include "extern.h"
#include "exitvalues.h"
long diskreads, totalreads; /* Disk cache statistics */
static void rwerror(const char *, daddr_t);
int
ftypeok(struct ext2fs_dinode *dp)
{
switch (fs2h16(dp->e2di_mode) & IFMT) {
case IFDIR:
case IFREG:
case IFBLK:
case IFCHR:
case IFLNK:
case IFSOCK:
case IFIFO:
return (1);
default:
if (debug)
printf("bad file type 0%o\n", fs2h16(dp->e2di_mode));
return (0);
}
}
int
reply(const char *question)
{
int persevere;
char c;
if (preen)
pfatal("INTERNAL ERROR: GOT TO reply()");
persevere = !strcmp(question, "CONTINUE");
printf("\n");
if (!persevere && (nflag || fswritefd < 0)) {
printf("%s? no\n\n", question);
return (0);
}
if (yflag || (persevere && nflag)) {
printf("%s? yes\n\n", question);
return (1);
}
do {
printf("%s? [yn] ", question);
(void) fflush(stdout);
c = getc(stdin);
while (c != '\n' && getc(stdin) != '\n')
if (feof(stdin))
return (0);
} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
printf("\n");
if (c == 'y' || c == 'Y')
return (1);
return (0);
}
/*
* Malloc buffers and set up cache.
*/
void
bufinit(void)
{
struct bufarea *bp;
long bufcnt, i;
char *bufp;
diskreads = totalreads = 0;
pbp = pdirbp = (struct bufarea *)0;
bufhead.b_next = bufhead.b_prev = &bufhead;
bufcnt = MAXBUFSPACE / sblock.e2fs_bsize;
if (bufcnt < MINBUFS)
bufcnt = MINBUFS;
for (i = 0; i < bufcnt; i++) {
bp = malloc(sizeof(struct bufarea));
bufp = malloc((size_t)sblock.e2fs_bsize);
if (bp == NULL || bufp == NULL) {
free(bp);
free(bufp);
if (i >= MINBUFS)
break;
errexit("cannot allocate buffer pool");
}
bp->b_un.b_buf = bufp;
bp->b_prev = &bufhead;
bp->b_next = bufhead.b_next;
bufhead.b_next->b_prev = bp;
bufhead.b_next = bp;
initbarea(bp);
}
bufhead.b_size = i; /* save number of buffers */
}
/*
* Manage a cache of directory blocks.
*/
struct bufarea *
getdatablk(daddr_t blkno, long size)
{
struct bufarea *bp;
for (bp = bufhead.b_next; bp != &bufhead; bp = bp->b_next)
if (bp->b_bno == EXT2_FSBTODB(&sblock, blkno))
goto foundit;
for (bp = bufhead.b_prev; bp != &bufhead; bp = bp->b_prev)
if ((bp->b_flags & B_INUSE) == 0)
break;
if (bp == &bufhead)
errexit("deadlocked buffer pool");
getblk(bp, blkno, size);
diskreads++;
/* fall through */
foundit:
totalreads++;
bp->b_prev->b_next = bp->b_next;
bp->b_next->b_prev = bp->b_prev;
bp->b_prev = &bufhead;
bp->b_next = bufhead.b_next;
bufhead.b_next->b_prev = bp;
bufhead.b_next = bp;
bp->b_flags |= B_INUSE;
return (bp);
}
void
getblk(struct bufarea *bp, daddr_t blk, long size)
{
daddr_t dblk;
dblk = EXT2_FSBTODB(&sblock, blk);
if (bp->b_bno != dblk) {
flush(fswritefd, bp);
bp->b_errs = bread(fsreadfd, bp->b_un.b_buf, dblk, size);
bp->b_bno = dblk;
bp->b_size = size;
}
}
void
flush(int fd, struct bufarea *bp)
{
int i;
if (!bp->b_dirty)
return;
if (bp->b_errs != 0)
pfatal("WRITING %sZERO'ED BLOCK %lld TO DISK\n",
(bp->b_errs == bp->b_size / dev_bsize) ? "" : "PARTIALLY ",
(long long)bp->b_bno);
bp->b_dirty = 0;
bp->b_errs = 0;
bwrite(fd, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
if (bp != &sblk)
return;
for (i = 0; i < sblock.e2fs_ngdb; i++) {
bwrite(fswritefd, (char *)
&sblock.e2fs_gd[i* sblock.e2fs_bsize / sizeof(struct ext2_gd)],
EXT2_FSBTODB(&sblock, ((sblock.e2fs_bsize>1024)?0:1)+i+1),
sblock.e2fs_bsize);
}
}
static void
rwerror(const char *mesg, daddr_t blk)
{
if (preen == 0)
printf("\n");
pfatal("CANNOT %s: BLK %lld", mesg, (long long)blk);
if (reply("CONTINUE") == 0)
errexit("Program terminated");
}
void
ckfini(int markclean)
{
struct bufarea *bp, *nbp;
int cnt = 0;
if (fswritefd < 0) {
(void)close(fsreadfd);
return;
}
flush(fswritefd, &sblk);
if (havesb && sblk.b_bno != SBOFF / dev_bsize &&
!preen && reply("UPDATE STANDARD SUPERBLOCKS")) {
sblk.b_bno = SBOFF / dev_bsize;
sbdirty();
flush(fswritefd, &sblk);
copyback_sb(&asblk);
asblk.b_dirty = 1;
flush(fswritefd, &asblk);
}
for (bp = bufhead.b_prev; bp && bp != &bufhead; bp = nbp) {
cnt++;
flush(fswritefd, bp);
nbp = bp->b_prev;
free(bp->b_un.b_buf);
free(bp);
}
if (bufhead.b_size != cnt)
errexit("Panic: lost %d buffers", bufhead.b_size - cnt);
pbp = pdirbp = (struct bufarea *)0;
if (markclean && (sblock.e2fs.e2fs_state & E2FS_ISCLEAN) == 0) {
/*
* Mark the file system as clean, and sync the superblock.
*/
if (preen)
pwarn("MARKING FILE SYSTEM CLEAN\n");
else if (!reply("MARK FILE SYSTEM CLEAN"))
markclean = 0;
if (markclean) {
sblock.e2fs.e2fs_state = E2FS_ISCLEAN;
sbdirty();
flush(fswritefd, &sblk);
}
}
if (debug)
printf("cache missed %ld of %ld (%d%%)\n", diskreads,
totalreads, (int)(diskreads * 100 / totalreads));
(void)close(fsreadfd);
(void)close(fswritefd);
}
int
bread(int fd, char *buf, daddr_t blk, long size)
{
char *cp;
int i, errs;
off_t offset;
offset = blk;
offset *= dev_bsize;
if (lseek(fd, offset, 0) < 0)
rwerror("SEEK", blk);
else if (read(fd, buf, (int)size) == size)
return (0);
rwerror("READ", blk);
if (lseek(fd, offset, 0) < 0)
rwerror("SEEK", blk);
errs = 0;
memset(buf, 0, (size_t)size);
printf("THE FOLLOWING DISK SECTORS COULD NOT BE READ:");
for (cp = buf, i = 0; i < size; i += secsize, cp += secsize) {
if (read(fd, cp, (int)secsize) != secsize) {
(void)lseek(fd, offset + i + secsize, 0);
if (secsize != dev_bsize && dev_bsize != 1)
printf(" %lld (%lld),",
(long long)((blk*dev_bsize + i) / secsize),
(long long)(blk + i / dev_bsize));
else
printf(" %lld,", (long long)(blk +
i / dev_bsize));
errs++;
}
}
printf("\n");
return (errs);
}
void
bwrite(int fd, char *buf, daddr_t blk, long size)
{
int i;
char *cp;
off_t offset;
if (fd < 0)
return;
offset = blk;
offset *= dev_bsize;
if (lseek(fd, offset, 0) < 0)
rwerror("SEEK", blk);
else if (write(fd, buf, (int)size) == size) {
fsmodified = 1;
return;
}
rwerror("WRITE", blk);
if (lseek(fd, offset, 0) < 0)
rwerror("SEEK", blk);
printf("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
for (cp = buf, i = 0; i < size; i += dev_bsize, cp += dev_bsize)
if (write(fd, cp, (int)dev_bsize) != dev_bsize) {
(void)lseek(fd, offset + i + dev_bsize, 0);
printf(" %lld,", (long long)(blk + i / dev_bsize));
}
printf("\n");
return;
}
/*
* allocate a data block
*/
int
allocblk(void)
{
int i;
for (i = 0; i < maxfsblock - 1; i++) {
if (testbmap(i))
continue;
setbmap(i);
n_blks++;
return (i);
}
return (0);
}
/*
* Free a previously allocated block
*/
void
freeblk(daddr_t blkno)
{
struct inodesc idesc;
idesc.id_blkno = blkno;
idesc.id_numfrags = 1;
(void)pass4check(&idesc);
}
/*
* Find a pathname
*/
void
getpathname(char *namebuf, size_t namebuflen, ino_t curdir, ino_t ino)
{
int len;
char *cp;
struct inodesc idesc;
static int busy = 0;
if (curdir == ino && ino == EXT2_ROOTINO) {
(void)strlcpy(namebuf, "/", namebuflen);
return;
}
if (busy ||
(statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
(void)strlcpy(namebuf, "?", namebuflen);
return;
}
busy = 1;
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = DATA;
idesc.id_fix = IGNORE;
cp = &namebuf[MAXPATHLEN - 1];
*cp = '\0';
if (curdir != ino) {
idesc.id_parent = curdir;
goto namelookup;
}
while (ino != EXT2_ROOTINO) {
idesc.id_number = ino;
idesc.id_func = findino;
idesc.id_name = "..";
if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
break;
namelookup:
idesc.id_number = idesc.id_parent;
idesc.id_parent = ino;
idesc.id_func = findname;
idesc.id_name = namebuf;
if ((ckinode(ginode(idesc.id_number), &idesc)&FOUND) == 0)
break;
len = strlen(namebuf);
cp -= len;
memcpy(cp, namebuf, (size_t)len);
*--cp = '/';
if (cp < &namebuf[EXT2FS_MAXNAMLEN])
break;
ino = idesc.id_number;
}
busy = 0;
if (ino != EXT2_ROOTINO)
*--cp = '?';
memcpy(namebuf, cp, (size_t)(&namebuf[MAXPATHLEN] - cp));
}
/*
* determine whether an inode should be fixed.
*/
int
dofix(struct inodesc *idesc, const char *msg)
{
switch (idesc->id_fix) {
case DONTKNOW:
if (idesc->id_type == DATA)
direrror(idesc->id_number, msg);
else
pwarn("%s", msg);
if (preen) {
printf(" (SALVAGED)\n");
idesc->id_fix = FIX;
return (ALTERED);
}
if (reply("SALVAGE") == 0) {
idesc->id_fix = NOFIX;
return (0);
}
idesc->id_fix = FIX;
return (ALTERED);
case FIX:
return (ALTERED);
case NOFIX:
case IGNORE:
return (0);
default:
errexit("UNKNOWN INODESC FIX MODE %d", idesc->id_fix);
}
/* NOTREACHED */
}

View File

@ -1,25 +0,0 @@
#ifndef _IFCONFIG_ENV_H
#define _IFCONFIG_ENV_H
#include <prop/proplib.h>
const char *getifname(prop_dictionary_t);
ssize_t getargstr(prop_dictionary_t, const char *, char *, size_t);
ssize_t getargdata(prop_dictionary_t, const char *, uint8_t *, size_t);
int getaf(prop_dictionary_t);
int getifflags(prop_dictionary_t, prop_dictionary_t, unsigned short *);
const char *getifinfo(prop_dictionary_t, prop_dictionary_t, unsigned short *);
prop_dictionary_t prop_dictionary_augment(prop_dictionary_t, prop_dictionary_t);
/*
* XXX: this really doesn't belong in here, but env.h is conveniently
* included from all source modules *after* system headers, so it
* allows us to be lazy. See Makefile for more details.
*/
#ifdef RUMP_ACTION
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
#include <rump/rumpclient.h>
#endif /* RUMP_ACTION */
#endif /* _IFCONFIG_ENV_H */

View File

@ -1,284 +0,0 @@
#ifndef _IFCONFIG_PARSE_H
#define _IFCONFIG_PARSE_H
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <sys/queue.h>
#include <prop/proplib.h>
#include <sys/socket.h>
struct match;
struct parser;
extern struct pbranch command_root;
typedef int (*parser_exec_t)(prop_dictionary_t, prop_dictionary_t);
typedef int (*parser_match_t)(const struct parser *, const struct match *,
struct match *, int, const char *);
typedef int (*parser_init_t)(struct parser *);
struct match {
prop_dictionary_t m_env;
const struct parser *m_nextparser;
const struct parser *m_parser;
int m_argidx;
parser_exec_t m_exec;
};
/* method table */
struct parser_methods {
parser_match_t pm_match;
parser_init_t pm_init;
};
struct parser {
const struct parser_methods *p_methods;
parser_exec_t p_exec;
const char *p_name;
struct parser *p_nextparser;
bool p_initialized;
};
struct branch {
SIMPLEQ_ENTRY(branch) b_next;
struct parser *b_nextparser;
};
struct pbranch {
struct parser pb_parser;
SIMPLEQ_HEAD(, branch) pb_branches;
bool pb_match_first;
const struct branch *pb_brinit;
size_t pb_nbrinit;
};
struct pterm {
struct parser pt_parser;
const char *pt_key;
};
extern const struct parser_methods paddr_methods;
extern const struct parser_methods pbranch_methods;
extern const struct parser_methods piface_methods;
extern const struct parser_methods pinteger_methods;
extern const struct parser_methods pstr_methods;
extern const struct parser_methods pkw_methods;
extern const struct parser_methods pterm_methods;
#define PTERM_INITIALIZER(__pt, __name, __exec, __key) \
{ \
.pt_parser = {.p_name = (__name), .p_methods = &pterm_methods, \
.p_exec = (__exec)}, \
.pt_key = (__key) \
}
#define PBRANCH_INITIALIZER(__pb, __name, __brs, __nbr, __match_first) \
{ \
.pb_parser = {.p_name = (__name), .p_methods = &pbranch_methods},\
.pb_branches = SIMPLEQ_HEAD_INITIALIZER((__pb)->pb_branches), \
.pb_brinit = (__brs), \
.pb_nbrinit = (__nbr), \
.pb_match_first = (__match_first) \
}
#define PSTR_INITIALIZER(__ps, __name, __defexec, __defkey, __defnext) \
PSTR_INITIALIZER1((__ps), (__name), (__defexec), (__defkey), \
true, (__defnext))
#define PSTR_INITIALIZER1(__ps, __name, __defexec, __defkey, __defhexok,\
__defnext) \
{ \
.ps_parser = {.p_name = (__name), .p_methods = &pstr_methods, \
.p_exec = (__defexec), \
.p_nextparser = (__defnext)}, \
.ps_key = (__defkey), \
.ps_hexok = (__defhexok) \
}
#define PADDR_INITIALIZER(__pa, __name, __defexec, __addrkey, \
__maskkey, __activator, __deactivator, __defnext) \
{ \
.pa_parser = {.p_name = (__name), .p_methods = &paddr_methods, \
.p_exec = (__defexec), \
.p_nextparser = (__defnext)}, \
.pa_addrkey = (__addrkey), \
.pa_maskkey = (__maskkey), \
.pa_activator = (__activator), \
.pa_deactivator = (__deactivator), \
}
#define PIFACE_INITIALIZER(__pif, __name, __defexec, __defkey, __defnext)\
{ \
.pif_parser = {.p_name = (__name), .p_methods = &piface_methods,\
.p_exec = (__defexec), \
.p_nextparser = (__defnext)}, \
.pif_key = (__defkey) \
}
#define PINTEGER_INITIALIZER1(__pi, __name, __min, __max, __base, \
__defexec, __defkey, __defnext) \
{ \
.pi_parser = {.p_name = (__name), .p_methods = &pinteger_methods,\
.p_exec = (__defexec), \
.p_nextparser = (__defnext), \
.p_initialized = false}, \
.pi_min = (__min), \
.pi_max = (__max), \
.pi_base = (__base), \
.pi_key = (__defkey) \
}
#define PINTEGER_INITIALIZER(__pi, __name, __base, __defexec, __defkey, \
__defnext) \
PINTEGER_INITIALIZER1(__pi, __name, INTMAX_MIN, INTMAX_MAX, \
__base, __defexec, __defkey, __defnext)
#define PKW_INITIALIZER(__pk, __name, __defexec, __defkey, __kws, __nkw,\
__defnext) \
{ \
.pk_parser = {.p_name = (__name), \
.p_exec = (__defexec), \
.p_methods = &pkw_methods, \
.p_initialized = false}, \
.pk_keywords = SIMPLEQ_HEAD_INITIALIZER((__pk)->pk_keywords), \
.pk_kwinit = (__kws), \
.pk_nkwinit = (__nkw), \
.pk_keyinit = (__defkey), \
.pk_nextinit = (__defnext) \
}
#define IFKW(__word, __flag) \
{ \
.k_word = (__word), .k_neg = true, .k_type = KW_T_INT, \
.k_int = (__flag), \
.k_negint = -(__flag) \
}
#define KW_T_NONE 0
#define KW_T_OBJ 1
#define KW_T_INT 2
#define KW_T_STR 3
#define KW_T_BOOL 4
#define KW_T_UINT 5
struct kwinst {
SIMPLEQ_ENTRY(kwinst) k_next;
int k_type;
const char *k_word;
const char *k_key;
const char *k_act;
const char *k_deact;
const char *k_altdeact;
parser_exec_t k_exec;
union kwval {
int64_t u_sint;
uint64_t u_uint;
const char *u_str;
prop_object_t u_obj;
bool u_bool;
} k_u, k_negu;
#define k_int k_u.u_sint
#define k_uint k_u.u_uint
#define k_str k_u.u_str
#define k_obj k_u.u_obj
#define k_bool k_u.u_bool
#define k_negint k_negu.u_sint
#define k_neguint k_negu.u_uint
#define k_negstr k_negu.u_str
#define k_negobj k_negu.u_obj
#define k_negbool k_negu.u_bool
bool k_neg; /* allow negative form, -keyword */
struct parser *k_nextparser;
};
struct pkw {
struct parser pk_parser;
const char *pk_key;
const char *pk_keyinit;
const struct kwinst *pk_kwinit;
size_t pk_nkwinit;
SIMPLEQ_HEAD(, kwinst) pk_keywords;
};
#define pk_nextinit pk_parser.p_nextparser
#define pk_execinit pk_parser.p_exec
struct pstr {
struct parser ps_parser;
const char *ps_key;
bool ps_hexok;
};
struct pinteger {
struct parser pi_parser;
int64_t pi_min;
int64_t pi_max;
int pi_base;
const char *pi_key;
};
struct intrange {
SIMPLEQ_ENTRY(intrange) r_next;
int64_t r_bottom;
int64_t r_top;
struct parser *r_nextparser;
};
struct pranges {
struct parser pr_parser;
SIMPLEQ_HEAD(, intrange) pr_ranges;
};
struct paddr_prefix {
int16_t pfx_len;
struct sockaddr pfx_addr;
};
static inline size_t
paddr_prefix_size(const struct paddr_prefix *pfx)
{
return offsetof(struct paddr_prefix, pfx_addr) + pfx->pfx_addr.sa_len;
}
struct paddr {
struct parser pa_parser;
const char *pa_addrkey;
const char *pa_maskkey;
const char *pa_activator;
const char *pa_deactivator;
};
struct piface {
struct parser pif_parser;
const char *pif_key;
};
struct prest {
struct parser pr_parser;
};
struct prest *prest_create(const char *);
struct paddr *paddr_create(const char *, parser_exec_t, const char *,
const char *, struct parser *);
struct pstr *pstr_create(const char *, parser_exec_t, const char *,
bool, struct parser *);
struct piface *piface_create(const char *, parser_exec_t, const char *,
struct parser *);
struct pkw *pkw_create(const char *, parser_exec_t,
const char *, const struct kwinst *, size_t, struct parser *);
struct pranges *pranges_create(const char *, parser_exec_t, const char *,
const struct intrange *, size_t, struct parser *);
struct pbranch *pbranch_create(const char *, const struct branch *, size_t,
bool);
int pbranch_addbranch(struct pbranch *, struct parser *);
int pbranch_setbranches(struct pbranch *, const struct branch *, size_t);
int parse(int, char **, const struct parser *, struct match *, size_t *, int *);
int matches_exec(const struct match *, prop_dictionary_t, size_t);
int parser_init(struct parser *);
#endif /* _IFCONFIG_PARSE_H */

View File

@ -1,33 +0,0 @@
#ifndef _IFCONFIG_UTIL_H
#define _IFCONFIG_UTIL_H
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include "parse.h"
struct afswtch {
const char *af_name;
short af_af;
void (*af_status)(prop_dictionary_t, prop_dictionary_t, bool);
void (*af_addr_commit)(prop_dictionary_t, prop_dictionary_t);
bool (*af_addr_tentative)(struct ifaddrs *);
SIMPLEQ_ENTRY(afswtch) af_next;
};
void print_link_addresses(prop_dictionary_t, bool);
const char *get_string(const char *, const char *, u_int8_t *, int *, bool);
const struct afswtch *lookup_af_byname(const char *);
const struct afswtch *lookup_af_bynum(int);
void print_string(const u_int8_t *, int);
int getsock(int);
struct paddr_prefix *prefixlen_to_mask(int, int);
int direct_ioctl(prop_dictionary_t, unsigned long, void *);
int indirect_ioctl(prop_dictionary_t, unsigned long, void *);
bool ifa_any_preferences(const char *, struct ifaddrs *, int);
void ifa_print_preference(const char *, const struct sockaddr *);
int16_t ifa_get_preference(const char *, const struct sockaddr *);
#endif /* _IFCONFIG_UTIL_H */

View File

@ -1,8 +0,0 @@
# $NetBSD: Makefile,v 1.13 2009/04/11 07:58:12 lukem Exp $
# @(#)Makefile 8.1 (Berkeley) 6/5/93
PROG= mknod
SRCS= mknod.c pack_dev.c
MAN= mknod.8
.include <bsd.prog.mk>

View File

@ -1,393 +0,0 @@
/* $NetBSD: mknod.c,v 1.42 2014/08/22 22:28:50 mlelstv Exp $ */
/*-
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Charles M. Hannum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1998\
The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD: mknod.c,v 1.42 2014/08/22 22:28:50 mlelstv Exp $");
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#if !HAVE_NBTOOL_CONFIG_H
#include <sys/sysctl.h>
#endif
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include <ctype.h>
#include "pack_dev.h"
static int gid_name(const char *, gid_t *);
static dev_t callPack(pack_t *, int, u_long *);
__dead static void usage(void);
#ifdef KERN_DRIVERS
static struct kinfo_drivers *kern_drivers;
static int num_drivers;
static void get_device_info(void);
static void print_device_info(char **);
static int major_from_name(const char *, mode_t);
#endif
#define MAXARGS 3 /* 3 for bsdos, 2 for rest */
int
main(int argc, char **argv)
{
char *name, *p;
mode_t mode;
dev_t dev;
pack_t *pack;
u_long numbers[MAXARGS];
int n, ch, fifo, hasformat;
int r_flag = 0; /* force: delete existing entry */
#ifdef KERN_DRIVERS
int l_flag = 0; /* list device names and numbers */
int major;
#endif
void *modes = 0;
uid_t uid = -1;
gid_t gid = -1;
int rval;
dev = 0;
fifo = hasformat = 0;
pack = pack_native;
#ifdef KERN_DRIVERS
while ((ch = getopt(argc, argv, "lrRF:g:m:u:")) != -1) {
#else
while ((ch = getopt(argc, argv, "rRF:g:m:u:")) != -1) {
#endif
switch (ch) {
#ifdef KERN_DRIVERS
case 'l':
l_flag = 1;
break;
#endif
case 'r':
r_flag = 1;
break;
case 'R':
r_flag = 2;
break;
case 'F':
pack = pack_find(optarg);
if (pack == NULL)
errx(1, "invalid format: %s", optarg);
hasformat++;
break;
case 'g':
if (optarg[0] == '#') {
gid = strtol(optarg + 1, &p, 10);
if (*p == 0)
break;
}
if (gid_name(optarg, &gid) == 0)
break;
gid = strtol(optarg, &p, 10);
if (*p == 0)
break;
errx(1, "%s: invalid group name", optarg);
case 'm':
modes = setmode(optarg);
if (modes == NULL)
err(1, "Cannot set file mode `%s'", optarg);
break;
case 'u':
if (optarg[0] == '#') {
uid = strtol(optarg + 1, &p, 10);
if (*p == 0)
break;
}
if (uid_from_user(optarg, &uid) == 0)
break;
uid = strtol(optarg, &p, 10);
if (*p == 0)
break;
errx(1, "%s: invalid user name", optarg);
default:
case '?':
usage();
}
}
argc -= optind;
argv += optind;
#ifdef KERN_DRIVERS
if (l_flag) {
print_device_info(argv);
return 0;
}
#endif
if (argc < 2 || argc > 10)
usage();
name = *argv;
argc--;
argv++;
umask(mode = umask(0));
mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) & ~mode;
if (argv[0][1] != '\0')
goto badtype;
switch (*argv[0]) {
case 'c':
mode |= S_IFCHR;
break;
case 'b':
mode |= S_IFBLK;
break;
case 'p':
if (hasformat)
errx(1, "format is meaningless for fifos");
mode |= S_IFIFO;
fifo = 1;
break;
default:
badtype:
errx(1, "node type must be 'b', 'c' or 'p'.");
}
argc--;
argv++;
if (fifo) {
if (argc != 0)
usage();
} else {
if (argc < 1 || argc > MAXARGS)
usage();
}
for (n = 0; n < argc; n++) {
errno = 0;
numbers[n] = strtoul(argv[n], &p, 0);
if (*p == 0 && errno == 0)
continue;
#ifdef KERN_DRIVERS
if (argc == 2 && n == 0) {
major = major_from_name(argv[0], mode);
if (major != -1) {
numbers[0] = major;
continue;
}
if (!isdigit(*(unsigned char *)argv[0]))
errx(1, "unknown driver: %s", argv[0]);
}
#endif
errx(1, "invalid number: %s", argv[n]);
}
switch (argc) {
case 0:
dev = 0;
break;
case 1:
dev = numbers[0];
break;
default:
dev = callPack(pack, argc, numbers);
break;
}
if (modes != NULL)
mode = getmode(modes, mode);
umask(0);
rval = fifo ? mkfifo(name, mode) : mknod(name, mode, dev);
if (rval < 0 && errno == EEXIST && r_flag) {
struct stat sb;
if (lstat(name, &sb) != 0 || (!fifo && sb.st_rdev != dev))
sb.st_mode = 0;
if ((sb.st_mode & S_IFMT) == (mode & S_IFMT)) {
if (r_flag == 1)
/* Ignore permissions and user/group */
return 0;
if (sb.st_mode != mode)
rval = chmod(name, mode);
else
rval = 0;
} else {
unlink(name);
rval = fifo ? mkfifo(name, mode)
: mknod(name, mode, dev);
}
}
if (rval < 0)
err(1, "%s", name);
if ((uid != (uid_t)-1 || gid != (uid_t)-1) && chown(name, uid, gid) == -1)
/* XXX Should we unlink the files here? */
warn("%s: uid/gid not changed", name);
return 0;
}
static void
usage(void)
{
const char *progname = getprogname();
(void)fprintf(stderr,
"usage: %s [-rR] [-F format] [-m mode] [-u user] [-g group]\n",
progname);
(void)fprintf(stderr,
#ifdef KERN_DRIVERS
" [ name [b | c] [major | driver] minor\n"
#else
" [ name [b | c] major minor\n"
#endif
" | name [b | c] major unit subunit\n"
" | name [b | c] number\n"
" | name p ]\n");
#ifdef KERN_DRIVERS
(void)fprintf(stderr, " %s -l [driver] ...\n", progname);
#endif
exit(1);
}
static int
gid_name(const char *name, gid_t *gid)
{
struct group *g;
g = getgrnam(name);
if (!g)
return -1;
*gid = g->gr_gid;
return 0;
}
static dev_t
callPack(pack_t *f, int n, u_long *numbers)
{
dev_t d;
const char *error = NULL;
d = (*f)(n, numbers, &error);
if (error != NULL)
errx(1, "%s", error);
return d;
}
#ifdef KERN_DRIVERS
static void
get_device_info(void)
{
static int mib[2] = {CTL_KERN, KERN_DRIVERS};
size_t len;
if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0)
err(1, "kern.drivers" );
kern_drivers = malloc(len);
if (kern_drivers == NULL)
err(1, "malloc");
if (sysctl(mib, 2, kern_drivers, &len, NULL, 0) != 0)
err(1, "kern.drivers" );
num_drivers = len / sizeof *kern_drivers;
}
static void
print_device_info(char **names)
{
int i;
struct kinfo_drivers *kd;
if (kern_drivers == NULL)
get_device_info();
do {
kd = kern_drivers;
for (i = 0; i < num_drivers; kd++, i++) {
if (*names && strcmp(*names, kd->d_name))
continue;
printf("%s", kd->d_name);
if (kd->d_cmajor != -1)
printf(" character major %d", kd->d_cmajor);
if (kd->d_bmajor != -1)
printf(" block major %d", kd->d_bmajor);
printf("\n");
}
} while (*names && *++names);
}
static int
major_from_name(const char *name, mode_t mode)
{
int i;
struct kinfo_drivers *kd;
if (kern_drivers == NULL)
get_device_info();
kd = kern_drivers;
for (i = 0; i < num_drivers; kd++, i++) {
if (strcmp(name, kd->d_name))
continue;
if (S_ISCHR(mode))
return kd->d_cmajor;
return kd->d_bmajor;
}
return -1;
}
#endif

View File

@ -1,3 +0,0 @@
#! /bin/sh
echo "This account is currently not available."
exit 1

View File

@ -1,22 +0,0 @@
# $NetBSD: Makefile,v 1.17 2013/11/09 21:39:27 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 6/5/93
USE_FORT?= yes # setuid
RUMPPRG=ping
MAN= ping.8
BINOWN= root
BINMODE=4555
LDADD= -lm
DPADD= ${LIBM}
.include <bsd.own.mk>
.if !defined(__MINIX)
CPPFLAGS+= -DIPSEC
LDADD+= -lipsec
DPADD+= ${LIBIPSEC}
.endif # !defined(__MINIX)
.if ${MACHINE_ARCH} == "vax"
COPTS.ping.c=-O0
.endif
.include <bsd.prog.mk>

View File

@ -1,478 +0,0 @@
.\" $NetBSD: ping.8,v 1.50 2011/09/10 20:47:33 wiz Exp $
.\"
.\" Copyright (c) 1985, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)ping.8 8.2 (Berkeley) 12/11/93
.\"
.Dd September 10, 2011
.Dt PING 8
.Os
.Sh NAME
.Nm ping
.Nd send
.Tn ICMP ECHO_REQUEST
packets to network hosts
.Sh SYNOPSIS
.Nm
.Op Fl aCDdfLnoPQqRrv
.Op Fl c Ar count
.Op Fl E Ar policy
.Op Fl g Ar gateway
.Op Fl h Ar host
.Op Fl I Ar srcaddr
.Op Fl i Ar interval
.Op Fl l Ar preload
.Op Fl p Ar pattern
.Op Fl s Ar packetsize
.Op Fl T Ar ttl
.Op Fl t Ar tos
.Op Fl w Ar deadline
.Ar host
.Sh DESCRIPTION
.Nm
uses the
.Tn ICMP
protocol's mandatory
.Tn ECHO_REQUEST
datagram to elicit an
.Tn ICMP ECHO_RESPONSE
from a host or gateway.
.Tn ECHO_REQUEST
datagrams (``pings'') have an IP and
.Tn ICMP
header,
followed by a
.Dq struct timespec
and then an arbitrary number of ``pad'' bytes used to fill out the
packet.
The options are as follows:
.Bl -tag -width Ds
.It Fl a
Emit an audible beep (by sending an ascii BEL character to the
standard error output) after each non-duplicate response is received.
This is disabled for flood pings as it would probably cause temporary
insanity.
.It Fl C
Send timestamps in compat format; two 32 bit words in little endian format,
the first one representing seconds, and the second one representing
microseconds.
.It Fl c Ar count
Stop after sending (and waiting the specified delay to receive)
.Ar count
.Tn ECHO_RESPONSE
packets.
.It Fl D
Set the
.Dv Don't Fragment
bit in the IP header.
This can be used to determine the path MTU.
.It Fl d
Set the
.Dv SO_DEBUG
option on the socket being used.
.It Fl E Ar policy
Use IPsec policy specification string
.Ar policy
for packets.
For the format of specification string, please refer
.Xr ipsec_set_policy 3 .
Please note that this option is same as
.Fl P
in KAME/FreeBSD and KAME/BSDI
(as
.Fl P
was already occupied in
.Nx ) .
.It Fl f
Flood ping.
Outputs packets as fast as they come back or one hundred times per second,
whichever is more.
For every
.Tn ECHO_REQUEST
sent a period ``.'' is printed, while for every
.Tn ECHO_REPLY
received a backspace is printed.
This provides a rapid display of how many packets are being dropped.
Only the super-user may use this option.
.Bf -emphasis
This can be very hard on a network and should be used with caution.
.Ef
.It Fl g Ar gateway
Use Loose Source Routing to send the ECHO_REQUEST packets via
.Ar gateway .
.It Fl h Ar host
is an alternate way of specifying the target host instead of as the
last argument.
.It Fl I Ar srcaddr
Set the source IP address to
.Ar srcaddr
which can be a hostname or an IP number.
For multicast datagrams, it also specifies the outgoing interface.
.It Fl i Ar interval
Wait
.Ar interval
seconds
.Em between sending each packet .
The default is to wait for one second between each packet,
except when the -f option is used the wait interval is 0.01 seconds.
.It Fl L
Disable loopback when sending to multicast destinations,
so the transmitting host doesn't see the ICMP requests.
.It Fl l Ar preload
If
.Ar preload
is specified,
.Nm
sends that many packets as fast as possible before falling into its normal
mode of behavior.
Only the super-user may use this option.
.It Fl n
Numeric output only.
No attempt will be made to look up symbolic names for host addresses.
.It Fl o
Exit successfully after receiving one reply packet.
.It Fl P
Use a pseudo-random sequence for the data instead of the default,
fixed sequence of incrementing 8-bit integers.
This is useful to foil compression on PPP and other links.
.It Fl p Ar pattern
You may specify up to 16 ``pad'' bytes to fill out the packet you send.
This is useful for diagnosing data-dependent problems in a network.
For example,
.Dq Li \-p ff
will cause the sent packet to be filled with all
ones.
.It Fl Q
Do not display responses such as Network Unreachable ICMP messages
concerning the ECHO_REQUESTs sent.
.It Fl q
Quiet output.
Nothing is displayed except the summary lines at startup time and
when finished.
.It Fl R
Record Route.
Includes the
.Tn RECORD_ROUTE
option in the
.Tn ECHO_REQUEST
packet and displays the route buffer on returned packets.
This should show the path to the target host and back, which is
especially useful in the case of asymmetric routing.
Note that the IP header is only large enough for nine such addresses,
and only seven when using the
.Fl g
option.
This is why it was necessary to invent
.Xr traceroute 8 .
Many hosts ignore or discard this option.
.It Fl r
Bypass the normal routing tables and send directly to a host on an attached
network.
If the host is not on a directly-attached network, an error is returned.
This option can be used to ping a local host through an interface
that has no route through it (e.g., after the interface was dropped by
.Xr routed 8 ) .
.It Fl s Ar packetsize
Specifies the number of data bytes to be sent.
The default is 56, which translates into 64
.Tn ICMP
data bytes when combined
with the 8 bytes of
.Tn ICMP
header data.
The maximum allowed value is 65467 bytes.
.It Fl T Ar ttl
Use the specified time-to-live.
.It Fl t Ar tos
Use the specified hexadecimal type of service.
.It Fl v
Verbose output.
.Tn ICMP
packets other than
.Tn ECHO_RESPONSE
that are received are listed.
.It Fl w Ar deadline
Specifies a timeout, in seconds, before ping exits regardless of
how many packets have been sent or received.
.El
.Pp
When using
.Nm
for fault isolation, it should first be run on the local host, to verify
that the local network interface is up and running.
Then, hosts and gateways further and further away should be ``pinged''.
.Pp
Round-trip times and packet loss statistics are computed.
If duplicate packets are received, they are not included in the packet
loss calculation, although the round trip time of these packets is used
in calculating the minimum/average/maximum round-trip time numbers.
.Pp
When the specified number of packets have been sent (and received) or
if the program is terminated with a
.Dv SIGINT ,
a brief summary is displayed.
The summary information can be displayed while
.Nm
is running by sending it a
.Dv SIGINFO
signal (see the
.Dq status
argument for
.Xr stty 1
for more information).
.Pp
.Nm
continually sends one datagram per second, and prints one line of
output for every ECHO_RESPONSE returned.
On a trusted system with IP
Security Options enabled, if the network idiom is not MONO,
.Nm
also prints a second line containing the hexadecimal representation
of the IP security option in the ECHO_RESPONSE.
If the
.Fl c
count option is given, only that number of requests is sent.
No output is produced if there is no response.
Round-trip times and packet loss statistics are computed.
If duplicate packets are received,
they are not included in the packet loss calculation,
although the round trip time of these packets is used in calculating
the minimum/average/maximum round-trip time numbers.
When the specified number of packets have been sent (and received) or if
the program is terminated with an interrupt (SIGINT), a brief
summary is displayed.
When not using the
.Fl f
(flood) option, the first interrupt, usually generated by control-C or DEL,
causes
.Nm
to wait for its outstanding requests to return.
It will wait no longer than the longest round trip time
encountered by previous, successful pings.
The second interrupt stops ping immediately.
.Pp
This program is intended for use in network testing, measurement and
management.
Because of the load it can impose on the network, it is unwise to use
.Nm
during normal operations or from automated scripts.
.Sh ICMP PACKET DETAILS
An IP header without options is 20 bytes.
An
.Tn ICMP
.Tn ECHO_REQUEST
packet contains an additional 8 bytes worth of
.Tn ICMP
header followed by an arbitrary amount of data.
When a
.Ar packetsize
is given, this indicated the size of this extra piece of data (the
default is 56).
Thus the amount of data received inside of an IP packet of type
.Tn ICMP
.Tn ECHO_REPLY
will always be 8 bytes more than the requested data space (the
.Tn ICMP
header).
.Pp
If the data space is at least
.Dv sizeof(struct timespec)
(16) large,
.Nm
uses the first
.Dv sizeof(struct timespec)
bytes to include a timestamp to compute round trip times.
Otherwise if the data space is at least eight bytes large (or the
.Fl C
flag is specified),
.Nm
uses the first eight bytes of this space to include a timestamp to compute
round trip times.
If there are not enough bytes of pad no round trip times are given.
.Sh DUPLICATE AND DAMAGED PACKETS
.Nm
will report duplicate and damaged packets.
Duplicate packets should never occur, and seem to be caused by
inappropriate link-level retransmissions.
Duplicates may occur in many situations and are rarely (if ever) a
good sign, although the presence of low levels of duplicates may not
always be cause for alarm.
.Pp
Damaged packets are obviously serious cause for alarm and often
indicate broken hardware somewhere in the
.Nm
packet's path (in the network or in the hosts).
.Sh TRYING DIFFERENT DATA PATTERNS
The (inter)network layer should never treat packets differently depending
on the data contained in the data portion.
Unfortunately, data-dependent problems have been known to sneak into
networks and remain undetected for long periods of time.
In many cases the particular pattern that will have problems is something
that doesn't have sufficient ``transitions'', such as all ones or all
zeros, or a pattern right at the edge, such as almost all zeros.
It isn't necessarily enough to specify a data pattern of all zeros (for
example) on the command line because the pattern that is of interest is
at the data link level, and the relationship between what you type and
what the controllers transmit can be complicated.
.Pp
This means that if you have a data-dependent problem you will probably
have to do a lot of testing to find it.
If you are lucky, you may manage to find a file that either can't be sent
across your network or that takes much longer to transfer than other
similar length files.
You can then examine this file for repeated patterns that you can test
using the
.Fl p
option of
.Nm .
.Sh TTL DETAILS
The
.Tn TTL
value of an IP packet represents the maximum number of IP routers
that the packet can go through before being thrown away.
In current practice you can expect each router in the Internet to decrement
the
.Tn TTL
field by exactly one.
.Pp
The
.Tn TCP/IP
specification states that the
.Tn TTL
field for
.Tn TCP
packets should
be set to 60, but many systems use smaller values
.Po
.Bx 4.3
uses 30,
.Bx 4.2
used 15
.Pc .
.Pp
The maximum possible value of this field is 255, and most
.Ux
systems set the
.Tn TTL
field of
.Tn ICMP ECHO_REQUEST
packets to 255.
This is why you will find you can ``ping'' some hosts, but not reach them
with
.Xr telnet 1
or
.Xr ftp 1 .
.Pp
In normal operation ping prints the ttl value from the packet it receives.
When a remote system receives a ping packet, it can do one of three things
with the
.Tn TTL
field in its response:
.Bl -bullet
.It
Not change it; this is what Berkeley
.Ux
systems did before the
.Bx 4.3 tahoe
release.
In this case the
.Tn TTL
value in the received packet will be 255 minus the
number of routers in the round-trip path.
.It
Set it to 255; this is what current Berkeley
.Ux
systems do.
In this case the
.Tn TTL
value in the received packet will be 255 minus the
number of routers in the path
.Em from
the remote system
.Em to
the
.Nm Ns Em ing
host.
.It
Set it to some other value.
Some machines use the same value for
.Tn ICMP
packets that they use for
.Tn TCP
packets, for example either 30 or 60.
Others may use completely wild values.
.El
.Sh EXIT STATUS
.Nm
returns 0 on success (the host is alive),
and non-zero if the arguments are incorrect or the host is not responding.
.Sh SEE ALSO
.Xr netstat 1 ,
.Xr icmp 4 ,
.Xr inet 4 ,
.Xr ip 4 ,
.Xr ifconfig 8 ,
.Xr routed 8 ,
.Xr spray 8 ,
.Xr traceroute 8
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.3 .
IPsec support was added by WIDE/KAME project.
.Sh BUGS
Flood pinging is not recommended in general, and flood pinging a broadcast
or multicast address should only be done under very controlled conditions.
.Pp
The
.Nm
program has evolved differently under different operating systems,
and in some cases the same flag performs a different function
under different operating systems.
The
.Fl t
flag conflicts with
.Fx .
The
.Fl a , c , I , i ,
.Fl l , P , p , s ,
and
.Fl t
flags conflict with
.Sy Solaris .
.Pp
Some hosts and gateways ignore the
.Tn RECORD_ROUTE
option.
.Pp
The maximum IP header length is too small for options like
.Tn RECORD_ROUTE
to
be completely useful.
There's not much that that can be done about this, however.

File diff suppressed because it is too large Load Diff

View File

@ -1,58 +0,0 @@
/* $NetBSD: ping_rumpops.c,v 1.2 2011/03/11 09:59:56 pooka Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: ping_rumpops.c,v 1.2 2011/03/11 09:59:56 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/socket.h>
#include <poll.h>
#include <unistd.h>
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
#include <rump/rumpclient.h>
#include "prog_ops.h"
const struct prog_ops prog_ops = {
.op_init = rumpclient_init,
.op_socket = rump_sys_socket,
.op_setsockopt= rump_sys_setsockopt,
.op_shutdown = rump_sys_shutdown,
.op_poll = rump_sys_poll,
.op_sendto = rump_sys_sendto,
.op_recvfrom = rump_sys_recvfrom,
.op_close = rump_sys_close,
.op_getuid = rump_sys_getuid,
.op_setuid = rump_sys_setuid,
};