Delete sbin directory
This commit is contained in:
parent
6598721502
commit
2fd6a38d64
|
|
@ -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>
|
|
||||||
|
|
@ -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
|
|
||||||
176
sbin/fsck/fsck.8
176
sbin/fsck/fsck.8
|
|
@ -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
|
|
||||||
614
sbin/fsck/fsck.c
614
sbin/fsck/fsck.c
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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_ */
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -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}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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]);
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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 */
|
|
||||||
}
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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>
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
echo "This account is currently not available."
|
|
||||||
exit 1
|
|
||||||
|
|
@ -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>
|
|
||||||
478
sbin/ping/ping.8
478
sbin/ping/ping.8
|
|
@ -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.
|
|
||||||
1924
sbin/ping/ping.c
1924
sbin/ping/ping.c
File diff suppressed because it is too large
Load Diff
|
|
@ -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,
|
|
||||||
};
|
|
||||||
Loading…
Reference in New Issue
Block a user