Update from 4.4-Lite, with local changes.

This commit is contained in:
mycroft 1994-06-08 18:57:30 +00:00
parent 175ecf65e1
commit ccfa3742b5
90 changed files with 10391 additions and 2782 deletions

View File

@ -1,5 +1,5 @@
# from: @(#)Makefile 5.16 (Berkeley) 7/15/92
# $Id: Makefile,v 1.13 1993/12/22 10:24:34 cgd Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/5/93
# $Id: Makefile,v 1.14 1994/06/08 18:57:30 mycroft Exp $
# dump.h header file
# itime.c reads /etc/dumpdates

View File

@ -1,4 +1,5 @@
.\" Copyright (c) 1980, 1991 Regents of the University of California.
.\" Copyright (c) 1980, 1991, 1993
.\" Regents of the University of California.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@ -29,10 +30,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)dump.8 6.10 (Berkeley) 6/20/92
.\" $Id: dump.8,v 1.8 1994/01/28 20:07:07 jtc Exp $
.\" from: @(#)dump.8 8.1 (Berkeley) 6/16/93
.\" $Id: dump.8,v 1.9 1994/06/08 18:57:31 mycroft Exp $
.\"
.Dd June 20, 1992
.Dd June 16, 1993
.Dt DUMP 8
.Os BSD 4
.Sh NAME
@ -40,7 +41,7 @@
.Nd filesystem backup
.Sh SYNOPSIS
.Nm dump
.Op Cm 0123456789fusTdWn Op Ar argument ...
.Op Cm 0123456789BbhfusTdWn Op Ar argument ...
.Op Ar filesystem
.Sh DESCRIPTION
.Nm Dump
@ -70,14 +71,33 @@ The following options are supported by
.It Cm 0\-9
Dump levels.
A level 0, full backup,
guarantees the entire file system is copied.
guarantees the entire file system is copied
(but see also the
.Cm h
option below).
A level number above 0,
incremental backup,
tells dump to
copy all files new or modified since the
last dump of the same or lower level. The default
level is 9.
.It Cm f Op Ar file
.It Cm B Ar records
The number of dump records per volume.
This option overrides the calculation of tape size
based on length and density.
.It Cm b Ar blocksize
The number of kilobytes per dump record.
.It Cm h Ar level
Honor the user
.Dq nodump
flag
.Dp Dv UF_NODUMP
only for dumps at or above the given
.Ar level .
The default honor level is 1,
so that incremental backups omit such files
but full backups retain them.
.It Cm f Ar file
Write the backup to
.Ar file ;
.Ar file
@ -98,6 +118,8 @@ the last file name will used for all remaining volumes after prompting
for media changes.
If the name of the file is of the form
.Dq host:file ,
or
.Dq user@host:file ,
.Nm dump
writes to the named file on the remote host using
.Xr rmt 8 .
@ -121,9 +143,6 @@ If this amount is exceeded,
prompts for a new tape.
It is recommended to be a bit conservative on this option.
The default tape length is 2300 feet.
.It Cm B Ar blocks
Set the size of the dump file to the specified number of 1024-byte blocks,
superseding the tape size and density.
.It Cm u
Update the file
.Pa /etc/dumpdates

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1980 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1980, 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
@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)dump.h 5.21 (Berkeley) 7/16/92
* $Id: dump.h,v 1.6 1993/12/22 10:24:39 cgd Exp $
* from: @(#)dump.h 8.1 (Berkeley) 6/5/93
* $Id: dump.h,v 1.7 1994/06/08 18:57:33 mycroft Exp $
*/
#define MAXINOPB (MAXBSIZE / sizeof(struct dinode))
@ -74,6 +74,7 @@ long tapesize; /* estimated tape size, blocks */
long tsize; /* tape size in 0.1" units */
long asize; /* number of 0.1" units written on current tape */
int etapes; /* estimated number of tapes */
int nonodump; /* if set, do not honor UF_NODUMP user flags */
int notify; /* notify operator flag */
int blockswritten; /* number of blocks written on current tape */
@ -85,6 +86,10 @@ long dev_bsize; /* block size of underlying disk device */
int dev_bshift; /* log2(dev_bsize) */
int tp_bshift; /* log2(TP_BSIZE) */
#ifndef __P
#include <sys/cdefs.h>
#endif
/* operator interface functions */
void broadcast __P((char *message));
void lastdump __P((int arg)); /* int should be char */
@ -113,18 +118,25 @@ void writeheader __P((ino_t ino));
int alloctape __P((void));
void close_rewind __P((void));
void dumpblock __P((daddr_t blkno, int size));
void flushtape __P((void));
void startnewtape __P((int top));
void trewind __P((void));
void writerec __P((char *dp, int isspcl));
void Exit __P((int status));
__dead void Exit __P((int status));
void dumpabort __P((int signo));
void getfstab __P((void));
char *rawname __P((char *cp));
struct dinode *getino __P((ino_t inum));
/* rdump routines */
#ifdef RDUMP
void rmtclose __P((void));
int rmthost __P((char *host));
int rmtopen __P((char *tape, int mode));
int rmtwrite __P((char *buf, int count));
#endif /* RDUMP */
void interrupt __P((int signo)); /* in case operator bangs on console */
/*
@ -171,14 +183,21 @@ void sig __P((int signo));
/*
* Compatibility with old systems.
*/
#ifndef __STDC__
#ifdef COMPAT
#include <sys/file.h>
#define _PATH_FSTAB "/etc/fstab"
extern char *index(), *strdup();
extern char *index(), *rindex(), *strdup();
extern char *ctime();
extern int read(), write();
extern int errno;
#endif
#ifndef _PATH_UTMP
#define _PATH_UTMP "/etc/utmp"
#endif
#ifndef _PATH_FSTAB
#define _PATH_FSTAB "/etc/fstab"
#endif
#ifdef sunos
extern char *calloc();
extern char *malloc();
@ -188,7 +207,7 @@ extern char *strncpy();
extern char *strcat();
extern time_t time();
extern void endgrent();
extern void exit();
extern __dead void exit();
extern off_t lseek();
extern char *strerror();
extern const char *strerror();
#endif

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1980 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1980, 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
@ -32,65 +32,69 @@
*/
#ifndef lint
/* from: static char sccsid[] = "@(#)dumprmt.c 5.15 (Berkeley) 6/18/92"; */
static char *rcsid = "$Id: dumprmt.c,v 1.5 1993/12/22 10:24:42 cgd Exp $";
/*static char sccsid[] = "from: @(#)dumprmt.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: dumprmt.c,v 1.6 1994/06/08 18:57:34 mycroft Exp $";
#endif /* not lint */
#ifdef sunos
#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/mtio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#else
#include <sys/param.h>
#include <sys/mtio.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <stdio.h>
#ifdef sunos
#include <sys/vnode.h>
#include <ufs/inode.h>
#else
#include <ufs/ufs/dinode.h>
#endif
#include <ufs/dinode.h>
#include <signal.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <protocols/dumprestore.h>
#include <ctype.h>
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#ifdef __STDC__
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "pathnames.h"
#include "dump.h"
#define TS_CLOSED 0
#define TS_OPEN 1
static int rmtstate = TS_CLOSED;
int rmtape;
void rmtgetconn();
void rmtconnaborted();
int rmtreply();
int rmtgetb();
void rmtgets();
int rmtcall();
char *rmtpeer;
static int rmtape;
static char *rmtpeer;
extern int ntrec; /* blocking factor on tape */
extern void msg();
static int okname __P((char *));
static int rmtcall __P((char *, char *));
static void rmtconnaborted __P((/* int, int */));
static int rmtgetb __P((void));
static void rmtgetconn __P((void));
static void rmtgets __P((char *, int));
static int rmtreply __P((char *));
extern void exit();
extern int ntrec; /* blocking factor on tape */
int
rmthost(host)
char *host;
{
rmtpeer = host;
rmtpeer = malloc(strlen(host) + 1);
if (rmtpeer)
strcpy(rmtpeer, host);
else
rmtpeer = host;
signal(SIGPIPE, rmtconnaborted);
rmtgetconn();
if (rmtape < 0)
@ -98,39 +102,86 @@ rmthost(host)
return (1);
}
void
static void
rmtconnaborted()
{
(void) fprintf(stderr, "rdump: Lost connection to remote host.\n");
(void) exit(1);
exit(1);
}
void
rmtgetconn()
{
static struct servent *sp = 0;
struct passwd *pw;
char *name = "root";
register char *cp;
static struct servent *sp = NULL;
static struct passwd *pwd = NULL;
#ifdef notdef
static int on = 1;
#endif
char *tuser;
int size;
int maxseg;
if (sp == 0) {
if (sp == NULL) {
sp = getservbyname("shell", "tcp");
if (sp == 0) {
if (sp == NULL) {
(void) fprintf(stderr,
"rdump: shell/tcp: unknown service\n");
(void) exit(1);
exit(1);
}
pwd = getpwuid(getuid());
if (pwd == NULL) {
(void) fprintf(stderr, "rdump: who are you?\n");
exit(1);
}
}
pw = getpwuid(getuid());
if (pw && pw->pw_name)
name = pw->pw_name;
rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, name, name, _PATH_RMT,
(int *)0);
if ((cp = index(rmtpeer, '@')) != NULL) {
tuser = rmtpeer;
*cp = '\0';
if (!okname(tuser))
exit(1);
rmtpeer = ++cp;
} else
tuser = pwd->pw_name;
rmtape = rcmd(&rmtpeer, (u_short)sp->s_port, pwd->pw_name, tuser,
_PATH_RMT, (int *)0);
size = ntrec * TP_BSIZE;
if (size > 60 * 1024) /* XXX */
size = 60 * 1024;
/* Leave some space for rmt request/response protocol */
size += 2 * 1024;
while (size > TP_BSIZE &&
setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
size -= TP_BSIZE;
size -= TP_BSIZE;
(void)setsockopt(rmtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
maxseg = 1024;
if (setsockopt(rmtape, IPPROTO_TCP, TCP_MAXSEG,
&maxseg, sizeof (maxseg)) < 0)
perror("TCP_MAXSEG setsockopt");
#ifdef notdef
if (setsockopt(rmtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)
perror("TCP_NODELAY setsockopt");
#endif
}
static int
okname(cp0)
char *cp0;
{
register char *cp;
register int c;
for (cp = cp0; *cp; cp++) {
c = *cp;
if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) {
(void) fprintf(stderr, "rdump: invalid user name %s\n",
cp0);
return (0);
}
}
return (1);
}
int
@ -237,7 +288,7 @@ rmtstatus()
register char *cp;
if (rmtstate != TS_OPEN)
return (0);
return (NULL);
rmtcall("status", "S\n");
for (i = 0, cp = (char *)&mts; i < sizeof(mts); i++)
*cp++ = rmtgetb();
@ -256,7 +307,7 @@ rmtioctl(cmd, count)
return (rmtcall("ioctl", buf));
}
int
static int
rmtcall(cmd, buf)
char *cmd, *buf;
{
@ -266,16 +317,17 @@ rmtcall(cmd, buf)
return (rmtreply(cmd));
}
int
static int
rmtreply(cmd)
char *cmd;
{
register char *cp;
char code[30], emsg[BUFSIZ];
rmtgets(code, sizeof (code));
if (*code == 'E' || *code == 'F') {
rmtgets(emsg, sizeof (emsg));
msg("%s: %s\n", cmd, emsg, code + 1);
msg("%s: %s", cmd, emsg);
if (*code == 'F') {
rmtstate = TS_CLOSED;
return (-1);
@ -283,7 +335,12 @@ rmtreply(cmd)
return (-1);
}
if (*code != 'A') {
msg("Protocol to remote tape server botched (code %s?).\n",
/* Kill trailing newline */
cp = code + strlen(code);
if (cp > code && *--cp == '\n')
*cp = '\0';
msg("Protocol to remote tape server botched (code \"%s\").\n",
code);
rmtconnaborted();
}
@ -300,21 +357,25 @@ rmtgetb()
return (c);
}
/* Get a line (guaranteed to have a trailing newline). */
void
rmtgets(cp, len)
char *cp;
rmtgets(line, len)
char *line;
int len;
{
register char *cp = line;
while (len > 1) {
*cp = rmtgetb();
if (*cp == '\n') {
cp[1] = 0;
cp[1] = '\0';
return;
}
cp++;
len--;
}
msg("Protocol to remote tape server botched (in rmtgets).\n");
*cp = '\0';
msg("Protocol to remote tape server botched.\n");
msg("(rmtgets got \"%s\").\n", line);
rmtconnaborted();
}

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1980 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1980, 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
@ -32,31 +32,33 @@
*/
#ifndef lint
/* from: static char sccsid[] = "@(#)itime.c 5.15 (Berkeley) 6/18/92"; */
static char *rcsid = "$Id: itime.c,v 1.1 1993/12/22 10:24:44 cgd Exp $";
/*static char sccsid[] = "from: @(#)itime.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: itime.c,v 1.2 1994/06/08 18:57:35 mycroft Exp $";
#endif /* not lint */
#ifdef sunos
#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <ufs/fs.h>
#else
#include <sys/param.h>
#include <sys/time.h>
#ifdef sunos
#include <sys/vnode.h>
#include <ufs/fsdir.h>
#include <ufs/inode.h>
#include <ufs/fs.h>
#else
#include <ufs/ufs/dinode.h>
#endif
#include <ufs/dinode.h>
#include <fcntl.h>
#include <protocols/dumprestore.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#ifdef __STDC__
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "dump.h"
struct dumpdates **ddatev = 0;
@ -64,11 +66,10 @@ int nddates = 0;
int ddates_in = 0;
struct dumptime *dthead = 0;
void readdumptimes();
int getrecord();
int makedumpdate();
static void dumprecout();
static void dumprecout __P((FILE *, struct dumpdates *));
static int getrecord __P((FILE *, struct dumpdates *));
static int makedumpdate __P((struct dumpdates *, char *));
static void readdumptimes __P((FILE *));
void
initdumptimes()
@ -102,7 +103,7 @@ initdumptimes()
(void) fclose(df);
}
void
static void
readdumptimes(df)
FILE *df;
{
@ -233,7 +234,8 @@ dumprecout(file, what)
}
int recno;
int
static int
getrecord(df, ddatep)
FILE *df;
struct dumpdates *ddatep;
@ -255,12 +257,12 @@ getrecord(df, ddatep)
return(0);
}
int
static int
makedumpdate(ddp, tbuf)
struct dumpdates *ddp;
char *tbuf;
{
char un_buf[32];
char un_buf[128];
(void) sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf);
ddp->dd_ddate = unctime(un_buf);

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1980, 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1980, 1991, 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
@ -32,45 +32,49 @@
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980, 1991 The Regents of the University of California.\n\
All rights reserved.\n";
static char copyright[] =
"@(#) Copyright (c) 1980, 1991, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/* from: static char sccsid[] = "@(#)main.c 5.24 (Berkeley) 7/16/92"; */
static char *rcsid = "$Id: main.c,v 1.2 1994/03/28 01:50:05 cgd Exp $";
/*static char sccsid[] = "from: @(#)main.c 8.4 (Berkeley) 4/15/94";*/
static char *rcsid = "$Id: main.c,v 1.3 1994/06/08 18:57:36 mycroft Exp $";
#endif /* not lint */
#ifdef sunos
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <ufs/fs.h>
#else
#include <sys/param.h>
#include <sys/time.h>
#ifdef sunos
#include <sys/vnode.h>
#include <ufs/inode.h>
#include <ufs/fs.h>
#else
#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
#endif
#include <ufs/dinode.h>
#include <protocols/dumprestore.h>
#include <signal.h>
#ifdef __STDC__
#include <time.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <fstab.h>
#include <signal.h>
#include <stdio.h>
#ifdef __STDC__
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "dump.h"
#include "pathnames.h"
#ifndef SBOFF
#define SBOFF (SBLOCK * DEV_BSIZE)
#endif
int notify = 0; /* notify operator flag */
int blockswritten = 0; /* number of blocks written on current tape */
int tapeno = 0; /* current tape number */
@ -80,10 +84,11 @@ int cartridge = 0; /* Assume non-cartridge tape */
long dev_bsize = 1; /* recalculated below */
long blocksperfile; /* output blocks per file */
char *host = NULL; /* remote host (if any) */
#ifdef RDUMP
int rmthost();
#endif
static long numarg __P((int, char *, long, long, int *, char ***));
static __dead void missingarg __P((int, char *));
int
main(argc, argv)
int argc;
char **argv;
@ -94,12 +99,11 @@ main(argc, argv)
register struct fstab *dt;
register char *map;
register char *cp;
int i, anydirskipped, bflag = 0, Tflag = 0;
float fetapes;
int i, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1;
ino_t maxino;
spcl.c_date = 0;
(void) time((time_t *) &(spcl.c_date));
(void)time((time_t *)&spcl.c_date);
tsize = 0; /* Default later, based on 'c' option for cart tapes */
tape = _PATH_DEFTAPE;
@ -114,147 +118,108 @@ main(argc, argv)
}
argv++;
argc -= 2;
for (cp = *argv++; *cp; cp++) {
for (cp = *argv++; cp != NULL && *cp != '\0'; cp++) {
switch (*cp) {
case '-':
continue;
break;
case 'w':
lastdump('w'); /* tell us only what has to be done */
(void) exit(0);
exit(0);
case 'W': /* what to do */
lastdump('W'); /* tell us state of what is done */
(void) exit(0); /* do nothing else */
exit(0); /* do nothing else */
case 'f': /* output file */
if (argc < 1)
break;
missingarg('f', "output file");
tape = *argv++;
argc--;
continue;
break;
case 'd': /* density, in bits per inch */
if (argc < 1)
break;
density = atoi(*argv) / 10;
if (density < 1) {
(void) fprintf(stderr, "bad density \"%s\"\n",
*argv);
Exit(X_ABORT);
}
argc--;
argv++;
density = numarg('d', "density",
10L, 327670L, &argc, &argv) / 10;
if (density >= 625 && !bflag)
ntrec = HIGHDENSITYTREC;
continue;
break;
case 's': /* tape size, feet */
if (argc < 1)
break;
tsize = atol(*argv);
if (tsize < 1) {
(void) fprintf(stderr, "bad size \"%s\"\n",
*argv);
Exit(X_ABORT);
}
argc--;
argv++;
tsize *= 12 * 10;
continue;
tsize = numarg('s', "size",
1L, 0L, &argc, &argv) * 12 * 10;
break;
case 'T': /* time of last dump */
if (argc < 1)
break;
missingarg('T', "time of last dump");
spcl.c_ddate = unctime(*argv);
if (spcl.c_ddate < 0) {
(void) fprintf(stderr, "bad time \"%s\"\n",
(void)fprintf(stderr, "bad time \"%s\"\n",
*argv);
Exit(X_ABORT);
exit(X_ABORT);
}
Tflag++;
Tflag = 1;
lastlevel = '?';
argc--;
argv++;
continue;
break;
case 'b': /* blocks per tape write */
if (argc < 1)
break;
bflag++;
ntrec = atoi(*argv);
if (ntrec < 1) {
(void) fprintf(stderr, "%s \"%s\"\n",
"bad number of blocks per write ", *argv);
Exit(X_ABORT);
}
argc--;
argv++;
continue;
ntrec = numarg('b', "number of blocks per write",
1L, 1000L, &argc, &argv);
break;
case 'B': /* blocks per output file */
if (argc < 1)
break;
blocksperfile = atol(*argv);
if (blocksperfile < 1) {
(void) fprintf(stderr, "%s \"%s\"\n",
"bad number of blocks per file ", *argv);
Exit(X_ABORT);
}
argc--;
argv++;
continue;
blocksperfile = numarg('B', "number of blocks per file",
1L, 0L, &argc, &argv);
break;
case 'c': /* Tape is cart. not 9-track */
cartridge++;
continue;
cartridge = 1;
break;
case '0': /* dump level */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
/* dump level */
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
level = *cp;
continue;
break;
case 'u': /* update /etc/dumpdates */
uflag++;
continue;
uflag = 1;
break;
case 'n': /* notify operators */
notify++;
continue;
notify = 1;
break;
case 'h':
honorlevel = numarg('h', "honor level",
0L, 10L, &argc, &argv);
break;
default:
(void) fprintf(stderr, "bad key '%c'\n", *cp);
Exit(X_ABORT);
(void)fprintf(stderr, "bad key '%c'\n", *cp);
exit(X_ABORT);
}
(void) fprintf(stderr, "missing argument to '%c'\n", *cp);
Exit(X_ABORT);
}
if (argc < 1) {
(void) fprintf(stderr, "Must specify disk or filesystem\n");
Exit(X_ABORT);
} else {
disk = *argv++;
argc--;
(void)fprintf(stderr, "Must specify disk or filesystem\n");
exit(X_ABORT);
}
disk = *argv++;
argc--;
if (argc >= 1) {
(void) fprintf(stderr, "Unknown arguments to dump:");
(void)fprintf(stderr, "Unknown arguments to dump:");
while (argc--)
(void) fprintf(stderr, " %s", *argv++);
(void) fprintf(stderr, "\n");
Exit(X_ABORT);
(void)fprintf(stderr, " %s", *argv++);
(void)fprintf(stderr, "\n");
exit(X_ABORT);
}
if (Tflag && uflag) {
(void) fprintf(stderr,
(void)fprintf(stderr,
"You cannot use the T and u flags together.\n");
Exit(X_ABORT);
exit(X_ABORT);
}
if (strcmp(tape, "-") == 0) {
pipeout++;
@ -282,16 +247,16 @@ main(argc, argv)
if (index(tape, ':')) {
host = tape;
tape = index(host, ':');
*tape++ = 0;
*tape++ = '\0';
#ifdef RDUMP
if (rmthost(host) == 0)
(void) exit(X_ABORT);
exit(X_ABORT);
#else
(void) fprintf(stderr, "remote dump not enabled\n");
(void) exit(X_ABORT);
(void)fprintf(stderr, "remote dump not enabled\n");
exit(X_ABORT);
#endif
}
(void) setuid(getuid()); /* rmthost() is the only reason to be setuid */
(void)setuid(getuid()); /* rmthost() is the only reason to be setuid */
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
signal(SIGHUP, sig);
@ -317,17 +282,17 @@ main(argc, argv)
* the file system name with or without the leading '/'.
*/
dt = fstabsearch(disk);
if (dt != 0) {
if (dt != NULL) {
disk = rawname(dt->fs_spec);
(void) strncpy(spcl.c_dev, dt->fs_spec, NAMELEN);
(void) strncpy(spcl.c_filesys, dt->fs_file, NAMELEN);
(void)strncpy(spcl.c_dev, dt->fs_spec, NAMELEN);
(void)strncpy(spcl.c_filesys, dt->fs_file, NAMELEN);
} else {
(void) strncpy(spcl.c_dev, disk, NAMELEN);
(void) strncpy(spcl.c_filesys, "an unlisted file system",
(void)strncpy(spcl.c_dev, disk, NAMELEN);
(void)strncpy(spcl.c_filesys, "an unlisted file system",
NAMELEN);
}
(void) strcpy(spcl.c_label, "none");
(void) gethostname(spcl.c_host, NAMELEN);
(void)strcpy(spcl.c_label, "none");
(void)gethostname(spcl.c_host, NAMELEN);
spcl.c_level = level - '0';
spcl.c_type = TS_TAPE;
if (!Tflag)
@ -338,7 +303,7 @@ main(argc, argv)
msg("Date of last level %c dump: %s", lastlevel,
spcl.c_ddate == 0 ? "the epoch\n" : ctime(&spcl.c_ddate));
msg("Dumping %s ", disk);
if (dt != 0)
if (dt != NULL)
msgtail("(%s) ", dt->fs_file);
if (host)
msgtail("to %s on host %s\n", tape, host);
@ -347,7 +312,7 @@ main(argc, argv)
if ((diskfd = open(disk, O_RDONLY)) < 0) {
msg("Cannot open %s\n", disk);
Exit(X_ABORT);
exit(X_ABORT);
}
sync();
sblock = (struct fs *)sblock_buf;
@ -361,18 +326,19 @@ main(argc, argv)
tp_bshift = ffs(TP_BSIZE) - 1;
if (TP_BSIZE != (1 << tp_bshift))
quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE);
#ifdef BSD44
#ifdef FS_44INODEFMT
if (sblock->fs_inodefmt >= FS_44INODEFMT)
spcl.c_flags |= DR_NEWINODEFMT;
#endif
maxino = sblock->fs_ipg * sblock->fs_ncg - 1;
mapsize = roundup(howmany(sblock->fs_ipg * sblock->fs_ncg, NBBY),
TP_BSIZE);
maxino = sblock->fs_ipg * sblock->fs_ncg;
mapsize = roundup(howmany(maxino, NBBY), TP_BSIZE);
usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
dumpdirmap = (char *)calloc((unsigned) mapsize, sizeof(char));
dumpinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
tapesize = 3 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1);
nonodump = spcl.c_level < honorlevel;
msg("mapping (Pass I) [regular files]\n");
anydirskipped = mapfiles(maxino, &tapesize);
@ -381,11 +347,14 @@ main(argc, argv)
anydirskipped = mapdirs(maxino, &tapesize);
}
if (pipeout)
if (pipeout) {
tapesize += 10; /* 10 trailer blocks */
else {
msg("estimated %ld tape blocks.\n", tapesize);
} else {
double fetapes;
if (blocksperfile)
fetapes = (float) tapesize / blocksperfile;
fetapes = (double) tapesize / blocksperfile;
else if (cartridge) {
/* Estimate number of tapes, assuming streaming stops at
the end of each block written, and not in mid-block.
@ -420,30 +389,27 @@ main(argc, argv)
tapesize += (etapes - 1) *
(howmany(mapsize * sizeof(char), TP_BSIZE) + 1);
tapesize += etapes + 10; /* headers + 10 trailer blks */
}
if (pipeout)
msg("estimated %ld tape blocks.\n", tapesize);
else
msg("estimated %ld tape blocks on %3.2f tape(s).\n",
tapesize, fetapes);
}
/*
* Allocate tape buffer
* Allocate tape buffer.
*/
if (!alloctape())
quit("can't allocate tape buffers - try a smaller blocking factor.\n");
startnewtape(1);
(void) time((time_t *)&(tstart_writing));
dumpmap(usedinomap, TS_CLRI, maxino);
(void)time((time_t *)&(tstart_writing));
dumpmap(usedinomap, TS_CLRI, maxino - 1);
msg("dumping (Pass III) [directories]\n");
for (map = dumpdirmap, ino = 0; ino < maxino; ) {
if ((ino % NBBY) == 0)
dirty = 0; /* XXX just to get gcc to shut up */
for (map = dumpdirmap, ino = 1; ino < maxino; ino++) {
if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */
dirty = *map++;
else
dirty >>= 1;
ino++;
if ((dirty & 1) == 0)
continue;
/*
@ -452,30 +418,32 @@ main(argc, argv)
dp = getino(ino);
if ((dp->di_mode & IFMT) != IFDIR)
continue;
(void) dumpino(dp, ino);
(void)dumpino(dp, ino);
}
msg("dumping (Pass IV) [regular files]\n");
for (map = dumpinomap, ino = 0; ino < maxino; ) {
if ((ino % NBBY) == 0)
for (map = dumpinomap, ino = 1; ino < maxino; ino++) {
int mode;
if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */
dirty = *map++;
else
dirty >>= 1;
ino++;
if ((dirty & 1) == 0)
continue;
/*
* Skip inodes deleted and reallocated as directories.
*/
dp = getino(ino);
if ((dp->di_mode & IFMT) == IFDIR)
mode = dp->di_mode & IFMT;
if (mode == IFDIR)
continue;
(void) dumpino(dp, ino);
(void)dumpino(dp, ino);
}
spcl.c_type = TS_END;
for (i = 0; i < ntrec; i++)
writeheader(maxino);
writeheader(maxino - 1);
if (pipeout)
msg("DUMP: %ld tape blocks\n",spcl.c_tapea);
else
@ -489,6 +457,50 @@ main(argc, argv)
/* NOTREACHED */
}
/*
* Pick up a numeric argument. It must be nonnegative and in the given
* range (except that a vmax of 0 means unlimited).
*/
static long
numarg(letter, meaning, vmin, vmax, pargc, pargv)
int letter;
char *meaning;
long vmin, vmax;
int *pargc;
char ***pargv;
{
register char *p;
long val;
char *str;
if (--*pargc < 0)
missingarg(letter, meaning);
str = *(*pargv)++;
for (p = str; *p; p++)
if (!isdigit(*p))
goto bad;
val = atol(str);
if (val < vmin || (vmax && val > vmax))
goto bad;
return (val);
bad:
(void)fprintf(stderr, "bad '%c' (%s) value \"%s\"\n",
letter, meaning, str);
exit(X_ABORT);
}
static __dead void
missingarg(letter, meaning)
int letter;
char *meaning;
{
(void)fprintf(stderr, "The '%c' flag (%s) requires an argument\n",
letter, meaning);
exit(X_ABORT);
}
void
sig(signo)
int signo;
@ -503,15 +515,15 @@ sig(signo)
if (pipeout)
quit("Signal on pipe: cannot recover\n");
msg("Rewriting attempted as response to unknown signal.\n");
(void) fflush(stderr);
(void) fflush(stdout);
(void)fflush(stderr);
(void)fflush(stdout);
close_rewind();
(void) exit(X_REWRITE);
exit(X_REWRITE);
/* NOTREACHED */
case SIGSEGV:
msg("SIGSEGV: ABORTING!\n");
(void) signal(SIGSEGV, SIG_DFL);
(void) kill(0, SIGSEGV);
(void)signal(SIGSEGV, SIG_DFL);
(void)kill(0, SIGSEGV);
/* NOTREACHED */
}
}
@ -521,31 +533,29 @@ rawname(cp)
char *cp;
{
static char rawbuf[MAXPATHLEN];
char *rindex();
char *dp = rindex(cp, '/');
if (dp == 0)
return (0);
*dp = 0;
(void) strcpy(rawbuf, cp);
if (dp == NULL)
return (NULL);
*dp = '\0';
(void)strcpy(rawbuf, cp);
*dp = '/';
(void) strcat(rawbuf, "/r");
(void) strcat(rawbuf, dp+1);
(void)strcat(rawbuf, "/r");
(void)strcat(rawbuf, dp + 1);
return (rawbuf);
}
#ifdef sunos
char *
const char *
strerror(errnum)
int errnum;
{
extern int sys_nerr;
extern char *sys_errlist[];
extern const char *const sys_errlist[];
if (errnum < sys_nerr) {
return(sys_errlist[errnum]);
} else {
return("bogus errno in strerror");
}
if (errnum < sys_nerr)
return (sys_errlist[errnum]);
else
return ("bogus errno in strerror");
}
#endif

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1980, 1988 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1980, 1988, 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
@ -32,42 +32,39 @@
*/
#ifndef lint
/* from: static char sccsid[] = "@(#)optr.c 5.14 (Berkeley) 7/16/92"; */
static char *rcsid = "$Id: optr.c,v 1.1 1993/12/22 10:24:50 cgd Exp $";
/*static char sccsid[] = "from: @(#)optr.c 8.2 (Berkeley) 1/6/94";*/
static char *rcsid = "$Id: optr.c,v 1.2 1994/06/08 18:57:37 mycroft Exp $";
#endif /* not lint */
#ifdef sunos
#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/time.h>
#else
#include <sys/param.h>
#include <sys/wait.h>
#include <stdio.h>
#endif
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <fstab.h>
#include <grp.h>
#include <utmp.h>
#include <tzfile.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#ifdef __STDC__
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#else
#endif
#include <tzfile.h>
#ifdef __STDC__
#include <unistd.h>
#endif
#include <utmp.h>
#ifndef __STDC__
#include <varargs.h>
#endif
#include "dump.h"
#include "pathnames.h"
static void alarmcatch();
static void sendmes();
void alarmcatch __P((/* int, int */));
int datesort __P((const void *, const void *));
static void sendmes __P((char *, char *));
/*
* Query the operator; This previously-fascist piece of code
@ -80,8 +77,8 @@ static void sendmes();
* Every 2 minutes we reprint the message, alerting others
* that dump needs attention.
*/
int timeout;
char *attnmessage; /* attention message */
static int timeout;
static char *attnmessage; /* attention message */
int
query(question)
@ -131,7 +128,7 @@ char lastmsg[100];
* Alert the console operator, and enable the alarm clock to
* sleep for 2 minutes in case nobody comes to satisfy dump
*/
static void
void
alarmcatch()
{
if (notify == 0) {
@ -190,7 +187,6 @@ set_operators()
}
}
struct tm *localtime();
struct tm *localclock;
/*
@ -428,7 +424,7 @@ getfstab()
_PATH_FSTAB, strerror(errno));
return;
}
while (fs = getfsent()) {
while ((fs = getfsent()) != NULL) {
if (strcmp(fs->fs_type, FSTAB_RW) &&
strcmp(fs->fs_type, FSTAB_RO) &&
strcmp(fs->fs_type, FSTAB_RQ))
@ -460,7 +456,7 @@ fstabsearch(key)
{
register struct pfstab *pf;
register struct fstab *fs;
char *rn, *rawname();
char *rn;
for (pf = table; pf != NULL; pf = pf->pf_next) {
fs = pf->pf_fstab;
@ -493,7 +489,7 @@ lastdump(arg)
register struct fstab *dt;
register struct dumpdates *dtwalk;
char *lastname, *date;
int dumpme, datesort();
int dumpme;
time_t tnow;
(void) time(&tnow);
@ -530,7 +526,7 @@ lastdump(arg)
int
datesort(a1, a2)
void *a1, *a2;
const void *a1, *a2;
{
struct dumpdates *d1 = *(struct dumpdates **)a1;
struct dumpdates *d2 = *(struct dumpdates **)a2;
@ -541,4 +537,3 @@ datesort(a1, a2)
return (d2->dd_ddate - d1->dd_ddate);
return (diff);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1989, 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
@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)pathnames.h 5.6 (Berkeley) 2/28/91
* $Id: pathnames.h,v 1.5 1993/12/22 10:24:53 cgd Exp $
* from: @(#)pathnames.h 8.1 (Berkeley) 6/5/93
* $Id: pathnames.h,v 1.6 1994/06/08 18:57:38 mycroft Exp $
*/
#include <paths.h>

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1980, 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1980, 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
@ -32,34 +32,39 @@
*/
#ifndef lint
/* from: static char sccsid[] = "@(#)tape.c 5.25 (Berkeley) 7/16/92"; */
static char *rcsid = "$Id: tape.c,v 1.2 1994/03/09 01:14:43 cgd Exp $";
/*static char sccsid[] = "from: @(#)tape.c 8.2 (Berkeley) 3/17/94";*/
static char *rcsid = "$Id: tape.c,v 1.3 1994/06/08 18:57:40 mycroft Exp $";
#endif /* not lint */
#ifdef sunos
#include <sys/param.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/stat.h>
#include <ufs/fs.h>
#else
#include <sys/param.h>
#include <sys/wait.h>
#include <ufs/fs.h>
#endif
#include <sys/socket.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/wait.h>
#ifdef sunos
#include <sys/vnode.h>
#include <ufs/fs.h>
#include <ufs/inode.h>
#else
#include <ufs/ffs/fs.h>
#include <ufs/ufs/dinode.h>
#endif
#include <protocols/dumprestore.h>
#include <errno.h>
#include <fcntl.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#ifdef __STDC__
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#else
int write(), read();
#endif
#include <sys/socket.h>
#include "dump.h"
#include "pathnames.h"
@ -72,13 +77,13 @@ extern int ntrec; /* blocking factor on tape */
extern int cartridge;
extern char *host;
char *nexttape;
#ifdef RDUMP
int rmtopen(), rmtwrite();
void rmtclose();
#endif
void rollforward();
int atomic();
void doslave(), enslave(), flushtape(), killall();
static int atomic __P((int (*)(), int, char *, int));
static void doslave __P((int, int));
static void enslave __P((void));
static void flushtape __P((void));
static void killall __P((void));
static void rollforward __P((void));
/*
* Concurrent dump mods (Caltech) - disk block reading and tape writing
@ -229,14 +234,11 @@ sigpipe(signo)
quit("Broken pipe\n");
}
void
static void
flushtape()
{
int i, blks, got;
long lastfirstrec;
#ifndef __STDC__
int write(), read();
#endif
int siz = (char *)nextblock - (char *)slp->req;
@ -403,6 +405,7 @@ rollforward()
* For each request in the current slave, copy it to tslp.
*/
prev = NULL;
for (p = slp->req; p->count > 0; p += p->count) {
*q = *p;
if (p->dblk == 0)
@ -410,6 +413,8 @@ rollforward()
prev = q;
q += q->count;
}
if (prev == NULL)
quit("rollforward: protocol botch");
if (prev->dblk != 0)
prev->count -= 1;
else
@ -502,7 +507,6 @@ startnewtape(top)
char *p;
#ifdef sunos
void (*interrupt_save)();
char *index();
#else
sig_t interrupt_save;
#endif
@ -510,7 +514,7 @@ startnewtape(top)
interrupt_save = signal(SIGINT, SIG_IGN);
parentpid = getpid();
restore_check_point:
restore_check_point:
(void)signal(SIGINT, interrupt_save);
/*
* All signals are inherited...
@ -531,7 +535,7 @@ startnewtape(top)
#ifdef TDEBUG
msg("Tape: %d; parent process: %d child process %d\n",
tapeno+1, parentpid, childpid);
#endif TDEBUG
#endif /* TDEBUG */
while ((waitpid = wait(&status)) != childpid)
msg("Parent %d waiting for child %d has another child %d return\n",
parentpid, childpid, waitpid);
@ -556,7 +560,7 @@ startnewtape(top)
childpid, status);
break;
}
#endif TDEBUG
#endif /* TDEBUG */
switch(status) {
case X_FINOK:
Exit(X_FINOK);
@ -574,7 +578,7 @@ startnewtape(top)
sleep(4); /* allow time for parent's message to get out */
msg("Child on Tape %d has parent %d, my pid = %d\n",
tapeno+1, parentpid, getpid());
#endif TDEBUG
#endif /* TDEBUG */
/*
* If we have a name like "/dev/rmt0,/dev/rmt1",
* use the name before the comma first, and save
@ -584,7 +588,7 @@ startnewtape(top)
if (nexttape || index(tape, ',')) {
if (nexttape && *nexttape)
tape = nexttape;
if (p = index(tape, ',')) {
if ((p = index(tape, ',')) != NULL) {
*p = '\0';
nexttape = p + 1;
} else
@ -645,15 +649,15 @@ dumpabort(signo)
Exit(X_ABORT);
}
void
__dead void
Exit(status)
int status;
{
#ifdef TDEBUG
msg("pid = %d exits with status %d\n", getpid(), status);
#endif TDEBUG
(void) exit(status);
#endif /* TDEBUG */
exit(status);
}
/*
@ -730,16 +734,13 @@ killall()
* file, allowing the following process to lock it and proceed. We
* get the lock back for the next cycle by swapping descriptors.
*/
void
static void
doslave(cmd, slave_number)
register int cmd;
int slave_number;
{
register int nread;
int nextslave, size, wrote, eot_count;
#ifndef __STDC__
int read();
#endif
/*
* Need our own seek pointer.
@ -845,10 +846,11 @@ doslave(cmd, slave_number)
* or a write may not write all we ask if we get a signal,
* loop until the count is satisfied (or error).
*/
int
static int
atomic(func, fd, buf, count)
int (*func)(), fd, count;
int (*func)(), fd;
char *buf;
int count;
{
int got, need = count;

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1980, 1988, 1991 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1980, 1988, 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
@ -32,34 +32,49 @@
*/
#ifndef lint
/* from: static char sccsid[] = "@(#)traverse.c 5.21 (Berkeley) 7/19/92"; */
static char *rcsid = "$Id: traverse.c,v 1.3 1994/04/25 18:22:50 cgd Exp $";
/*static char sccsid[] = "from: @(#)traverse.c 8.2 (Berkeley) 9/23/93";*/
static char *rcsid = "$Id: traverse.c,v 1.4 1994/06/08 18:57:42 mycroft Exp $";
#endif /* not lint */
#ifdef sunos
#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
#include <ufs/fs.h>
#else
#include <sys/param.h>
#include <ufs/fs.h>
#endif
#include <sys/time.h>
#include <sys/stat.h>
#include <ufs/dir.h>
#include <ufs/dinode.h>
#include <protocols/dumprestore.h>
#ifdef __STDC__
#include <unistd.h>
#include <string.h>
#ifdef sunos
#include <sys/vnode.h>
#include <ufs/fs.h>
#include <ufs/fsdir.h>
#include <ufs/inode.h>
#else
#include <ufs/ffs/fs.h>
#include <ufs/ufs/dir.h>
#include <ufs/ufs/dinode.h>
#endif
#include <protocols/dumprestore.h>
#include <ctype.h>
#include <stdio.h>
#ifdef __STDC__
#include <string.h>
#include <unistd.h>
#endif
#include "dump.h"
void dmpindir();
#define HASDUMPEDFILE 0x1
#define HASSUBDIRS 0x2
#ifdef FS_44INODEFMT
typedef quad_t fsizeT;
#else
typedef long fsizeT;
#endif
static int dirindir __P((ino_t ino, daddr_t blkno, int level, long *size));
static void dmpindir __P((ino_t ino, daddr_t blk, int level, fsizeT *size));
static int searchdir __P((ino_t ino, daddr_t blkno, long size, long filesize));
/*
* This is an estimation of the number of TP_BSIZE blocks in the file.
* It estimates the number of blocks in files with holes by assuming
@ -100,6 +115,24 @@ blockest(dp)
return (blkest + 1);
}
/* Auxiliary macro to pick up files changed since previous dump. */
#ifdef FS_44INODEFMT
#define CHANGEDSINCE(dp, t) \
((dp)->di_mtime.ts_sec >= (t) || (dp)->di_ctime.ts_sec >= (t))
#else
#define CHANGEDSINCE(dp, t) \
((dp)->di_mtime >= (t) || (dp)->di_ctime >= (t))
#endif
/* The WANTTODUMP macro decides whether a file should be dumped. */
#ifdef UF_NODUMP
#define WANTTODUMP(dp) \
(CHANGEDSINCE(dp, spcl.c_ddate) && \
(nonodump || ((dp)->di_flags & UF_NODUMP) != UF_NODUMP))
#else
#define WANTTODUMP(dp) CHANGEDSINCE(dp, spcl.c_ddate)
#endif
/*
* Dump pass 1.
*
@ -107,6 +140,7 @@ blockest(dp)
* that have been modified since the previous dump time. Also, find all
* the directories in the filesystem.
*/
int
mapfiles(maxino, tapesize)
ino_t maxino;
long *tapesize;
@ -123,20 +157,12 @@ mapfiles(maxino, tapesize)
SETINO(ino, usedinomap);
if (mode == IFDIR)
SETINO(ino, dumpdirmap);
if ((dp->di_mtime.ts_sec >= spcl.c_ddate ||
dp->di_ctime.ts_sec >= spcl.c_ddate)
#ifdef BSD44
# ifndef sunos
&& (dp->di_flags & NODUMP) != NODUMP
# endif /* sunos */
#endif /* BSD44 */
) {
if (WANTTODUMP(dp)) {
SETINO(ino, dumpinomap);
if (mode != IFREG && mode != IFDIR && mode != IFLNK) {
if (mode != IFREG && mode != IFDIR && mode != IFLNK)
*tapesize += 1;
continue;
}
*tapesize += blockest(dp);
else
*tapesize += blockest(dp);
continue;
}
if (mode == IFDIR)
@ -162,6 +188,7 @@ mapfiles(maxino, tapesize)
* its parent may now qualify for the same treatment on this or a later
* pass using this algorithm.
*/
int
mapdirs(maxino, tapesize)
ino_t maxino;
long *tapesize;
@ -173,12 +200,12 @@ mapdirs(maxino, tapesize)
long filesize;
int ret, change = 0;
for (map = dumpdirmap, ino = 0; ino < maxino; ) {
if ((ino % NBBY) == 0)
isdir = 0; /* XXX just to get gcc to shut up */
for (map = dumpdirmap, ino = 1; ino < maxino; ino++) {
if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */
isdir = *map++;
else
isdir >>= 1;
ino++;
if ((isdir & 1) == 0 || TSTINO(ino, dumpinomap))
continue;
dp = getino(ino);
@ -219,6 +246,7 @@ mapdirs(maxino, tapesize)
* as directories. Quit as soon as any entry is found that will
* require the directory to be dumped.
*/
static int
dirindir(ino, blkno, ind_level, filesize)
ino_t ino;
daddr_t blkno;
@ -257,6 +285,7 @@ dirindir(ino, blkno, ind_level, filesize)
* any of the entries are on the dump list and to see if the directory
* contains any subdirectories.
*/
static int
searchdir(ino, blkno, size, filesize)
ino_t ino;
daddr_t blkno;
@ -310,7 +339,7 @@ dumpino(dp, ino)
ino_t ino;
{
int ind_level, cnt;
long size;
fsizeT size;
char buf[TP_BSIZE];
if (newtape) {
@ -321,22 +350,22 @@ dumpino(dp, ino)
spcl.c_dinode = *dp;
spcl.c_type = TS_INODE;
spcl.c_count = 0;
switch (dp->di_mode & S_IFMT) {
switch (IFTODT(dp->di_mode)) {
case DT_UNKNOWN:
case 0:
/*
* Freed inode.
*/
return;
case DT_LNK:
#ifdef BSD44
case S_IFLNK:
/*
* Check for short symbolic link.
*/
#ifdef FS_44INODEFMT
if (dp->di_size > 0 &&
dp->di_size < sblock->fs_maxsymlinklen) {
(dp->di_size < sblock->fs_maxsymlinklen ||
(sblock->fs_maxsymlinklen == 0 && OLDFASTLINK(dp)))) {
spcl.c_addr[0] = 1;
spcl.c_count = 1;
writeheader(ino);
@ -346,31 +375,19 @@ dumpino(dp, ino)
writerec(buf, 0);
return;
}
#endif
#ifdef NetBSD
if (DFASTLINK(*dp)) {
spcl.c_addr[0] = 1;
spcl.c_count = 1;
writeheader(ino);
bcopy((caddr_t)dp->di_symlink, buf,
(u_long)dp->di_size);
buf[dp->di_size] = '\0';
writerec(buf, 0);
return;
}
#endif
/* fall through */
case DT_DIR:
case DT_REG:
case S_IFDIR:
case S_IFREG:
if (dp->di_size > 0)
break;
/* fall through */
case DT_FIFO:
case DT_SOCK:
case DT_CHR:
case DT_BLK:
case S_IFIFO:
case S_IFSOCK:
case S_IFCHR:
case S_IFBLK:
writeheader(ino);
return;
@ -378,7 +395,6 @@ dumpino(dp, ino)
msg("Warning: undefined file type 0%o\n", dp->di_mode & IFMT);
return;
}
if (dp->di_size > NDADDR * sblock->fs_bsize)
cnt = NDADDR * sblock->fs_frag;
else
@ -396,12 +412,12 @@ dumpino(dp, ino)
/*
* Read indirect blocks, and pass the data blocks to be dumped.
*/
void
static void
dmpindir(ino, blk, ind_level, size)
ino_t ino;
daddr_t blk;
int ind_level;
long *size;
fsizeT *size;
{
int i, cnt;
daddr_t idblk[MAXNINDIR];
@ -518,7 +534,7 @@ getino(inum)
curino = inum;
if (inum >= minino && inum < maxino)
return (&inoblock[inum - minino]);
bread(fsbtodb(sblock, itod(sblock, inum)), (char *)inoblock,
bread(fsbtodb(sblock, ino_to_fsba(sblock, inum)), (char *)inoblock,
(int)sblock->fs_bsize);
minino = inum - (inum % INOPB(sblock));
maxino = minino + INOPB(sblock);

View File

@ -1,6 +1,6 @@
/*-
* Copyright (c) 1980 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1980, 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
@ -32,18 +32,23 @@
*/
#ifndef lint
/* from: static char sccsid[] = "@(#)unctime.c 5.5 (Berkeley) 6/18/92"; */
static char *rcsid = "$Id: unctime.c,v 1.6 1993/12/24 01:16:59 jtc Exp $";
/*static char sccsid[] = "from: @(#)unctime.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: unctime.c,v 1.7 1994/06/08 18:57:43 mycroft Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <time.h>
#include <stdio.h>
#include <time.h>
#ifdef __STDC__
#include <stdlib.h>
#include <string.h>
#endif
#ifndef __P
#include <sys/cdefs.h>
#endif
/*
* Convert a ctime(3) format string into a system format date.
* Return the date thus calculated.
@ -62,19 +67,19 @@ static char *rcsid = "$Id: unctime.c,v 1.6 1993/12/24 01:16:59 jtc Exp $";
#define E_SECOND 17
#define E_YEAR 20
static int lookup();
static int lookup __P((char *));
time_t
unctime(str)
char *str;
{
struct tm then;
char dbuf[30];
char dbuf[26];
if (strlen(str) != 25)
str[25] = 0;
(void) strcpy(dbuf, str);
dbuf[E_MONTH+3] = 0;
(void) strncpy(dbuf, str, sizeof(dbuf) - 1);
dbuf[sizeof(dbuf) - 1] = '\0';
dbuf[E_MONTH+3] = '\0';
if ((then.tm_mon = lookup(&dbuf[E_MONTH])) < 0)
return (-1);
then.tm_mday = atoi(&dbuf[E_DAY]);
@ -95,7 +100,7 @@ lookup(str)
{
register char *cp, *cp2;
for (cp = months, cp2 = str; *cp != 0; cp += 3)
for (cp = months, cp2 = str; *cp != '\0'; cp += 3)
if (strncmp(cp, cp2, 3) == 0)
return((cp-months) / 3);
return(-1);

View File

@ -1,5 +1,5 @@
# from: @(#)Makefile 5.3 (Berkeley) 5/11/90
# $Id: Makefile,v 1.4 1993/08/01 05:38:06 mycroft Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/5/93
# $Id: Makefile,v 1.5 1994/06/08 18:58:21 mycroft Exp $
PROG= dumpfs
MAN8= dumpfs.0

View File

@ -1,5 +1,5 @@
.\" Copyright (c) 1983, 1991 Regents of the University of California.
.\" All rights reserved.
.\" Copyright (c) 1983, 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
@ -29,10 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)dumpfs.8 6.2 (Berkeley) 3/16/91
.\" $Id: dumpfs.8,v 1.4 1993/08/01 07:39:20 mycroft Exp $
.\" from: @(#)dumpfs.8 8.1 (Berkeley) 6/5/93
.\" $Id: dumpfs.8,v 1.5 1994/06/08 18:58:22 mycroft Exp $
.\"
.Dd March 16, 1991
.Dd June 5, 1993
.Dt DUMPFS 8
.Os BSD 4.2
.Sh NAME

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1983 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1983, 1992, 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
@ -32,27 +32,29 @@
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
All rights reserved.\n";
static char copyright[] =
"@(#) Copyright (c) 1983, 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)dumpfs.c 5.10 (Berkeley) 6/1/90";*/
static char rcsid[] = "$Id: dumpfs.c,v 1.5 1994/04/25 18:23:19 cgd Exp $";
/*static char sccsid[] = "from: @(#)dumpfs.c 8.2 (Berkeley) 2/2/94";*/
static char *rcsid = "$Id: dumpfs.c,v 1.6 1994/06/08 18:58:23 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <stdio.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <fstab.h>
/*
* dumpfs
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
union {
struct fs fs;
@ -68,46 +70,60 @@ union {
long dev_bsize = 1;
int dumpfs __P((char *));
int dumpcg __P((char *, int, int));
void pbits __P((void *, int));
void usage __P((void));
int
main(argc, argv)
char **argv;
int argc;
char *argv[];
{
register struct fstab *fs;
int ch, eval;
argc--, argv++;
if (argc < 1) {
fprintf(stderr, "usage: dumpfs fs ...\n");
exit(1);
}
for (; argc > 0; argv++, argc--) {
fs = getfsfile(*argv);
if (fs == 0)
dumpfs(*argv);
while ((ch = getopt(argc, argv, "")) != EOF)
switch(ch) {
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc < 1)
usage();
for (eval = 0; *argv; ++argv)
if ((fs = getfsfile(*argv)) == NULL)
eval |= dumpfs(*argv);
else
dumpfs(fs->fs_spec);
}
eval |= dumpfs(fs->fs_spec);
exit(eval);
}
int
dumpfs(name)
char *name;
{
int c, i, j, k, size;
int fd, c, i, j, k, size;
if ((fd = open(name, O_RDONLY, 0)) < 0)
goto err;
if (lseek(fd, (off_t)SBOFF, SEEK_SET) == (off_t)-1)
goto err;
if (read(fd, &afs, SBSIZE) != SBSIZE)
goto err;
close(0);
if (open(name, 0) != 0) {
perror(name);
return;
}
lseek(0, SBOFF, 0);
if (read(0, &afs, SBSIZE) != SBSIZE) {
perror(name);
return;
}
if (afs.fs_postblformat == FS_42POSTBLFMT)
afs.fs_nrpos = 8;
dev_bsize = afs.fs_fsize / fsbtodb(&afs, 1);
printf("magic\t%x\tformat\t%s\ttime\t%s", afs.fs_magic,
afs.fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic",
printf("magic\t%x\ttime\t%s", afs.fs_magic,
ctime(&afs.fs_time));
printf("cylgrp\t%s\tinodes\t%s\n",
afs.fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic",
afs.fs_inodefmt < FS_44INODEFMT ? "4.2/4.3BSD" : "4.4BSD");
printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir,
afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree);
@ -128,8 +144,9 @@ dumpfs(name)
afs.fs_rotdelay, afs.fs_headswitch, afs.fs_trkseek, afs.fs_rps);
printf("ntrak\t%d\tnsect\t%d\tnpsect\t%d\tspc\t%d\n",
afs.fs_ntrak, afs.fs_nsect, afs.fs_npsect, afs.fs_spc);
printf("trackskew %d\tinterleave %d\n",
afs.fs_trackskew, afs.fs_interleave);
printf("symlinklen %d\ttrackskew %d\tinterleave %d\tcontigsumsize %d\n",
afs.fs_maxsymlinklen, afs.fs_trackskew, afs.fs_interleave,
afs.fs_contigsumsize);
printf("nindir\t%d\tinopb\t%d\tnspf\t%d\n",
afs.fs_nindir, afs.fs_inopb, afs.fs_nspf);
printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n",
@ -165,13 +182,13 @@ dumpfs(name)
for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) {
size = afs.fs_cssize - i < afs.fs_bsize ?
afs.fs_cssize - i : afs.fs_bsize;
afs.fs_csp[j] = (struct csum *)calloc(1, size);
lseek(0, fsbtodb(&afs, (afs.fs_csaddr + j * afs.fs_frag)) *
dev_bsize, 0);
if (read(0, afs.fs_csp[j], size) != size) {
perror(name);
return;
}
afs.fs_csp[j] = calloc(1, size);
if (lseek(fd,
(off_t)(fsbtodb(&afs, (afs.fs_csaddr + j * afs.fs_frag)) *
dev_bsize), SEEK_SET) == (off_t)-1)
goto err;
if (read(fd, afs.fs_csp[j], size) != size)
goto err;
}
for (i = 0; i < afs.fs_ncg; i++) {
struct csum *cs = &afs.fs_cs(&afs, i);
@ -189,27 +206,37 @@ dumpfs(name)
}
printf("\n");
for (i = 0; i < afs.fs_ncg; i++)
dumpcg(name, i);
close(0);
if (dumpcg(name, fd, i))
goto err;
(void)close(fd);
return (0);
err: if (fd != -1)
(void)close(fd);
(void)fprintf(stderr, "dumpfs: %s: %s\n", name, strerror(errno));
return (1);
};
dumpcg(name, c)
int
dumpcg(name, fd, c)
char *name;
int c;
int fd, c;
{
int i,j;
off_t cur;
int i, j;
printf("\ncg %d:\n", c);
lseek(0, fsbtodb(&afs, cgtod(&afs, c)) * dev_bsize, 0);
i = lseek(0, 0, 1);
if (read(0, (char *)&acg, afs.fs_bsize) != afs.fs_bsize) {
printf("dumpfs: %s: error reading cg\n", name);
return;
if ((cur = lseek(fd, (off_t)(fsbtodb(&afs, cgtod(&afs, c)) * dev_bsize),
SEEK_SET)) == (off_t)-1)
return (1);
if (read(fd, &acg, afs.fs_bsize) != afs.fs_bsize) {
(void)fprintf(stderr, "dumpfs: %s: error reading cg\n", name);
return (1);
}
printf("magic\t%x\ttell\t%x\ttime\t%s",
printf("magic\t%x\ttell\t%qx\ttime\t%s",
afs.fs_postblformat == FS_42POSTBLFMT ?
((struct ocg *)&acg)->cg_magic : acg.cg_magic,
i, ctime(&acg.cg_time));
cur, ctime(&acg.cg_time));
printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
acg.cg_cgx, acg.cg_ncyl, acg.cg_niblk, acg.cg_ndblk);
printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
@ -221,7 +248,23 @@ dumpcg(name, c)
printf("\t%d", acg.cg_frsum[i]);
j += i * acg.cg_frsum[i];
}
printf("\nsum of frsum: %d\niused:\t", j);
printf("\nsum of frsum: %d", j);
if (afs.fs_contigsumsize > 0) {
for (i = 1; i < afs.fs_contigsumsize; i++) {
if ((i - 1) % 8 == 0)
printf("\nclusters %d-%d:", i,
afs.fs_contigsumsize - 1 < i + 7 ?
afs.fs_contigsumsize - 1 : i + 7);
printf("\t%d", cg_clustersum(&acg)[i]);
}
printf("\nclusters size %d and over: %d\n",
afs.fs_contigsumsize,
cg_clustersum(&acg)[afs.fs_contigsumsize]);
printf("clusters free:\t");
pbits(cg_clustersfree(&acg), acg.cg_nclusterblks);
} else
printf("\n");
printf("iused:\t");
pbits(cg_inosused(&acg), afs.fs_ipg);
printf("free:\t");
pbits(cg_blksfree(&acg), afs.fs_fpg);
@ -238,26 +281,36 @@ dumpcg(name, c)
}
printf("\n");
}
return (0);
};
pbits(cp, max)
register char *cp;
void
pbits(vp, max)
register void *vp;
int max;
{
register int i;
int count = 0, j;
register char *p;
int count, j;
for (i = 0; i < max; i++)
if (isset(cp, i)) {
for (count = i = 0, p = vp; i < max; i++)
if (isset(p, i)) {
if (count)
printf(",%s", count % 6 ? " " : "\n\t");
count++;
printf("%d", i);
j = i;
while ((i+1)<max && isset(cp, i+1))
while ((i+1)<max && isset(p, i+1))
i++;
if (i != j)
printf("-%d", i);
}
printf("\n");
}
void
usage()
{
(void)fprintf(stderr, "usage: dumpfs filesys | device\n");
exit(1);
}

10
sbin/dumplfs/Makefile Normal file
View File

@ -0,0 +1,10 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/18/93
# $Id: Makefile,v 1.1 1994/06/08 18:58:47 mycroft Exp $
PROG= dumplfs
CFLAGS+=-I/sys/ufs/lfs
SRCS= dumplfs.c lfs_cksum.c misc.c
.PATH: /sys/ufs/lfs
MAN8= dumplfs.0
.include <bsd.prog.mk>

60
sbin/dumplfs/dumplfs.8 Normal file
View File

@ -0,0 +1,60 @@
.\" Copyright (c) 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)dumplfs.8 8.1 (Berkeley) 6/18/93
.\" $Id: dumplfs.8,v 1.1 1994/06/08 18:58:48 mycroft Exp $
.\"
.Dd June 18, 1993
.Dt DUMPLFS 8
.Os BSD 4.4
.Sh NAME
.Nm dumplfs
.Nd dump file system information
.Sh SYNOPSIS
.Nm dumplfs
.Op Ar filesys No \&| Ar device
.Sh DESCRIPTION
.Nm Dumplfs
prints out the file system layout information for the
LFS file system or special device specified.
The listing is very long and detailed.
This command is useful mostly for finding out certain file system
information such as the file system block size.
.Sh SEE ALSO
.Xr fs 5 ,
.Xr disktab 5 ,
.Xr disklabel 8 ,
.Xr newlfs 8 ,
.Sh HISTORY
The
.Nm dumplfs
command appeared in
.Bx 4.4 .

613
sbin/dumplfs/dumplfs.c Normal file
View File

@ -0,0 +1,613 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)dumplfs.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: dumplfs.c,v 1.1 1994/06/08 18:58:50 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/lfs/lfs.h>
#include <fcntl.h>
#include <fstab.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "extern.h"
static void addseg __P((char *));
static void dump_cleaner_info __P((struct lfs *, void *));
static void dump_dinode __P((struct dinode *));
static void dump_ifile __P((int, struct lfs *, int));
static int dump_ipage_ifile __P((int, IFILE *, int));
static int dump_ipage_segusage __P((struct lfs *, int, IFILE *, int));
static void dump_segment __P((int, int, daddr_t, struct lfs *, int));
static int dump_sum __P((int, struct lfs *, SEGSUM *, int, daddr_t));
static void dump_super __P((struct lfs *));
static void usage __P((void));
typedef struct seglist SEGLIST;
struct seglist {
SEGLIST *next;
int num;
};
SEGLIST *seglist;
int daddr_shift;
char *special;
/* Segment Usage formats */
#define print_suheader \
(void)printf("segnum\tflags\tnbytes\tninos\tnsums\tlastmod\n")
#define print_suentry(i, sp) \
(void)printf("%d\t%c%c%c\t%d\t%d\t%d\t%s", i, \
(((sp)->su_flags & SEGUSE_ACTIVE) ? 'A' : ' '), \
(((sp)->su_flags & SEGUSE_DIRTY) ? 'D' : 'C'), \
(((sp)->su_flags & SEGUSE_SUPERBLOCK) ? 'S' : ' '), \
(sp)->su_nbytes, (sp)->su_ninos, (sp)->su_nsums, \
ctime((time_t *)&(sp)->su_lastmod))
/* Ifile formats */
#define print_iheader \
(void)printf("inum\tstatus\tversion\tdaddr\t\tfreeptr\n")
#define print_ientry(i, ip) \
if (ip->if_daddr == LFS_UNUSED_DADDR) \
(void)printf("%d\tFREE\t%d\t \t\t%d\n", \
i, ip->if_version, ip->if_nextfree); \
else \
(void)printf("%d\tINUSE\t%d\t%8X \n", \
i, ip->if_version, ip->if_daddr)
int
main(argc, argv)
int argc;
char *argv[];
{
struct lfs lfs_sb1, lfs_sb2, *lfs_master;
daddr_t seg_addr;
int ch, do_allsb, do_ientries, fd, segnum;
do_allsb = 0;
do_ientries = 0;
while ((ch = getopt(argc, argv, "ais:")) != EOF)
switch(ch) {
case 'a': /* Dump all superblocks */
do_allsb = 1;
break;
case 'i': /* Dump ifile entries */
do_ientries = 1;
break;
case 's': /* Dump out these segments */
addseg(optarg);
break;
default:
usage();
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
special = argv[0];
if ((fd = open(special, O_RDONLY, 0)) < 0)
err("%s: %s", special, strerror(errno));
/* Read the first superblock */
get(fd, LFS_LABELPAD, &lfs_sb1, sizeof(struct lfs));
daddr_shift = lfs_sb1.lfs_bshift - lfs_sb1.lfs_fsbtodb;
/*
* Read the second superblock and figure out which check point is
* most up to date.
*/
get(fd,
lfs_sb1.lfs_sboffs[1] << daddr_shift, &lfs_sb2, sizeof(struct lfs));
lfs_master = &lfs_sb1;
if (lfs_sb1.lfs_tstamp < lfs_sb2.lfs_tstamp)
lfs_master = &lfs_sb2;
(void)printf("Master Superblock:\n");
dump_super(lfs_master);
dump_ifile(fd, lfs_master, do_ientries);
if (seglist != NULL)
for (; seglist != NULL; seglist = seglist->next) {
seg_addr = lfs_master->lfs_sboffs[0] + seglist->num *
(lfs_master->lfs_ssize << lfs_master->lfs_fsbtodb);
dump_segment(fd,
seglist->num, seg_addr, lfs_master, do_allsb);
}
else
for (segnum = 0, seg_addr = lfs_master->lfs_sboffs[0];
segnum < lfs_master->lfs_nseg; segnum++, seg_addr +=
lfs_master->lfs_ssize << lfs_master->lfs_fsbtodb)
dump_segment(fd,
segnum, seg_addr, lfs_master, do_allsb);
(void)close(fd);
exit(0);
}
/*
* We are reading all the blocks of an inode and dumping out the ifile table.
* This code could be tighter, but this is a first pass at getting the stuff
* printed out rather than making this code incredibly efficient.
*/
static void
dump_ifile(fd, lfsp, do_ientries)
int fd;
struct lfs *lfsp;
int do_ientries;
{
IFILE *ipage;
struct dinode *dip, *dpage;
daddr_t addr, *addrp, *dindir, *iaddrp, *indir;
int block_limit, i, inum, j, nblocks, nsupb, psize;
psize = lfsp->lfs_bsize;
addr = lfsp->lfs_idaddr;
if (!(dpage = malloc(psize)))
err("%s", strerror(errno));
get(fd, addr << daddr_shift, dpage, psize);
for (dip = dpage + INOPB(lfsp) - 1; dip >= dpage; --dip)
if (dip->di_inumber == LFS_IFILE_INUM)
break;
if (dip < dpage)
err("unable to locate ifile inode");
(void)printf("\nIFILE inode\n");
dump_dinode(dip);
(void)printf("\nIFILE contents\n");
nblocks = dip->di_size >> lfsp->lfs_bshift;
block_limit = MIN(nblocks, NDADDR);
/* Get the direct block */
if ((ipage = malloc(psize)) == NULL)
err("%s", strerror(errno));
for (inum = 0, addrp = dip->di_db, i = 0; i < block_limit;
i++, addrp++) {
get(fd, *addrp << daddr_shift, ipage, psize);
if (i < lfsp->lfs_cleansz) {
dump_cleaner_info(lfsp, ipage);
print_suheader;
continue;
}
if (i < (lfsp->lfs_segtabsz + lfsp->lfs_cleansz)) {
inum = dump_ipage_segusage(lfsp, inum, ipage,
lfsp->lfs_sepb);
if (!inum)
if(!do_ientries)
goto e0;
else
print_iheader;
} else
inum = dump_ipage_ifile(inum, ipage, lfsp->lfs_ifpb);
}
if (nblocks <= NDADDR)
goto e0;
/* Dump out blocks off of single indirect block */
if (!(indir = malloc(psize)))
err("%s", strerror(errno));
get(fd, dip->di_ib[0] << daddr_shift, indir, psize);
block_limit = MIN(i + lfsp->lfs_nindir, nblocks);
for (addrp = indir; i < block_limit; i++, addrp++) {
if (*addrp == LFS_UNUSED_DADDR)
break;
get(fd, *addrp << daddr_shift,ipage, psize);
if (i < lfsp->lfs_cleansz) {
dump_cleaner_info(lfsp, ipage);
continue;
} else
i -= lfsp->lfs_cleansz;
if (i < lfsp->lfs_segtabsz) {
inum = dump_ipage_segusage(lfsp, inum, ipage,
lfsp->lfs_sepb);
if (!inum)
if(!do_ientries)
goto e1;
else
print_iheader;
} else
inum = dump_ipage_ifile(inum, ipage, lfsp->lfs_ifpb);
}
if (nblocks <= lfsp->lfs_nindir * lfsp->lfs_ifpb)
goto e1;
/* Get the double indirect block */
if (!(dindir = malloc(psize)))
err("%s", strerror(errno));
get(fd, dip->di_ib[1] << daddr_shift, dindir, psize);
for (iaddrp = dindir, j = 0; j < lfsp->lfs_nindir; j++, iaddrp++) {
if (*iaddrp == LFS_UNUSED_DADDR)
break;
get(fd, *iaddrp << daddr_shift, indir, psize);
block_limit = MIN(i + lfsp->lfs_nindir, nblocks);
for (addrp = indir; i < block_limit; i++, addrp++) {
if (*addrp == LFS_UNUSED_DADDR)
break;
get(fd, *addrp << daddr_shift, ipage, psize);
if (i < lfsp->lfs_cleansz) {
dump_cleaner_info(lfsp, ipage);
continue;
} else
i -= lfsp->lfs_cleansz;
if (i < lfsp->lfs_segtabsz) {
inum = dump_ipage_segusage(lfsp,
inum, ipage, lfsp->lfs_sepb);
if (!inum)
if(!do_ientries)
goto e2;
else
print_iheader;
} else
inum = dump_ipage_ifile(inum,
ipage, lfsp->lfs_ifpb);
}
}
e2: free(dindir);
e1: free(indir);
e0: free(dpage);
free(ipage);
}
static int
dump_ipage_ifile(i, pp, tot)
int i;
IFILE *pp;
int tot;
{
IFILE *ip;
int cnt, max;
max = i + tot;
for (ip = pp, cnt = i; cnt < max; cnt++, ip++)
print_ientry(cnt, ip);
return (max);
}
static int
dump_ipage_segusage(lfsp, i, pp, tot)
struct lfs *lfsp;
int i;
IFILE *pp;
int tot;
{
SEGUSE *sp;
int cnt, max;
max = i + tot;
for (sp = (SEGUSE *)pp, cnt = i;
cnt < lfsp->lfs_nseg && cnt < max; cnt++, sp++)
print_suentry(cnt, sp);
if (max >= lfsp->lfs_nseg)
return (0);
else
return (max);
}
static void
dump_dinode(dip)
struct dinode *dip;
{
int i;
(void)printf("%s%d\t%s%d\t%s%d\t%s%d\t%s%d\n",
"mode ", dip->di_mode,
"nlink ", dip->di_nlink,
"uid ", dip->di_uid,
"gid ", dip->di_gid,
"size ", dip->di_size);
(void)printf("%s%s%s%s%s%s",
"atime ", ctime(&dip->di_atime.ts_sec),
"mtime ", ctime(&dip->di_mtime.ts_sec),
"ctime ", ctime(&dip->di_ctime.ts_sec));
(void)printf("inum %d\n", dip->di_inumber);
(void)printf("Direct Addresses\n");
for (i = 0; i < NDADDR; i++) {
(void)printf("\t0x%X", dip->di_db[i]);
if ((i % 6) == 5)
(void)printf("\n");
}
for (i = 0; i < NIADDR; i++)
(void)printf("\t0x%X", dip->di_ib[i]);
(void)printf("\n");
}
static int
dump_sum(fd, lfsp, sp, segnum, addr)
struct lfs *lfsp;
SEGSUM *sp;
int fd, segnum;
daddr_t addr;
{
FINFO *fp;
long *dp;
int i, j;
int ck;
int numblocks;
struct dinode *inop;
if (sp->ss_sumsum != (ck = cksum(&sp->ss_datasum,
LFS_SUMMARY_SIZE - sizeof(sp->ss_sumsum)))) {
(void)printf("dumplfs: %s %d address 0x%lx\n",
"corrupt summary block; segment", segnum, addr);
return(0);
}
(void)printf("Segment Summary Info at 0x%lx\n", addr);
(void)printf(" %s0x%X\t%s%d\t%s%d\n %s0x%X\t%s0x%X",
"next ", sp->ss_next,
"nfinfo ", sp->ss_nfinfo,
"ninos ", sp->ss_ninos,
"sumsum ", sp->ss_sumsum,
"datasum ", sp->ss_datasum );
(void)printf("\tcreate %s", ctime((time_t *)&sp->ss_create));
numblocks = (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp);
/* Dump out inode disk addresses */
dp = (daddr_t *)sp;
dp += LFS_SUMMARY_SIZE / sizeof(daddr_t);
inop = malloc(1 << lfsp->lfs_bshift);
printf(" Inode addresses:");
for (dp--, i = 0; i < sp->ss_ninos; dp--) {
printf("\t0x%X {", *dp);
get(fd, *dp << (lfsp->lfs_bshift - lfsp->lfs_fsbtodb), inop,
(1 << lfsp->lfs_bshift));
for (j = 0; i < sp->ss_ninos && j < INOPB(lfsp); j++, i++) {
if (j > 0)
(void)printf(", ");
(void)printf("%d", inop[j].di_inumber);
}
(void)printf("}");
if (((i/INOPB(lfsp)) % 4) == 3)
(void)printf("\n");
}
free(inop);
printf("\n");
for (fp = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; i++) {
numblocks += fp->fi_nblocks;
(void)printf(" FINFO for inode: %d version %d nblocks %d\n",
fp->fi_ino, fp->fi_version, fp->fi_nblocks);
dp = &(fp->fi_blocks[0]);
for (j = 0; j < fp->fi_nblocks; j++, dp++) {
(void)printf("\t%d", *dp);
if ((j % 8) == 7)
(void)printf("\n");
}
if ((j % 8) != 0)
(void)printf("\n");
fp = (FINFO *)dp;
}
return (numblocks);
}
static void
dump_segment(fd, segnum, addr, lfsp, dump_sb)
int fd, segnum;
daddr_t addr;
struct lfs *lfsp;
int dump_sb;
{
struct lfs lfs_sb, *sbp;
SEGSUM *sump;
char sumblock[LFS_SUMMARY_SIZE];
int did_one, nblocks, sb;
off_t sum_offset, super_off;
(void)printf("\nSEGMENT %d (Disk Address 0x%X)\n",
addr >> (lfsp->lfs_segshift - daddr_shift), addr);
sum_offset = (addr << (lfsp->lfs_bshift - lfsp->lfs_fsbtodb));
sb = 0;
did_one = 0;
do {
get(fd, sum_offset, sumblock, LFS_SUMMARY_SIZE);
sump = (SEGSUM *)sumblock;
if (sump->ss_sumsum != cksum (&sump->ss_datasum,
LFS_SUMMARY_SIZE - sizeof(sump->ss_sumsum))) {
sbp = (struct lfs *)sump;
if (sb = (sbp->lfs_magic == LFS_MAGIC)) {
super_off = sum_offset;
sum_offset += LFS_SBPAD;
} else if (did_one)
break;
else {
printf("Segment at 0x%X corrupt\n", addr);
break;
}
} else {
nblocks = dump_sum(fd, lfsp, sump, segnum, sum_offset >>
(lfsp->lfs_bshift - lfsp->lfs_fsbtodb));
if (nblocks)
sum_offset += LFS_SUMMARY_SIZE +
(nblocks << lfsp->lfs_bshift);
else
sum_offset = 0;
did_one = 1;
}
} while (sum_offset);
if (dump_sb && sb) {
get(fd, super_off, &lfs_sb, sizeof(struct lfs));
dump_super(&lfs_sb);
}
return;
}
static void
dump_super(lfsp)
struct lfs *lfsp;
{
int i;
(void)printf("%s0x%X\t%s0x%X\t%s%d\t%s%d\n",
"magic ", lfsp->lfs_magic,
"version ", lfsp->lfs_version,
"size ", lfsp->lfs_size,
"ssize ", lfsp->lfs_ssize);
(void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n",
"dsize ", lfsp->lfs_dsize,
"bsize ", lfsp->lfs_bsize,
"fsize ", lfsp->lfs_fsize,
"frag ", lfsp->lfs_frag);
(void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n",
"minfree ", lfsp->lfs_minfree,
"inopb ", lfsp->lfs_inopb,
"ifpb ", lfsp->lfs_ifpb,
"nindir ", lfsp->lfs_nindir);
(void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n",
"nseg ", lfsp->lfs_nseg,
"nspf ", lfsp->lfs_nspf,
"cleansz ", lfsp->lfs_cleansz,
"segtabsz ", lfsp->lfs_segtabsz);
(void)printf("%s0x%X\t%s%d\t%s0x%X\t%s%d\n",
"segmask ", lfsp->lfs_segmask,
"segshift ", lfsp->lfs_segshift,
"bmask ", lfsp->lfs_bmask,
"bshift ", lfsp->lfs_bshift);
(void)printf("%s0x%X\t\t%s%d\t%s0x%X\t%s%d\n",
"ffmask ", lfsp->lfs_ffmask,
"ffshift ", lfsp->lfs_ffshift,
"fbmask ", lfsp->lfs_fbmask,
"fbshift ", lfsp->lfs_fbshift);
(void)printf("%s%d\t%s%d\t%s0x%X\t%s0x%qx\n",
"sushift ", lfsp->lfs_sushift,
"fsbtodb ", lfsp->lfs_fsbtodb,
"cksum ", lfsp->lfs_cksum,
"maxfilesize ", lfsp->lfs_maxfilesize);
(void)printf("Superblock disk addresses:\t");
for (i = 0; i < LFS_MAXNUMSB; i++) {
(void)printf(" 0x%X", lfsp->lfs_sboffs[i]);
if ( i == (LFS_MAXNUMSB >> 1))
(void)printf("\n\t\t\t\t");
}
(void)printf("\n");
(void)printf("Checkpoint Info\n");
(void)printf("%s%d\t%s0x%X\t%s%d\n",
"free ", lfsp->lfs_free,
"idaddr ", lfsp->lfs_idaddr,
"ifile ", lfsp->lfs_ifile);
(void)printf("%s%d\t%s%d\t%s%d\n",
"bfree ", lfsp->lfs_bfree,
"avail ", lfsp->lfs_avail,
"uinodes ", lfsp->lfs_uinodes);
(void)printf("%s%d\t%s0x%X\t%s0x%X\n%s0x%X\t%s0x%X\t",
"nfiles ", lfsp->lfs_nfiles,
"lastseg ", lfsp->lfs_lastseg,
"nextseg ", lfsp->lfs_nextseg,
"curseg ", lfsp->lfs_curseg,
"offset ", lfsp->lfs_offset);
(void)printf("tstamp %s", ctime((time_t *)&lfsp->lfs_tstamp));
(void)printf("\nIn-Memory Information\n");
(void)printf("%s%d\t%s0x%X\t%s%d%s%d\t%s%d\n",
"seglock ", lfsp->lfs_seglock,
"iocount ", lfsp->lfs_iocount,
"writer ", lfsp->lfs_writer,
"dirops ", lfsp->lfs_dirops,
"doifile ", lfsp->lfs_doifile);
(void)printf("%s%d\t%s%d\t%s0x%X\t%s%d\n",
"nactive ", lfsp->lfs_nactive,
"fmod ", lfsp->lfs_fmod,
"clean ", lfsp->lfs_clean,
"ronly ", lfsp->lfs_ronly);
}
static void
addseg(arg)
char *arg;
{
SEGLIST *p;
if ((p = malloc(sizeof(SEGLIST))) == NULL)
err("%s", strerror(errno));
p->next = seglist;
p->num = atoi(arg);
seglist = p;
}
static void
dump_cleaner_info(lfsp, ipage)
struct lfs *lfsp;
void *ipage;
{
CLEANERINFO *cip;
cip = (CLEANERINFO *)ipage;
(void)printf("segments clean\t%d\tsegments dirty\t%d\n\n",
cip->clean, cip->dirty);
}
static void
usage()
{
(void)fprintf(stderr, "usage: dumplfs [-ai] [-s segnum] file\n");
exit(1);
}

40
sbin/dumplfs/extern.h Normal file
View File

@ -0,0 +1,40 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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: @(#)extern.h 8.1 (Berkeley) 6/5/93
* $Id: extern.h,v 1.1 1994/06/08 18:58:51 mycroft Exp $
*/
void err __P((const char *, ...));
void get __P((int, off_t, void *, size_t));
extern char *special;

91
sbin/dumplfs/misc.c Normal file
View File

@ -0,0 +1,91 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)misc.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: misc.c,v 1.1 1994/06/08 18:58:52 mycroft Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "extern.h"
void
get(fd, off, p, len)
int fd;
off_t off;
void *p;
size_t len;
{
int rbytes;
if (lseek(fd, off, SEEK_SET) < 0)
err("%s: %s", special, strerror(errno));
if ((rbytes = read(fd, p, len)) < 0)
err("%s: %s", special, strerror(errno));
if (rbytes != len)
err("%s: short read (%d, not %d)", special, rbytes, len);
}
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
void
#if __STDC__
err(const char *fmt, ...)
#else
err(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
(void)fprintf(stderr, "dumplfs: ");
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
(void)fprintf(stderr, "\n");
exit(1);
/* NOTREACHED */
}

View File

@ -1,10 +1,10 @@
# from: @(#)Makefile 5.15 (Berkeley) 6/29/90
# $Id: Makefile,v 1.5 1993/08/01 05:37:50 mycroft Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/5/93
# $Id: Makefile,v 1.6 1994/06/08 19:00:18 mycroft Exp $
PROG= fsck
MAN8= fsck.0
SRCS= dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \
pass5.c preen.c setup.c utilities.c ufs_subr.c ufs_tables.c
.PATH: ${.CURDIR}/../../sys/ufs
pass5.c preen.c setup.c utilities.c ffs_subr.c ffs_tables.c
.PATH: ${.CURDIR}/../../sys/ufs/ffs
.include <bsd.prog.mk>

151
sbin/fsck/SMM.doc/0.t Normal file
View File

@ -0,0 +1,151 @@
.\" Copyright (c) 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)0.t 8.1 (Berkeley) 6/8/93
.\" $Id: 0.t,v 1.1 1994/06/08 19:00:49 mycroft Exp $
.\"
.if n .ND
.TL
Fsck \- The UNIX\(dg File System Check Program
.EH 'SMM:3-%''The \s-2UNIX\s+2 File System Check Program'
.OH 'The \s-2UNIX\s+2 File System Check Program''SMM:3-%'
.AU
Marshall Kirk McKusick
.AI
Computer Systems Research Group
Computer Science Division
Department of Electrical Engineering and Computer Science
University of California, Berkeley
Berkeley, CA 94720
.AU
T. J. Kowalski
.AI
Bell Laboratories
Murray Hill, New Jersey 07974
.AB
.FS
\(dgUNIX is a trademark of Bell Laboratories.
.FE
.FS
This work was done under grants from
the National Science Foundation under grant MCS80-05144,
and the Defense Advance Research Projects Agency (DoD) under
Arpa Order No. 4031 monitored by Naval Electronic System Command under
Contract No. N00039-82-C-0235.
.FE
This document reflects the use of
.I fsck
with the 4.2BSD and 4.3BSD file system organization. This
is a revision of the
original paper written by
T. J. Kowalski.
.PP
File System Check Program (\fIfsck\fR)
is an interactive file system check and repair program.
.I Fsck
uses the redundant structural information in the
UNIX file system to perform several consistency checks.
If an inconsistency is detected, it is reported
to the operator, who may elect to fix or ignore
each inconsistency.
These inconsistencies result from the permanent interruption
of the file system updates, which are performed every
time a file is modified.
Unless there has been a hardware failure,
.I fsck
is able to repair corrupted file systems
using procedures based upon the order in which UNIX honors
these file system update requests.
.PP
The purpose of this document is to describe the normal updating
of the file system,
to discuss the possible causes of file system corruption,
and to present the corrective actions implemented
by
.I fsck.
Both the program and the interaction between the
program and the operator are described.
.sp 2
.LP
Revised July 16, 1985
.AE
.LP
.bp
.ce
.B "TABLE OF CONTENTS"
.LP
.sp 1
.nf
.B "1. Introduction"
.LP
.sp .5v
.nf
.B "2. Overview of the file system
2.1. Superblock
2.2. Summary Information
2.3. Cylinder groups
2.4. Fragments
2.5. Updates to the file system
.LP
.sp .5v
.nf
.B "3. Fixing corrupted file systems
3.1. Detecting and correcting corruption
3.2. Super block checking
3.3. Free block checking
3.4. Checking the inode state
3.5. Inode links
3.6. Inode data size
3.7. Checking the data associated with an inode
3.8. File system connectivity
.LP
.sp .5v
.nf
.B Acknowledgements
.LP
.sp .5v
.nf
.B References
.LP
.sp .5v
.nf
.B "4. Appendix A
4.1. Conventions
4.2. Initialization
4.3. Phase 1 - Check Blocks and Sizes
4.4. Phase 1b - Rescan for more Dups
4.5. Phase 2 - Check Pathnames
4.6. Phase 3 - Check Connectivity
4.7. Phase 4 - Check Reference Counts
4.8. Phase 5 - Check Cyl groups
4.9. Cleanup
.ds RH Introduction
.bp

84
sbin/fsck/SMM.doc/1.t Normal file
View File

@ -0,0 +1,84 @@
.\" Copyright (c) 1982, 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)1.t 8.1 (Berkeley) 6/5/93
.\" $Id: 1.t,v 1.1 1994/06/08 19:01:21 mycroft Exp $
.\"
.ds RH Introduction
.NH
Introduction
.PP
This document reflects the use of
.I fsck
with the 4.2BSD and 4.3BSD file system organization. This
is a revision of the
original paper written by
T. J. Kowalski.
.PP
When a UNIX
operating system is brought up, a consistency
check of the file systems should always be performed.
This precautionary measure helps to insure
a reliable environment for file storage on disk.
If an inconsistency is discovered,
corrective action must be taken.
.I Fsck
runs in two modes.
Normally it is run non-interactively by the system after
a normal boot.
When running in this mode,
it will only make changes to the file system that are known
to always be correct.
If an unexpected inconsistency is found
.I fsck
will exit with a non-zero exit status,
leaving the system running single-user.
Typically the operator then runs
.I fsck
interactively.
When running in this mode,
each problem is listed followed by a suggested corrective action.
The operator must decide whether or not the suggested correction
should be made.
.PP
The purpose of this memo is to dispel the
mystique surrounding
file system inconsistencies.
It first describes the updating of the file system
(the calm before the storm) and
then describes file system corruption (the storm).
Finally,
the set of deterministic corrective actions
used by
.I fsck
(the Coast Guard
to the rescue) is presented.
.ds RH Overview of the File System

266
sbin/fsck/SMM.doc/2.t Normal file
View File

@ -0,0 +1,266 @@
.\" Copyright (c) 1982, 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)2.t 8.1 (Berkeley) 6/5/93
.\" $Id: 2.t,v 1.1 1994/06/08 19:01:22 mycroft Exp $
.\"
.ds RH Overview of the file system
.NH
Overview of the file system
.PP
The file system is discussed in detail in [Mckusick84];
this section gives a brief overview.
.NH 2
Superblock
.PP
A file system is described by its
.I "super-block" .
The super-block is built when the file system is created (\c
.I newfs (8))
and never changes.
The super-block
contains the basic parameters of the file system,
such as the number of data blocks it contains
and a count of the maximum number of files.
Because the super-block contains critical data,
.I newfs
replicates it to protect against catastrophic loss.
The
.I "default super block"
always resides at a fixed offset from the beginning
of the file system's disk partition.
The
.I "redundant super blocks"
are not referenced unless a head crash
or other hard disk error causes the default super-block
to be unusable.
The redundant blocks are sprinkled throughout the disk partition.
.PP
Within the file system are files.
Certain files are distinguished as directories and contain collections
of pointers to files that may themselves be directories.
Every file has a descriptor associated with it called an
.I "inode".
The inode contains information describing ownership of the file,
time stamps indicating modification and access times for the file,
and an array of indices pointing to the data blocks for the file.
In this section,
we assume that the first 12 blocks
of the file are directly referenced by values stored
in the inode structure itself\(dg.
.FS
\(dgThe actual number may vary from system to system, but is usually in
the range 5-13.
.FE
The inode structure may also contain references to indirect blocks
containing further data block indices.
In a file system with a 4096 byte block size, a singly indirect
block contains 1024 further block addresses,
a doubly indirect block contains 1024 addresses of further single indirect
blocks,
and a triply indirect block contains 1024 addresses of further doubly indirect
blocks (the triple indirect block is never needed in practice).
.PP
In order to create files with up to
2\(ua32 bytes,
using only two levels of indirection,
the minimum size of a file system block is 4096 bytes.
The size of file system blocks can be any power of two
greater than or equal to 4096.
The block size of the file system is maintained in the super-block,
so it is possible for file systems of different block sizes
to be accessible simultaneously on the same system.
The block size must be decided when
.I newfs
creates the file system;
the block size cannot be subsequently
changed without rebuilding the file system.
.NH 2
Summary information
.PP
Associated with the super block is non replicated
.I "summary information" .
The summary information changes
as the file system is modified.
The summary information contains
the number of blocks, fragments, inodes and directories in the file system.
.NH 2
Cylinder groups
.PP
The file system partitions the disk into one or more areas called
.I "cylinder groups".
A cylinder group is comprised of one or more consecutive
cylinders on a disk.
Each cylinder group includes inode slots for files, a
.I "block map"
describing available blocks in the cylinder group,
and summary information describing the usage of data blocks
within the cylinder group.
A fixed number of inodes is allocated for each cylinder group
when the file system is created.
The current policy is to allocate one inode for each 2048
bytes of disk space;
this is expected to be far more inodes than will ever be needed.
.PP
All the cylinder group bookkeeping information could be
placed at the beginning of each cylinder group.
However if this approach were used,
all the redundant information would be on the top platter.
A single hardware failure that destroyed the top platter
could cause the loss of all copies of the redundant super-blocks.
Thus the cylinder group bookkeeping information
begins at a floating offset from the beginning of the cylinder group.
The offset for
the
.I "i+1" st
cylinder group is about one track further
from the beginning of the cylinder group
than it was for the
.I "i" th
cylinder group.
In this way,
the redundant
information spirals down into the pack;
any single track, cylinder,
or platter can be lost without losing all copies of the super-blocks.
Except for the first cylinder group,
the space between the beginning of the cylinder group
and the beginning of the cylinder group information stores data.
.NH 2
Fragments
.PP
To avoid waste in storing small files,
the file system space allocator divides a single
file system block into one or more
.I "fragments".
The fragmentation of the file system is specified
when the file system is created;
each file system block can be optionally broken into
2, 4, or 8 addressable fragments.
The lower bound on the size of these fragments is constrained
by the disk sector size;
typically 512 bytes is the lower bound on fragment size.
The block map associated with each cylinder group
records the space availability at the fragment level.
Aligned fragments are examined
to determine block availability.
.PP
On a file system with a block size of 4096 bytes
and a fragment size of 1024 bytes,
a file is represented by zero or more 4096 byte blocks of data,
and possibly a single fragmented block.
If a file system block must be fragmented to obtain
space for a small amount of data,
the remainder of the block is made available for allocation
to other files.
For example,
consider an 11000 byte file stored on
a 4096/1024 byte file system.
This file uses two full size blocks and a 3072 byte fragment.
If no fragments with at least 3072 bytes
are available when the file is created,
a full size block is split yielding the necessary 3072 byte
fragment and an unused 1024 byte fragment.
This remaining fragment can be allocated to another file, as needed.
.NH 2
Updates to the file system
.PP
Every working day hundreds of files
are created, modified, and removed.
Every time a file is modified,
the operating system performs a
series of file system updates.
These updates, when written on disk, yield a consistent file system.
The file system stages
all modifications of critical information;
modification can
either be completed or cleanly backed out after a crash.
Knowing the information that is first written to the file system,
deterministic procedures can be developed to
repair a corrupted file system.
To understand this process,
the order that the update
requests were being honored must first be understood.
.PP
When a user program does an operation to change the file system,
such as a
.I write ,
the data to be written is copied into an internal
.I "in-core"
buffer in the kernel.
Normally, the disk update is handled asynchronously;
the user process is allowed to proceed even though
the data has not yet been written to the disk.
The data,
along with the inode information reflecting the change,
is eventually written out to disk.
The real disk write may not happen until long after the
.I write
system call has returned.
Thus at any given time, the file system,
as it resides on the disk,
lags the state of the file system represented by the in-core information.
.PP
The disk information is updated to reflect the in-core information
when the buffer is required for another use,
when a
.I sync (2)
is done (at 30 second intervals) by
.I "/etc/update" "(8),"
or by manual operator intervention with the
.I sync (8)
command.
If the system is halted without writing out the in-core information,
the file system on the disk will be in an inconsistent state.
.PP
If all updates are done asynchronously, several serious
inconsistencies can arise.
One inconsistency is that a block may be claimed by two inodes.
Such an inconsistency can occur when the system is halted before
the pointer to the block in the old inode has been cleared
in the copy of the old inode on the disk,
and after the pointer to the block in the new inode has been written out
to the copy of the new inode on the disk.
Here,
there is no deterministic method for deciding
which inode should really claim the block.
A similar problem can arise with a multiply claimed inode.
.PP
The problem with asynchronous inode updates
can be avoided by doing all inode deallocations synchronously.
Consequently,
inodes and indirect blocks are written to the disk synchronously
(\fIi.e.\fP the process blocks until the information is
really written to disk)
when they are being deallocated.
Similarly inodes are kept consistent by synchronously
deleting, adding, or changing directory entries.
.ds RH Fixing corrupted file systems

440
sbin/fsck/SMM.doc/3.t Normal file
View File

@ -0,0 +1,440 @@
.\" Copyright (c) 1982, 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)3.t 8.1 (Berkeley) 6/5/93
.\" $Id: 3.t,v 1.1 1994/06/08 19:01:23 mycroft Exp $
.\"
.ds RH Fixing corrupted file systems
.NH
Fixing corrupted file systems
.PP
A file system
can become corrupted in several ways.
The most common of these ways are
improper shutdown procedures
and hardware failures.
.PP
File systems may become corrupted during an
.I "unclean halt" .
This happens when proper shutdown
procedures are not observed,
physically write-protecting a mounted file system,
or a mounted file system is taken off-line.
The most common operator procedural failure is forgetting to
.I sync
the system before halting the CPU.
.PP
File systems may become further corrupted if proper startup
procedures are not observed, e.g.,
not checking a file system for inconsistencies,
and not repairing inconsistencies.
Allowing a corrupted file system to be used (and, thus, to be modified
further) can be disastrous.
.PP
Any piece of hardware can fail at any time.
Failures
can be as subtle as a bad block
on a disk pack, or as blatant as a non-functional disk-controller.
.NH 2
Detecting and correcting corruption
.PP
Normally
.I fsck
is run non-interactively.
In this mode it will only fix
corruptions that are expected to occur from an unclean halt.
These actions are a proper subset of the actions that
.I fsck
will take when it is running interactively.
Throughout this paper we assume that
.I fsck
is being run interactively,
and all possible errors can be encountered.
When an inconsistency is discovered in this mode,
.I fsck
reports the inconsistency for the operator to
chose a corrective action.
.PP
A quiescent\(dd
.FS
\(dd I.e., unmounted and not being written on.
.FE
file system may be checked for structural integrity
by performing consistency checks on the
redundant data intrinsic to a file system.
The redundant data is either read from
the file system,
or computed from other known values.
The file system
.B must
be in a quiescent state when
.I fsck
is run,
since
.I fsck
is a multi-pass program.
.PP
In the following sections,
we discuss methods to discover inconsistencies
and possible corrective actions
for the cylinder group blocks, the inodes, the indirect blocks, and
the data blocks containing directory entries.
.NH 2
Super-block checking
.PP
The most commonly corrupted item in a file system
is the summary information
associated with the super-block.
The summary information is prone to corruption
because it is modified with every change to the file
system's blocks or inodes,
and is usually corrupted
after an unclean halt.
.PP
The super-block is checked for inconsistencies
involving file-system size, number of inodes,
free-block count, and the free-inode count.
The file-system size must be larger than the
number of blocks used by the super-block
and the number of blocks used by the list of inodes.
The file-system size and layout information
are the most critical pieces of information for
.I fsck .
While there is no way to actually check these sizes,
since they are statically determined by
.I newfs ,
.I fsck
can check that these sizes are within reasonable bounds.
All other file system checks require that these sizes be correct.
If
.I fsck
detects corruption in the static parameters of the default super-block,
.I fsck
requests the operator to specify the location of an alternate super-block.
.NH 2
Free block checking
.PP
.I Fsck
checks that all the blocks
marked as free in the cylinder group block maps
are not claimed by any files.
When all the blocks have been initially accounted for,
.I fsck
checks that
the number of free blocks
plus the number of blocks claimed by the inodes
equals the total number of blocks in the file system.
.PP
If anything is wrong with the block allocation maps,
.I fsck
will rebuild them,
based on the list it has computed of allocated blocks.
.PP
The summary information associated with the super-block
counts the total number of free blocks within the file system.
.I Fsck
compares this count to the
number of free blocks it found within the file system.
If the two counts do not agree, then
.I fsck
replaces the incorrect count in the summary information
by the actual free-block count.
.PP
The summary information
counts the total number of free inodes within the file system.
.I Fsck
compares this count to the number
of free inodes it found within the file system.
If the two counts do not agree, then
.I fsck
replaces the incorrect count in the
summary information by the actual free-inode count.
.NH 2
Checking the inode state
.PP
An individual inode is not as likely to be corrupted as
the allocation information.
However, because of the great number of active inodes,
a few of the inodes are usually corrupted.
.PP
The list of inodes in the file system
is checked sequentially starting with inode 2
(inode 0 marks unused inodes;
inode 1 is saved for future generations)
and progressing through the last inode in the file system.
The state of each inode is checked for
inconsistencies involving format and type,
link count,
duplicate blocks,
bad blocks,
and inode size.
.PP
Each inode contains a mode word.
This mode word describes the type and state of the inode.
Inodes must be one of six types:
regular inode, directory inode, symbolic link inode,
special block inode, special character inode, or socket inode.
Inodes may be found in one of three allocation states:
unallocated, allocated, and neither unallocated nor allocated.
This last state suggests an incorrectly formated inode.
An inode can get in this state if
bad data is written into the inode list.
The only possible corrective action is for
.I fsck
is to clear the inode.
.NH 2
Inode links
.PP
Each inode counts the
total number of directory entries
linked to the inode.
.I Fsck
verifies the link count of each inode
by starting at the root of the file system,
and descending through the directory structure.
The actual link count for each inode
is calculated during the descent.
.PP
If the stored link count is non-zero and the actual
link count is zero,
then no directory entry appears for the inode.
If this happens,
.I fsck
will place the disconnected file in the
.I lost+found
directory.
If the stored and actual link counts are non-zero and unequal,
a directory entry may have been added or removed without the inode being
updated.
If this happens,
.I fsck
replaces the incorrect stored link count by the actual link count.
.PP
Each inode contains a list,
or pointers to
lists (indirect blocks),
of all the blocks claimed by the inode.
Since indirect blocks are owned by an inode,
inconsistencies in indirect blocks directly
affect the inode that owns it.
.PP
.I Fsck
compares each block number claimed by an inode
against a list of already allocated blocks.
If another inode already claims a block number,
then the block number is added to a list of
.I "duplicate blocks" .
Otherwise, the list of allocated blocks
is updated to include the block number.
.PP
If there are any duplicate blocks,
.I fsck
will perform a partial second
pass over the inode list
to find the inode of the duplicated block.
The second pass is needed,
since without examining the files associated with
these inodes for correct content,
not enough information is available
to determine which inode is corrupted and should be cleared.
If this condition does arise
(only hardware failure will cause it),
then the inode with the earliest
modify time is usually incorrect,
and should be cleared.
If this happens,
.I fsck
prompts the operator to clear both inodes.
The operator must decide which one should be kept
and which one should be cleared.
.PP
.I Fsck
checks the range of each block number claimed by an inode.
If the block number is
lower than the first data block in the file system,
or greater than the last data block,
then the block number is a
.I "bad block number" .
Many bad blocks in an inode are usually caused by
an indirect block that was not written to the file system,
a condition which can only occur if there has been a hardware failure.
If an inode contains bad block numbers,
.I fsck
prompts the operator to clear it.
.NH 2
Inode data size
.PP
Each inode contains a count of the number of data blocks
that it contains.
The number of actual data blocks
is the sum of the allocated data blocks
and the indirect blocks.
.I Fsck
computes the actual number of data blocks
and compares that block count against
the actual number of blocks the inode claims.
If an inode contains an incorrect count
.I fsck
prompts the operator to fix it.
.PP
Each inode contains a thirty-two bit size field.
The size is the number of data bytes
in the file associated with the inode.
The consistency of the byte size field is roughly checked
by computing from the size field the maximum number of blocks
that should be associated with the inode,
and comparing that expected block count against
the actual number of blocks the inode claims.
.NH 2
Checking the data associated with an inode
.PP
An inode can directly or indirectly
reference three kinds of data blocks.
All referenced blocks must be the same kind.
The three types of data blocks are:
plain data blocks, symbolic link data blocks, and directory data blocks.
Plain data blocks
contain the information stored in a file;
symbolic link data blocks
contain the path name stored in a link.
Directory data blocks contain directory entries.
.I Fsck
can only check the validity of directory data blocks.
.PP
Each directory data block is checked for
several types of inconsistencies.
These inconsistencies include
directory inode numbers pointing to unallocated inodes,
directory inode numbers that are greater than
the number of inodes in the file system,
incorrect directory inode numbers for ``\fB.\fP'' and ``\fB..\fP'',
and directories that are not attached to the file system.
If the inode number in a directory data block
references an unallocated inode,
then
.I fsck
will remove that directory entry.
Again,
this condition can only arise when there has been a hardware failure.
.PP
If a directory entry inode number references
outside the inode list, then
.I fsck
will remove that directory entry.
This condition occurs if bad data is written into a directory data block.
.PP
The directory inode number entry for ``\fB.\fP''
must be the first entry in the directory data block.
The inode number for ``\fB.\fP''
must reference itself;
e.g., it must equal the inode number
for the directory data block.
The directory inode number entry
for ``\fB..\fP'' must be
the second entry in the directory data block.
Its value must equal the inode number for the
parent of the directory entry
(or the inode number of the directory
data block if the directory is the
root directory).
If the directory inode numbers are
incorrect,
.I fsck
will replace them with the correct values.
If there are multiple hard links to a directory,
the first one encountered is considered the real parent
to which ``\fB..\fP'' should point;
\fIfsck\fP recommends deletion for the subsequently discovered names.
.NH 2
File system connectivity
.PP
.I Fsck
checks the general connectivity of the file system.
If directories are not linked into the file system, then
.I fsck
links the directory back into the file system in the
.I lost+found
directory.
This condition only occurs when there has been a hardware failure.
.ds RH "References"
.SH
\s+2Acknowledgements\s0
.PP
I thank Bill Joy, Sam Leffler, Robert Elz and Dennis Ritchie
for their suggestions and help in implementing the new file system.
Thanks also to Robert Henry for his editorial input to
get this document together.
Finally we thank our sponsors,
the National Science Foundation under grant MCS80-05144,
and the Defense Advance Research Projects Agency (DoD) under
Arpa Order No. 4031 monitored by Naval Electronic System Command under
Contract No. N00039-82-C-0235. (Kirk McKusick, July 1983)
.PP
I would like to thank Larry A. Wehr for advice that lead
to the first version of
.I fsck
and Rick B. Brandt for adapting
.I fsck
to
UNIX/TS. (T. Kowalski, July 1979)
.sp 2
.SH
\s+2References\s0
.LP
.IP [Dolotta78] 20
Dolotta, T. A., and Olsson, S. B. eds.,
.I "UNIX User's Manual, Edition 1.1\^" ,
January 1978.
.IP [Joy83] 20
Joy, W., Cooper, E., Fabry, R., Leffler, S., McKusick, M., and Mosher, D.
4.2BSD System Manual,
.I "University of California at Berkeley" ,
.I "Computer Systems Research Group Technical Report"
#4, 1982.
.IP [McKusick84] 20
McKusick, M., Joy, W., Leffler, S., and Fabry, R.
A Fast File System for UNIX,
\fIACM Transactions on Computer Systems 2\fP, 3.
pp. 181-197, August 1984.
.IP [Ritchie78] 20
Ritchie, D. M., and Thompson, K.,
The UNIX Time-Sharing System,
.I "The Bell System Technical Journal"
.B 57 ,
6 (July-August 1978, Part 2), pp. 1905-29.
.IP [Thompson78] 20
Thompson, K.,
UNIX Implementation,
.I "The Bell System Technical Journal\^"
.B 57 ,
6 (July-August 1978, Part 2), pp. 1931-46.
.ds RH Appendix A \- Fsck Error Conditions
.bp

1425
sbin/fsck/SMM.doc/4.t Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/8/93
# $Id: Makefile,v 1.1 1994/06/08 19:01:26 mycroft Exp $
DIR= smm/03.fsck
SRCS= 0.t 1.t 2.t 3.t 4.t
MACROS= -ms
.include <bsd.doc.mk>

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,18 +32,15 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)dir.c 5.19 (Berkeley) 7/26/91";*/
static char rcsid[] = "$Id: dir.c,v 1.6 1994/04/25 18:28:20 cgd Exp $";
/*static char sccsid[] = "from: @(#)dir.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: dir.c,v 1.7 1994/06/08 19:00:19 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#define KERNEL
#include <ufs/dir.h>
#undef KERNEL
#include <stddef.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <stdlib.h>
#include <string.h>
#include "fsck.h"
@ -51,7 +48,14 @@ static char rcsid[] = "$Id: dir.c,v 1.6 1994/04/25 18:28:20 cgd Exp $";
char *lfname = "lost+found";
int lfmode = 01777;
struct dirtemplate emptydir = { 0, DIRBLKSIZ };
struct dirtemplate dirhead = { 0, 12, 1, ".", 0, DIRBLKSIZ - 12, 2, ".." };
struct dirtemplate dirhead = {
0, 12, DT_DIR, 1, ".",
0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
};
struct odirtemplate odirhead = {
0, 12, 1, ".",
0, DIRBLKSIZ - 12, 2, ".."
};
struct direct *fsck_readdir();
struct bufarea *getdirblk();
@ -107,8 +111,29 @@ dirscan(idesc)
for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
dsize = dp->d_reclen;
bcopy((char *)dp, dbuf, (size_t)dsize);
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt) {
struct direct *tdp = (struct direct *)dbuf;
u_char tmp;
tmp = tdp->d_namlen;
tdp->d_namlen = tdp->d_type;
tdp->d_type = tmp;
}
# endif
idesc->id_dirp = (struct direct *)dbuf;
if ((n = (*idesc->id_func)(idesc)) & ALTERED) {
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt && !doinglevel2) {
struct direct *tdp;
u_char tmp;
tdp = (struct direct *)dbuf;
tmp = tdp->d_namlen;
tdp->d_namlen = tdp->d_type;
tdp->d_type = tmp;
}
# endif
bp = getdirblk(idesc->id_blkno, blksiz);
bcopy(dbuf, bp->b_un.b_buf + idesc->id_loc - dsize,
(size_t)dsize);
@ -130,39 +155,34 @@ fsck_readdir(idesc)
{
register struct direct *dp, *ndp;
register struct bufarea *bp;
long blksiz, new_id_filesize;
int fix, new_id_loc, new_reclen, orig_id_loc, size;
long size, blksiz, fix, dploc;
blksiz = idesc->id_numfrags * sblock.fs_fsize;
bp = getdirblk(idesc->id_blkno, blksiz);
orig_id_loc = idesc->id_loc;
if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 &&
idesc->id_loc < blksiz) {
dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
if (dircheck(idesc, dp))
goto dpok;
/*
* See below about recursion.
*/
new_id_loc = idesc->id_loc + DIRBLKSIZ;
new_id_filesize = idesc->id_filesize - DIRBLKSIZ;
fix = dofix(idesc, "DIRECTORY CORRUPTED");
idesc->id_loc = new_id_loc;
idesc->id_filesize = new_id_filesize;
bp = getdirblk(idesc->id_blkno, blksiz);
dp = (struct direct *)(bp->b_un.b_buf + orig_id_loc);
dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
dp->d_reclen = DIRBLKSIZ;
dp->d_ino = 0;
dp->d_type = 0;
dp->d_namlen = 0;
dp->d_name[0] = '\0';
if (fix)
dirty(bp);
idesc->id_loc += DIRBLKSIZ;
idesc->id_filesize -= DIRBLKSIZ;
return (dp);
}
dpok:
if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz)
return NULL;
dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
dploc = idesc->id_loc;
dp = (struct direct *)(bp->b_un.b_buf + dploc);
idesc->id_loc += dp->d_reclen;
idesc->id_filesize -= dp->d_reclen;
if ((idesc->id_loc % DIRBLKSIZ) == 0)
@ -171,23 +191,12 @@ dpok:
if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
dircheck(idesc, ndp) == 0) {
size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
/*
* dofix() may recurse here. Don't let it cause multiple
* fixups.
*/
new_id_loc = idesc->id_loc + size;
new_id_filesize = idesc->id_filesize - size;
new_reclen = dp->d_reclen + size;
idesc->id_loc += size;
idesc->id_filesize -= size;
fix = dofix(idesc, "DIRECTORY CORRUPTED");
idesc->id_loc = new_id_loc;
idesc->id_filesize = new_id_filesize;
/*
* dofix() calls fsck_readdir() and getdirblk() discards
* the lock on bp so bp may now be invalid.
*/
bp = getdirblk(idesc->id_blkno, blksiz);
dp = (struct direct *)(bp->b_un.b_buf + orig_id_loc);
dp->d_reclen = new_reclen;
dp = (struct direct *)(bp->b_un.b_buf + dploc);
dp->d_reclen += size;
if (fix)
dirty(bp);
}
@ -204,22 +213,34 @@ dircheck(idesc, dp)
{
register int size;
register char *cp;
u_char namlen, type;
int spaceleft;
size = DIRSIZ(!newinofmt, dp);
spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
if (spaceleft < offsetof(struct direct, d_name))
return (0); /* dp is bad; don't use it */
size = DIRSIZ(dp);
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt) {
type = dp->d_namlen;
namlen = dp->d_type;
} else {
namlen = dp->d_namlen;
type = dp->d_type;
}
# else
namlen = dp->d_namlen;
type = dp->d_type;
# endif
if (dp->d_ino < maxino &&
dp->d_reclen != 0 &&
dp->d_reclen <= spaceleft &&
(dp->d_reclen & 0x3) == 0 &&
dp->d_reclen >= size &&
idesc->id_filesize >= size &&
dp->d_namlen <= MAXNAMLEN) {
namlen <= MAXNAMLEN &&
type <= 15) {
if (dp->d_ino == 0)
return (1);
for (cp = dp->d_name, size = 0; size < dp->d_namlen; size++)
for (cp = dp->d_name, size = 0; size < namlen; size++)
if (*cp == 0 || (*cp++ == '/'))
return (0);
if (*cp == 0)
@ -297,9 +318,9 @@ mkentry(idesc)
int newlen, oldlen;
newent.d_namlen = strlen(idesc->id_name);
newlen = DIRSIZ(&newent);
newlen = DIRSIZ(0, &newent);
if (dirp->d_ino != 0)
oldlen = DIRSIZ(dirp);
oldlen = DIRSIZ(0, dirp);
else
oldlen = 0;
if (dirp->d_reclen - oldlen < newlen)
@ -308,6 +329,10 @@ mkentry(idesc)
dirp->d_reclen = oldlen;
dirp = (struct direct *)(((char *)dirp) + oldlen);
dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */
if (newinofmt)
dirp->d_type = typemap[idesc->id_parent];
else
dirp->d_type = 0;
dirp->d_reclen = newent.d_reclen;
dirp->d_namlen = newent.d_namlen;
bcopy(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1);
@ -322,6 +347,10 @@ chgino(idesc)
if (bcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1))
return (KEEPON);
dirp->d_ino = idesc->id_parent;
if (newinofmt)
dirp->d_type = typemap[idesc->id_parent];
else
dirp->d_type = 0;
return (ALTERED|STOP);
}
@ -551,17 +580,22 @@ allocdir(parent, request, mode)
char *cp;
struct dinode *dp;
register struct bufarea *bp;
struct dirtemplate *dirp;
ino = allocino(request, IFDIR|mode);
dirhead.dot_ino = ino;
dirhead.dotdot_ino = parent;
if (newinofmt)
dirp = &dirhead;
else
dirp = (struct dirtemplate *)&odirhead;
dirp->dot_ino = ino;
dirp->dotdot_ino = parent;
dp = ginode(ino);
bp = getdirblk(dp->di_db[0], sblock.fs_fsize);
if (bp->b_errs) {
freeino(ino);
return (0);
}
bcopy((char *)&dirhead, bp->b_un.b_buf, sizeof dirhead);
bcopy((char *)dirp, bp->b_un.b_buf, sizeof(struct dirtemplate));
for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
cp < &bp->b_un.b_buf[sblock.fs_fsize];
cp += DIRBLKSIZ)

View File

@ -1,5 +1,5 @@
.\" Copyright (c) 1980, 1989 Regents of the University of California.
.\" All rights reserved.
.\" 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
@ -29,33 +29,32 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)fsck.8 6.9 (Berkeley) 4/20/91
.\" $Id: fsck.8,v 1.6 1994/04/13 10:12:33 deraadt Exp $
.\" from: @(#)fsck.8 8.2 (Berkeley) 12/11/93
.\" $Id: fsck.8,v 1.7 1994/06/08 19:00:20 mycroft Exp $
.\"
.Dd April 20, 1991
.Dd December 11, 1993
.Dt FSCK 8
.Os BSD 4.2
.de us
\\$1\l'|0\(ul'
..
.Os BSD 4
.Sh NAME
.Nm fsck
.Nd file system consistency check and interactive repair
.Nm fsck
.Nd filesystem consistency check and interactive repair
.Sh SYNOPSIS
.Nm fsck
.Fl p
.Op Fl m Ar mode
.Nm fsck
.Op Fl b Ar block#
.Op Fl c
.Op Fl c Ar level
.Op Fl l Ar maxparallel
.Op Fl y
.Op Fl n
.Op Fl m Ar mode
.Op Ar filesystem ...
.Op Ar filesystem
.Ar ...
.Sh DESCRIPTION
The first form of
.Nm fsck
preens a standard set of filesystems or the specified file systems.
preens a standard set of filesystems or the specified filesystems.
It is normally used in the script
.Pa /etc/rc
during automatic reboot.
@ -63,12 +62,8 @@ Here
.Nm fsck
reads the table
.Pa /etc/fstab
to determine which file systems to check.
Only partitions in fstab that are mounted
.Dq rw ,
.Dq rq
or
.Dq ro
to determine which filesystems to check.
Only partitions in fstab that are mounted ``rw,'' ``rq'' or ``ro''
and that have non-zero pass number are checked.
Filesystems with pass number 1 (normally just the root filesystem)
are checked one at a time.
@ -78,10 +73,10 @@ The disk drive containing each filesystem 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 system takes care that only a restricted class of innocuous
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:
.Bl -item -offset indent
.Bl -item -compact
.It
Unreferenced inodes
.It
@ -101,27 +96,29 @@ with the
option will correct; if it encounters other inconsistencies, it exits
with an abnormal return status and an automatic reboot will then fail.
For each corrected inconsistency one or more lines will be printed
identifying the file system on which the correction will take place,
and the nature of the correction. After successfully correcting a file
system,
identifying the filesystem on which the correction will take place,
and the nature of the correction. After successfully correcting a filesystem,
.Nm fsck
will print the number of files on that file system,
will print the number of files on that filesystem,
the number of used and free blocks,
and the percentage of fragmentation.
.Pp
If sent a QUIT signal,
If sent a
.Dv QUIT
signal,
.Nm fsck
will finish the file system checks, then exit with an abnormal
will finish the filesystem checks, then exit with an abnormal
return status that causes an automatic reboot to fail.
This is useful when to finish the file system checks during an automatic reboot,
This is useful when you want to finish the filesystem checks during an
automatic reboot,
but do not want the machine to come up multiuser after the checks complete.
.Pp
Without the
.Fl p
option,
.Nm fsck
audits and interactively repairs inconsistent conditions for file systems.
If the file system is inconsistent the operator is prompted for concurrence
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
@ -130,11 +127,11 @@ 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
.Ic yes
is to wait for the operator to respond
.Li yes
or
.Ic no .
If the operator does not have write permission on the file system
.Li no .
If the operator does not have write permission on the filesystem
.Nm fsck
will default to a
.Fl n
@ -143,19 +140,17 @@ action.
.Nm Fsck
has more consistency checks than
its predecessors
.Nm check ,
.Nm dcheck ,
.Nm fcheck ,
.Em check , dcheck , fcheck ,
and
.Nm icheck
.Em icheck
combined.
.Pp
The following flags are interpreted by
.Nm fsck.
.Nm fsck .
.Bl -tag -width indent
.It Fl b
Use the block specified immediately after the flag as
the super block for the file system. Block 32 is usually
the super block for the filesystem. Block 32 is usually
an alternate super block.
.It Fl l
Limit the number of parallel checks to the number specified in the following
@ -165,8 +160,9 @@ If a smaller limit is given, the disks are checked round-robin, one filesystem
at a time.
.It Fl m
Use the mode specified in octal immediately after the flag as the
permission bits to use when creating the lost+found directory
rather than the default 1777.
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.
@ -178,50 +174,60 @@ to continue after essentially unlimited trouble has been encountered.
.It Fl n
Assume a no response to all questions asked by
.Nm fsck
except for
.Dq CONTINUE? ,
which is assumed to be affirmative; do not open the file system for writing.
except for
.Ql CONTINUE? ,
which is assumed to be affirmative;
do not open the filesystem for writing.
.It Fl c
If the file system is in the old (static table) format,
convert it to the new (dynamic table) format.
If the file system is in the new format,
convert it to the old format provided the old format
can support the filesystem configuration.
Convert the filesystem to the specified level.
Note that the level of a filesystem can only be raised.
.Bl -tag -width indent
There are currently three levels defined:
.It 0
The filesystem is in the old (static table) format.
.It 1
The filesystem is in the new (dynamic table) format.
.It 2
The filesystem supports 32-bit uid's and gid's,
short symbolic links are stored in the inode,
and directories have an added field showing the file type.
.El
.Pp
In interactive mode,
.Nm fsck
will list the direction the conversion is to be made
will list the conversion to be made
and ask whether the conversion should be done.
If a negative answer is given,
no further operations are done on the filesystem.
In preen mode,
the direction of the conversion is listed and done if
the conversion is listed and done if
possible without user interaction.
Conversion in preen mode is best used when all the file systems
Conversion in preen mode is best used when all the filesystems
are being converted at once.
The format of a file system can be determined from the
The format of a filesystem can be determined from the
first line of output from
.Xr dumpfs 8 .
.El
.Pp
If no filesystems are given to
.Nm fsck
then a default list of file systems is read from
then a default list of filesystems is read from
the file
.Pa /etc/fstab .
.Pp
.Bl -enum -indent indent -compact
Inconsistencies checked are as follows:
.Bl -enum -width 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 file system.
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 of proper format.
.Bl -item -indent indent -compact
.It
Directory size not a multiple of DIRBLKSIZ.
.It
Partially truncated file.
.El
@ -231,8 +237,8 @@ Bad inode format.
Blocks not accounted for anywhere.
.It
Directory checks:
.Bl -item -offset indent -compact
.It
.Bl -item -indent indent -compact
.It
File pointing to unallocated inode.
.It
Inode number out of range.
@ -242,15 +248,15 @@ 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 file system.
.El
.Bl -item -indent 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
@ -266,15 +272,17 @@ If there is insufficient space its size is increased.
Because of inconsistencies between the block device and the buffer cache,
the raw device should always be used.
.Sh FILES
.Bl -tag -width indent-two -compact
.Bl -tag -width /etc/fstab -compact
.It Pa /etc/fstab
contains default list of file systems to check.
contains default list of filesystems to check.
.El
.Sh DIAGNOSTICS
The diagnostics produced by
.Nm fsck
are fully enumerated and explained in Appendix A of
``Fsck \- The UNIX File System Check Program'' (SMM:5).
.Rs
.%T "Fsck \- The UNIX File System Check Program"
.Re
.Sh SEE ALSO
.Xr fstab 5 ,
.Xr fs 5 ,

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)fsck.h 5.17 (Berkeley) 7/27/90
* $Id: fsck.h,v 1.5 1994/05/02 10:18:21 pk Exp $
* from: @(#)fsck.h 8.1 (Berkeley) 6/5/93
* $Id: fsck.h,v 1.6 1994/06/08 19:00:21 mycroft Exp $
*/
#define MAXDUP 10 /* limit on dup blks (per inode) */
@ -78,6 +78,7 @@ struct bufarea sblk; /* file system superblock */
struct bufarea cgblk; /* cylinder group blocks */
struct bufarea *pdirbp; /* current directory contents */
struct bufarea *pbp; /* current inode block */
struct bufarea *getdatablk();
#define dirty(bp) (bp)->b_dirty = 1
#define initbarea(bp) \
@ -99,7 +100,7 @@ struct inodesc {
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 */
long id_filesize; /* for DATA nodes, the size of the directory */
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 direct *id_dirp; /* for DATA nodes, ptr to current entry */
@ -161,14 +162,17 @@ struct inoinfo {
} **inphead, **inpsort;
long numdirs, listmax, inplast;
char *devname; /* name of device being checked */
char *cdevname; /* name of device being checked */
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 debug; /* output debugging info */
int cvtflag; /* convert to old file system format */
int cvtlevel; /* convert to newer file system format */
int doinglevel1; /* converting to new cylinder group format */
int doinglevel2; /* converting to new inode format */
int newinofmt; /* filesystem has new inode format */
char preen; /* just fix normal inconsistencies */
char hotroot; /* checking root device */
char havesb; /* superblock has been read */
@ -181,6 +185,7 @@ 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 */
char *typemap; /* ptr to inode type table */
short *lncntp; /* ptr to link count table */
ino_t lfdir; /* lost & found directory inode number */
@ -203,32 +208,9 @@ struct dinode zino;
#define ALTERED 0x08
#define FOUND 0x10
int ckinode __P((struct dinode *, struct inodesc *));
int iblock __P((struct inodesc *, long, u_long));
int chkrange __P((daddr_t, int));
struct dinode *ginode __P((ino_t));
struct dinode *getnextinode __P((ino_t));
void cacheino __P((struct dinode *, ino_t));
struct inoinfo *getinoinfo __P((ino_t));
void resetinodebuf __P((void));
void freeinodebuf __P((void));
void inocleanup __P((void));
void inodirty __P((void));
void clri __P((struct inodesc *, char *, int));
int findname __P((struct inodesc *));
int findino __P((struct inodesc *));
void pinode __P((ino_t));
void blkerror __P((ino_t, char *, daddr_t));
ino_t allocino __P((ino_t, int));
void freeino __P((ino_t));
int ftypeok __P((struct dinode *));
struct bufarea *getdatablk __P((daddr_t, long));
void getblk __P((struct bufarea *, daddr_t, long));
void flush __P((int, struct bufarea *));
int bread __P((int, char *, daddr_t, long));
int bwrite __P((int, char *, daddr_t, long));
int allocblk __P((long));
void freeblk __P((daddr_t, long));
void getpathname __P((char *, ino_t, ino_t));
time_t time();
struct dinode *ginode();
struct inoinfo *getinoinfo();
void getblk();
ino_t allocino();
int findino();

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,15 +32,15 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)inode.c 5.18 (Berkeley) 3/19/91";*/
static char rcsid[] = "$Id: inode.c,v 1.8 1994/05/02 10:18:23 pk Exp $";
/*static char sccsid[] = "from: @(#)inode.c 8.4 (Berkeley) 4/18/94";*/
static char *rcsid = "$Id: inode.c,v 1.9 1994/06/08 19:00:23 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/dir.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#ifndef SMALL
#include <pwd.h>
#endif
@ -50,7 +50,6 @@ static char rcsid[] = "$Id: inode.c,v 1.8 1994/05/02 10:18:23 pk Exp $";
static ino_t startinum;
int
ckinode(dp, idesc)
struct dinode *dp;
register struct inodesc *idesc;
@ -58,13 +57,17 @@ ckinode(dp, idesc)
register daddr_t *ap;
long ret, n, ndb, offset;
struct dinode dino;
quad_t remsize, sizepb;
mode_t mode;
if (idesc->id_fix != IGNORE)
idesc->id_fix = DONTKNOW;
idesc->id_entryno = 0;
idesc->id_filesize = dp->di_size;
if ((dp->di_mode & IFMT) == IFBLK || (dp->di_mode & IFMT) == IFCHR ||
DFASTLINK(*dp))
mode = dp->di_mode & IFMT;
if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
(dp->di_size < sblock.fs_maxsymlinklen ||
(sblock.fs_maxsymlinklen == 0 && OLDFASTLINK(dp)))))
return (KEEPON);
dino = *dp;
ndb = howmany(dino.di_size, sblock.fs_bsize);
@ -85,28 +88,31 @@ ckinode(dp, idesc)
return (ret);
}
idesc->id_numfrags = sblock.fs_frag;
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
sizepb = sblock.fs_bsize;
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
if (*ap) {
idesc->id_blkno = *ap;
ret = iblock(idesc, n,
dino.di_size - sblock.fs_bsize * NDADDR);
ret = iblock(idesc, n, remsize);
if (ret & STOP)
return (ret);
}
sizepb *= NINDIR(&sblock);
remsize -= sizepb;
}
return (KEEPON);
}
int
iblock(idesc, ilevel, isize)
struct inodesc *idesc;
register long ilevel;
u_long isize;
long ilevel;
quad_t isize;
{
register daddr_t *ap;
register daddr_t *aplim;
int i, n, (*func)(), nif, sizepb;
register struct bufarea *bp;
int i, n, (*func)(), nif;
quad_t sizepb;
char buf[BUFSIZ];
extern int dirscan(), pass1check();
@ -122,7 +128,7 @@ iblock(idesc, ilevel, isize)
ilevel--;
for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
sizepb *= NINDIR(&sblock);
nif = isize / sizepb + 1;
nif = howmany(isize , sizepb);
if (nif > NINDIR(&sblock))
nif = NINDIR(&sblock);
if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
@ -140,18 +146,19 @@ iblock(idesc, ilevel, isize)
flush(fswritefd, bp);
}
aplim = &bp->b_un.b_indir[nif];
for (ap = bp->b_un.b_indir, i = 1; ap < aplim; ap++, i++) {
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
if (*ap) {
idesc->id_blkno = *ap;
if (ilevel > 0)
n = iblock(idesc, ilevel, isize - i * sizepb);
else
if (ilevel == 0)
n = (*func)(idesc);
else
n = iblock(idesc, ilevel, isize);
if (n & STOP) {
bp->b_flags &= ~B_INUSE;
return (n);
}
}
isize -= sizepb;
}
bp->b_flags &= ~B_INUSE;
return (KEEPON);
@ -161,7 +168,6 @@ iblock(idesc, ilevel, isize)
* Check that a block in a legal block number.
* Return 0 if in range, 1 if out of range.
*/
int
chkrange(blk, cnt)
daddr_t blk;
int cnt;
@ -208,7 +214,7 @@ ginode(inumber)
errexit("bad inode number %d to ginode\n", inumber);
if (startinum == 0 ||
inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
iblk = itod(&sblock, inumber);
iblk = ino_to_fsba(&sblock, inumber);
if (pbp != 0)
pbp->b_flags &= ~B_INUSE;
pbp = getdatablk(iblk, sblock.fs_bsize);
@ -237,7 +243,7 @@ getnextinode(inumber)
errexit("bad inode number %d to nextinode\n", inumber);
if (inumber >= lastinum) {
readcnt++;
dblk = fsbtodb(&sblock, itod(&sblock, lastinum));
dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum));
if (readcnt % readpercg == 0) {
size = partialsize;
lastinum += partialcnt;
@ -251,7 +257,6 @@ getnextinode(inumber)
return (dp++);
}
void
resetinodebuf()
{
@ -277,7 +282,6 @@ resetinodebuf()
(void)getnextinode(nextino);
}
void
freeinodebuf()
{
@ -293,7 +297,6 @@ freeinodebuf()
*
* Enter inodes into the cache.
*/
void
cacheino(dp, inumber)
register struct dinode *dp;
ino_t inumber;
@ -350,7 +353,6 @@ getinoinfo(inumber)
/*
* Clean up all the inode cache structure.
*/
void
inocleanup()
{
register struct inoinfo **inpp;
@ -363,15 +365,13 @@ inocleanup()
free((char *)inpsort);
inphead = inpsort = NULL;
}
void
inodirty()
{
dirty(pbp);
}
void
clri(idesc, type, flag)
register struct inodesc *idesc;
char *type;
@ -396,7 +396,6 @@ clri(idesc, type, flag)
}
}
int
findname(idesc)
struct inodesc *idesc;
{
@ -408,7 +407,6 @@ findname(idesc)
return (STOP|FOUND);
}
int
findino(idesc)
struct inodesc *idesc;
{
@ -424,7 +422,6 @@ findino(idesc)
return (KEEPON);
}
void
pinode(ino)
ino_t ino;
{
@ -446,13 +443,12 @@ pinode(ino)
printf("%u ", (unsigned)dp->di_uid);
printf("MODE=%o\n", dp->di_mode);
if (preen)
printf("%s: ", devname);
printf("SIZE=%lu ", dp->di_size);
p = ctime(&dp->di_mtime);
printf("%s: ", cdevname);
printf("SIZE=%qu ", dp->di_size);
p = ctime(&dp->di_mtime.ts_sec);
printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]);
}
void
blkerror(ino, type, blk)
ino_t ino;
char *type;
@ -520,19 +516,19 @@ allocino(request, type)
}
dp->di_mode = type;
(void)time(&dp->di_atime.ts_sec);
dp->di_atime.ts_nsec = 0;
dp->di_mtime = dp->di_ctime = dp->di_atime;
dp->di_size = sblock.fs_fsize;
dp->di_blocks = btodb(sblock.fs_fsize);
n_files++;
inodirty();
if (newinofmt)
typemap[ino] = IFTODT(type);
return (ino);
}
/*
* deallocate an inode
*/
void
freeino(ino)
ino_t ino;
{

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,20 +32,21 @@
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\
All rights reserved.\n";
static char copyright[] =
"@(#) Copyright (c) 1980, 1986, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)main.c 5.27 (Berkeley) 8/7/90";*/
static char rcsid[] = "$Id: main.c,v 1.12 1994/04/25 18:28:29 cgd Exp $";
/*static char sccsid[] = "from: @(#)main.c 8.2 (Berkeley) 1/23/94";*/
static char *rcsid = "$Id: main.c,v 1.13 1994/06/08 19:00:24 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <sys/mount.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <fstab.h>
#include <stdlib.h>
#include <string.h>
@ -63,11 +64,11 @@ main(argc, argv)
int ch;
int ret, maxrun = 0;
extern int docheck(), checkfilesys();
extern char *optarg;
extern char *optarg, *blockcheck();
extern int optind;
sync();
while ((ch = getopt(argc, argv, "cdpnNyYb:l:m:")) != EOF) {
while ((ch = getopt(argc, argv, "dpnNyYb:c:l:m:")) != EOF) {
switch (ch) {
case 'p':
preen++;
@ -79,9 +80,9 @@ main(argc, argv)
break;
case 'c':
cvtflag++;
cvtlevel = argtoi('c', "conversion level", optarg, 10);
break;
case 'd':
debug++;
break;
@ -121,7 +122,7 @@ main(argc, argv)
(void)signal(SIGQUIT, catchquit);
if (argc) {
while (argc-- > 0)
(void)checkfilesys(*argv++, (char *)0, 0L, 0);
(void)checkfilesys(blockcheck(*argv++), 0, 0L, 0);
exit(0);
}
ret = checkfstab(preen, maxrun, docheck, checkfilesys);
@ -170,11 +171,11 @@ checkfilesys(filesys, mntpt, auxdata, child)
daddr_t n_ffree, n_bfree;
struct dups *dp;
struct zlncnt *zlnp;
int clean;
int cylno;
if (preen && child)
(void)signal(SIGQUIT, voidquit);
devname = filesys;
cdevname = filesys;
if (debug && preen)
pwarn("starting\n");
if (setup(filesys) == 0) {
@ -182,71 +183,55 @@ checkfilesys(filesys, mntpt, auxdata, child)
pfatal("CAN'T CHECK FILE SYSTEM.");
return (0);
}
/*
* 1: scan inodes tallying blocks used
*/
if (preen == 0) {
printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
if (hotroot)
printf("** Root file system\n");
printf("** Phase 1 - Check Blocks and Sizes\n");
}
pass1();
/*
* 0: check whether file system is already clean
* 1b: locate first references to duplicates, if any
*/
clean = preen && (sblock.fs_state == FSOKAY) && sblock.fs_clean;
#ifdef notyet
if (clean) {
#else
if (0) {
#endif
printf("** filesystem clean -- skipping checks\n");
} else {
/*
* 1: scan inodes tallying blocks used
*/
if (preen == 0) {
printf("** Last Mounted on %s\n", sblock.fs_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();
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
*/
@ -254,8 +239,9 @@ checkfilesys(filesys, mntpt, auxdata, child)
n_bfree = sblock.fs_cstotal.cs_nbfree;
pwarn("%ld files, %ld used, %ld free ",
n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n",
n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n",
n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize,
((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10);
if (debug &&
(n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
printf("%ld files missing\n", n_files);
@ -281,30 +267,51 @@ checkfilesys(filesys, mntpt, auxdata, child)
}
zlnhead = (struct zlncnt *)0;
duplist = (struct dups *)0;
muldup = (struct dups *)0;
inocleanup();
#ifdef notyet
if (!clean && !nflag && fswritefd != -1) {
sblock.fs_state = FSOKAY;
sblock.fs_clean = FS_CLEANFREQ;
fsmodified = 1;
}
#endif
if (fsmodified) {
(void)time(&sblock.fs_time);
sbdirty();
}
if (cvtlevel && sblk.b_dirty) {
/*
* Write out the duplicate super blocks
*/
for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
bwrite(fswritefd, (char *)&sblock,
fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE);
}
ckfini();
free(blockmap);
free(statemap);
free((char *)lncntp);
if (!fsmodified)
return (0);
if (!preen) {
if (!preen)
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
if (hotroot)
printf("\n***** REBOOT NETBSD *****\n");
}
if (hotroot) {
struct statfs stfs_buf;
/*
* We modified the root. Do a mount update on
* it, unless it is read-write, so we can continue.
*/
if (statfs("/", &stfs_buf) == 0) {
long flags = stfs_buf.f_flags;
struct ufs_args args;
int ret;
if (flags & MNT_RDONLY) {
args.fspec = 0;
args.export.ex_flags = 0;
args.export.ex_root = 0;
flags |= MNT_UPDATE | MNT_RELOAD;
ret = mount(MOUNT_UFS, "/", flags, &args);
if (ret == 0)
return(0);
}
}
if (!preen)
printf("\n***** REBOOT NOW *****\n");
sync();
return (4);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,14 +32,15 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass1.c 5.16 (Berkeley) 3/19/91";*/
static char rcsid[] = "$Id: pass1.c,v 1.6 1994/04/25 18:28:35 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass1.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: pass1.c,v 1.7 1994/06/08 19:00:25 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <stdlib.h>
#include <string.h>
#include "fsck.h"
@ -51,12 +52,9 @@ struct dinode *getnextinode();
pass1()
{
register int c, i, j;
register struct dinode *dp;
struct zlncnt *zlnp;
int ndb, cgd;
struct inodesc idesc;
ino_t inumber;
int c, i, cgd;
struct inodesc idesc;
/*
* Set file system reserved blocks in used block map.
@ -84,123 +82,177 @@ pass1()
for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
if (inumber < ROOTINO)
continue;
dp = getnextinode(inumber);
if ((dp->di_mode & IFMT) == 0) {
if (bcmp((char *)dp->di_db, (char *)zino.di_db,
NDADDR * sizeof(daddr_t)) ||
bcmp((char *)dp->di_ib, (char *)zino.di_ib,
NIADDR * sizeof(daddr_t)) ||
dp->di_mode || dp->di_size) {
pfatal("PARTIALLY ALLOCATED INODE I=%lu",
inumber);
if (reply("CLEAR") == 1) {
dp = ginode(inumber);
clearinode(dp);
inodirty();
}
}
statemap[inumber] = USTATE;
continue;
}
lastino = inumber;
/* is fast symlink? */
if (DFASTLINK(*dp)) {
lncntp[inumber] = dp->di_nlink;
statemap[inumber] = FSTATE;
n_files++;
continue;
}
if (/* dp->di_size < 0 || */
dp->di_size + sblock.fs_bsize - 1 < dp->di_size) {
if (debug)
printf("bad size %lu:", dp->di_size);
goto unknown;
}
if (!preen && (dp->di_mode & IFMT) == IFMT &&
reply("HOLD BAD BLOCK") == 1) {
dp = ginode(inumber);
dp->di_size = sblock.fs_fsize;
dp->di_mode = IFREG|0600;
inodirty();
}
ndb = howmany(dp->di_size, sblock.fs_bsize);
if (ndb < 0) {
if (debug)
printf("bad size %lu ndb %d:",
dp->di_size, ndb);
goto unknown;
}
if ((dp->di_mode & IFMT) == IFBLK ||
(dp->di_mode & IFMT) == IFCHR)
ndb++;
for (j = ndb; j < NDADDR; j++)
if (dp->di_db[j] != 0) {
if (debug)
printf("bad direct addr: %ld\n",
dp->di_db[j]);
goto unknown;
}
for (j = 0, ndb -= NDADDR; ndb > 0; j++)
ndb /= NINDIR(&sblock);
for (; j < NIADDR; j++)
if (dp->di_ib[j] != 0) {
if (debug)
printf("bad indirect addr: %ld\n",
dp->di_ib[j]);
goto unknown;
}
if (ftypeok(dp) == 0)
goto unknown;
n_files++;
lncntp[inumber] = dp->di_nlink;
if (dp->di_nlink <= 0) {
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0)
errexit("");
} else {
zlnp->zlncnt = inumber;
zlnp->next = zlnhead;
zlnhead = zlnp;
}
}
if ((dp->di_mode & IFMT) == IFDIR) {
if (dp->di_size == 0)
statemap[inumber] = DCLEAR;
else
statemap[inumber] = DSTATE;
cacheino(dp, inumber);
} else
statemap[inumber] = FSTATE;
badblk = dupblk = 0;
idesc.id_number = inumber;
(void)ckinode(dp, &idesc);
idesc.id_entryno *= btodb(sblock.fs_fsize);
if (dp->di_blocks != idesc.id_entryno) {
pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)",
inumber, dp->di_blocks, idesc.id_entryno);
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
continue;
dp = ginode(inumber);
dp->di_blocks = idesc.id_entryno;
inodirty();
}
continue;
unknown:
pfatal("UNKNOWN FILE TYPE I=%lu", inumber);
statemap[inumber] = FCLEAR;
checkinode(inumber, &idesc);
}
}
freeinodebuf();
}
checkinode(inumber, idesc)
ino_t inumber;
register struct inodesc *idesc;
{
register struct dinode *dp;
struct zlncnt *zlnp;
int ndb, j;
mode_t mode;
char symbuf[MAXSYMLINKLEN];
dp = getnextinode(inumber);
mode = dp->di_mode & IFMT;
if (mode == 0) {
if (bcmp((char *)dp->di_db, (char *)zino.di_db,
NDADDR * sizeof(daddr_t)) ||
bcmp((char *)dp->di_ib, (char *)zino.di_ib,
NIADDR * sizeof(daddr_t)) ||
dp->di_mode || dp->di_size) {
pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber);
if (reply("CLEAR") == 1) {
statemap[inumber] = USTATE;
dp = ginode(inumber);
clearinode(dp);
inodirty();
}
}
statemap[inumber] = USTATE;
return;
}
lastino = inumber;
if (/* dp->di_size < 0 || */
dp->di_size + sblock.fs_bsize - 1 < dp->di_size) {
if (debug)
printf("bad size %qu:", dp->di_size);
goto unknown;
}
if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
dp = ginode(inumber);
dp->di_size = sblock.fs_fsize;
dp->di_mode = IFREG|0600;
inodirty();
}
ndb = howmany(dp->di_size, sblock.fs_bsize);
if (ndb < 0) {
if (debug)
printf("bad size %qu ndb %d:",
dp->di_size, ndb);
goto unknown;
}
if (mode == IFBLK || mode == IFCHR)
ndb++;
if (mode == IFLNK) {
/*
* Note that the old fastlink format always had di_blocks set
* to 0. Other than that we no longer use the `spare' field
* (which is now the extended uid) for sanity checking, the
* new format is the same as the old. We simply ignore the
* conversion altogether. - mycroft, 19MAY1994
*/
if (doinglevel2 &&
dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN &&
dp->di_blocks != 0) {
if (bread(fsreadfd, symbuf,
fsbtodb(&sblock, dp->di_db[0]),
(long)dp->di_size) != 0)
errexit("cannot read symlink");
if (debug) {
symbuf[dp->di_size] = 0;
printf("convert symlink %d(%s) of size %d\n",
inumber, symbuf, (long)dp->di_size);
}
dp = ginode(inumber);
bcopy(symbuf, (caddr_t)dp->di_shortlink,
(long)dp->di_size);
dp->di_blocks = 0;
inodirty();
}
/*
* Fake ndb value so direct/indirect block checks below
* will detect any garbage after symlink string.
*/
if (dp->di_size < sblock.fs_maxsymlinklen ||
(sblock.fs_maxsymlinklen == 0 && OLDFASTLINK(dp))) {
ndb = howmany(dp->di_size, sizeof(daddr_t));
if (ndb > NDADDR) {
j = ndb - NDADDR;
for (ndb = 1; j > 1; j--)
ndb *= NINDIR(&sblock);
ndb += NDADDR;
}
}
}
for (j = ndb; j < NDADDR; j++)
if (dp->di_db[j] != 0) {
if (debug)
printf("bad direct addr: %ld\n", dp->di_db[j]);
goto unknown;
}
for (j = 0, ndb -= NDADDR; ndb > 0; j++)
ndb /= NINDIR(&sblock);
for (; j < NIADDR; j++)
if (dp->di_ib[j] != 0) {
if (debug)
printf("bad indirect addr: %ld\n",
dp->di_ib[j]);
goto unknown;
}
if (ftypeok(dp) == 0)
goto unknown;
n_files++;
lncntp[inumber] = dp->di_nlink;
if (dp->di_nlink <= 0) {
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0)
errexit("");
} else {
zlnp->zlncnt = inumber;
zlnp->next = zlnhead;
zlnhead = zlnp;
}
}
if (mode == IFDIR) {
if (dp->di_size == 0)
statemap[inumber] = DCLEAR;
else
statemap[inumber] = DSTATE;
cacheino(dp, inumber);
} else
statemap[inumber] = FSTATE;
typemap[inumber] = IFTODT(mode);
if (doinglevel2 &&
(dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) {
dp = ginode(inumber);
dp->di_uid = dp->di_ouid;
dp->di_ouid = -1;
dp->di_gid = dp->di_ogid;
dp->di_ogid = -1;
inodirty();
}
badblk = dupblk = 0;
idesc->id_number = inumber;
(void)ckinode(dp, idesc);
idesc->id_entryno *= btodb(sblock.fs_fsize);
if (dp->di_blocks != idesc->id_entryno) {
pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)",
inumber, dp->di_blocks, idesc->id_entryno);
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
return;
dp = ginode(inumber);
dp->di_blocks = idesc->id_entryno;
inodirty();
}
return;
unknown:
pfatal("UNKNOWN FILE TYPE I=%lu", inumber);
statemap[inumber] = FCLEAR;
if (reply("CLEAR") == 1) {
statemap[inumber] = USTATE;
dp = ginode(inumber);
clearinode(dp);
inodirty();
}
freeinodebuf();
}
pass1check(idesc)

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,14 +32,14 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass1b.c 5.8 (Berkeley) 7/20/90";*/
static char rcsid[] = "$Id: pass1b.c,v 1.5 1994/04/25 18:28:42 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass1b.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: pass1b.c,v 1.6 1994/06/08 19:00:26 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <string.h>
#include "fsck.h"

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,17 +32,15 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass2.c 5.17 (Berkeley) 12/28/90";*/
static char rcsid[] = "$Id: pass2.c,v 1.5 1994/04/25 18:28:47 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass2.c 8.2 (Berkeley) 2/27/94";*/
static char *rcsid = "$Id: pass2.c,v 1.6 1994/06/08 19:00:27 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#define KERNEL
#include <ufs/dir.h>
#undef KERNEL
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <stdlib.h>
#include <string.h>
#include "fsck.h"
@ -116,7 +114,6 @@ pass2()
bzero((char *)&curino, sizeof(struct inodesc));
curino.id_type = DATA;
curino.id_func = pass2check;
dino.di_mode = IFDIR;
dp = &dino;
inpend = &inpsort[inplast];
for (inpp = inpsort; inpp < inpend; inpp++) {
@ -146,6 +143,8 @@ pass2()
dp = &dino;
}
}
bzero((char *)&dino, sizeof(struct dinode));
dino.di_mode = IFDIR;
dp->di_size = inp->i_isize;
bcopy((char *)&inp->i_blks[0], (char *)&dp->di_db[0],
(size_t)inp->i_numblks);
@ -177,7 +176,7 @@ pass2()
continue;
}
fileerror(inp->i_parent, inp->i_number,
"BAD INODE NUMBER FOR '..'");
"BAD INODE NUMBER FOR '..'");
if (reply("FIX") == 0)
continue;
lncntp[inp->i_dotdot]++;
@ -203,6 +202,13 @@ pass2check(idesc)
char namebuf[MAXPATHLEN + 1];
char pathbuf[MAXPATHLEN + 1];
/*
* If converting, set directory entry type.
*/
if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) {
dirp->d_type = typemap[dirp->d_ino];
ret |= ALTERED;
}
/*
* check for "."
*/
@ -215,13 +221,23 @@ pass2check(idesc)
if (reply("FIX") == 1)
ret |= ALTERED;
}
if (newinofmt && dirp->d_type != DT_DIR) {
direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'");
dirp->d_type = DT_DIR;
if (reply("FIX") == 1)
ret |= ALTERED;
}
goto chk1;
}
direrror(idesc->id_number, "MISSING '.'");
proto.d_ino = idesc->id_number;
if (newinofmt)
proto.d_type = DT_DIR;
else
proto.d_type = 0;
proto.d_namlen = 1;
(void)strcpy(proto.d_name, ".");
entrysize = DIRSIZ(&proto);
entrysize = DIRSIZ(0, &proto);
if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
dirp->d_name);
@ -249,11 +265,15 @@ chk1:
goto chk2;
inp = getinoinfo(idesc->id_number);
proto.d_ino = inp->i_parent;
if (newinofmt)
proto.d_type = DT_DIR;
else
proto.d_type = 0;
proto.d_namlen = 2;
(void)strcpy(proto.d_name, "..");
entrysize = DIRSIZ(&proto);
entrysize = DIRSIZ(0, &proto);
if (idesc->id_entryno == 0) {
n = DIRSIZ(dirp);
n = DIRSIZ(0, dirp);
if (dirp->d_reclen < n + entrysize)
goto chk2;
proto.d_reclen = dirp->d_reclen - n;
@ -266,6 +286,12 @@ chk1:
}
if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
inp->i_dotdot = dirp->d_ino;
if (newinofmt && dirp->d_type != DT_DIR) {
direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'");
dirp->d_type = DT_DIR;
if (reply("FIX") == 1)
ret |= ALTERED;
}
goto chk2;
}
if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {
@ -332,10 +358,14 @@ again:
case FCLEAR:
if (idesc->id_entryno <= 2)
break;
if (statemap[dirp->d_ino] == DCLEAR)
errmsg = "ZERO LENGTH DIRECTORY";
else
if (statemap[dirp->d_ino] == FCLEAR)
errmsg = "DUP/BAD";
else if (!preen)
errmsg = "ZERO LENGTH DIRECTORY";
else {
n = 1;
break;
}
fileerror(idesc->id_number, dirp->d_ino, errmsg);
if ((n = reply("REMOVE")) == 1)
break;
@ -369,6 +399,13 @@ again:
/* fall through */
case FSTATE:
if (newinofmt && dirp->d_type != typemap[dirp->d_ino]) {
fileerror(idesc->id_number, dirp->d_ino,
"BAD TYPE VALUE");
dirp->d_type = typemap[dirp->d_ino];
if (reply("FIX") == 1)
ret |= ALTERED;
}
lncntp[dirp->d_ino]--;
break;

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,14 +32,14 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass3.c 5.10 (Berkeley) 6/1/90";*/
static char rcsid[] = "$Id: pass3.c,v 1.5 1994/04/25 18:28:51 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass3.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: pass3.c,v 1.6 1994/06/08 19:00:28 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include "fsck.h"
pass3()

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,14 +32,14 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass4.c 5.10 (Berkeley) 7/20/90";*/
static char rcsid[] = "$Id: pass4.c,v 1.5 1994/04/25 18:28:54 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass4.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: pass4.c,v 1.6 1994/06/08 19:00:29 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <stdlib.h>
#include <string.h>
#include "fsck.h"

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,14 +32,14 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass5.c 5.13 (Berkeley) 7/20/90";*/
static char rcsid[] = "$Id: pass5.c,v 1.5 1994/04/25 18:28:57 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass5.c 8.2 (Berkeley) 2/2/94";*/
static char *rcsid = "$Id: pass5.c,v 1.6 1994/06/08 19:00:30 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <string.h>
#include "fsck.h"
@ -52,7 +52,6 @@ pass5()
register daddr_t d;
register long i, j;
struct csum *cs;
time_t now;
struct csum cstotal;
struct inodesc idesc[3];
char buf[MAXBSIZE];
@ -61,6 +60,45 @@ pass5()
bzero((char *)newcg, (size_t)fs->fs_cgsize);
newcg->cg_niblk = fs->fs_ipg;
if (cvtlevel > 3) {
if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
if (preen)
pwarn("DELETING CLUSTERING MAPS\n");
if (preen || reply("DELETE CLUSTERING MAPS")) {
fs->fs_contigsumsize = 0;
doinglevel1 = 1;
sbdirty();
}
}
if (fs->fs_maxcontig > 1) {
char *doit = 0;
if (fs->fs_contigsumsize < 1) {
doit = "CREAT";
} else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
fs->fs_contigsumsize < FS_MAXCONTIG) {
doit = "EXPAND";
}
if (doit) {
i = fs->fs_contigsumsize;
fs->fs_contigsumsize =
MIN(fs->fs_maxcontig, FS_MAXCONTIG);
if (CGSIZE(fs) > fs->fs_bsize) {
pwarn("CANNOT %s CLUSTER MAPS\n", doit);
fs->fs_contigsumsize = i;
} else if (preen ||
reply("CREATE CLUSTER MAPS")) {
if (preen)
pwarn("%sING CLUSTER MAPS\n",
doit);
fs->fs_cgsize =
fragroundup(fs, CGSIZE(fs));
doinglevel1 = 1;
sbdirty();
}
}
}
}
switch ((int)fs->fs_postblformat) {
case FS_42POSTBLFMT:
@ -75,16 +113,27 @@ pass5()
case FS_DYNAMICPOSTBLFMT:
newcg->cg_btotoff =
&newcg->cg_space[0] - (u_char *)(&newcg->cg_link);
&newcg->cg_space[0] - (u_char *)(&newcg->cg_link);
newcg->cg_boff =
newcg->cg_btotoff + fs->fs_cpg * sizeof(long);
newcg->cg_btotoff + fs->fs_cpg * sizeof(long);
newcg->cg_iusedoff = newcg->cg_boff +
fs->fs_cpg * fs->fs_nrpos * sizeof(short);
fs->fs_cpg * fs->fs_nrpos * sizeof(short);
newcg->cg_freeoff =
newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs),
NBBY);
newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
if (fs->fs_contigsumsize <= 0) {
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
} else {
newcg->cg_clustersumoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY) -
sizeof(long);
newcg->cg_clustersumoff =
roundup(newcg->cg_clustersumoff, sizeof(long));
newcg->cg_clusteroff = newcg->cg_clustersumoff +
(fs->fs_contigsumsize + 1) * sizeof(long);
newcg->cg_nextfreeoff = newcg->cg_clusteroff +
howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY);
}
newcg->cg_magic = CG_MAGIC;
basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_link);
sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
@ -96,10 +145,12 @@ pass5()
fs->fs_postblformat);
}
bzero((char *)&idesc[0], sizeof idesc);
for (i = 0; i < 3; i++)
for (i = 0; i < 3; i++) {
idesc[i].id_type = ADDR;
if (doinglevel2)
idesc[i].id_fix = FIX;
}
bzero((char *)&cstotal, sizeof(struct csum));
(void)time(&now);
j = blknum(fs, fs->fs_size + fs->fs_frag - 1);
for (i = fs->fs_size; i < j; i++)
setbmap(i);
@ -111,16 +162,15 @@ pass5()
dmax = dbase + fs->fs_fpg;
if (dmax > fs->fs_size)
dmax = fs->fs_size;
if (now > cg->cg_time)
newcg->cg_time = cg->cg_time;
else
newcg->cg_time = now;
newcg->cg_time = cg->cg_time;
newcg->cg_cgx = c;
if (c == fs->fs_ncg - 1)
newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
else
newcg->cg_ncyl = fs->fs_cpg;
newcg->cg_ndblk = dmax - dbase;
if (fs->fs_contigsumsize > 0)
newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
newcg->cg_cs.cs_ndir = 0;
newcg->cg_cs.cs_nffree = 0;
newcg->cg_cs.cs_nbfree = 0;
@ -188,10 +238,42 @@ pass5()
j = cbtocylno(fs, i);
cg_blktot(newcg)[j]++;
cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++;
if (fs->fs_contigsumsize > 0)
setbit(cg_clustersfree(newcg),
i / fs->fs_frag);
} else if (frags > 0) {
newcg->cg_cs.cs_nffree += frags;
blk = blkmap(fs, cg_blksfree(newcg), i);
fragacct(fs, blk, newcg->cg_frsum, 1);
ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
}
}
if (fs->fs_contigsumsize > 0) {
long *sump = cg_clustersum(newcg);
u_char *mapp = cg_clustersfree(newcg);
int map = *mapp++;
int bit = 1;
int run = 0;
for (i = 0; i < newcg->cg_nclusterblks; i++) {
if ((map & bit) != 0) {
run++;
} else if (run != 0) {
if (run > fs->fs_contigsumsize)
run = fs->fs_contigsumsize;
sump[run]++;
run = 0;
}
if ((i & (NBBY - 1)) != (NBBY - 1)) {
bit <<= 1;
} else {
map = *mapp++;
bit = 1;
}
}
if (run != 0) {
if (run > fs->fs_contigsumsize)
run = fs->fs_contigsumsize;
sump[run]++;
}
}
cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
@ -204,7 +286,7 @@ pass5()
bcopy((char *)&newcg->cg_cs, (char *)cs, sizeof *cs);
sbdirty();
}
if (cvtflag) {
if (doinglevel1) {
bcopy((char *)newcg, (char *)cg, (size_t)fs->fs_cgsize);
cgdirty();
continue;

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,13 +32,12 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)preen.c 5.7 (Berkeley) 3/19/91";*/
static char rcsid[] = "$Id: preen.c,v 1.5 1994/04/25 18:29:01 cgd Exp $";
/*static char sccsid[] = "from: @(#)preen.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: preen.c,v 1.6 1994/06/08 19:00:31 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <fstab.h>
#include <string.h>

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,20 +32,19 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)setup.c 5.33 (Berkeley) 2/22/91";*/
static char rcsid[] = "$Id: setup.c,v 1.9 1994/04/25 18:33:42 cgd Exp $";
/*static char sccsid[] = "from: @(#)setup.c 8.2 (Berkeley) 2/21/94";*/
static char *rcsid = "$Id: setup.c,v 1.10 1994/06/08 19:00:32 mycroft Exp $";
#endif /* not lint */
#define DKTYPENAMES
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/disklabel.h>
#include <sys/file.h>
#include <sys/mount.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@ -56,22 +55,7 @@ struct bufarea asblk;
#define altsblock (*asblk.b_un.b_fs)
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
/*
* The size of a cylinder group is calculated by CGSIZE. The maximum size
* is limited by the fact that cylinder groups are at most one block.
* Its size is derived from the size of the maps maintained in the
* cylinder group and the (struct cg) size.
*/
#define CGSIZE(fs) \
/* base cg */ (sizeof(struct cg) + \
/* blktot size */ (fs)->fs_cpg * sizeof(long) + \
/* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \
/* inode map */ howmany((fs)->fs_ipg, NBBY) + \
/* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
char *index();
struct disklabel *getdisklabel();
char *getmntdev();
setup(dev)
char *dev;
@ -79,47 +63,17 @@ setup(dev)
long cg, size, asked, i, j;
long bmapsize;
struct disklabel *lp;
struct stat statb, statb2;
off_t sizepb;
struct stat statb;
struct fs proto;
char path2[MAXPATHLEN];
char *dev2;
havesb = 0;
fswritefd = -1;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
return (0);
}
switch (statb.st_mode & S_IFMT) {
case S_IFCHR:
break;
case S_IFDIR:
dev2 = getmntdev(dev);
if (dev2 != NULL && !strncmp(dev2, "/dev/", 5)) {
snprintf(path2, sizeof(path2), "/dev/r%s", dev2 + 5);
if (stat(path2, &statb2) == 0 &&
(statb2.st_mode & S_IFMT) == S_IFCHR) {
dev = path2;
statb = statb2;
break;
}
}
pfatal("%s is not a character device", dev);
if (reply("CONTINUE") == 0)
return (0);
break;
case S_IFBLK:
if (!strncmp(dev, "/dev/", 5)) {
sprintf(path2, "/dev/r%s", dev + 5);
if (stat(path2, &statb2) == 0 &&
(statb2.st_mode & S_IFMT) == S_IFCHR &&
minor(statb2.st_rdev) == minor(statb.st_rdev)) {
dev = path2;
statb = statb2;
break;
}
}
/* fall through */
default:
if ((statb.st_mode & S_IFMT) != S_IFCHR) {
pfatal("%s is not a character device", dev);
if (reply("CONTINUE") == 0)
return (0);
@ -150,14 +104,6 @@ setup(dev)
dev_bsize = secsize = lp->d_secsize;
else
dev_bsize = secsize = DEV_BSIZE;
#ifdef tahoe
/*
* On the tahoe, the disk label and the disk driver disagree.
* The label knows that sectors are 512 bytes, but the disk
* drivers will only transfer in 1024 sized pieces.
*/
secsize = 1024;
#endif
/*
* Read in the superblock, looking for alternates if necessary
*/
@ -227,64 +173,55 @@ setup(dev)
dirty(&asblk);
}
}
if (cvtflag) {
if (sblock.fs_postblformat == FS_42POSTBLFMT) {
/*
* Requested to convert from old format to new format
*/
if (preen)
pwarn("CONVERTING TO NEW FILE SYSTEM FORMAT\n");
else if (!reply("CONVERT TO NEW FILE SYSTEM FORMAT"))
return(0);
sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
sblock.fs_nrpos = 8;
sblock.fs_postbloff =
(char *)(&sblock.fs_opostbl[0][0]) -
(char *)(&sblock.fs_link);
sblock.fs_rotbloff = &sblock.fs_space[0] -
(u_char *)(&sblock.fs_link);
sblock.fs_cgsize =
fragroundup(&sblock, CGSIZE(&sblock));
/*
* Planning now for future expansion.
*/
# if (BYTE_ORDER == BIG_ENDIAN)
sblock.fs_qbmask.val[0] = 0;
sblock.fs_qbmask.val[1] = ~sblock.fs_bmask;
sblock.fs_qfmask.val[0] = 0;
sblock.fs_qfmask.val[1] = ~sblock.fs_fmask;
# endif /* BIG_ENDIAN */
# if (BYTE_ORDER == LITTLE_ENDIAN)
sblock.fs_qbmask.val[0] = ~sblock.fs_bmask;
sblock.fs_qbmask.val[1] = 0;
sblock.fs_qfmask.val[0] = ~sblock.fs_fmask;
sblock.fs_qfmask.val[1] = 0;
# endif /* LITTLE_ENDIAN */
sbdirty();
dirty(&asblk);
} else if (sblock.fs_postblformat == FS_DYNAMICPOSTBLFMT) {
/*
* Requested to convert from new format to old format
*/
if (sblock.fs_nrpos != 8 || sblock.fs_ipg > 2048 ||
sblock.fs_cpg > 32 || sblock.fs_cpc > 16) {
printf(
"PARAMETERS OF CURRENT FILE SYSTEM DO NOT\n\t");
errexit(
"ALLOW CONVERSION TO OLD FILE SYSTEM FORMAT\n");
}
if (preen)
pwarn("CONVERTING TO OLD FILE SYSTEM FORMAT\n");
else if (!reply("CONVERT TO OLD FILE SYSTEM FORMAT"))
return(0);
sblock.fs_postblformat = FS_42POSTBLFMT;
sblock.fs_cgsize = fragroundup(&sblock,
sizeof(struct ocg) + howmany(sblock.fs_fpg, NBBY));
sbdirty();
dirty(&asblk);
} else {
errexit("UNKNOWN FILE SYSTEM FORMAT\n");
if (sblock.fs_inodefmt >= FS_44INODEFMT) {
newinofmt = 1;
} else {
sblock.fs_qbmask = ~sblock.fs_bmask;
sblock.fs_qfmask = ~sblock.fs_fmask;
newinofmt = 0;
}
/*
* Convert to new inode format.
*/
if (cvtlevel >= 2 && sblock.fs_inodefmt < FS_44INODEFMT) {
if (preen)
pwarn("CONVERTING TO NEW INODE FORMAT\n");
else if (!reply("CONVERT TO NEW INODE FORMAT"))
return(0);
doinglevel2++;
sblock.fs_inodefmt = FS_44INODEFMT;
sizepb = sblock.fs_bsize;
sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1;
for (i = 0; i < NIADDR; i++) {
sizepb *= NINDIR(&sblock);
sblock.fs_maxfilesize += sizepb;
}
sblock.fs_maxsymlinklen = MAXSYMLINKLEN;
sblock.fs_qbmask = ~sblock.fs_bmask;
sblock.fs_qfmask = ~sblock.fs_fmask;
sbdirty();
dirty(&asblk);
}
/*
* Convert to new cylinder group format.
*/
if (cvtlevel >= 1 && sblock.fs_postblformat == FS_42POSTBLFMT) {
if (preen)
pwarn("CONVERTING TO NEW CYLINDER GROUP FORMAT\n");
else if (!reply("CONVERT TO NEW CYLINDER GROUP FORMAT"))
return(0);
doinglevel1++;
sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
sblock.fs_nrpos = 8;
sblock.fs_postbloff =
(char *)(&sblock.fs_opostbl[0][0]) -
(char *)(&sblock.fs_link);
sblock.fs_rotbloff = &sblock.fs_space[0] -
(u_char *)(&sblock.fs_link);
sblock.fs_cgsize =
fragroundup(&sblock, CGSIZE(&sblock));
sbdirty();
dirty(&asblk);
}
if (asblk.b_dirty) {
bcopy((char *)&sblock, (char *)&altsblock,
@ -324,6 +261,12 @@ setup(dev)
(unsigned)(maxino + 1));
goto badsb;
}
typemap = calloc((unsigned)(maxino + 1), sizeof(char));
if (typemap == NULL) {
printf("cannot alloc %u bytes for typemap\n",
(unsigned)(maxino + 1));
goto badsb;
}
lncntp = (short *)calloc((unsigned)(maxino + 1), sizeof(short));
if (lncntp == NULL) {
printf("cannot alloc %u bytes for lncntp\n",
@ -384,6 +327,10 @@ readsb(listerr)
super *= dev_bsize;
dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
sblk.b_bno = super / dev_bsize;
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.
@ -392,10 +339,6 @@ readsb(listerr)
getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize);
if (asblk.b_errs)
return (0);
if (bflag) {
havesb = 1;
return (1);
}
altsblock.fs_link = sblock.fs_link;
altsblock.fs_rlink = sblock.fs_rlink;
altsblock.fs_time = sblock.fs_time;
@ -403,7 +346,6 @@ readsb(listerr)
altsblock.fs_cgrotor = sblock.fs_cgrotor;
altsblock.fs_fmod = sblock.fs_fmod;
altsblock.fs_clean = sblock.fs_clean;
altsblock.fs_state = sblock.fs_state;
altsblock.fs_ronly = sblock.fs_ronly;
altsblock.fs_flags = sblock.fs_flags;
altsblock.fs_maxcontig = sblock.fs_maxcontig;
@ -424,6 +366,10 @@ readsb(listerr)
altsblock.fs_interleave = sblock.fs_interleave;
altsblock.fs_npsect = sblock.fs_npsect;
altsblock.fs_nrpos = sblock.fs_nrpos;
altsblock.fs_qbmask = sblock.fs_qbmask;
altsblock.fs_qfmask = sblock.fs_qfmask;
altsblock.fs_state = sblock.fs_state;
altsblock.fs_maxfilesize = sblock.fs_maxfilesize;
if (bcmp((char *)&sblock, (char *)&altsblock, (int)sblock.fs_sbsize)) {
badsb(listerr,
"VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
@ -441,7 +387,7 @@ badsb(listerr, s)
if (!listerr)
return;
if (preen)
printf("%s: ", devname);
printf("%s: ", cdevname);
pfatal("BAD SUPER BLOCK: %s\n", s);
}
@ -519,20 +465,3 @@ getdisklabel(s, fd)
}
return (&lab);
}
char *
getmntdev(name)
char *name;
{
long mntsize;
register long i;
struct statfs *mntbuf;
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
for (i = 0; i < mntsize; i++) {
if (!strncmp(mntbuf[i].f_fstypename, MOUNT_UFS, MFSNAMELEN) &&
!strcmp(mntbuf[i].f_mntonname, name))
return (mntbuf[i].f_mntfromname);
}
return ((char *)0);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,15 +32,15 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)utilities.c 5.30 (Berkeley) 7/26/91";*/
static char rcsid[] = "$Id: utilities.c,v 1.8 1994/05/02 10:18:25 pk Exp $";
/*static char sccsid[] = "from: @(#)utilities.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: utilities.c,v 1.9 1994/06/08 19:00:33 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/dir.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -49,7 +49,6 @@ static char rcsid[] = "$Id: utilities.c,v 1.8 1994/05/02 10:18:25 pk Exp $";
long diskreads, totalreads; /* Disk cache statistics */
int
ftypeok(dp)
struct dinode *dp;
{
@ -71,7 +70,6 @@ ftypeok(dp)
}
}
int
reply(question)
char *question;
{
@ -107,7 +105,6 @@ reply(question)
/*
* Malloc buffers and set up cache.
*/
void
bufinit()
{
register struct bufarea *bp;
@ -192,7 +189,6 @@ getblk(bp, blk, size)
}
}
void
flush(fd, bp)
int fd;
register struct bufarea *bp;
@ -218,7 +214,6 @@ flush(fd, bp)
}
}
void
rwerror(mesg, blk)
char *mesg;
daddr_t blk;
@ -231,12 +226,15 @@ rwerror(mesg, blk)
errexit("Program terminated\n");
}
void
ckfini()
{
register 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 SUPERBLOCK")) {
@ -271,20 +269,23 @@ bread(fd, buf, blk, size)
{
char *cp;
int i, errs;
off_t offset;
if (lseek(fd, blk * dev_bsize, 0) < 0)
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, blk * dev_bsize, 0) < 0)
if (lseek(fd, offset, 0) < 0)
rwerror("SEEK", blk);
errs = 0;
bzero(buf, (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, blk * dev_bsize + i + secsize, 0);
(void)lseek(fd, offset + i + secsize, 0);
if (secsize != dev_bsize && dev_bsize != 1)
printf(" %ld (%ld),",
(blk * dev_bsize + i) / secsize,
@ -306,22 +307,25 @@ bwrite(fd, buf, blk, size)
{
int i;
char *cp;
off_t offset;
if (fd < 0)
return;
if (lseek(fd, blk * dev_bsize, 0) < 0)
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, blk * dev_bsize, 0) < 0)
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, blk * dev_bsize + i + dev_bsize, 0);
(void)lseek(fd, offset + i + dev_bsize, 0);
printf(" %ld,", blk + i / dev_bsize);
}
printf("\n");
@ -361,7 +365,6 @@ allocblk(frags)
/*
* Free a previously allocated block
*/
void
freeblk(blkno, frags)
daddr_t blkno;
long frags;
@ -376,7 +379,6 @@ freeblk(blkno, frags)
/*
* Find a pathname
*/
void
getpathname(namebuf, curdir, ino)
char *namebuf;
ino_t curdir, ino;
@ -387,6 +389,10 @@ getpathname(namebuf, curdir, ino)
static int busy = 0;
extern int findname();
if (curdir == ino && ino == ROOTINO) {
(void)strcpy(namebuf, "/");
return;
}
if (busy ||
(statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
(void)strcpy(namebuf, "?");
@ -432,7 +438,8 @@ getpathname(namebuf, curdir, ino)
void
catch()
{
ckfini();
if (!doinglevel2)
ckfini();
exit(12);
}
@ -522,11 +529,11 @@ pfatal(s, a1, a2, a3)
{
if (preen) {
printf("%s: ", devname);
printf("%s: ", cdevname);
printf(s, a1, a2, a3);
printf("\n");
printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
devname);
cdevname);
exit(8);
}
printf(s, a1, a2, a3);
@ -542,7 +549,7 @@ pwarn(s, a1, a2, a3, a4, a5, a6)
{
if (preen)
printf("%s: ", devname);
printf("%s: ", cdevname);
printf(s, a1, a2, a3, a4, a5, a6);
}

View File

@ -1,10 +1,10 @@
# from: @(#)Makefile 5.15 (Berkeley) 6/29/90
# $Id: Makefile,v 1.5 1993/08/01 05:37:50 mycroft Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/5/93
# $Id: Makefile,v 1.6 1994/06/08 19:00:18 mycroft Exp $
PROG= fsck
MAN8= fsck.0
SRCS= dir.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c pass4.c \
pass5.c preen.c setup.c utilities.c ufs_subr.c ufs_tables.c
.PATH: ${.CURDIR}/../../sys/ufs
pass5.c preen.c setup.c utilities.c ffs_subr.c ffs_tables.c
.PATH: ${.CURDIR}/../../sys/ufs/ffs
.include <bsd.prog.mk>

151
sbin/fsck_ffs/SMM.doc/0.t Normal file
View File

@ -0,0 +1,151 @@
.\" Copyright (c) 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)0.t 8.1 (Berkeley) 6/8/93
.\" $Id: 0.t,v 1.1 1994/06/08 19:00:49 mycroft Exp $
.\"
.if n .ND
.TL
Fsck \- The UNIX\(dg File System Check Program
.EH 'SMM:3-%''The \s-2UNIX\s+2 File System Check Program'
.OH 'The \s-2UNIX\s+2 File System Check Program''SMM:3-%'
.AU
Marshall Kirk McKusick
.AI
Computer Systems Research Group
Computer Science Division
Department of Electrical Engineering and Computer Science
University of California, Berkeley
Berkeley, CA 94720
.AU
T. J. Kowalski
.AI
Bell Laboratories
Murray Hill, New Jersey 07974
.AB
.FS
\(dgUNIX is a trademark of Bell Laboratories.
.FE
.FS
This work was done under grants from
the National Science Foundation under grant MCS80-05144,
and the Defense Advance Research Projects Agency (DoD) under
Arpa Order No. 4031 monitored by Naval Electronic System Command under
Contract No. N00039-82-C-0235.
.FE
This document reflects the use of
.I fsck
with the 4.2BSD and 4.3BSD file system organization. This
is a revision of the
original paper written by
T. J. Kowalski.
.PP
File System Check Program (\fIfsck\fR)
is an interactive file system check and repair program.
.I Fsck
uses the redundant structural information in the
UNIX file system to perform several consistency checks.
If an inconsistency is detected, it is reported
to the operator, who may elect to fix or ignore
each inconsistency.
These inconsistencies result from the permanent interruption
of the file system updates, which are performed every
time a file is modified.
Unless there has been a hardware failure,
.I fsck
is able to repair corrupted file systems
using procedures based upon the order in which UNIX honors
these file system update requests.
.PP
The purpose of this document is to describe the normal updating
of the file system,
to discuss the possible causes of file system corruption,
and to present the corrective actions implemented
by
.I fsck.
Both the program and the interaction between the
program and the operator are described.
.sp 2
.LP
Revised July 16, 1985
.AE
.LP
.bp
.ce
.B "TABLE OF CONTENTS"
.LP
.sp 1
.nf
.B "1. Introduction"
.LP
.sp .5v
.nf
.B "2. Overview of the file system
2.1. Superblock
2.2. Summary Information
2.3. Cylinder groups
2.4. Fragments
2.5. Updates to the file system
.LP
.sp .5v
.nf
.B "3. Fixing corrupted file systems
3.1. Detecting and correcting corruption
3.2. Super block checking
3.3. Free block checking
3.4. Checking the inode state
3.5. Inode links
3.6. Inode data size
3.7. Checking the data associated with an inode
3.8. File system connectivity
.LP
.sp .5v
.nf
.B Acknowledgements
.LP
.sp .5v
.nf
.B References
.LP
.sp .5v
.nf
.B "4. Appendix A
4.1. Conventions
4.2. Initialization
4.3. Phase 1 - Check Blocks and Sizes
4.4. Phase 1b - Rescan for more Dups
4.5. Phase 2 - Check Pathnames
4.6. Phase 3 - Check Connectivity
4.7. Phase 4 - Check Reference Counts
4.8. Phase 5 - Check Cyl groups
4.9. Cleanup
.ds RH Introduction
.bp

84
sbin/fsck_ffs/SMM.doc/1.t Normal file
View File

@ -0,0 +1,84 @@
.\" Copyright (c) 1982, 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)1.t 8.1 (Berkeley) 6/5/93
.\" $Id: 1.t,v 1.1 1994/06/08 19:01:21 mycroft Exp $
.\"
.ds RH Introduction
.NH
Introduction
.PP
This document reflects the use of
.I fsck
with the 4.2BSD and 4.3BSD file system organization. This
is a revision of the
original paper written by
T. J. Kowalski.
.PP
When a UNIX
operating system is brought up, a consistency
check of the file systems should always be performed.
This precautionary measure helps to insure
a reliable environment for file storage on disk.
If an inconsistency is discovered,
corrective action must be taken.
.I Fsck
runs in two modes.
Normally it is run non-interactively by the system after
a normal boot.
When running in this mode,
it will only make changes to the file system that are known
to always be correct.
If an unexpected inconsistency is found
.I fsck
will exit with a non-zero exit status,
leaving the system running single-user.
Typically the operator then runs
.I fsck
interactively.
When running in this mode,
each problem is listed followed by a suggested corrective action.
The operator must decide whether or not the suggested correction
should be made.
.PP
The purpose of this memo is to dispel the
mystique surrounding
file system inconsistencies.
It first describes the updating of the file system
(the calm before the storm) and
then describes file system corruption (the storm).
Finally,
the set of deterministic corrective actions
used by
.I fsck
(the Coast Guard
to the rescue) is presented.
.ds RH Overview of the File System

266
sbin/fsck_ffs/SMM.doc/2.t Normal file
View File

@ -0,0 +1,266 @@
.\" Copyright (c) 1982, 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)2.t 8.1 (Berkeley) 6/5/93
.\" $Id: 2.t,v 1.1 1994/06/08 19:01:22 mycroft Exp $
.\"
.ds RH Overview of the file system
.NH
Overview of the file system
.PP
The file system is discussed in detail in [Mckusick84];
this section gives a brief overview.
.NH 2
Superblock
.PP
A file system is described by its
.I "super-block" .
The super-block is built when the file system is created (\c
.I newfs (8))
and never changes.
The super-block
contains the basic parameters of the file system,
such as the number of data blocks it contains
and a count of the maximum number of files.
Because the super-block contains critical data,
.I newfs
replicates it to protect against catastrophic loss.
The
.I "default super block"
always resides at a fixed offset from the beginning
of the file system's disk partition.
The
.I "redundant super blocks"
are not referenced unless a head crash
or other hard disk error causes the default super-block
to be unusable.
The redundant blocks are sprinkled throughout the disk partition.
.PP
Within the file system are files.
Certain files are distinguished as directories and contain collections
of pointers to files that may themselves be directories.
Every file has a descriptor associated with it called an
.I "inode".
The inode contains information describing ownership of the file,
time stamps indicating modification and access times for the file,
and an array of indices pointing to the data blocks for the file.
In this section,
we assume that the first 12 blocks
of the file are directly referenced by values stored
in the inode structure itself\(dg.
.FS
\(dgThe actual number may vary from system to system, but is usually in
the range 5-13.
.FE
The inode structure may also contain references to indirect blocks
containing further data block indices.
In a file system with a 4096 byte block size, a singly indirect
block contains 1024 further block addresses,
a doubly indirect block contains 1024 addresses of further single indirect
blocks,
and a triply indirect block contains 1024 addresses of further doubly indirect
blocks (the triple indirect block is never needed in practice).
.PP
In order to create files with up to
2\(ua32 bytes,
using only two levels of indirection,
the minimum size of a file system block is 4096 bytes.
The size of file system blocks can be any power of two
greater than or equal to 4096.
The block size of the file system is maintained in the super-block,
so it is possible for file systems of different block sizes
to be accessible simultaneously on the same system.
The block size must be decided when
.I newfs
creates the file system;
the block size cannot be subsequently
changed without rebuilding the file system.
.NH 2
Summary information
.PP
Associated with the super block is non replicated
.I "summary information" .
The summary information changes
as the file system is modified.
The summary information contains
the number of blocks, fragments, inodes and directories in the file system.
.NH 2
Cylinder groups
.PP
The file system partitions the disk into one or more areas called
.I "cylinder groups".
A cylinder group is comprised of one or more consecutive
cylinders on a disk.
Each cylinder group includes inode slots for files, a
.I "block map"
describing available blocks in the cylinder group,
and summary information describing the usage of data blocks
within the cylinder group.
A fixed number of inodes is allocated for each cylinder group
when the file system is created.
The current policy is to allocate one inode for each 2048
bytes of disk space;
this is expected to be far more inodes than will ever be needed.
.PP
All the cylinder group bookkeeping information could be
placed at the beginning of each cylinder group.
However if this approach were used,
all the redundant information would be on the top platter.
A single hardware failure that destroyed the top platter
could cause the loss of all copies of the redundant super-blocks.
Thus the cylinder group bookkeeping information
begins at a floating offset from the beginning of the cylinder group.
The offset for
the
.I "i+1" st
cylinder group is about one track further
from the beginning of the cylinder group
than it was for the
.I "i" th
cylinder group.
In this way,
the redundant
information spirals down into the pack;
any single track, cylinder,
or platter can be lost without losing all copies of the super-blocks.
Except for the first cylinder group,
the space between the beginning of the cylinder group
and the beginning of the cylinder group information stores data.
.NH 2
Fragments
.PP
To avoid waste in storing small files,
the file system space allocator divides a single
file system block into one or more
.I "fragments".
The fragmentation of the file system is specified
when the file system is created;
each file system block can be optionally broken into
2, 4, or 8 addressable fragments.
The lower bound on the size of these fragments is constrained
by the disk sector size;
typically 512 bytes is the lower bound on fragment size.
The block map associated with each cylinder group
records the space availability at the fragment level.
Aligned fragments are examined
to determine block availability.
.PP
On a file system with a block size of 4096 bytes
and a fragment size of 1024 bytes,
a file is represented by zero or more 4096 byte blocks of data,
and possibly a single fragmented block.
If a file system block must be fragmented to obtain
space for a small amount of data,
the remainder of the block is made available for allocation
to other files.
For example,
consider an 11000 byte file stored on
a 4096/1024 byte file system.
This file uses two full size blocks and a 3072 byte fragment.
If no fragments with at least 3072 bytes
are available when the file is created,
a full size block is split yielding the necessary 3072 byte
fragment and an unused 1024 byte fragment.
This remaining fragment can be allocated to another file, as needed.
.NH 2
Updates to the file system
.PP
Every working day hundreds of files
are created, modified, and removed.
Every time a file is modified,
the operating system performs a
series of file system updates.
These updates, when written on disk, yield a consistent file system.
The file system stages
all modifications of critical information;
modification can
either be completed or cleanly backed out after a crash.
Knowing the information that is first written to the file system,
deterministic procedures can be developed to
repair a corrupted file system.
To understand this process,
the order that the update
requests were being honored must first be understood.
.PP
When a user program does an operation to change the file system,
such as a
.I write ,
the data to be written is copied into an internal
.I "in-core"
buffer in the kernel.
Normally, the disk update is handled asynchronously;
the user process is allowed to proceed even though
the data has not yet been written to the disk.
The data,
along with the inode information reflecting the change,
is eventually written out to disk.
The real disk write may not happen until long after the
.I write
system call has returned.
Thus at any given time, the file system,
as it resides on the disk,
lags the state of the file system represented by the in-core information.
.PP
The disk information is updated to reflect the in-core information
when the buffer is required for another use,
when a
.I sync (2)
is done (at 30 second intervals) by
.I "/etc/update" "(8),"
or by manual operator intervention with the
.I sync (8)
command.
If the system is halted without writing out the in-core information,
the file system on the disk will be in an inconsistent state.
.PP
If all updates are done asynchronously, several serious
inconsistencies can arise.
One inconsistency is that a block may be claimed by two inodes.
Such an inconsistency can occur when the system is halted before
the pointer to the block in the old inode has been cleared
in the copy of the old inode on the disk,
and after the pointer to the block in the new inode has been written out
to the copy of the new inode on the disk.
Here,
there is no deterministic method for deciding
which inode should really claim the block.
A similar problem can arise with a multiply claimed inode.
.PP
The problem with asynchronous inode updates
can be avoided by doing all inode deallocations synchronously.
Consequently,
inodes and indirect blocks are written to the disk synchronously
(\fIi.e.\fP the process blocks until the information is
really written to disk)
when they are being deallocated.
Similarly inodes are kept consistent by synchronously
deleting, adding, or changing directory entries.
.ds RH Fixing corrupted file systems

440
sbin/fsck_ffs/SMM.doc/3.t Normal file
View File

@ -0,0 +1,440 @@
.\" Copyright (c) 1982, 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)3.t 8.1 (Berkeley) 6/5/93
.\" $Id: 3.t,v 1.1 1994/06/08 19:01:23 mycroft Exp $
.\"
.ds RH Fixing corrupted file systems
.NH
Fixing corrupted file systems
.PP
A file system
can become corrupted in several ways.
The most common of these ways are
improper shutdown procedures
and hardware failures.
.PP
File systems may become corrupted during an
.I "unclean halt" .
This happens when proper shutdown
procedures are not observed,
physically write-protecting a mounted file system,
or a mounted file system is taken off-line.
The most common operator procedural failure is forgetting to
.I sync
the system before halting the CPU.
.PP
File systems may become further corrupted if proper startup
procedures are not observed, e.g.,
not checking a file system for inconsistencies,
and not repairing inconsistencies.
Allowing a corrupted file system to be used (and, thus, to be modified
further) can be disastrous.
.PP
Any piece of hardware can fail at any time.
Failures
can be as subtle as a bad block
on a disk pack, or as blatant as a non-functional disk-controller.
.NH 2
Detecting and correcting corruption
.PP
Normally
.I fsck
is run non-interactively.
In this mode it will only fix
corruptions that are expected to occur from an unclean halt.
These actions are a proper subset of the actions that
.I fsck
will take when it is running interactively.
Throughout this paper we assume that
.I fsck
is being run interactively,
and all possible errors can be encountered.
When an inconsistency is discovered in this mode,
.I fsck
reports the inconsistency for the operator to
chose a corrective action.
.PP
A quiescent\(dd
.FS
\(dd I.e., unmounted and not being written on.
.FE
file system may be checked for structural integrity
by performing consistency checks on the
redundant data intrinsic to a file system.
The redundant data is either read from
the file system,
or computed from other known values.
The file system
.B must
be in a quiescent state when
.I fsck
is run,
since
.I fsck
is a multi-pass program.
.PP
In the following sections,
we discuss methods to discover inconsistencies
and possible corrective actions
for the cylinder group blocks, the inodes, the indirect blocks, and
the data blocks containing directory entries.
.NH 2
Super-block checking
.PP
The most commonly corrupted item in a file system
is the summary information
associated with the super-block.
The summary information is prone to corruption
because it is modified with every change to the file
system's blocks or inodes,
and is usually corrupted
after an unclean halt.
.PP
The super-block is checked for inconsistencies
involving file-system size, number of inodes,
free-block count, and the free-inode count.
The file-system size must be larger than the
number of blocks used by the super-block
and the number of blocks used by the list of inodes.
The file-system size and layout information
are the most critical pieces of information for
.I fsck .
While there is no way to actually check these sizes,
since they are statically determined by
.I newfs ,
.I fsck
can check that these sizes are within reasonable bounds.
All other file system checks require that these sizes be correct.
If
.I fsck
detects corruption in the static parameters of the default super-block,
.I fsck
requests the operator to specify the location of an alternate super-block.
.NH 2
Free block checking
.PP
.I Fsck
checks that all the blocks
marked as free in the cylinder group block maps
are not claimed by any files.
When all the blocks have been initially accounted for,
.I fsck
checks that
the number of free blocks
plus the number of blocks claimed by the inodes
equals the total number of blocks in the file system.
.PP
If anything is wrong with the block allocation maps,
.I fsck
will rebuild them,
based on the list it has computed of allocated blocks.
.PP
The summary information associated with the super-block
counts the total number of free blocks within the file system.
.I Fsck
compares this count to the
number of free blocks it found within the file system.
If the two counts do not agree, then
.I fsck
replaces the incorrect count in the summary information
by the actual free-block count.
.PP
The summary information
counts the total number of free inodes within the file system.
.I Fsck
compares this count to the number
of free inodes it found within the file system.
If the two counts do not agree, then
.I fsck
replaces the incorrect count in the
summary information by the actual free-inode count.
.NH 2
Checking the inode state
.PP
An individual inode is not as likely to be corrupted as
the allocation information.
However, because of the great number of active inodes,
a few of the inodes are usually corrupted.
.PP
The list of inodes in the file system
is checked sequentially starting with inode 2
(inode 0 marks unused inodes;
inode 1 is saved for future generations)
and progressing through the last inode in the file system.
The state of each inode is checked for
inconsistencies involving format and type,
link count,
duplicate blocks,
bad blocks,
and inode size.
.PP
Each inode contains a mode word.
This mode word describes the type and state of the inode.
Inodes must be one of six types:
regular inode, directory inode, symbolic link inode,
special block inode, special character inode, or socket inode.
Inodes may be found in one of three allocation states:
unallocated, allocated, and neither unallocated nor allocated.
This last state suggests an incorrectly formated inode.
An inode can get in this state if
bad data is written into the inode list.
The only possible corrective action is for
.I fsck
is to clear the inode.
.NH 2
Inode links
.PP
Each inode counts the
total number of directory entries
linked to the inode.
.I Fsck
verifies the link count of each inode
by starting at the root of the file system,
and descending through the directory structure.
The actual link count for each inode
is calculated during the descent.
.PP
If the stored link count is non-zero and the actual
link count is zero,
then no directory entry appears for the inode.
If this happens,
.I fsck
will place the disconnected file in the
.I lost+found
directory.
If the stored and actual link counts are non-zero and unequal,
a directory entry may have been added or removed without the inode being
updated.
If this happens,
.I fsck
replaces the incorrect stored link count by the actual link count.
.PP
Each inode contains a list,
or pointers to
lists (indirect blocks),
of all the blocks claimed by the inode.
Since indirect blocks are owned by an inode,
inconsistencies in indirect blocks directly
affect the inode that owns it.
.PP
.I Fsck
compares each block number claimed by an inode
against a list of already allocated blocks.
If another inode already claims a block number,
then the block number is added to a list of
.I "duplicate blocks" .
Otherwise, the list of allocated blocks
is updated to include the block number.
.PP
If there are any duplicate blocks,
.I fsck
will perform a partial second
pass over the inode list
to find the inode of the duplicated block.
The second pass is needed,
since without examining the files associated with
these inodes for correct content,
not enough information is available
to determine which inode is corrupted and should be cleared.
If this condition does arise
(only hardware failure will cause it),
then the inode with the earliest
modify time is usually incorrect,
and should be cleared.
If this happens,
.I fsck
prompts the operator to clear both inodes.
The operator must decide which one should be kept
and which one should be cleared.
.PP
.I Fsck
checks the range of each block number claimed by an inode.
If the block number is
lower than the first data block in the file system,
or greater than the last data block,
then the block number is a
.I "bad block number" .
Many bad blocks in an inode are usually caused by
an indirect block that was not written to the file system,
a condition which can only occur if there has been a hardware failure.
If an inode contains bad block numbers,
.I fsck
prompts the operator to clear it.
.NH 2
Inode data size
.PP
Each inode contains a count of the number of data blocks
that it contains.
The number of actual data blocks
is the sum of the allocated data blocks
and the indirect blocks.
.I Fsck
computes the actual number of data blocks
and compares that block count against
the actual number of blocks the inode claims.
If an inode contains an incorrect count
.I fsck
prompts the operator to fix it.
.PP
Each inode contains a thirty-two bit size field.
The size is the number of data bytes
in the file associated with the inode.
The consistency of the byte size field is roughly checked
by computing from the size field the maximum number of blocks
that should be associated with the inode,
and comparing that expected block count against
the actual number of blocks the inode claims.
.NH 2
Checking the data associated with an inode
.PP
An inode can directly or indirectly
reference three kinds of data blocks.
All referenced blocks must be the same kind.
The three types of data blocks are:
plain data blocks, symbolic link data blocks, and directory data blocks.
Plain data blocks
contain the information stored in a file;
symbolic link data blocks
contain the path name stored in a link.
Directory data blocks contain directory entries.
.I Fsck
can only check the validity of directory data blocks.
.PP
Each directory data block is checked for
several types of inconsistencies.
These inconsistencies include
directory inode numbers pointing to unallocated inodes,
directory inode numbers that are greater than
the number of inodes in the file system,
incorrect directory inode numbers for ``\fB.\fP'' and ``\fB..\fP'',
and directories that are not attached to the file system.
If the inode number in a directory data block
references an unallocated inode,
then
.I fsck
will remove that directory entry.
Again,
this condition can only arise when there has been a hardware failure.
.PP
If a directory entry inode number references
outside the inode list, then
.I fsck
will remove that directory entry.
This condition occurs if bad data is written into a directory data block.
.PP
The directory inode number entry for ``\fB.\fP''
must be the first entry in the directory data block.
The inode number for ``\fB.\fP''
must reference itself;
e.g., it must equal the inode number
for the directory data block.
The directory inode number entry
for ``\fB..\fP'' must be
the second entry in the directory data block.
Its value must equal the inode number for the
parent of the directory entry
(or the inode number of the directory
data block if the directory is the
root directory).
If the directory inode numbers are
incorrect,
.I fsck
will replace them with the correct values.
If there are multiple hard links to a directory,
the first one encountered is considered the real parent
to which ``\fB..\fP'' should point;
\fIfsck\fP recommends deletion for the subsequently discovered names.
.NH 2
File system connectivity
.PP
.I Fsck
checks the general connectivity of the file system.
If directories are not linked into the file system, then
.I fsck
links the directory back into the file system in the
.I lost+found
directory.
This condition only occurs when there has been a hardware failure.
.ds RH "References"
.SH
\s+2Acknowledgements\s0
.PP
I thank Bill Joy, Sam Leffler, Robert Elz and Dennis Ritchie
for their suggestions and help in implementing the new file system.
Thanks also to Robert Henry for his editorial input to
get this document together.
Finally we thank our sponsors,
the National Science Foundation under grant MCS80-05144,
and the Defense Advance Research Projects Agency (DoD) under
Arpa Order No. 4031 monitored by Naval Electronic System Command under
Contract No. N00039-82-C-0235. (Kirk McKusick, July 1983)
.PP
I would like to thank Larry A. Wehr for advice that lead
to the first version of
.I fsck
and Rick B. Brandt for adapting
.I fsck
to
UNIX/TS. (T. Kowalski, July 1979)
.sp 2
.SH
\s+2References\s0
.LP
.IP [Dolotta78] 20
Dolotta, T. A., and Olsson, S. B. eds.,
.I "UNIX User's Manual, Edition 1.1\^" ,
January 1978.
.IP [Joy83] 20
Joy, W., Cooper, E., Fabry, R., Leffler, S., McKusick, M., and Mosher, D.
4.2BSD System Manual,
.I "University of California at Berkeley" ,
.I "Computer Systems Research Group Technical Report"
#4, 1982.
.IP [McKusick84] 20
McKusick, M., Joy, W., Leffler, S., and Fabry, R.
A Fast File System for UNIX,
\fIACM Transactions on Computer Systems 2\fP, 3.
pp. 181-197, August 1984.
.IP [Ritchie78] 20
Ritchie, D. M., and Thompson, K.,
The UNIX Time-Sharing System,
.I "The Bell System Technical Journal"
.B 57 ,
6 (July-August 1978, Part 2), pp. 1905-29.
.IP [Thompson78] 20
Thompson, K.,
UNIX Implementation,
.I "The Bell System Technical Journal\^"
.B 57 ,
6 (July-August 1978, Part 2), pp. 1931-46.
.ds RH Appendix A \- Fsck Error Conditions
.bp

1425
sbin/fsck_ffs/SMM.doc/4.t Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/8/93
# $Id: Makefile,v 1.1 1994/06/08 19:01:26 mycroft Exp $
DIR= smm/03.fsck
SRCS= 0.t 1.t 2.t 3.t 4.t
MACROS= -ms
.include <bsd.doc.mk>

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,18 +32,15 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)dir.c 5.19 (Berkeley) 7/26/91";*/
static char rcsid[] = "$Id: dir.c,v 1.6 1994/04/25 18:28:20 cgd Exp $";
/*static char sccsid[] = "from: @(#)dir.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: dir.c,v 1.7 1994/06/08 19:00:19 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#define KERNEL
#include <ufs/dir.h>
#undef KERNEL
#include <stddef.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <stdlib.h>
#include <string.h>
#include "fsck.h"
@ -51,7 +48,14 @@ static char rcsid[] = "$Id: dir.c,v 1.6 1994/04/25 18:28:20 cgd Exp $";
char *lfname = "lost+found";
int lfmode = 01777;
struct dirtemplate emptydir = { 0, DIRBLKSIZ };
struct dirtemplate dirhead = { 0, 12, 1, ".", 0, DIRBLKSIZ - 12, 2, ".." };
struct dirtemplate dirhead = {
0, 12, DT_DIR, 1, ".",
0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
};
struct odirtemplate odirhead = {
0, 12, 1, ".",
0, DIRBLKSIZ - 12, 2, ".."
};
struct direct *fsck_readdir();
struct bufarea *getdirblk();
@ -107,8 +111,29 @@ dirscan(idesc)
for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
dsize = dp->d_reclen;
bcopy((char *)dp, dbuf, (size_t)dsize);
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt) {
struct direct *tdp = (struct direct *)dbuf;
u_char tmp;
tmp = tdp->d_namlen;
tdp->d_namlen = tdp->d_type;
tdp->d_type = tmp;
}
# endif
idesc->id_dirp = (struct direct *)dbuf;
if ((n = (*idesc->id_func)(idesc)) & ALTERED) {
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt && !doinglevel2) {
struct direct *tdp;
u_char tmp;
tdp = (struct direct *)dbuf;
tmp = tdp->d_namlen;
tdp->d_namlen = tdp->d_type;
tdp->d_type = tmp;
}
# endif
bp = getdirblk(idesc->id_blkno, blksiz);
bcopy(dbuf, bp->b_un.b_buf + idesc->id_loc - dsize,
(size_t)dsize);
@ -130,39 +155,34 @@ fsck_readdir(idesc)
{
register struct direct *dp, *ndp;
register struct bufarea *bp;
long blksiz, new_id_filesize;
int fix, new_id_loc, new_reclen, orig_id_loc, size;
long size, blksiz, fix, dploc;
blksiz = idesc->id_numfrags * sblock.fs_fsize;
bp = getdirblk(idesc->id_blkno, blksiz);
orig_id_loc = idesc->id_loc;
if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 &&
idesc->id_loc < blksiz) {
dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
if (dircheck(idesc, dp))
goto dpok;
/*
* See below about recursion.
*/
new_id_loc = idesc->id_loc + DIRBLKSIZ;
new_id_filesize = idesc->id_filesize - DIRBLKSIZ;
fix = dofix(idesc, "DIRECTORY CORRUPTED");
idesc->id_loc = new_id_loc;
idesc->id_filesize = new_id_filesize;
bp = getdirblk(idesc->id_blkno, blksiz);
dp = (struct direct *)(bp->b_un.b_buf + orig_id_loc);
dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
dp->d_reclen = DIRBLKSIZ;
dp->d_ino = 0;
dp->d_type = 0;
dp->d_namlen = 0;
dp->d_name[0] = '\0';
if (fix)
dirty(bp);
idesc->id_loc += DIRBLKSIZ;
idesc->id_filesize -= DIRBLKSIZ;
return (dp);
}
dpok:
if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz)
return NULL;
dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
dploc = idesc->id_loc;
dp = (struct direct *)(bp->b_un.b_buf + dploc);
idesc->id_loc += dp->d_reclen;
idesc->id_filesize -= dp->d_reclen;
if ((idesc->id_loc % DIRBLKSIZ) == 0)
@ -171,23 +191,12 @@ dpok:
if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
dircheck(idesc, ndp) == 0) {
size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
/*
* dofix() may recurse here. Don't let it cause multiple
* fixups.
*/
new_id_loc = idesc->id_loc + size;
new_id_filesize = idesc->id_filesize - size;
new_reclen = dp->d_reclen + size;
idesc->id_loc += size;
idesc->id_filesize -= size;
fix = dofix(idesc, "DIRECTORY CORRUPTED");
idesc->id_loc = new_id_loc;
idesc->id_filesize = new_id_filesize;
/*
* dofix() calls fsck_readdir() and getdirblk() discards
* the lock on bp so bp may now be invalid.
*/
bp = getdirblk(idesc->id_blkno, blksiz);
dp = (struct direct *)(bp->b_un.b_buf + orig_id_loc);
dp->d_reclen = new_reclen;
dp = (struct direct *)(bp->b_un.b_buf + dploc);
dp->d_reclen += size;
if (fix)
dirty(bp);
}
@ -204,22 +213,34 @@ dircheck(idesc, dp)
{
register int size;
register char *cp;
u_char namlen, type;
int spaceleft;
size = DIRSIZ(!newinofmt, dp);
spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
if (spaceleft < offsetof(struct direct, d_name))
return (0); /* dp is bad; don't use it */
size = DIRSIZ(dp);
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt) {
type = dp->d_namlen;
namlen = dp->d_type;
} else {
namlen = dp->d_namlen;
type = dp->d_type;
}
# else
namlen = dp->d_namlen;
type = dp->d_type;
# endif
if (dp->d_ino < maxino &&
dp->d_reclen != 0 &&
dp->d_reclen <= spaceleft &&
(dp->d_reclen & 0x3) == 0 &&
dp->d_reclen >= size &&
idesc->id_filesize >= size &&
dp->d_namlen <= MAXNAMLEN) {
namlen <= MAXNAMLEN &&
type <= 15) {
if (dp->d_ino == 0)
return (1);
for (cp = dp->d_name, size = 0; size < dp->d_namlen; size++)
for (cp = dp->d_name, size = 0; size < namlen; size++)
if (*cp == 0 || (*cp++ == '/'))
return (0);
if (*cp == 0)
@ -297,9 +318,9 @@ mkentry(idesc)
int newlen, oldlen;
newent.d_namlen = strlen(idesc->id_name);
newlen = DIRSIZ(&newent);
newlen = DIRSIZ(0, &newent);
if (dirp->d_ino != 0)
oldlen = DIRSIZ(dirp);
oldlen = DIRSIZ(0, dirp);
else
oldlen = 0;
if (dirp->d_reclen - oldlen < newlen)
@ -308,6 +329,10 @@ mkentry(idesc)
dirp->d_reclen = oldlen;
dirp = (struct direct *)(((char *)dirp) + oldlen);
dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */
if (newinofmt)
dirp->d_type = typemap[idesc->id_parent];
else
dirp->d_type = 0;
dirp->d_reclen = newent.d_reclen;
dirp->d_namlen = newent.d_namlen;
bcopy(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1);
@ -322,6 +347,10 @@ chgino(idesc)
if (bcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1))
return (KEEPON);
dirp->d_ino = idesc->id_parent;
if (newinofmt)
dirp->d_type = typemap[idesc->id_parent];
else
dirp->d_type = 0;
return (ALTERED|STOP);
}
@ -551,17 +580,22 @@ allocdir(parent, request, mode)
char *cp;
struct dinode *dp;
register struct bufarea *bp;
struct dirtemplate *dirp;
ino = allocino(request, IFDIR|mode);
dirhead.dot_ino = ino;
dirhead.dotdot_ino = parent;
if (newinofmt)
dirp = &dirhead;
else
dirp = (struct dirtemplate *)&odirhead;
dirp->dot_ino = ino;
dirp->dotdot_ino = parent;
dp = ginode(ino);
bp = getdirblk(dp->di_db[0], sblock.fs_fsize);
if (bp->b_errs) {
freeino(ino);
return (0);
}
bcopy((char *)&dirhead, bp->b_un.b_buf, sizeof dirhead);
bcopy((char *)dirp, bp->b_un.b_buf, sizeof(struct dirtemplate));
for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
cp < &bp->b_un.b_buf[sblock.fs_fsize];
cp += DIRBLKSIZ)

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -30,8 +30,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)fsck.h 5.17 (Berkeley) 7/27/90
* $Id: fsck.h,v 1.5 1994/05/02 10:18:21 pk Exp $
* from: @(#)fsck.h 8.1 (Berkeley) 6/5/93
* $Id: fsck.h,v 1.6 1994/06/08 19:00:21 mycroft Exp $
*/
#define MAXDUP 10 /* limit on dup blks (per inode) */
@ -78,6 +78,7 @@ struct bufarea sblk; /* file system superblock */
struct bufarea cgblk; /* cylinder group blocks */
struct bufarea *pdirbp; /* current directory contents */
struct bufarea *pbp; /* current inode block */
struct bufarea *getdatablk();
#define dirty(bp) (bp)->b_dirty = 1
#define initbarea(bp) \
@ -99,7 +100,7 @@ struct inodesc {
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 */
long id_filesize; /* for DATA nodes, the size of the directory */
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 direct *id_dirp; /* for DATA nodes, ptr to current entry */
@ -161,14 +162,17 @@ struct inoinfo {
} **inphead, **inpsort;
long numdirs, listmax, inplast;
char *devname; /* name of device being checked */
char *cdevname; /* name of device being checked */
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 debug; /* output debugging info */
int cvtflag; /* convert to old file system format */
int cvtlevel; /* convert to newer file system format */
int doinglevel1; /* converting to new cylinder group format */
int doinglevel2; /* converting to new inode format */
int newinofmt; /* filesystem has new inode format */
char preen; /* just fix normal inconsistencies */
char hotroot; /* checking root device */
char havesb; /* superblock has been read */
@ -181,6 +185,7 @@ 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 */
char *typemap; /* ptr to inode type table */
short *lncntp; /* ptr to link count table */
ino_t lfdir; /* lost & found directory inode number */
@ -203,32 +208,9 @@ struct dinode zino;
#define ALTERED 0x08
#define FOUND 0x10
int ckinode __P((struct dinode *, struct inodesc *));
int iblock __P((struct inodesc *, long, u_long));
int chkrange __P((daddr_t, int));
struct dinode *ginode __P((ino_t));
struct dinode *getnextinode __P((ino_t));
void cacheino __P((struct dinode *, ino_t));
struct inoinfo *getinoinfo __P((ino_t));
void resetinodebuf __P((void));
void freeinodebuf __P((void));
void inocleanup __P((void));
void inodirty __P((void));
void clri __P((struct inodesc *, char *, int));
int findname __P((struct inodesc *));
int findino __P((struct inodesc *));
void pinode __P((ino_t));
void blkerror __P((ino_t, char *, daddr_t));
ino_t allocino __P((ino_t, int));
void freeino __P((ino_t));
int ftypeok __P((struct dinode *));
struct bufarea *getdatablk __P((daddr_t, long));
void getblk __P((struct bufarea *, daddr_t, long));
void flush __P((int, struct bufarea *));
int bread __P((int, char *, daddr_t, long));
int bwrite __P((int, char *, daddr_t, long));
int allocblk __P((long));
void freeblk __P((daddr_t, long));
void getpathname __P((char *, ino_t, ino_t));
time_t time();
struct dinode *ginode();
struct inoinfo *getinoinfo();
void getblk();
ino_t allocino();
int findino();

View File

@ -1,5 +1,5 @@
.\" Copyright (c) 1980, 1989 Regents of the University of California.
.\" All rights reserved.
.\" 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
@ -29,33 +29,32 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)fsck.8 6.9 (Berkeley) 4/20/91
.\" $Id: fsck_ffs.8,v 1.6 1994/04/13 10:12:33 deraadt Exp $
.\" from: @(#)fsck.8 8.2 (Berkeley) 12/11/93
.\" $Id: fsck_ffs.8,v 1.7 1994/06/08 19:00:20 mycroft Exp $
.\"
.Dd April 20, 1991
.Dd December 11, 1993
.Dt FSCK 8
.Os BSD 4.2
.de us
\\$1\l'|0\(ul'
..
.Os BSD 4
.Sh NAME
.Nm fsck
.Nd file system consistency check and interactive repair
.Nm fsck
.Nd filesystem consistency check and interactive repair
.Sh SYNOPSIS
.Nm fsck
.Fl p
.Op Fl m Ar mode
.Nm fsck
.Op Fl b Ar block#
.Op Fl c
.Op Fl c Ar level
.Op Fl l Ar maxparallel
.Op Fl y
.Op Fl n
.Op Fl m Ar mode
.Op Ar filesystem ...
.Op Ar filesystem
.Ar ...
.Sh DESCRIPTION
The first form of
.Nm fsck
preens a standard set of filesystems or the specified file systems.
preens a standard set of filesystems or the specified filesystems.
It is normally used in the script
.Pa /etc/rc
during automatic reboot.
@ -63,12 +62,8 @@ Here
.Nm fsck
reads the table
.Pa /etc/fstab
to determine which file systems to check.
Only partitions in fstab that are mounted
.Dq rw ,
.Dq rq
or
.Dq ro
to determine which filesystems to check.
Only partitions in fstab that are mounted ``rw,'' ``rq'' or ``ro''
and that have non-zero pass number are checked.
Filesystems with pass number 1 (normally just the root filesystem)
are checked one at a time.
@ -78,10 +73,10 @@ The disk drive containing each filesystem 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 system takes care that only a restricted class of innocuous
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:
.Bl -item -offset indent
.Bl -item -compact
.It
Unreferenced inodes
.It
@ -101,27 +96,29 @@ with the
option will correct; if it encounters other inconsistencies, it exits
with an abnormal return status and an automatic reboot will then fail.
For each corrected inconsistency one or more lines will be printed
identifying the file system on which the correction will take place,
and the nature of the correction. After successfully correcting a file
system,
identifying the filesystem on which the correction will take place,
and the nature of the correction. After successfully correcting a filesystem,
.Nm fsck
will print the number of files on that file system,
will print the number of files on that filesystem,
the number of used and free blocks,
and the percentage of fragmentation.
.Pp
If sent a QUIT signal,
If sent a
.Dv QUIT
signal,
.Nm fsck
will finish the file system checks, then exit with an abnormal
will finish the filesystem checks, then exit with an abnormal
return status that causes an automatic reboot to fail.
This is useful when to finish the file system checks during an automatic reboot,
This is useful when you want to finish the filesystem checks during an
automatic reboot,
but do not want the machine to come up multiuser after the checks complete.
.Pp
Without the
.Fl p
option,
.Nm fsck
audits and interactively repairs inconsistent conditions for file systems.
If the file system is inconsistent the operator is prompted for concurrence
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
@ -130,11 +127,11 @@ 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
.Ic yes
is to wait for the operator to respond
.Li yes
or
.Ic no .
If the operator does not have write permission on the file system
.Li no .
If the operator does not have write permission on the filesystem
.Nm fsck
will default to a
.Fl n
@ -143,19 +140,17 @@ action.
.Nm Fsck
has more consistency checks than
its predecessors
.Nm check ,
.Nm dcheck ,
.Nm fcheck ,
.Em check , dcheck , fcheck ,
and
.Nm icheck
.Em icheck
combined.
.Pp
The following flags are interpreted by
.Nm fsck.
.Nm fsck .
.Bl -tag -width indent
.It Fl b
Use the block specified immediately after the flag as
the super block for the file system. Block 32 is usually
the super block for the filesystem. Block 32 is usually
an alternate super block.
.It Fl l
Limit the number of parallel checks to the number specified in the following
@ -165,8 +160,9 @@ If a smaller limit is given, the disks are checked round-robin, one filesystem
at a time.
.It Fl m
Use the mode specified in octal immediately after the flag as the
permission bits to use when creating the lost+found directory
rather than the default 1777.
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.
@ -178,50 +174,60 @@ to continue after essentially unlimited trouble has been encountered.
.It Fl n
Assume a no response to all questions asked by
.Nm fsck
except for
.Dq CONTINUE? ,
which is assumed to be affirmative; do not open the file system for writing.
except for
.Ql CONTINUE? ,
which is assumed to be affirmative;
do not open the filesystem for writing.
.It Fl c
If the file system is in the old (static table) format,
convert it to the new (dynamic table) format.
If the file system is in the new format,
convert it to the old format provided the old format
can support the filesystem configuration.
Convert the filesystem to the specified level.
Note that the level of a filesystem can only be raised.
.Bl -tag -width indent
There are currently three levels defined:
.It 0
The filesystem is in the old (static table) format.
.It 1
The filesystem is in the new (dynamic table) format.
.It 2
The filesystem supports 32-bit uid's and gid's,
short symbolic links are stored in the inode,
and directories have an added field showing the file type.
.El
.Pp
In interactive mode,
.Nm fsck
will list the direction the conversion is to be made
will list the conversion to be made
and ask whether the conversion should be done.
If a negative answer is given,
no further operations are done on the filesystem.
In preen mode,
the direction of the conversion is listed and done if
the conversion is listed and done if
possible without user interaction.
Conversion in preen mode is best used when all the file systems
Conversion in preen mode is best used when all the filesystems
are being converted at once.
The format of a file system can be determined from the
The format of a filesystem can be determined from the
first line of output from
.Xr dumpfs 8 .
.El
.Pp
If no filesystems are given to
.Nm fsck
then a default list of file systems is read from
then a default list of filesystems is read from
the file
.Pa /etc/fstab .
.Pp
.Bl -enum -indent indent -compact
Inconsistencies checked are as follows:
.Bl -enum -width 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 file system.
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 of proper format.
.Bl -item -indent indent -compact
.It
Directory size not a multiple of DIRBLKSIZ.
.It
Partially truncated file.
.El
@ -231,8 +237,8 @@ Bad inode format.
Blocks not accounted for anywhere.
.It
Directory checks:
.Bl -item -offset indent -compact
.It
.Bl -item -indent indent -compact
.It
File pointing to unallocated inode.
.It
Inode number out of range.
@ -242,15 +248,15 @@ 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 file system.
.El
.Bl -item -indent 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
@ -266,15 +272,17 @@ If there is insufficient space its size is increased.
Because of inconsistencies between the block device and the buffer cache,
the raw device should always be used.
.Sh FILES
.Bl -tag -width indent-two -compact
.Bl -tag -width /etc/fstab -compact
.It Pa /etc/fstab
contains default list of file systems to check.
contains default list of filesystems to check.
.El
.Sh DIAGNOSTICS
The diagnostics produced by
.Nm fsck
are fully enumerated and explained in Appendix A of
``Fsck \- The UNIX File System Check Program'' (SMM:5).
.Rs
.%T "Fsck \- The UNIX File System Check Program"
.Re
.Sh SEE ALSO
.Xr fstab 5 ,
.Xr fs 5 ,

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,15 +32,15 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)inode.c 5.18 (Berkeley) 3/19/91";*/
static char rcsid[] = "$Id: inode.c,v 1.8 1994/05/02 10:18:23 pk Exp $";
/*static char sccsid[] = "from: @(#)inode.c 8.4 (Berkeley) 4/18/94";*/
static char *rcsid = "$Id: inode.c,v 1.9 1994/06/08 19:00:23 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/dir.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#ifndef SMALL
#include <pwd.h>
#endif
@ -50,7 +50,6 @@ static char rcsid[] = "$Id: inode.c,v 1.8 1994/05/02 10:18:23 pk Exp $";
static ino_t startinum;
int
ckinode(dp, idesc)
struct dinode *dp;
register struct inodesc *idesc;
@ -58,13 +57,17 @@ ckinode(dp, idesc)
register daddr_t *ap;
long ret, n, ndb, offset;
struct dinode dino;
quad_t remsize, sizepb;
mode_t mode;
if (idesc->id_fix != IGNORE)
idesc->id_fix = DONTKNOW;
idesc->id_entryno = 0;
idesc->id_filesize = dp->di_size;
if ((dp->di_mode & IFMT) == IFBLK || (dp->di_mode & IFMT) == IFCHR ||
DFASTLINK(*dp))
mode = dp->di_mode & IFMT;
if (mode == IFBLK || mode == IFCHR || (mode == IFLNK &&
(dp->di_size < sblock.fs_maxsymlinklen ||
(sblock.fs_maxsymlinklen == 0 && OLDFASTLINK(dp)))))
return (KEEPON);
dino = *dp;
ndb = howmany(dino.di_size, sblock.fs_bsize);
@ -85,28 +88,31 @@ ckinode(dp, idesc)
return (ret);
}
idesc->id_numfrags = sblock.fs_frag;
remsize = dino.di_size - sblock.fs_bsize * NDADDR;
sizepb = sblock.fs_bsize;
for (ap = &dino.di_ib[0], n = 1; n <= NIADDR; ap++, n++) {
if (*ap) {
idesc->id_blkno = *ap;
ret = iblock(idesc, n,
dino.di_size - sblock.fs_bsize * NDADDR);
ret = iblock(idesc, n, remsize);
if (ret & STOP)
return (ret);
}
sizepb *= NINDIR(&sblock);
remsize -= sizepb;
}
return (KEEPON);
}
int
iblock(idesc, ilevel, isize)
struct inodesc *idesc;
register long ilevel;
u_long isize;
long ilevel;
quad_t isize;
{
register daddr_t *ap;
register daddr_t *aplim;
int i, n, (*func)(), nif, sizepb;
register struct bufarea *bp;
int i, n, (*func)(), nif;
quad_t sizepb;
char buf[BUFSIZ];
extern int dirscan(), pass1check();
@ -122,7 +128,7 @@ iblock(idesc, ilevel, isize)
ilevel--;
for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
sizepb *= NINDIR(&sblock);
nif = isize / sizepb + 1;
nif = howmany(isize , sizepb);
if (nif > NINDIR(&sblock))
nif = NINDIR(&sblock);
if (idesc->id_func == pass1check && nif < NINDIR(&sblock)) {
@ -140,18 +146,19 @@ iblock(idesc, ilevel, isize)
flush(fswritefd, bp);
}
aplim = &bp->b_un.b_indir[nif];
for (ap = bp->b_un.b_indir, i = 1; ap < aplim; ap++, i++) {
for (ap = bp->b_un.b_indir; ap < aplim; ap++) {
if (*ap) {
idesc->id_blkno = *ap;
if (ilevel > 0)
n = iblock(idesc, ilevel, isize - i * sizepb);
else
if (ilevel == 0)
n = (*func)(idesc);
else
n = iblock(idesc, ilevel, isize);
if (n & STOP) {
bp->b_flags &= ~B_INUSE;
return (n);
}
}
isize -= sizepb;
}
bp->b_flags &= ~B_INUSE;
return (KEEPON);
@ -161,7 +168,6 @@ iblock(idesc, ilevel, isize)
* Check that a block in a legal block number.
* Return 0 if in range, 1 if out of range.
*/
int
chkrange(blk, cnt)
daddr_t blk;
int cnt;
@ -208,7 +214,7 @@ ginode(inumber)
errexit("bad inode number %d to ginode\n", inumber);
if (startinum == 0 ||
inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
iblk = itod(&sblock, inumber);
iblk = ino_to_fsba(&sblock, inumber);
if (pbp != 0)
pbp->b_flags &= ~B_INUSE;
pbp = getdatablk(iblk, sblock.fs_bsize);
@ -237,7 +243,7 @@ getnextinode(inumber)
errexit("bad inode number %d to nextinode\n", inumber);
if (inumber >= lastinum) {
readcnt++;
dblk = fsbtodb(&sblock, itod(&sblock, lastinum));
dblk = fsbtodb(&sblock, ino_to_fsba(&sblock, lastinum));
if (readcnt % readpercg == 0) {
size = partialsize;
lastinum += partialcnt;
@ -251,7 +257,6 @@ getnextinode(inumber)
return (dp++);
}
void
resetinodebuf()
{
@ -277,7 +282,6 @@ resetinodebuf()
(void)getnextinode(nextino);
}
void
freeinodebuf()
{
@ -293,7 +297,6 @@ freeinodebuf()
*
* Enter inodes into the cache.
*/
void
cacheino(dp, inumber)
register struct dinode *dp;
ino_t inumber;
@ -350,7 +353,6 @@ getinoinfo(inumber)
/*
* Clean up all the inode cache structure.
*/
void
inocleanup()
{
register struct inoinfo **inpp;
@ -363,15 +365,13 @@ inocleanup()
free((char *)inpsort);
inphead = inpsort = NULL;
}
void
inodirty()
{
dirty(pbp);
}
void
clri(idesc, type, flag)
register struct inodesc *idesc;
char *type;
@ -396,7 +396,6 @@ clri(idesc, type, flag)
}
}
int
findname(idesc)
struct inodesc *idesc;
{
@ -408,7 +407,6 @@ findname(idesc)
return (STOP|FOUND);
}
int
findino(idesc)
struct inodesc *idesc;
{
@ -424,7 +422,6 @@ findino(idesc)
return (KEEPON);
}
void
pinode(ino)
ino_t ino;
{
@ -446,13 +443,12 @@ pinode(ino)
printf("%u ", (unsigned)dp->di_uid);
printf("MODE=%o\n", dp->di_mode);
if (preen)
printf("%s: ", devname);
printf("SIZE=%lu ", dp->di_size);
p = ctime(&dp->di_mtime);
printf("%s: ", cdevname);
printf("SIZE=%qu ", dp->di_size);
p = ctime(&dp->di_mtime.ts_sec);
printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]);
}
void
blkerror(ino, type, blk)
ino_t ino;
char *type;
@ -520,19 +516,19 @@ allocino(request, type)
}
dp->di_mode = type;
(void)time(&dp->di_atime.ts_sec);
dp->di_atime.ts_nsec = 0;
dp->di_mtime = dp->di_ctime = dp->di_atime;
dp->di_size = sblock.fs_fsize;
dp->di_blocks = btodb(sblock.fs_fsize);
n_files++;
inodirty();
if (newinofmt)
typemap[ino] = IFTODT(type);
return (ino);
}
/*
* deallocate an inode
*/
void
freeino(ino)
ino_t ino;
{

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,20 +32,21 @@
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\
All rights reserved.\n";
static char copyright[] =
"@(#) Copyright (c) 1980, 1986, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)main.c 5.27 (Berkeley) 8/7/90";*/
static char rcsid[] = "$Id: main.c,v 1.12 1994/04/25 18:28:29 cgd Exp $";
/*static char sccsid[] = "from: @(#)main.c 8.2 (Berkeley) 1/23/94";*/
static char *rcsid = "$Id: main.c,v 1.13 1994/06/08 19:00:24 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <sys/mount.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <fstab.h>
#include <stdlib.h>
#include <string.h>
@ -63,11 +64,11 @@ main(argc, argv)
int ch;
int ret, maxrun = 0;
extern int docheck(), checkfilesys();
extern char *optarg;
extern char *optarg, *blockcheck();
extern int optind;
sync();
while ((ch = getopt(argc, argv, "cdpnNyYb:l:m:")) != EOF) {
while ((ch = getopt(argc, argv, "dpnNyYb:c:l:m:")) != EOF) {
switch (ch) {
case 'p':
preen++;
@ -79,9 +80,9 @@ main(argc, argv)
break;
case 'c':
cvtflag++;
cvtlevel = argtoi('c', "conversion level", optarg, 10);
break;
case 'd':
debug++;
break;
@ -121,7 +122,7 @@ main(argc, argv)
(void)signal(SIGQUIT, catchquit);
if (argc) {
while (argc-- > 0)
(void)checkfilesys(*argv++, (char *)0, 0L, 0);
(void)checkfilesys(blockcheck(*argv++), 0, 0L, 0);
exit(0);
}
ret = checkfstab(preen, maxrun, docheck, checkfilesys);
@ -170,11 +171,11 @@ checkfilesys(filesys, mntpt, auxdata, child)
daddr_t n_ffree, n_bfree;
struct dups *dp;
struct zlncnt *zlnp;
int clean;
int cylno;
if (preen && child)
(void)signal(SIGQUIT, voidquit);
devname = filesys;
cdevname = filesys;
if (debug && preen)
pwarn("starting\n");
if (setup(filesys) == 0) {
@ -182,71 +183,55 @@ checkfilesys(filesys, mntpt, auxdata, child)
pfatal("CAN'T CHECK FILE SYSTEM.");
return (0);
}
/*
* 1: scan inodes tallying blocks used
*/
if (preen == 0) {
printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
if (hotroot)
printf("** Root file system\n");
printf("** Phase 1 - Check Blocks and Sizes\n");
}
pass1();
/*
* 0: check whether file system is already clean
* 1b: locate first references to duplicates, if any
*/
clean = preen && (sblock.fs_state == FSOKAY) && sblock.fs_clean;
#ifdef notyet
if (clean) {
#else
if (0) {
#endif
printf("** filesystem clean -- skipping checks\n");
} else {
/*
* 1: scan inodes tallying blocks used
*/
if (preen == 0) {
printf("** Last Mounted on %s\n", sblock.fs_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();
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
*/
@ -254,8 +239,9 @@ checkfilesys(filesys, mntpt, auxdata, child)
n_bfree = sblock.fs_cstotal.cs_nbfree;
pwarn("%ld files, %ld used, %ld free ",
n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree);
printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n",
n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize);
printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n",
n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize,
((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10);
if (debug &&
(n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree))
printf("%ld files missing\n", n_files);
@ -281,30 +267,51 @@ checkfilesys(filesys, mntpt, auxdata, child)
}
zlnhead = (struct zlncnt *)0;
duplist = (struct dups *)0;
muldup = (struct dups *)0;
inocleanup();
#ifdef notyet
if (!clean && !nflag && fswritefd != -1) {
sblock.fs_state = FSOKAY;
sblock.fs_clean = FS_CLEANFREQ;
fsmodified = 1;
}
#endif
if (fsmodified) {
(void)time(&sblock.fs_time);
sbdirty();
}
if (cvtlevel && sblk.b_dirty) {
/*
* Write out the duplicate super blocks
*/
for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
bwrite(fswritefd, (char *)&sblock,
fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE);
}
ckfini();
free(blockmap);
free(statemap);
free((char *)lncntp);
if (!fsmodified)
return (0);
if (!preen) {
if (!preen)
printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
if (hotroot)
printf("\n***** REBOOT NETBSD *****\n");
}
if (hotroot) {
struct statfs stfs_buf;
/*
* We modified the root. Do a mount update on
* it, unless it is read-write, so we can continue.
*/
if (statfs("/", &stfs_buf) == 0) {
long flags = stfs_buf.f_flags;
struct ufs_args args;
int ret;
if (flags & MNT_RDONLY) {
args.fspec = 0;
args.export.ex_flags = 0;
args.export.ex_root = 0;
flags |= MNT_UPDATE | MNT_RELOAD;
ret = mount(MOUNT_UFS, "/", flags, &args);
if (ret == 0)
return(0);
}
}
if (!preen)
printf("\n***** REBOOT NOW *****\n");
sync();
return (4);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,14 +32,15 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass1.c 5.16 (Berkeley) 3/19/91";*/
static char rcsid[] = "$Id: pass1.c,v 1.6 1994/04/25 18:28:35 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass1.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: pass1.c,v 1.7 1994/06/08 19:00:25 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <stdlib.h>
#include <string.h>
#include "fsck.h"
@ -51,12 +52,9 @@ struct dinode *getnextinode();
pass1()
{
register int c, i, j;
register struct dinode *dp;
struct zlncnt *zlnp;
int ndb, cgd;
struct inodesc idesc;
ino_t inumber;
int c, i, cgd;
struct inodesc idesc;
/*
* Set file system reserved blocks in used block map.
@ -84,123 +82,177 @@ pass1()
for (i = 0; i < sblock.fs_ipg; i++, inumber++) {
if (inumber < ROOTINO)
continue;
dp = getnextinode(inumber);
if ((dp->di_mode & IFMT) == 0) {
if (bcmp((char *)dp->di_db, (char *)zino.di_db,
NDADDR * sizeof(daddr_t)) ||
bcmp((char *)dp->di_ib, (char *)zino.di_ib,
NIADDR * sizeof(daddr_t)) ||
dp->di_mode || dp->di_size) {
pfatal("PARTIALLY ALLOCATED INODE I=%lu",
inumber);
if (reply("CLEAR") == 1) {
dp = ginode(inumber);
clearinode(dp);
inodirty();
}
}
statemap[inumber] = USTATE;
continue;
}
lastino = inumber;
/* is fast symlink? */
if (DFASTLINK(*dp)) {
lncntp[inumber] = dp->di_nlink;
statemap[inumber] = FSTATE;
n_files++;
continue;
}
if (/* dp->di_size < 0 || */
dp->di_size + sblock.fs_bsize - 1 < dp->di_size) {
if (debug)
printf("bad size %lu:", dp->di_size);
goto unknown;
}
if (!preen && (dp->di_mode & IFMT) == IFMT &&
reply("HOLD BAD BLOCK") == 1) {
dp = ginode(inumber);
dp->di_size = sblock.fs_fsize;
dp->di_mode = IFREG|0600;
inodirty();
}
ndb = howmany(dp->di_size, sblock.fs_bsize);
if (ndb < 0) {
if (debug)
printf("bad size %lu ndb %d:",
dp->di_size, ndb);
goto unknown;
}
if ((dp->di_mode & IFMT) == IFBLK ||
(dp->di_mode & IFMT) == IFCHR)
ndb++;
for (j = ndb; j < NDADDR; j++)
if (dp->di_db[j] != 0) {
if (debug)
printf("bad direct addr: %ld\n",
dp->di_db[j]);
goto unknown;
}
for (j = 0, ndb -= NDADDR; ndb > 0; j++)
ndb /= NINDIR(&sblock);
for (; j < NIADDR; j++)
if (dp->di_ib[j] != 0) {
if (debug)
printf("bad indirect addr: %ld\n",
dp->di_ib[j]);
goto unknown;
}
if (ftypeok(dp) == 0)
goto unknown;
n_files++;
lncntp[inumber] = dp->di_nlink;
if (dp->di_nlink <= 0) {
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0)
errexit("");
} else {
zlnp->zlncnt = inumber;
zlnp->next = zlnhead;
zlnhead = zlnp;
}
}
if ((dp->di_mode & IFMT) == IFDIR) {
if (dp->di_size == 0)
statemap[inumber] = DCLEAR;
else
statemap[inumber] = DSTATE;
cacheino(dp, inumber);
} else
statemap[inumber] = FSTATE;
badblk = dupblk = 0;
idesc.id_number = inumber;
(void)ckinode(dp, &idesc);
idesc.id_entryno *= btodb(sblock.fs_fsize);
if (dp->di_blocks != idesc.id_entryno) {
pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)",
inumber, dp->di_blocks, idesc.id_entryno);
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
continue;
dp = ginode(inumber);
dp->di_blocks = idesc.id_entryno;
inodirty();
}
continue;
unknown:
pfatal("UNKNOWN FILE TYPE I=%lu", inumber);
statemap[inumber] = FCLEAR;
checkinode(inumber, &idesc);
}
}
freeinodebuf();
}
checkinode(inumber, idesc)
ino_t inumber;
register struct inodesc *idesc;
{
register struct dinode *dp;
struct zlncnt *zlnp;
int ndb, j;
mode_t mode;
char symbuf[MAXSYMLINKLEN];
dp = getnextinode(inumber);
mode = dp->di_mode & IFMT;
if (mode == 0) {
if (bcmp((char *)dp->di_db, (char *)zino.di_db,
NDADDR * sizeof(daddr_t)) ||
bcmp((char *)dp->di_ib, (char *)zino.di_ib,
NIADDR * sizeof(daddr_t)) ||
dp->di_mode || dp->di_size) {
pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber);
if (reply("CLEAR") == 1) {
statemap[inumber] = USTATE;
dp = ginode(inumber);
clearinode(dp);
inodirty();
}
}
statemap[inumber] = USTATE;
return;
}
lastino = inumber;
if (/* dp->di_size < 0 || */
dp->di_size + sblock.fs_bsize - 1 < dp->di_size) {
if (debug)
printf("bad size %qu:", dp->di_size);
goto unknown;
}
if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
dp = ginode(inumber);
dp->di_size = sblock.fs_fsize;
dp->di_mode = IFREG|0600;
inodirty();
}
ndb = howmany(dp->di_size, sblock.fs_bsize);
if (ndb < 0) {
if (debug)
printf("bad size %qu ndb %d:",
dp->di_size, ndb);
goto unknown;
}
if (mode == IFBLK || mode == IFCHR)
ndb++;
if (mode == IFLNK) {
/*
* Note that the old fastlink format always had di_blocks set
* to 0. Other than that we no longer use the `spare' field
* (which is now the extended uid) for sanity checking, the
* new format is the same as the old. We simply ignore the
* conversion altogether. - mycroft, 19MAY1994
*/
if (doinglevel2 &&
dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN &&
dp->di_blocks != 0) {
if (bread(fsreadfd, symbuf,
fsbtodb(&sblock, dp->di_db[0]),
(long)dp->di_size) != 0)
errexit("cannot read symlink");
if (debug) {
symbuf[dp->di_size] = 0;
printf("convert symlink %d(%s) of size %d\n",
inumber, symbuf, (long)dp->di_size);
}
dp = ginode(inumber);
bcopy(symbuf, (caddr_t)dp->di_shortlink,
(long)dp->di_size);
dp->di_blocks = 0;
inodirty();
}
/*
* Fake ndb value so direct/indirect block checks below
* will detect any garbage after symlink string.
*/
if (dp->di_size < sblock.fs_maxsymlinklen ||
(sblock.fs_maxsymlinklen == 0 && OLDFASTLINK(dp))) {
ndb = howmany(dp->di_size, sizeof(daddr_t));
if (ndb > NDADDR) {
j = ndb - NDADDR;
for (ndb = 1; j > 1; j--)
ndb *= NINDIR(&sblock);
ndb += NDADDR;
}
}
}
for (j = ndb; j < NDADDR; j++)
if (dp->di_db[j] != 0) {
if (debug)
printf("bad direct addr: %ld\n", dp->di_db[j]);
goto unknown;
}
for (j = 0, ndb -= NDADDR; ndb > 0; j++)
ndb /= NINDIR(&sblock);
for (; j < NIADDR; j++)
if (dp->di_ib[j] != 0) {
if (debug)
printf("bad indirect addr: %ld\n",
dp->di_ib[j]);
goto unknown;
}
if (ftypeok(dp) == 0)
goto unknown;
n_files++;
lncntp[inumber] = dp->di_nlink;
if (dp->di_nlink <= 0) {
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0)
errexit("");
} else {
zlnp->zlncnt = inumber;
zlnp->next = zlnhead;
zlnhead = zlnp;
}
}
if (mode == IFDIR) {
if (dp->di_size == 0)
statemap[inumber] = DCLEAR;
else
statemap[inumber] = DSTATE;
cacheino(dp, inumber);
} else
statemap[inumber] = FSTATE;
typemap[inumber] = IFTODT(mode);
if (doinglevel2 &&
(dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) {
dp = ginode(inumber);
dp->di_uid = dp->di_ouid;
dp->di_ouid = -1;
dp->di_gid = dp->di_ogid;
dp->di_ogid = -1;
inodirty();
}
badblk = dupblk = 0;
idesc->id_number = inumber;
(void)ckinode(dp, idesc);
idesc->id_entryno *= btodb(sblock.fs_fsize);
if (dp->di_blocks != idesc->id_entryno) {
pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)",
inumber, dp->di_blocks, idesc->id_entryno);
if (preen)
printf(" (CORRECTED)\n");
else if (reply("CORRECT") == 0)
return;
dp = ginode(inumber);
dp->di_blocks = idesc->id_entryno;
inodirty();
}
return;
unknown:
pfatal("UNKNOWN FILE TYPE I=%lu", inumber);
statemap[inumber] = FCLEAR;
if (reply("CLEAR") == 1) {
statemap[inumber] = USTATE;
dp = ginode(inumber);
clearinode(dp);
inodirty();
}
freeinodebuf();
}
pass1check(idesc)

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,14 +32,14 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass1b.c 5.8 (Berkeley) 7/20/90";*/
static char rcsid[] = "$Id: pass1b.c,v 1.5 1994/04/25 18:28:42 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass1b.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: pass1b.c,v 1.6 1994/06/08 19:00:26 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <string.h>
#include "fsck.h"

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,17 +32,15 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass2.c 5.17 (Berkeley) 12/28/90";*/
static char rcsid[] = "$Id: pass2.c,v 1.5 1994/04/25 18:28:47 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass2.c 8.2 (Berkeley) 2/27/94";*/
static char *rcsid = "$Id: pass2.c,v 1.6 1994/06/08 19:00:27 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#define KERNEL
#include <ufs/dir.h>
#undef KERNEL
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <stdlib.h>
#include <string.h>
#include "fsck.h"
@ -116,7 +114,6 @@ pass2()
bzero((char *)&curino, sizeof(struct inodesc));
curino.id_type = DATA;
curino.id_func = pass2check;
dino.di_mode = IFDIR;
dp = &dino;
inpend = &inpsort[inplast];
for (inpp = inpsort; inpp < inpend; inpp++) {
@ -146,6 +143,8 @@ pass2()
dp = &dino;
}
}
bzero((char *)&dino, sizeof(struct dinode));
dino.di_mode = IFDIR;
dp->di_size = inp->i_isize;
bcopy((char *)&inp->i_blks[0], (char *)&dp->di_db[0],
(size_t)inp->i_numblks);
@ -177,7 +176,7 @@ pass2()
continue;
}
fileerror(inp->i_parent, inp->i_number,
"BAD INODE NUMBER FOR '..'");
"BAD INODE NUMBER FOR '..'");
if (reply("FIX") == 0)
continue;
lncntp[inp->i_dotdot]++;
@ -203,6 +202,13 @@ pass2check(idesc)
char namebuf[MAXPATHLEN + 1];
char pathbuf[MAXPATHLEN + 1];
/*
* If converting, set directory entry type.
*/
if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) {
dirp->d_type = typemap[dirp->d_ino];
ret |= ALTERED;
}
/*
* check for "."
*/
@ -215,13 +221,23 @@ pass2check(idesc)
if (reply("FIX") == 1)
ret |= ALTERED;
}
if (newinofmt && dirp->d_type != DT_DIR) {
direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'");
dirp->d_type = DT_DIR;
if (reply("FIX") == 1)
ret |= ALTERED;
}
goto chk1;
}
direrror(idesc->id_number, "MISSING '.'");
proto.d_ino = idesc->id_number;
if (newinofmt)
proto.d_type = DT_DIR;
else
proto.d_type = 0;
proto.d_namlen = 1;
(void)strcpy(proto.d_name, ".");
entrysize = DIRSIZ(&proto);
entrysize = DIRSIZ(0, &proto);
if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
dirp->d_name);
@ -249,11 +265,15 @@ chk1:
goto chk2;
inp = getinoinfo(idesc->id_number);
proto.d_ino = inp->i_parent;
if (newinofmt)
proto.d_type = DT_DIR;
else
proto.d_type = 0;
proto.d_namlen = 2;
(void)strcpy(proto.d_name, "..");
entrysize = DIRSIZ(&proto);
entrysize = DIRSIZ(0, &proto);
if (idesc->id_entryno == 0) {
n = DIRSIZ(dirp);
n = DIRSIZ(0, dirp);
if (dirp->d_reclen < n + entrysize)
goto chk2;
proto.d_reclen = dirp->d_reclen - n;
@ -266,6 +286,12 @@ chk1:
}
if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
inp->i_dotdot = dirp->d_ino;
if (newinofmt && dirp->d_type != DT_DIR) {
direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'");
dirp->d_type = DT_DIR;
if (reply("FIX") == 1)
ret |= ALTERED;
}
goto chk2;
}
if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {
@ -332,10 +358,14 @@ again:
case FCLEAR:
if (idesc->id_entryno <= 2)
break;
if (statemap[dirp->d_ino] == DCLEAR)
errmsg = "ZERO LENGTH DIRECTORY";
else
if (statemap[dirp->d_ino] == FCLEAR)
errmsg = "DUP/BAD";
else if (!preen)
errmsg = "ZERO LENGTH DIRECTORY";
else {
n = 1;
break;
}
fileerror(idesc->id_number, dirp->d_ino, errmsg);
if ((n = reply("REMOVE")) == 1)
break;
@ -369,6 +399,13 @@ again:
/* fall through */
case FSTATE:
if (newinofmt && dirp->d_type != typemap[dirp->d_ino]) {
fileerror(idesc->id_number, dirp->d_ino,
"BAD TYPE VALUE");
dirp->d_type = typemap[dirp->d_ino];
if (reply("FIX") == 1)
ret |= ALTERED;
}
lncntp[dirp->d_ino]--;
break;

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,14 +32,14 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass3.c 5.10 (Berkeley) 6/1/90";*/
static char rcsid[] = "$Id: pass3.c,v 1.5 1994/04/25 18:28:51 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass3.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: pass3.c,v 1.6 1994/06/08 19:00:28 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include "fsck.h"
pass3()

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,14 +32,14 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass4.c 5.10 (Berkeley) 7/20/90";*/
static char rcsid[] = "$Id: pass4.c,v 1.5 1994/04/25 18:28:54 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass4.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: pass4.c,v 1.6 1994/06/08 19:00:29 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <stdlib.h>
#include <string.h>
#include "fsck.h"

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,14 +32,14 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)pass5.c 5.13 (Berkeley) 7/20/90";*/
static char rcsid[] = "$Id: pass5.c,v 1.5 1994/04/25 18:28:57 cgd Exp $";
/*static char sccsid[] = "from: @(#)pass5.c 8.2 (Berkeley) 2/2/94";*/
static char *rcsid = "$Id: pass5.c,v 1.6 1994/06/08 19:00:30 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <string.h>
#include "fsck.h"
@ -52,7 +52,6 @@ pass5()
register daddr_t d;
register long i, j;
struct csum *cs;
time_t now;
struct csum cstotal;
struct inodesc idesc[3];
char buf[MAXBSIZE];
@ -61,6 +60,45 @@ pass5()
bzero((char *)newcg, (size_t)fs->fs_cgsize);
newcg->cg_niblk = fs->fs_ipg;
if (cvtlevel > 3) {
if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
if (preen)
pwarn("DELETING CLUSTERING MAPS\n");
if (preen || reply("DELETE CLUSTERING MAPS")) {
fs->fs_contigsumsize = 0;
doinglevel1 = 1;
sbdirty();
}
}
if (fs->fs_maxcontig > 1) {
char *doit = 0;
if (fs->fs_contigsumsize < 1) {
doit = "CREAT";
} else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
fs->fs_contigsumsize < FS_MAXCONTIG) {
doit = "EXPAND";
}
if (doit) {
i = fs->fs_contigsumsize;
fs->fs_contigsumsize =
MIN(fs->fs_maxcontig, FS_MAXCONTIG);
if (CGSIZE(fs) > fs->fs_bsize) {
pwarn("CANNOT %s CLUSTER MAPS\n", doit);
fs->fs_contigsumsize = i;
} else if (preen ||
reply("CREATE CLUSTER MAPS")) {
if (preen)
pwarn("%sING CLUSTER MAPS\n",
doit);
fs->fs_cgsize =
fragroundup(fs, CGSIZE(fs));
doinglevel1 = 1;
sbdirty();
}
}
}
}
switch ((int)fs->fs_postblformat) {
case FS_42POSTBLFMT:
@ -75,16 +113,27 @@ pass5()
case FS_DYNAMICPOSTBLFMT:
newcg->cg_btotoff =
&newcg->cg_space[0] - (u_char *)(&newcg->cg_link);
&newcg->cg_space[0] - (u_char *)(&newcg->cg_link);
newcg->cg_boff =
newcg->cg_btotoff + fs->fs_cpg * sizeof(long);
newcg->cg_btotoff + fs->fs_cpg * sizeof(long);
newcg->cg_iusedoff = newcg->cg_boff +
fs->fs_cpg * fs->fs_nrpos * sizeof(short);
fs->fs_cpg * fs->fs_nrpos * sizeof(short);
newcg->cg_freeoff =
newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs),
NBBY);
newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
if (fs->fs_contigsumsize <= 0) {
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
} else {
newcg->cg_clustersumoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY) -
sizeof(long);
newcg->cg_clustersumoff =
roundup(newcg->cg_clustersumoff, sizeof(long));
newcg->cg_clusteroff = newcg->cg_clustersumoff +
(fs->fs_contigsumsize + 1) * sizeof(long);
newcg->cg_nextfreeoff = newcg->cg_clusteroff +
howmany(fs->fs_cpg * fs->fs_spc / NSPB(fs), NBBY);
}
newcg->cg_magic = CG_MAGIC;
basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_link);
sumsize = newcg->cg_iusedoff - newcg->cg_btotoff;
@ -96,10 +145,12 @@ pass5()
fs->fs_postblformat);
}
bzero((char *)&idesc[0], sizeof idesc);
for (i = 0; i < 3; i++)
for (i = 0; i < 3; i++) {
idesc[i].id_type = ADDR;
if (doinglevel2)
idesc[i].id_fix = FIX;
}
bzero((char *)&cstotal, sizeof(struct csum));
(void)time(&now);
j = blknum(fs, fs->fs_size + fs->fs_frag - 1);
for (i = fs->fs_size; i < j; i++)
setbmap(i);
@ -111,16 +162,15 @@ pass5()
dmax = dbase + fs->fs_fpg;
if (dmax > fs->fs_size)
dmax = fs->fs_size;
if (now > cg->cg_time)
newcg->cg_time = cg->cg_time;
else
newcg->cg_time = now;
newcg->cg_time = cg->cg_time;
newcg->cg_cgx = c;
if (c == fs->fs_ncg - 1)
newcg->cg_ncyl = fs->fs_ncyl % fs->fs_cpg;
else
newcg->cg_ncyl = fs->fs_cpg;
newcg->cg_ndblk = dmax - dbase;
if (fs->fs_contigsumsize > 0)
newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
newcg->cg_cs.cs_ndir = 0;
newcg->cg_cs.cs_nffree = 0;
newcg->cg_cs.cs_nbfree = 0;
@ -188,10 +238,42 @@ pass5()
j = cbtocylno(fs, i);
cg_blktot(newcg)[j]++;
cg_blks(fs, newcg, j)[cbtorpos(fs, i)]++;
if (fs->fs_contigsumsize > 0)
setbit(cg_clustersfree(newcg),
i / fs->fs_frag);
} else if (frags > 0) {
newcg->cg_cs.cs_nffree += frags;
blk = blkmap(fs, cg_blksfree(newcg), i);
fragacct(fs, blk, newcg->cg_frsum, 1);
ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
}
}
if (fs->fs_contigsumsize > 0) {
long *sump = cg_clustersum(newcg);
u_char *mapp = cg_clustersfree(newcg);
int map = *mapp++;
int bit = 1;
int run = 0;
for (i = 0; i < newcg->cg_nclusterblks; i++) {
if ((map & bit) != 0) {
run++;
} else if (run != 0) {
if (run > fs->fs_contigsumsize)
run = fs->fs_contigsumsize;
sump[run]++;
run = 0;
}
if ((i & (NBBY - 1)) != (NBBY - 1)) {
bit <<= 1;
} else {
map = *mapp++;
bit = 1;
}
}
if (run != 0) {
if (run > fs->fs_contigsumsize)
run = fs->fs_contigsumsize;
sump[run]++;
}
}
cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
@ -204,7 +286,7 @@ pass5()
bcopy((char *)&newcg->cg_cs, (char *)cs, sizeof *cs);
sbdirty();
}
if (cvtflag) {
if (doinglevel1) {
bcopy((char *)newcg, (char *)cg, (size_t)fs->fs_cgsize);
cgdirty();
continue;

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,13 +32,12 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)preen.c 5.7 (Berkeley) 3/19/91";*/
static char rcsid[] = "$Id: preen.c,v 1.5 1994/04/25 18:29:01 cgd Exp $";
/*static char sccsid[] = "from: @(#)preen.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: preen.c,v 1.6 1994/06/08 19:00:31 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <fstab.h>
#include <string.h>

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,20 +32,19 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)setup.c 5.33 (Berkeley) 2/22/91";*/
static char rcsid[] = "$Id: setup.c,v 1.9 1994/04/25 18:33:42 cgd Exp $";
/*static char sccsid[] = "from: @(#)setup.c 8.2 (Berkeley) 2/21/94";*/
static char *rcsid = "$Id: setup.c,v 1.10 1994/06/08 19:00:32 mycroft Exp $";
#endif /* not lint */
#define DKTYPENAMES
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/disklabel.h>
#include <sys/file.h>
#include <sys/mount.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@ -56,22 +55,7 @@ struct bufarea asblk;
#define altsblock (*asblk.b_un.b_fs)
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
/*
* The size of a cylinder group is calculated by CGSIZE. The maximum size
* is limited by the fact that cylinder groups are at most one block.
* Its size is derived from the size of the maps maintained in the
* cylinder group and the (struct cg) size.
*/
#define CGSIZE(fs) \
/* base cg */ (sizeof(struct cg) + \
/* blktot size */ (fs)->fs_cpg * sizeof(long) + \
/* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \
/* inode map */ howmany((fs)->fs_ipg, NBBY) + \
/* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
char *index();
struct disklabel *getdisklabel();
char *getmntdev();
setup(dev)
char *dev;
@ -79,47 +63,17 @@ setup(dev)
long cg, size, asked, i, j;
long bmapsize;
struct disklabel *lp;
struct stat statb, statb2;
off_t sizepb;
struct stat statb;
struct fs proto;
char path2[MAXPATHLEN];
char *dev2;
havesb = 0;
fswritefd = -1;
if (stat(dev, &statb) < 0) {
printf("Can't stat %s: %s\n", dev, strerror(errno));
return (0);
}
switch (statb.st_mode & S_IFMT) {
case S_IFCHR:
break;
case S_IFDIR:
dev2 = getmntdev(dev);
if (dev2 != NULL && !strncmp(dev2, "/dev/", 5)) {
snprintf(path2, sizeof(path2), "/dev/r%s", dev2 + 5);
if (stat(path2, &statb2) == 0 &&
(statb2.st_mode & S_IFMT) == S_IFCHR) {
dev = path2;
statb = statb2;
break;
}
}
pfatal("%s is not a character device", dev);
if (reply("CONTINUE") == 0)
return (0);
break;
case S_IFBLK:
if (!strncmp(dev, "/dev/", 5)) {
sprintf(path2, "/dev/r%s", dev + 5);
if (stat(path2, &statb2) == 0 &&
(statb2.st_mode & S_IFMT) == S_IFCHR &&
minor(statb2.st_rdev) == minor(statb.st_rdev)) {
dev = path2;
statb = statb2;
break;
}
}
/* fall through */
default:
if ((statb.st_mode & S_IFMT) != S_IFCHR) {
pfatal("%s is not a character device", dev);
if (reply("CONTINUE") == 0)
return (0);
@ -150,14 +104,6 @@ setup(dev)
dev_bsize = secsize = lp->d_secsize;
else
dev_bsize = secsize = DEV_BSIZE;
#ifdef tahoe
/*
* On the tahoe, the disk label and the disk driver disagree.
* The label knows that sectors are 512 bytes, but the disk
* drivers will only transfer in 1024 sized pieces.
*/
secsize = 1024;
#endif
/*
* Read in the superblock, looking for alternates if necessary
*/
@ -227,64 +173,55 @@ setup(dev)
dirty(&asblk);
}
}
if (cvtflag) {
if (sblock.fs_postblformat == FS_42POSTBLFMT) {
/*
* Requested to convert from old format to new format
*/
if (preen)
pwarn("CONVERTING TO NEW FILE SYSTEM FORMAT\n");
else if (!reply("CONVERT TO NEW FILE SYSTEM FORMAT"))
return(0);
sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
sblock.fs_nrpos = 8;
sblock.fs_postbloff =
(char *)(&sblock.fs_opostbl[0][0]) -
(char *)(&sblock.fs_link);
sblock.fs_rotbloff = &sblock.fs_space[0] -
(u_char *)(&sblock.fs_link);
sblock.fs_cgsize =
fragroundup(&sblock, CGSIZE(&sblock));
/*
* Planning now for future expansion.
*/
# if (BYTE_ORDER == BIG_ENDIAN)
sblock.fs_qbmask.val[0] = 0;
sblock.fs_qbmask.val[1] = ~sblock.fs_bmask;
sblock.fs_qfmask.val[0] = 0;
sblock.fs_qfmask.val[1] = ~sblock.fs_fmask;
# endif /* BIG_ENDIAN */
# if (BYTE_ORDER == LITTLE_ENDIAN)
sblock.fs_qbmask.val[0] = ~sblock.fs_bmask;
sblock.fs_qbmask.val[1] = 0;
sblock.fs_qfmask.val[0] = ~sblock.fs_fmask;
sblock.fs_qfmask.val[1] = 0;
# endif /* LITTLE_ENDIAN */
sbdirty();
dirty(&asblk);
} else if (sblock.fs_postblformat == FS_DYNAMICPOSTBLFMT) {
/*
* Requested to convert from new format to old format
*/
if (sblock.fs_nrpos != 8 || sblock.fs_ipg > 2048 ||
sblock.fs_cpg > 32 || sblock.fs_cpc > 16) {
printf(
"PARAMETERS OF CURRENT FILE SYSTEM DO NOT\n\t");
errexit(
"ALLOW CONVERSION TO OLD FILE SYSTEM FORMAT\n");
}
if (preen)
pwarn("CONVERTING TO OLD FILE SYSTEM FORMAT\n");
else if (!reply("CONVERT TO OLD FILE SYSTEM FORMAT"))
return(0);
sblock.fs_postblformat = FS_42POSTBLFMT;
sblock.fs_cgsize = fragroundup(&sblock,
sizeof(struct ocg) + howmany(sblock.fs_fpg, NBBY));
sbdirty();
dirty(&asblk);
} else {
errexit("UNKNOWN FILE SYSTEM FORMAT\n");
if (sblock.fs_inodefmt >= FS_44INODEFMT) {
newinofmt = 1;
} else {
sblock.fs_qbmask = ~sblock.fs_bmask;
sblock.fs_qfmask = ~sblock.fs_fmask;
newinofmt = 0;
}
/*
* Convert to new inode format.
*/
if (cvtlevel >= 2 && sblock.fs_inodefmt < FS_44INODEFMT) {
if (preen)
pwarn("CONVERTING TO NEW INODE FORMAT\n");
else if (!reply("CONVERT TO NEW INODE FORMAT"))
return(0);
doinglevel2++;
sblock.fs_inodefmt = FS_44INODEFMT;
sizepb = sblock.fs_bsize;
sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1;
for (i = 0; i < NIADDR; i++) {
sizepb *= NINDIR(&sblock);
sblock.fs_maxfilesize += sizepb;
}
sblock.fs_maxsymlinklen = MAXSYMLINKLEN;
sblock.fs_qbmask = ~sblock.fs_bmask;
sblock.fs_qfmask = ~sblock.fs_fmask;
sbdirty();
dirty(&asblk);
}
/*
* Convert to new cylinder group format.
*/
if (cvtlevel >= 1 && sblock.fs_postblformat == FS_42POSTBLFMT) {
if (preen)
pwarn("CONVERTING TO NEW CYLINDER GROUP FORMAT\n");
else if (!reply("CONVERT TO NEW CYLINDER GROUP FORMAT"))
return(0);
doinglevel1++;
sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
sblock.fs_nrpos = 8;
sblock.fs_postbloff =
(char *)(&sblock.fs_opostbl[0][0]) -
(char *)(&sblock.fs_link);
sblock.fs_rotbloff = &sblock.fs_space[0] -
(u_char *)(&sblock.fs_link);
sblock.fs_cgsize =
fragroundup(&sblock, CGSIZE(&sblock));
sbdirty();
dirty(&asblk);
}
if (asblk.b_dirty) {
bcopy((char *)&sblock, (char *)&altsblock,
@ -324,6 +261,12 @@ setup(dev)
(unsigned)(maxino + 1));
goto badsb;
}
typemap = calloc((unsigned)(maxino + 1), sizeof(char));
if (typemap == NULL) {
printf("cannot alloc %u bytes for typemap\n",
(unsigned)(maxino + 1));
goto badsb;
}
lncntp = (short *)calloc((unsigned)(maxino + 1), sizeof(short));
if (lncntp == NULL) {
printf("cannot alloc %u bytes for lncntp\n",
@ -384,6 +327,10 @@ readsb(listerr)
super *= dev_bsize;
dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
sblk.b_bno = super / dev_bsize;
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.
@ -392,10 +339,6 @@ readsb(listerr)
getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize);
if (asblk.b_errs)
return (0);
if (bflag) {
havesb = 1;
return (1);
}
altsblock.fs_link = sblock.fs_link;
altsblock.fs_rlink = sblock.fs_rlink;
altsblock.fs_time = sblock.fs_time;
@ -403,7 +346,6 @@ readsb(listerr)
altsblock.fs_cgrotor = sblock.fs_cgrotor;
altsblock.fs_fmod = sblock.fs_fmod;
altsblock.fs_clean = sblock.fs_clean;
altsblock.fs_state = sblock.fs_state;
altsblock.fs_ronly = sblock.fs_ronly;
altsblock.fs_flags = sblock.fs_flags;
altsblock.fs_maxcontig = sblock.fs_maxcontig;
@ -424,6 +366,10 @@ readsb(listerr)
altsblock.fs_interleave = sblock.fs_interleave;
altsblock.fs_npsect = sblock.fs_npsect;
altsblock.fs_nrpos = sblock.fs_nrpos;
altsblock.fs_qbmask = sblock.fs_qbmask;
altsblock.fs_qfmask = sblock.fs_qfmask;
altsblock.fs_state = sblock.fs_state;
altsblock.fs_maxfilesize = sblock.fs_maxfilesize;
if (bcmp((char *)&sblock, (char *)&altsblock, (int)sblock.fs_sbsize)) {
badsb(listerr,
"VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
@ -441,7 +387,7 @@ badsb(listerr, s)
if (!listerr)
return;
if (preen)
printf("%s: ", devname);
printf("%s: ", cdevname);
pfatal("BAD SUPER BLOCK: %s\n", s);
}
@ -519,20 +465,3 @@ getdisklabel(s, fd)
}
return (&lab);
}
char *
getmntdev(name)
char *name;
{
long mntsize;
register long i;
struct statfs *mntbuf;
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
for (i = 0; i < mntsize; i++) {
if (!strncmp(mntbuf[i].f_fstypename, MOUNT_UFS, MFSNAMELEN) &&
!strcmp(mntbuf[i].f_mntonname, name))
return (mntbuf[i].f_mntfromname);
}
return ((char *)0);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1980, 1986 The Regents of the University of California.
* All rights reserved.
* 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
@ -32,15 +32,15 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)utilities.c 5.30 (Berkeley) 7/26/91";*/
static char rcsid[] = "$Id: utilities.c,v 1.8 1994/05/02 10:18:25 pk Exp $";
/*static char sccsid[] = "from: @(#)utilities.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: utilities.c,v 1.9 1994/06/08 19:00:33 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <ufs/dir.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -49,7 +49,6 @@ static char rcsid[] = "$Id: utilities.c,v 1.8 1994/05/02 10:18:25 pk Exp $";
long diskreads, totalreads; /* Disk cache statistics */
int
ftypeok(dp)
struct dinode *dp;
{
@ -71,7 +70,6 @@ ftypeok(dp)
}
}
int
reply(question)
char *question;
{
@ -107,7 +105,6 @@ reply(question)
/*
* Malloc buffers and set up cache.
*/
void
bufinit()
{
register struct bufarea *bp;
@ -192,7 +189,6 @@ getblk(bp, blk, size)
}
}
void
flush(fd, bp)
int fd;
register struct bufarea *bp;
@ -218,7 +214,6 @@ flush(fd, bp)
}
}
void
rwerror(mesg, blk)
char *mesg;
daddr_t blk;
@ -231,12 +226,15 @@ rwerror(mesg, blk)
errexit("Program terminated\n");
}
void
ckfini()
{
register 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 SUPERBLOCK")) {
@ -271,20 +269,23 @@ bread(fd, buf, blk, size)
{
char *cp;
int i, errs;
off_t offset;
if (lseek(fd, blk * dev_bsize, 0) < 0)
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, blk * dev_bsize, 0) < 0)
if (lseek(fd, offset, 0) < 0)
rwerror("SEEK", blk);
errs = 0;
bzero(buf, (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, blk * dev_bsize + i + secsize, 0);
(void)lseek(fd, offset + i + secsize, 0);
if (secsize != dev_bsize && dev_bsize != 1)
printf(" %ld (%ld),",
(blk * dev_bsize + i) / secsize,
@ -306,22 +307,25 @@ bwrite(fd, buf, blk, size)
{
int i;
char *cp;
off_t offset;
if (fd < 0)
return;
if (lseek(fd, blk * dev_bsize, 0) < 0)
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, blk * dev_bsize, 0) < 0)
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, blk * dev_bsize + i + dev_bsize, 0);
(void)lseek(fd, offset + i + dev_bsize, 0);
printf(" %ld,", blk + i / dev_bsize);
}
printf("\n");
@ -361,7 +365,6 @@ allocblk(frags)
/*
* Free a previously allocated block
*/
void
freeblk(blkno, frags)
daddr_t blkno;
long frags;
@ -376,7 +379,6 @@ freeblk(blkno, frags)
/*
* Find a pathname
*/
void
getpathname(namebuf, curdir, ino)
char *namebuf;
ino_t curdir, ino;
@ -387,6 +389,10 @@ getpathname(namebuf, curdir, ino)
static int busy = 0;
extern int findname();
if (curdir == ino && ino == ROOTINO) {
(void)strcpy(namebuf, "/");
return;
}
if (busy ||
(statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
(void)strcpy(namebuf, "?");
@ -432,7 +438,8 @@ getpathname(namebuf, curdir, ino)
void
catch()
{
ckfini();
if (!doinglevel2)
ckfini();
exit(12);
}
@ -522,11 +529,11 @@ pfatal(s, a1, a2, a3)
{
if (preen) {
printf("%s: ", devname);
printf("%s: ", cdevname);
printf(s, a1, a2, a3);
printf("\n");
printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
devname);
cdevname);
exit(8);
}
printf(s, a1, a2, a3);
@ -542,7 +549,7 @@ pwarn(s, a1, a2, a3, a4, a5, a6)
{
if (preen)
printf("%s: ", devname);
printf("%s: ", cdevname);
printf(s, a1, a2, a3, a4, a5, a6);
}

View File

@ -1,9 +1,9 @@
# from: @(#)Makefile 5.5 (Berkeley) 5/11/90
# $Id: Makefile,v 1.6 1993/10/08 00:51:12 cgd Exp $
# from: @(#)Makefile 8.5 (Berkeley) 3/27/94
# $Id: Makefile,v 1.7 1994/06/08 19:02:36 mycroft Exp $
PROG= mount
CFLAGS+=-DNFS -DNFSCLIENT
SRCS= mount.c mount_ufs.c getmntopts.c
MAN8= mount.0
MLINKS= mount.8 umount.8
# We do NOT install the getmntopts.3 man page.
.include <bsd.prog.mk>

164
sbin/mount/getmntopts.3 Normal file
View File

@ -0,0 +1,164 @@
.\" Copyright (c) 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)getmntopts.3 8.1 (Berkeley) 3/27/94
.\" $Id: getmntopts.3,v 1.1 1994/06/08 19:02:37 mycroft Exp $
.\"
.Dd March 27, 1994
.Dt GETMNTOPTS 3
.Os BSD 4.4
.Sh NAME
.Nm getmntopts
.Nd scan mount options
.Sh SYNOPSIS
.Fd #include <mntopts.h>
.Ft void
.Fn getmntopts "char *options" "struct mntopt *mopts" "int *flagp"
.Sh DESCRIPTION
The
.Nm getmntopts
function takes a comma separated option list and a list
of valid option names, and computes the bitmask
corresponding to the requested set of options.
.Pp
The string
.Dv options
is broken down into a sequence of comma separated tokens.
Each token is looked up in the table described by
.Dv mopts
and the bits in
the word referenced by
.Dv flagp
are updated.
The flag word is not initialized by
.Nm getmntopt .
The table,
.Dv mopts ,
has the following format:
.Bd -literal
struct mntopt {
char *m_option; /* option name */
int m_inverse; /* is this a negative option, eg "dev" */
int m_flag; /* bit to set, eg MNT_RDONLY */
};
.Ed
.Pp
The members of this structure are:
.Bl -tag -width m_inverse
.It Fa m_option
the option name,
for example
.Dq suid .
.It Fa m_inverse
tells
.Nm getmntopts
that the name has the inverse meaning of the
bit.
For example,
.Dq suid
is the string, whereas the
mount flag is
.Dv MNT_NOSUID .
In this case, the sense of the string and the flag
are inverted, so the
.Dv m_inverse
flag should be set.
.It Fa m_flag
the value of the bit to be set or cleared in
the flag word when the option is recognized.
The bit is set when the option is discovered,
but cleared if the option name was preceded
by the letters
.Dq no .
The
.Dv m_inverse
flag causes these two operations to be reversed.
.El
.Pp
Each of the user visible
.Dv MNT_
flags has a corresponding
.Dv MOPT_
macro which defines an appropriate
.Li "struct mntopt"
entry.
To simplify the program interface and ensure consistency across all
programs, a general purpose macro,
.Dv MOPT_STDOPTS ,
is defined which
contains an entry for all the generic VFS options.
In addition, the macros
.Dv MOPT_FORCE
and
.Dv MOPT_UPDATE
exist to enable the
.Dv MNT_FORCE
and
.Dv MNT_UPDATE
flags to be set.
Finally, the table must be terminated by an entry with a NULL
first element.
.Sh EXAMPLES
Most commands will use the standard option set.
Local filesystems which support the
.Dv MNT_UPDATE
flag, would also have an
.Dv MOPT_UPDATE
entry.
This can be declared and used as follows:
.Bd -literal
#include "mntopts.h"
struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_UPDATE,
{ NULL }
};
...
mntflags = 0;
...
getmntopts(options, mopts, &mntflags)
...
.Ed
.Sh DIAGNOSTICS
The
.Nm getmntopts
function displays an error message and exits if an
unrecognized option is encountered.
.Sh SEE ALSO
.Xr err 3 ,
.Xr mount 8
.Sh HISTORY
The
.Fn getmntopts
function appeared in
.Bx 4.4 .

88
sbin/mount/getmntopts.c Normal file
View File

@ -0,0 +1,88 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)getmntopts.c 8.1 (Berkeley) 3/27/94";*/
static char *rcsid = "$Id: getmntopts.c,v 1.1 1994/06/08 19:02:38 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/mount.h>
#include <err.h>
#include <errno.h>
#include <fstab.h>
#include <stdlib.h>
#include <string.h>
#include "mntopts.h"
void
getmntopts(options, m0, flagp)
const char *options;
const struct mntopt *m0;
int *flagp;
{
const struct mntopt *m;
int negative;
char *opt, *optbuf;
/* Copy option string, since it is about to be torn asunder... */
if ((optbuf = strdup(options)) == NULL)
err(1, NULL);
for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
/* Check for "no" prefix. */
if (opt[0] == 'n' && opt[1] == 'o') {
negative = 1;
opt += 2;
} else
negative = 0;
/* Scan option table. */
for (m = m0; m->m_option != NULL; ++m)
if (strcasecmp(opt, m->m_option) == 0)
break;
/* Save flag, or fail if option is not recognised. */
if (m->m_option) {
if (negative == m->m_inverse)
*flagp |= m->m_flag;
else
*flagp &= ~m->m_flag;
} else
errx(1, "-o %s: option not supported", opt);
}
free(optbuf);
}

78
sbin/mount/mntopts.h Normal file
View File

@ -0,0 +1,78 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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: @(#)mntopts.h 8.3 (Berkeley) 3/27/94
* $Id: mntopts.h,v 1.1 1994/06/08 19:02:39 mycroft Exp $
*/
struct mntopt {
const char *m_option; /* option name */
int m_inverse; /* if a negative option, eg "dev" */
int m_flag; /* bit to set, eg. MNT_RDONLY */
};
/* User-visible MNT_ flags. */
#define MOPT_ASYNC { "async", 0, MNT_ASYNC }
#define MOPT_NODEV { "dev", 1, MNT_NODEV }
#define MOPT_NOEXEC { "exec", 1, MNT_NOEXEC }
#define MOPT_NOSUID { "suid", 1, MNT_NOSUID }
#define MOPT_RDONLY { "rdonly", 0, MNT_RDONLY }
#define MOPT_SYNC { "sync", 0, MNT_SYNCHRONOUS }
#define MOPT_UNION { "union", 0, MNT_UNION }
/* Control flags. */
#define MOPT_FORCE { "force", 1, MNT_FORCE }
#define MOPT_UPDATE { "update", 0, MNT_UPDATE }
#define MOPT_RELOAD { "reload", 0, MNT_RELOAD }
/* Support for old-style "ro", "rw" flags. */
#define MOPT_RO { "ro", 0, MNT_RDONLY }
#define MOPT_RW { "rw", 1, MNT_RDONLY }
/* This is parse by mount(8), but is ignored by specific mount_*(8)s. */
#define MOPT_AUTO { "auto", 0, 0 }
#define MOPT_FSTAB_COMPAT \
MOPT_RO, \
MOPT_RW, \
MOPT_AUTO
/* Standard options which all mounts can understand. */
#define MOPT_STDOPTS \
MOPT_FSTAB_COMPAT, \
MOPT_NODEV, \
MOPT_NOEXEC, \
MOPT_NOSUID, \
MOPT_RDONLY, \
MOPT_UNION
void getmntopts __P((const char *, const struct mntopt *, int *));

View File

@ -1,5 +1,5 @@
.\" Copyright (c) 1980, 1989, 1991 The Regents of the University of California.
.\" All rights reserved.
.\" 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
@ -29,35 +29,27 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)mount.8 6.17 (Berkeley) 8/5/91
.\" $Id: mount.8,v 1.6 1994/01/05 08:32:10 cgd Exp $
.\" from: @(#)mount.8 8.7 (Berkeley) 3/27/94
.\" $Id: mount.8,v 1.7 1994/06/08 19:02:42 mycroft Exp $
.\"
.Dd August 5, 1991
.Dd March 27, 1994
.Dt MOUNT 8
.Os BSD 4
.Sh NAME
.Nm mount ,
.Nm umount
.Nd mount and dismount file systems
.Nm mount
.Nd mount file systems
.Sh SYNOPSIS
.Nm mount
.Op Fl afrwu
.Op Fl t Ar nfs | ufs | external_type
.Op Fl adfruvw
.Op Fl t Ar ufs | lfs | external_type
.Nm mount
.Op Fl frwu
.Ar special| node
.Nm mount
.Op Fl frwu
.Op Fl t Ar nfs | ufs | external_type
.Op | Ar external_type
.Op Fl o Ar options
.Ar special node
.Nm umount
.Op Fl af
.Op Fl t Ar nfs | ufs | external_type
.Nm umount
.Op Fl f
.Op Fl dfruvw
.Ar special | node
.Nm mount
.Op Fl dfruvw
.Op Fl o Ar options
.Op Fl t Ar ufs | lfs | external_type
.Ar special node
.Sh DESCRIPTION
The
.Nm mount
@ -65,17 +57,14 @@ command
calls the
.Xr mount 2
system call to prepare and graft a
.Ar special
device or the remote node
(rhost:path)
on to the file system tree at the point
.Ar node.
.Ar "special device"
or the remote node (rhost:path) on to the file system tree at the point
.Ar node .
If either
.Ar special
or
.Ar node
are not provided, the appropriate
information is taken from the
are not provided, the appropriate information is taken from the
.Xr fstab 5
file.
.Pp
@ -84,47 +73,61 @@ If no arguments are given to
.Nm mount,
this list is printed.
.Pp
Options available for the
.Nm mount
command:
The options are as follows:
.Bl -tag -width indent
.It Fl F
The standard mount options are parsed and
passed to external program via the
.Fl F
option
as a decimal number.
(See example below.)
.It Fl f
Causes everything to be done except for the actual system call; if it's
not obvious, this ``fakes'' mounting the file system.
.It Fl d
Causes everything to be done except for the actual system call.
This option is useful in conjunction with the
.Fl v
flag to
determine what the
.Nm mount
command is trying to do.
.It Fl f
Forces the revocation of write access when trying to downgrade
a filesystem mount status from read-write to read-only.
.It Fl o
Options are specified with a
.Fl o
flag
followed by a comma separated string of options.
The following options apply to any file system that is being mounted:
flag followed by a comma separated string of options.
The following options are available:
.Bl -tag -width indent
.It async
All
.Tn I/O
to the file system should be done asynchronously.
This is a
.Em dangerous
flag to set,
and should not be used unless you are prepared to recreate the file
system should your system crash.
.It force
The same as
.Fl f ;
forces the revocation of write access when trying to downgrade
a filesystem mount status from read-write to read-only.
.It nodev
Do not interpret character or block special devices on the file system.
This option is useful for a server that has file systems containing
special devices for architectures other than its own.
.It noexec
Do not allow execution of any binaries on the mounted file system.
This options is useful for a server that has file systems containing
This option is useful for a server that has file systems containing
binaries for architectures other than its own.
.It nosuid
Do not allow set-user-identifier or set-group-identifier bits to take effect.
.It nodev
Do not interpret character or block special devices on the file system.
This options is useful for a server that has file systems containing
special devices for architectures other than its own.
.It synchronous
.It rdonly
The same as
.Fl r ;
mount the file system read-only (even the super-user may not write it).
.It sync
All
.Tn I/O
to the file system should be done synchronously.
.It update
The same as
.Fl u ;
indicate that the status of an already mounted file system should be changed.
.It union
Causes the namespace at the mount point to appear as the union
of the mounted filesystem root and the existing directory.
@ -133,15 +136,50 @@ If those operations fail due to a non-existent file the underlying
directory is then accessed.
All creates are done in the mounted filesystem.
.El
.Pp
Any additional options specific to a filesystem type that is not
one of the internally known types (see the
.Fl t
option) may be passed as a comma separated list; these options are
distinguished by a leading
.Dq \&-
(dash).
Options that take a value are specified using the syntax -option=value.
For example, the mount command:
.Bd -literal -offset indent
mount -t mfs -o nosuid,-N,-s=4000 /dev/dk0b /tmp
.Ed
.Pp
causes
.Nm mount
to execute the equivalent of:
.Bd -literal -offset indent
/sbin/mount_mfs -o nosuid -N -s 4000 /dev/dk0b /tmp
.Ed
.It Fl r
The file system object is to be mounted read-only.
.It Fl t Ar "nfs \\*(Ba ufs \\*(Ba external type"
The file system is to be mounted read-only.
Mount the file system read-only (even the super-user may not write it).
The same as the
.Dq rdonly
argument to the
.Fl o
option.
.It Fl t Ar "ufs \\*(Ba lfs \\*(Ba external type"
The argument following the
.Fl t
is used to indicate the file system type.
The type
.Ar ufs
is the default.
The \fI-t\fP option can be used
to indicate that the actions should only be taken on
filesystems of the specified type.
More than one type may be specified in a comma separated list.
The list of filesystem types can be prefixed with
.Dq no
to specify the filesystem types for which action should
.Em not
be taken.
For example, the
.Nm mount
command:
@ -160,6 +198,8 @@ mount will attempt to execute a program in
where
.Em XXX
is replaced by the type name.
For example, nfs filesystems are mounted by the program
.Pa /sbin/mount_nfs .
.It Fl u
The
.Fl u
@ -169,7 +209,12 @@ Any of the options discussed above (the
.Fl o
option)
may be changed;
also a file system can be changed from read-only to read-write.
also a file system can be changed from read-only to read-write
or vice versa.
An attempt to change from read-write to read-only will fail if any
files on the filesystem are currently open for writing unless the
.Fl f
flag is also specified.
The set of options is determined by first extracting the options
for the file system from the
.Xr fstab
@ -186,112 +231,10 @@ option.
Verbose mode.
.It Fl w
The file system object is to be read and write.
.It Fl
Any additional options specific to the program can
be passed as a comma separated list;
these options are distinguished by starting with a
.Fl
(dash).
.El
.Pp
Those options that take a value are specified
using the syntax -option=value.
For example, the mount command:
.Bd -literal -offset indent
mount -t mfs -o nosuid,-N,-s=4000 /dev/dk0b /tmp
.Ed
.Pp
causes mount to attempt to execute:
.Bd -literal -offset indent
/sbin/mount_mfs -F 8 -N -s 4000 /dev/dk0b /tmp
.Ed
.Pp
The following list can be used to override
the defaults for an nfs mount:
.Bl -tag -width indent
.It hard
.Tn I/O
system calls will retry until the server responds (default)
.It soft
.Tn I/O
system calls will fail and return errno after
.Em retrans
request
retransmissions
.It spongy
Soft semantics for the stat, lookup, fsstat, readlink and readdir
filesystem operations and hard semantics for the others.
This option is meant to be similar to hard,
except that processes will not be hung forever when
they trip over mount points to dead servers.
.It bg
If the first mount request times out, do retries in background
.It intr
.Tn I/O
system calls can be interrupted.
.It noconn
Do not connect the socket.
Used for
.Tn UDP
servers that send replies from a
socket other than the nfs server socket.
.It tcp
Use
.Tn TCP
transport instead of
.Tn UDP .
.It rsize=#
Set read size to
.Ar #
bytes.
.It wsize=#
Set write size to
.Ar #
bytes.
.It retry=#
Set mount retry count to
.Ar # .
.It retrans=#
Set retransmission count for nfs rpc's to
.Ar # .
.It timeo=#
Set initial nfs timeout to
.Ar #
in 0.1 sec intervals.
.El
.Pp
.Nm Umount
removes the
.Ar special
device
grafted
at point
.Ar node
from file system tree.
.Pp
Options for the
.Nm umount
command:
.Bl -tag -width indent
.It Fl f
The file system is forcibly unmounted.
Active special devices continue to work,
but all other files return errors if further accesses are attempted.
The root file system cannot be forcibly unmounted.
.It Fl a
All of the file systems described in
.Xr fstab
are unmounted.
.It Fl t
Is used to indicate the actions should only be taken on
filesystems of the specified type.
More than one type may be specified in a comma separated list.
The list of filesystem types can be prefixed with ``no'' to
specify the filesystem types on which no action should be taken.
(See example above for the
.Nm mount
command.)
.El
The options specific to NFS filesystems are described in the
.Xr mount_nfs 8
manual page.
.Sh FILES
.Bl -tag -width /etc/fstab -compact
.It Pa /etc/fstab
@ -299,13 +242,24 @@ file system table
.El
.Sh SEE ALSO
.Xr mount 2 ,
.Xr unmount 2 ,
.Xr fstab 5 ,
.Xr mount_XXX 8
.Xr mount_cd9660 8 ,
.Xr mount_fdesc 8 ,
.Xr mount_kernfs 8 ,
.Xr mount_lfs 8 ,
.Xr mount_lofs 8 ,
.Xr mount_mfs 8 ,
.Xr mount_nfs 8 ,
.Xr mount_null 8 ,
.Xr mount_portal 8 ,
.Xr mount_procfs 8 ,
.Xr mount_umap 8 ,
.Xr mount_union 8 ,
.Xr umount 8
.Sh BUGS
It is possible for a corrupted file system to cause a crash.
.Sh HISTORY
A
.Nm
.Nm mount
command appeared in
.At v6 .

File diff suppressed because it is too large Load Diff

133
sbin/mount/mount_ufs.c Normal file
View File

@ -0,0 +1,133 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)mount_ufs.c 8.2 (Berkeley) 3/27/94";*/
static char *rcsid = "$Id: mount_ufs.c,v 1.1 1994/06/08 19:02:45 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/mount.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mntopts.h"
void ufs_usage __P((void));
static struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_ASYNC,
MOPT_SYNC,
MOPT_UPDATE,
MOPT_RELOAD,
{ NULL }
};
int
mount_ufs(argc, argv)
int argc;
char * const argv[];
{
extern int optreset;
struct ufs_args args;
int ch, mntflags;
char *fs_name;
mntflags = 0;
optind = optreset = 1; /* Reset for parse of new argv. */
while ((ch = getopt(argc, argv, "o:")) != EOF)
switch (ch) {
case 'o':
getmntopts(optarg, mopts, &mntflags);
break;
case '?':
default:
ufs_usage();
}
argc -= optind;
argv += optind;
if (argc != 2)
ufs_usage();
args.fspec = argv[0]; /* The name of the device file. */
fs_name = argv[1]; /* The mount point. */
#define DEFAULT_ROOTUID -2
args.export.ex_root = DEFAULT_ROOTUID;
if (mntflags & MNT_RDONLY)
args.export.ex_flags = MNT_EXRDONLY;
else
args.export.ex_flags = 0;
if (mount(MOUNT_UFS, fs_name, mntflags, &args) < 0) {
(void)fprintf(stderr, "%s on %s: ", args.fspec, fs_name);
switch (errno) {
case EMFILE:
(void)fprintf(stderr, "mount table full.\n");
break;
case EINVAL:
if (mntflags & MNT_UPDATE)
(void)fprintf(stderr,
"Specified device does not match mounted device.\n");
else
(void)fprintf(stderr,
"Incorrect super block.\n");
break;
default:
(void)fprintf(stderr, "%s\n", strerror(errno));
break;
}
return (1);
}
return (0);
}
void
ufs_usage()
{
(void)fprintf(stderr, "usage: mount_ufs [-o options] special node\n");
exit(1);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 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
@ -30,10 +30,10 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)pathnames.h 6.4 (Berkeley) 6/1/90
* $Id: pathnames.h,v 1.4 1993/08/01 18:26:29 mycroft Exp $
* from: @(#)pathnames.h 8.2 (Berkeley) 3/27/94
* $Id: pathnames.h,v 1.5 1994/06/08 19:02:46 mycroft Exp $
*/
#define _PATH_EXECDIR "/sbin"
#define _PATH_EXPORTS "/etc/exports"
#define _PATH_SBIN "/sbin"
#define _PATH_USRSBIN "/usr/sbin"
#define _PATH_MOUNTDPID "/var/run/mountd.pid"

View File

@ -0,0 +1,12 @@
# from: @(#)Makefile 8.3 (Berkeley) 3/27/94
# $Id: Makefile,v 1.1 1994/06/08 19:08:27 mycroft Exp $
PROG= mount_cd9660
SRCS= mount_cd9660.c getmntopts.c
MAN8= mount_cd9660.0
MOUNT= ${.CURDIR}/../mount
CFLAGS+= -I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>

View File

@ -0,0 +1,101 @@
.\" Copyright (c) 1993, 1994
.\" The Regents of the University of California. All rights reserved.
.\" All rights reserved.
.\"
.\" This code is derived from software donated to Berkeley by
.\" Christopher G. Demetriou.
.\"
.\" 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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_cd9660.8 8.3 (Berkeley) 3/27/94
.\" $Id: mount_cd9660.8,v 1.1 1994/06/08 19:07:36 mycroft Exp $
.\"
.Dd March 27, 1994
.Dt MOUNT_CD9660 8
.Os BSD 4
.Sh NAME
.Nm mount_cd9660
.Nd mount an ISO-9660 filesystem
.Sh SYNOPSIS
.Nm mount_cd9660
.Op Fl egr
.Op Fl o Ar options
.Ar special | node
.Sh DESCRIPTION
The
.Nm mount_cd9660
command attaches the ISO-9660 filesystem residing on the device
.Pa special
to the global filesystem namespace at the location indicated by
.Pa node .
This command is normally executed by
.Xr mount 8
at boot time.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl e
Enable the use of extended attributes.
.It Fl g
Do not strip version numbers on files.
(By default, if there are files with different version numbers on the disk,
only the last one will be listed.)
In either case, files may be opened without explicitly stating a
version number.
.It Fl o
Options are specified with a
.Fl o
flag followed by a comma separated string of options.
See the
.Xr mount 8
man page for possible options and their meanings.
.It Fl r
Do not use any Rockridge extensions included in the filesystem.
.El
.Sh SEE ALSO
.Xr mount 2 ,
.Xr unmount 2 ,
.Xr fstab 5 ,
.Xr mount 8
.Sh BUGS
The cd9660 filesystem does not support the original "High Sierra"
("CDROM001") format.
.Pp
POSIX device node mapping is currently not supported.
.Pp
Version numbers are not stripped if Rockridge extensions are in use.
In this case, accessing files that don't have Rockridge names without
version numbers gets the one with the lowest version number and not
the one with the highest.
.Pp
There is no ECMA support.
.Sh HISTORY
The
.Nm mount_cd9660
utility first appeared 4.4BSD.

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley
* by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
* Support code is derived from software contributed to Berkeley
* by Atsushi Murai (amurai@spec.co.jp).
*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1992, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)mount_cd9660.c 8.4 (Berkeley) 3/27/94";*/
static char *rcsid = "$Id: mount_cd9660.c,v 1.1 1994/06/08 19:07:37 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#define CD9660
#include <sys/mount.h>
#include <err.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "mntopts.h"
struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_UPDATE,
{ NULL }
};
void usage __P((void));
int
main(argc, argv)
int argc;
char **argv;
{
struct iso_args args;
int ch, mntflags, opts;
char *dev, *dir;
mntflags = opts = 0;
while ((ch = getopt(argc, argv, "ego:r")) != EOF)
switch (ch) {
case 'e':
opts |= ISOFSMNT_EXTATT;
break;
case 'g':
opts |= ISOFSMNT_GENS;
break;
case 'o':
getmntopts(optarg, mopts, &mntflags);
break;
case 'r':
opts |= ISOFSMNT_NORRIP;
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc != 2)
usage();
dev = argv[0];
dir = argv[1];
#define DEFAULT_ROOTUID -2
args.fspec = dev;
args.export.ex_root = DEFAULT_ROOTUID;
if (mntflags & MNT_RDONLY)
args.export.ex_flags = MNT_EXRDONLY;
else
args.export.ex_flags = 0;
args.flags = opts;
if (mount(MOUNT_CD9660, dir, mntflags, &args) < 0)
err(1, NULL);
exit(0);
}
void
usage()
{
(void)fprintf(stderr,
"usage: mount_cd9660 [-egrt] [-o options] special node\n");
exit(1);
}

View File

@ -1,7 +1,12 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/5/93
# $Id: Makefile,v 1.3 1994/01/12 19:01:00 cgd Exp $
# from: @(#)Makefile 8.2 (Berkeley) 3/27/94
# $Id: Makefile,v 1.4 1994/06/08 19:11:36 mycroft Exp $
PROG= mount_fdesc
SRCS= mount_fdesc.c getmntopts.c
MAN8= mount_fdesc.0
MOUNT= ${.CURDIR}/../mount
CFLAGS+= -I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>

View File

@ -1,5 +1,5 @@
.\"
.\" Copyright (c) 1992, 1993
.\" Copyright (c) 1992, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
.\" All rights reserved.
.\"
@ -34,10 +34,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)mount_fdesc.8 8.1 (Berkeley) 6/9/93
.\" $Id: mount_fdesc.8,v 1.2 1994/01/12 19:01:12 cgd Exp $
.\" from: @(#)mount_fdesc.8 8.2 (Berkeley) 3/27/94
.\" $Id: mount_fdesc.8,v 1.3 1994/06/08 19:11:37 mycroft Exp $
.\"
.Dd June 9, 1993
.Dd March 27, 1994
.Dt MOUNT_FDESC 8
.Os BSD 4.4
.Sh NAME
@ -45,9 +45,9 @@
.Nd mount the file-descriptor file system
.Sh SYNOPSIS
.Nm mount_fdesc
.Op Fl F Ar fsoptions
.Pa fdesc
.Pa mount_point
.Op Fl o Ar options
.Ar fdesc
.Ar mount_point
.Sh DESCRIPTION
The
.Nm mount_fdesc
@ -62,6 +62,17 @@ This command is normally executed by
.Xr mount 8
at boot time.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl o
Options are specified with a
.Fl o
flag followed by a comma separated string of options.
See the
.Xr mount 8
man page for possible options and their meanings.
.El
.Pp
The contents of the mount point are
.Pa fd ,
.Pa stderr ,
@ -135,7 +146,8 @@ the real controlling terminal device.
.Xr mount 2 ,
.Xr unmount 2 ,
.Xr tty 4 ,
.Xr fstab 5
.Xr fstab 5 ,
.Xr mount 8
.Sh CAVEATS
No
.Pa .

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1990, 1992 Jan-Simon Pendry
* Copyright (c) 1992, 1993
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@ -33,21 +33,36 @@
* 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_fdesc.c 8.1 (Berkeley) 6/5/93
* $Id: mount_fdesc.c,v 1.4 1994/01/12 19:01:21 cgd Exp $
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1992, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)mount_fdesc.c 8.2 (Berkeley) 3/27/94";*/
static char *rcsid = "$Id: mount_fdesc.c,v 1.5 1994/06/08 19:11:38 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/mount.h>
#include <errno.h>
#include <err.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void usage __P((void));
#include "mntopts.h"
struct mntopt mopts[] = {
MOPT_STDOPTS,
{ NULL }
};
void usage __P((void));
int
main(argc, argv)
@ -57,10 +72,10 @@ main(argc, argv)
int ch, mntflags;
mntflags = 0;
while ((ch = getopt(argc, argv, "F:")) != EOF)
switch(ch) {
case 'F':
mntflags = atoi(optarg);
while ((ch = getopt(argc, argv, "o:")) != EOF)
switch (ch) {
case 'o':
getmntopts(optarg, mopts, &mntflags);
break;
case '?':
default:
@ -72,10 +87,8 @@ main(argc, argv)
if (argc != 2)
usage();
if (mount(MOUNT_FDESC, argv[1], mntflags, NULL)) {
(void)fprintf(stderr, "mount_fdesc: %s\n", strerror(errno));
exit(1);
}
if (mount(MOUNT_FDESC, argv[1], mntflags, NULL))
err(1, NULL);
exit(0);
}
@ -83,6 +96,6 @@ void
usage()
{
(void)fprintf(stderr,
"usage: mount_fdesc [ -F fsoptions ] /dev/fd mount_point\n");
"usage: mount_fdesc [-o options] fdesc mount_point\n");
exit(1);
}

View File

@ -1,7 +1,12 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/5/93
# $Id: Makefile,v 1.3 1994/01/12 19:11:02 cgd Exp $
# from: @(#)Makefile 8.2 (Berkeley) 3/27/94
# $Id: Makefile,v 1.4 1994/06/08 19:15:25 mycroft Exp $
PROG= mount_kernfs
SRCS= mount_kernfs.c getmntopts.c
MAN8= mount_kernfs.0
MOUNT= ${.CURDIR}/../mount
CFLAGS+= -I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>

View File

@ -1,5 +1,5 @@
.\"
.\" Copyright (c) 1992, 1993
.\" Copyright (c) 1992, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
.\" All rights reserved.
.\"
@ -34,10 +34,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)mount_kernfs.8 8.1 (Berkeley) 6/9/93
.\" $Id: mount_kernfs.8,v 1.3 1994/01/12 19:11:09 cgd Exp $
.\" from: @(#)mount_kernfs.8 8.2 (Berkeley) 3/27/94
.\" $Id: mount_kernfs.8,v 1.4 1994/06/08 19:15:26 mycroft Exp $
.\"
.Dd June 9, 1993
.Dd March 27, 1994
.Dt MOUNT_KERNFS 8
.Os BSD 4.4
.Sh NAME
@ -45,9 +45,9 @@
.Nd mount the /kern file system
.Sh SYNOPSIS
.Nm mount_kernfs
.Op Fl F Ar fsoptions
.Pa /kern
.Pa mount_point
.Op Fl o Ar options
.Ar /kern
.Ar mount_point
.Sh DESCRIPTION
The
.Nm mount_kern
@ -64,6 +64,17 @@ some of which can also be written.
The contents of the files is in a machine-independent format,
either a string, or an integer in decimal ASCII.
Where numbers are returned, a trailing newline character is also added.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl o
Options are specified with a
.Fl o
flag followed by a comma separated string of options.
See the
.Xr mount 8
man page for possible options and their meanings.
.El
.Sh FILES
.Bl -tag -width copyright -compact
.It Pa boottime
@ -80,23 +91,23 @@ the frequency of the system clock (decimal ASCII).
the 1, 5 and 15 minute load average in kernel fixed-point format.
The final integer is the fix-point scaling factor.
All numbers are in decimal ASCII.
.\" .It Pa pagesize
.\" the machine pagesize (decimal ASCII).
.It Pa pagesize
the machine pagesize (decimal ASCII).
.It Pa physmem
the number of pages of physical memory in the machine (decimal ASCII).
.\" .It Pa root
.\" the system root directory.
.\" In a chroot'ed environment,
.\" .Nm
.\" can be used to create a new
.\" .Pa /kern
.\" mount point.
.\" .Pa /kern/root
.\" will then refer to the system global root, not the current process root.
.It Pa root
the system root directory.
In a chroot'ed environment,
.Nm
can be used to create a new
.Pa /kern
mount point.
.Pa /kern/root
will then refer to the system global root, not the current process root.
.It Pa rootdev
the root device.
.\" .It Pa rrootdev
.\" the raw root device.
.It Pa rrootdev
the raw root device.
.It Pa time
the second and microsecond value of the system clock.
Both numbers are in decimal ASCII.
@ -110,7 +121,8 @@ can be generated by running:
.Sh SEE ALSO
.Xr mount 2 ,
.Xr unmount 2 ,
.Xr fstab 5
.Xr fstab 5 ,
.Xr mount 8
.Sh CAVEATS
This filesystem may not be NFS-exported.
.Sh HISTORY

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1990, 1992 Jan-Simon Pendry
* Copyright (c) 1992, 1993
* Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@ -33,21 +33,36 @@
* 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_kernfs.c 8.1 (Berkeley) 6/5/93
* $Id: mount_kernfs.c,v 1.4 1994/01/12 19:11:10 cgd Exp $
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1992, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)mount_kernfs.c 8.2 (Berkeley) 3/27/94";*/
static char *rcsid = "$Id: mount_kernfs.c,v 1.5 1994/06/08 19:15:27 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/mount.h>
#include <errno.h>
#include <err.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void usage __P((void));
#include "mntopts.h"
struct mntopt mopts[] = {
MOPT_STDOPTS,
{ NULL }
};
void usage __P((void));
int
main(argc, argv)
@ -57,10 +72,10 @@ main(argc, argv)
int ch, mntflags;
mntflags = 0;
while ((ch = getopt(argc, argv, "F:")) != EOF)
switch(ch) {
case 'F':
mntflags = atoi(optarg);
while ((ch = getopt(argc, argv, "o:")) != EOF)
switch (ch) {
case 'o':
getmntopts(optarg, mopts, &mntflags);
break;
case '?':
default:
@ -72,10 +87,8 @@ main(argc, argv)
if (argc != 2)
usage();
if (mount(MOUNT_KERNFS, argv[1], mntflags, NULL)) {
(void)fprintf(stderr, "mount_kernfs: %s\n", strerror(errno));
exit(1);
}
if (mount(MOUNT_KERNFS, argv[1], mntflags, NULL))
err(1, NULL);
exit(0);
}
@ -83,6 +96,6 @@ void
usage()
{
(void)fprintf(stderr,
"usage: mount_kernfs [ -F fsoptions ] /kern mount_point\n");
"usage: mount_kernfs [-o options] /kern mount_point\n");
exit(1);
}

12
sbin/mount_lfs/Makefile Normal file
View File

@ -0,0 +1,12 @@
# from: @(#)Makefile 8.2 (Berkeley) 3/27/94
# $Id: Makefile,v 1.1 1994/06/08 19:15:55 mycroft Exp $
PROG= mount_lfs
SRCS= mount_lfs.c getmntopts.c
MAN8= mount_lfs.0
MOUNT= ${.CURDIR}/../mount
CFLAGS+= -I${MOUNT}
.PATH: ${MOUNT}
.include <bsd.prog.mk>

126
sbin/mount_lfs/mount_lfs.8 Normal file
View File

@ -0,0 +1,126 @@
.\" Copyright (c) 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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_lfs.8 8.5 (Berkeley) 3/30/94
.\" $Id: mount_lfs.8,v 1.1 1994/06/08 19:15:56 mycroft Exp $
.\"
.Dd "March 30, 1994"
.Dt MOUNT_LFS 8
.Os BSD 4.4
.Sh NAME
.Nm mount_lfs
.Nd mount a log-structured file system
.Sh SYNOPSIS
.Nm mount_lfs
.Op Fl dns
.Op Fl o Ar options
.Ar special
.Ar node
.Sh DESCRIPTION
The
.Nm mount_lfs
command attaches a log-structured file system
.Ar special
device on to the file system tree at the point
.Ar node .
In addition, the
.Xr lfs_cleanerd 8
utility is invoked to clean the file system periodically.
.Pp
This command is normally executed by
.Xr mount 8
at boot time.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl d
Run
.Xr lfs_cleanerd 8
in debug mode.
.It Fl o
Options are specified with a
.Fl o
flag followed by a comma separated string of options.
See the
.Xr mount 8
man page for possible options and their meanings.
.It Fl n
Don't start
.Xr lfs_cleanerd 8
on the file system.
.It Fl s
Cause
.Xr lfs_cleanerd 8
to read data in small chunks when cleaning the file system.
.El
.Sh SEE ALSO
.Xr mount 2 ,
.Xr unmount 2 ,
.Xr fstab 5 ,
.Xr lfs_cleanerd 8 ,
.Xr mount 8
.sp
.Rs
.%A Ousterhout and Douglis
.%D 1989
.%T "Beating the I/O Bottleneck: A Case for Log-structured File Systems"
.%J "Operating Systems Review"
.%V Vol. 23
.%N No. 1
.%P pp. 11-27
.%O "also available as Technical Report UCB/CSD 88/467"
.Re
.Rs
.%A Rosenblum and Ousterhout
.%D 1991
.%T "The Design and Implementation of a Log-Structured File System"
.%J "ACM SIGOPS Operating Systems Review"
.%V Vol. 25
.%N No. 5
.Re
.Rs
.%A Seltzer
.%D 1992
.%T "File System Performance and Transaction Support"
.%B "PhD Thesis, University of California, Berkeley"
.%O "also available as Technical Report UCB/ERL M92"
.Re
.Rs
.%A Seltzer, Bostic, McKusick and Staelin
.%D 1993
.%T "An Implementation of a Log-Structured File System for UNIX"
.%J "Proc. of the Winter 1993 USENIX Conf."
.%P pp. 315-331
.Re
.Sh HISTORY
The
.Nm mount_lfs
function first appeared in 4.4BSD.

148
sbin/mount_lfs/mount_lfs.c Normal file
View File

@ -0,0 +1,148 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)mount_lfs.c 8.3 (Berkeley) 3/27/94";*/
static char *rcsid = "$Id: mount_lfs.c,v 1.1 1994/06/08 19:15:57 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/mount.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mntopts.h"
#include "pathnames.h"
struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_UPDATE,
{ NULL }
};
void usage __P((void));
void invoke_cleaner __P((char *));
int short_rds, cleaner_debug;
int
main(argc, argv)
int argc;
char *argv[];
{
struct ufs_args args;
int ch, mntflags, noclean;
char *fs_name, *options;
options = NULL;
mntflags = noclean = 0;
while ((ch = getopt(argc, argv, "dno:s")) != EOF)
switch (ch) {
case 'd':
cleaner_debug = 1;
break;
case 'n':
noclean = 1;
break;
case 'o':
getmntopts(optarg, mopts, &mntflags);
break;
case 's':
short_rds = 1;
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc != 2)
usage();
args.fspec = argv[0]; /* the name of the device file */
fs_name = argv[1]; /* the mount point */
#define DEFAULT_ROOTUID -2
args.export.ex_root = DEFAULT_ROOTUID;
if (mntflags & MNT_RDONLY)
args.export.ex_flags = MNT_EXRDONLY;
else
args.export.ex_flags = 0;
if (mount(MOUNT_LFS, fs_name, mntflags, &args))
err(1, NULL);
if (!noclean)
invoke_cleaner(fs_name);
/* NOTREACHED */
exit(0);
}
void
invoke_cleaner(name)
char *name;
{
char *args[6], **ap = args;
/* Build the argument list. */
*ap++ = _PATH_LFS_CLEANERD;
if (short_rds)
*ap++ = "-s";
if (cleaner_debug)
*ap++ = "-d";
*ap++ = name;
*ap = NULL;
execv(args[0], args);
err(1, "exec %s", _PATH_LFS_CLEANERD);
}
void
usage()
{
(void)fprintf(stderr,
"usage: mount_lfs [-dns] [-o options] special node\n");
exit(1);
}

View File

@ -0,0 +1,37 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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: @(#)pathnames.h 8.1 (Berkeley) 6/8/93
* $Id: pathnames.h,v 1.1 1994/06/08 19:15:59 mycroft Exp $
*/
#define _PATH_LFS_CLEANERD "/usr/libexec/lfs_cleanerd"

View File

@ -1,5 +1,5 @@
# from: @(#)Makefile 5.3 (Berkeley) 5/11/90
# $Id: Makefile,v 1.4 1993/08/01 05:38:06 mycroft Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/5/93
# $Id: Makefile,v 1.5 1994/06/08 18:58:21 mycroft Exp $
PROG= dumpfs
MAN8= dumpfs.0

View File

@ -1,5 +1,5 @@
.\" Copyright (c) 1983, 1991 Regents of the University of California.
.\" All rights reserved.
.\" Copyright (c) 1983, 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
@ -29,10 +29,10 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)dumpfs.8 6.2 (Berkeley) 3/16/91
.\" $Id: dumpfs.8,v 1.4 1993/08/01 07:39:20 mycroft Exp $
.\" from: @(#)dumpfs.8 8.1 (Berkeley) 6/5/93
.\" $Id: dumpfs.8,v 1.5 1994/06/08 18:58:22 mycroft Exp $
.\"
.Dd March 16, 1991
.Dd June 5, 1993
.Dt DUMPFS 8
.Os BSD 4.2
.Sh NAME

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1983 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 1983, 1992, 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
@ -32,27 +32,29 @@
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
All rights reserved.\n";
static char copyright[] =
"@(#) Copyright (c) 1983, 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)dumpfs.c 5.10 (Berkeley) 6/1/90";*/
static char rcsid[] = "$Id: dumpfs.c,v 1.5 1994/04/25 18:23:19 cgd Exp $";
/*static char sccsid[] = "from: @(#)dumpfs.c 8.2 (Berkeley) 2/2/94";*/
static char *rcsid = "$Id: dumpfs.c,v 1.6 1994/06/08 18:58:23 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/dinode.h>
#include <ufs/fs.h>
#include <stdio.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <fstab.h>
/*
* dumpfs
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
union {
struct fs fs;
@ -68,46 +70,60 @@ union {
long dev_bsize = 1;
int dumpfs __P((char *));
int dumpcg __P((char *, int, int));
void pbits __P((void *, int));
void usage __P((void));
int
main(argc, argv)
char **argv;
int argc;
char *argv[];
{
register struct fstab *fs;
int ch, eval;
argc--, argv++;
if (argc < 1) {
fprintf(stderr, "usage: dumpfs fs ...\n");
exit(1);
}
for (; argc > 0; argv++, argc--) {
fs = getfsfile(*argv);
if (fs == 0)
dumpfs(*argv);
while ((ch = getopt(argc, argv, "")) != EOF)
switch(ch) {
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc < 1)
usage();
for (eval = 0; *argv; ++argv)
if ((fs = getfsfile(*argv)) == NULL)
eval |= dumpfs(*argv);
else
dumpfs(fs->fs_spec);
}
eval |= dumpfs(fs->fs_spec);
exit(eval);
}
int
dumpfs(name)
char *name;
{
int c, i, j, k, size;
int fd, c, i, j, k, size;
if ((fd = open(name, O_RDONLY, 0)) < 0)
goto err;
if (lseek(fd, (off_t)SBOFF, SEEK_SET) == (off_t)-1)
goto err;
if (read(fd, &afs, SBSIZE) != SBSIZE)
goto err;
close(0);
if (open(name, 0) != 0) {
perror(name);
return;
}
lseek(0, SBOFF, 0);
if (read(0, &afs, SBSIZE) != SBSIZE) {
perror(name);
return;
}
if (afs.fs_postblformat == FS_42POSTBLFMT)
afs.fs_nrpos = 8;
dev_bsize = afs.fs_fsize / fsbtodb(&afs, 1);
printf("magic\t%x\tformat\t%s\ttime\t%s", afs.fs_magic,
afs.fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic",
printf("magic\t%x\ttime\t%s", afs.fs_magic,
ctime(&afs.fs_time));
printf("cylgrp\t%s\tinodes\t%s\n",
afs.fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic",
afs.fs_inodefmt < FS_44INODEFMT ? "4.2/4.3BSD" : "4.4BSD");
printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
afs.fs_cstotal.cs_nbfree, afs.fs_cstotal.cs_ndir,
afs.fs_cstotal.cs_nifree, afs.fs_cstotal.cs_nffree);
@ -128,8 +144,9 @@ dumpfs(name)
afs.fs_rotdelay, afs.fs_headswitch, afs.fs_trkseek, afs.fs_rps);
printf("ntrak\t%d\tnsect\t%d\tnpsect\t%d\tspc\t%d\n",
afs.fs_ntrak, afs.fs_nsect, afs.fs_npsect, afs.fs_spc);
printf("trackskew %d\tinterleave %d\n",
afs.fs_trackskew, afs.fs_interleave);
printf("symlinklen %d\ttrackskew %d\tinterleave %d\tcontigsumsize %d\n",
afs.fs_maxsymlinklen, afs.fs_trackskew, afs.fs_interleave,
afs.fs_contigsumsize);
printf("nindir\t%d\tinopb\t%d\tnspf\t%d\n",
afs.fs_nindir, afs.fs_inopb, afs.fs_nspf);
printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n",
@ -165,13 +182,13 @@ dumpfs(name)
for (i = 0, j = 0; i < afs.fs_cssize; i += afs.fs_bsize, j++) {
size = afs.fs_cssize - i < afs.fs_bsize ?
afs.fs_cssize - i : afs.fs_bsize;
afs.fs_csp[j] = (struct csum *)calloc(1, size);
lseek(0, fsbtodb(&afs, (afs.fs_csaddr + j * afs.fs_frag)) *
dev_bsize, 0);
if (read(0, afs.fs_csp[j], size) != size) {
perror(name);
return;
}
afs.fs_csp[j] = calloc(1, size);
if (lseek(fd,
(off_t)(fsbtodb(&afs, (afs.fs_csaddr + j * afs.fs_frag)) *
dev_bsize), SEEK_SET) == (off_t)-1)
goto err;
if (read(fd, afs.fs_csp[j], size) != size)
goto err;
}
for (i = 0; i < afs.fs_ncg; i++) {
struct csum *cs = &afs.fs_cs(&afs, i);
@ -189,27 +206,37 @@ dumpfs(name)
}
printf("\n");
for (i = 0; i < afs.fs_ncg; i++)
dumpcg(name, i);
close(0);
if (dumpcg(name, fd, i))
goto err;
(void)close(fd);
return (0);
err: if (fd != -1)
(void)close(fd);
(void)fprintf(stderr, "dumpfs: %s: %s\n", name, strerror(errno));
return (1);
};
dumpcg(name, c)
int
dumpcg(name, fd, c)
char *name;
int c;
int fd, c;
{
int i,j;
off_t cur;
int i, j;
printf("\ncg %d:\n", c);
lseek(0, fsbtodb(&afs, cgtod(&afs, c)) * dev_bsize, 0);
i = lseek(0, 0, 1);
if (read(0, (char *)&acg, afs.fs_bsize) != afs.fs_bsize) {
printf("dumpfs: %s: error reading cg\n", name);
return;
if ((cur = lseek(fd, (off_t)(fsbtodb(&afs, cgtod(&afs, c)) * dev_bsize),
SEEK_SET)) == (off_t)-1)
return (1);
if (read(fd, &acg, afs.fs_bsize) != afs.fs_bsize) {
(void)fprintf(stderr, "dumpfs: %s: error reading cg\n", name);
return (1);
}
printf("magic\t%x\ttell\t%x\ttime\t%s",
printf("magic\t%x\ttell\t%qx\ttime\t%s",
afs.fs_postblformat == FS_42POSTBLFMT ?
((struct ocg *)&acg)->cg_magic : acg.cg_magic,
i, ctime(&acg.cg_time));
cur, ctime(&acg.cg_time));
printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
acg.cg_cgx, acg.cg_ncyl, acg.cg_niblk, acg.cg_ndblk);
printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
@ -221,7 +248,23 @@ dumpcg(name, c)
printf("\t%d", acg.cg_frsum[i]);
j += i * acg.cg_frsum[i];
}
printf("\nsum of frsum: %d\niused:\t", j);
printf("\nsum of frsum: %d", j);
if (afs.fs_contigsumsize > 0) {
for (i = 1; i < afs.fs_contigsumsize; i++) {
if ((i - 1) % 8 == 0)
printf("\nclusters %d-%d:", i,
afs.fs_contigsumsize - 1 < i + 7 ?
afs.fs_contigsumsize - 1 : i + 7);
printf("\t%d", cg_clustersum(&acg)[i]);
}
printf("\nclusters size %d and over: %d\n",
afs.fs_contigsumsize,
cg_clustersum(&acg)[afs.fs_contigsumsize]);
printf("clusters free:\t");
pbits(cg_clustersfree(&acg), acg.cg_nclusterblks);
} else
printf("\n");
printf("iused:\t");
pbits(cg_inosused(&acg), afs.fs_ipg);
printf("free:\t");
pbits(cg_blksfree(&acg), afs.fs_fpg);
@ -238,26 +281,36 @@ dumpcg(name, c)
}
printf("\n");
}
return (0);
};
pbits(cp, max)
register char *cp;
void
pbits(vp, max)
register void *vp;
int max;
{
register int i;
int count = 0, j;
register char *p;
int count, j;
for (i = 0; i < max; i++)
if (isset(cp, i)) {
for (count = i = 0, p = vp; i < max; i++)
if (isset(p, i)) {
if (count)
printf(",%s", count % 6 ? " " : "\n\t");
count++;
printf("%d", i);
j = i;
while ((i+1)<max && isset(cp, i+1))
while ((i+1)<max && isset(p, i+1))
i++;
if (i != j)
printf("-%d", i);
}
printf("\n");
}
void
usage()
{
(void)fprintf(stderr, "usage: dumpfs filesys | device\n");
exit(1);
}

10
usr.sbin/dumplfs/Makefile Normal file
View File

@ -0,0 +1,10 @@
# from: @(#)Makefile 8.1 (Berkeley) 6/18/93
# $Id: Makefile,v 1.1 1994/06/08 18:58:47 mycroft Exp $
PROG= dumplfs
CFLAGS+=-I/sys/ufs/lfs
SRCS= dumplfs.c lfs_cksum.c misc.c
.PATH: /sys/ufs/lfs
MAN8= dumplfs.0
.include <bsd.prog.mk>

View File

@ -0,0 +1,60 @@
.\" Copyright (c) 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. 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: @(#)dumplfs.8 8.1 (Berkeley) 6/18/93
.\" $Id: dumplfs.8,v 1.1 1994/06/08 18:58:48 mycroft Exp $
.\"
.Dd June 18, 1993
.Dt DUMPLFS 8
.Os BSD 4.4
.Sh NAME
.Nm dumplfs
.Nd dump file system information
.Sh SYNOPSIS
.Nm dumplfs
.Op Ar filesys No \&| Ar device
.Sh DESCRIPTION
.Nm Dumplfs
prints out the file system layout information for the
LFS file system or special device specified.
The listing is very long and detailed.
This command is useful mostly for finding out certain file system
information such as the file system block size.
.Sh SEE ALSO
.Xr fs 5 ,
.Xr disktab 5 ,
.Xr disklabel 8 ,
.Xr newlfs 8 ,
.Sh HISTORY
The
.Nm dumplfs
command appeared in
.Bx 4.4 .

613
usr.sbin/dumplfs/dumplfs.c Normal file
View File

@ -0,0 +1,613 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)dumplfs.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: dumplfs.c,v 1.1 1994/06/08 18:58:50 mycroft Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/lfs/lfs.h>
#include <fcntl.h>
#include <fstab.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "extern.h"
static void addseg __P((char *));
static void dump_cleaner_info __P((struct lfs *, void *));
static void dump_dinode __P((struct dinode *));
static void dump_ifile __P((int, struct lfs *, int));
static int dump_ipage_ifile __P((int, IFILE *, int));
static int dump_ipage_segusage __P((struct lfs *, int, IFILE *, int));
static void dump_segment __P((int, int, daddr_t, struct lfs *, int));
static int dump_sum __P((int, struct lfs *, SEGSUM *, int, daddr_t));
static void dump_super __P((struct lfs *));
static void usage __P((void));
typedef struct seglist SEGLIST;
struct seglist {
SEGLIST *next;
int num;
};
SEGLIST *seglist;
int daddr_shift;
char *special;
/* Segment Usage formats */
#define print_suheader \
(void)printf("segnum\tflags\tnbytes\tninos\tnsums\tlastmod\n")
#define print_suentry(i, sp) \
(void)printf("%d\t%c%c%c\t%d\t%d\t%d\t%s", i, \
(((sp)->su_flags & SEGUSE_ACTIVE) ? 'A' : ' '), \
(((sp)->su_flags & SEGUSE_DIRTY) ? 'D' : 'C'), \
(((sp)->su_flags & SEGUSE_SUPERBLOCK) ? 'S' : ' '), \
(sp)->su_nbytes, (sp)->su_ninos, (sp)->su_nsums, \
ctime((time_t *)&(sp)->su_lastmod))
/* Ifile formats */
#define print_iheader \
(void)printf("inum\tstatus\tversion\tdaddr\t\tfreeptr\n")
#define print_ientry(i, ip) \
if (ip->if_daddr == LFS_UNUSED_DADDR) \
(void)printf("%d\tFREE\t%d\t \t\t%d\n", \
i, ip->if_version, ip->if_nextfree); \
else \
(void)printf("%d\tINUSE\t%d\t%8X \n", \
i, ip->if_version, ip->if_daddr)
int
main(argc, argv)
int argc;
char *argv[];
{
struct lfs lfs_sb1, lfs_sb2, *lfs_master;
daddr_t seg_addr;
int ch, do_allsb, do_ientries, fd, segnum;
do_allsb = 0;
do_ientries = 0;
while ((ch = getopt(argc, argv, "ais:")) != EOF)
switch(ch) {
case 'a': /* Dump all superblocks */
do_allsb = 1;
break;
case 'i': /* Dump ifile entries */
do_ientries = 1;
break;
case 's': /* Dump out these segments */
addseg(optarg);
break;
default:
usage();
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
special = argv[0];
if ((fd = open(special, O_RDONLY, 0)) < 0)
err("%s: %s", special, strerror(errno));
/* Read the first superblock */
get(fd, LFS_LABELPAD, &lfs_sb1, sizeof(struct lfs));
daddr_shift = lfs_sb1.lfs_bshift - lfs_sb1.lfs_fsbtodb;
/*
* Read the second superblock and figure out which check point is
* most up to date.
*/
get(fd,
lfs_sb1.lfs_sboffs[1] << daddr_shift, &lfs_sb2, sizeof(struct lfs));
lfs_master = &lfs_sb1;
if (lfs_sb1.lfs_tstamp < lfs_sb2.lfs_tstamp)
lfs_master = &lfs_sb2;
(void)printf("Master Superblock:\n");
dump_super(lfs_master);
dump_ifile(fd, lfs_master, do_ientries);
if (seglist != NULL)
for (; seglist != NULL; seglist = seglist->next) {
seg_addr = lfs_master->lfs_sboffs[0] + seglist->num *
(lfs_master->lfs_ssize << lfs_master->lfs_fsbtodb);
dump_segment(fd,
seglist->num, seg_addr, lfs_master, do_allsb);
}
else
for (segnum = 0, seg_addr = lfs_master->lfs_sboffs[0];
segnum < lfs_master->lfs_nseg; segnum++, seg_addr +=
lfs_master->lfs_ssize << lfs_master->lfs_fsbtodb)
dump_segment(fd,
segnum, seg_addr, lfs_master, do_allsb);
(void)close(fd);
exit(0);
}
/*
* We are reading all the blocks of an inode and dumping out the ifile table.
* This code could be tighter, but this is a first pass at getting the stuff
* printed out rather than making this code incredibly efficient.
*/
static void
dump_ifile(fd, lfsp, do_ientries)
int fd;
struct lfs *lfsp;
int do_ientries;
{
IFILE *ipage;
struct dinode *dip, *dpage;
daddr_t addr, *addrp, *dindir, *iaddrp, *indir;
int block_limit, i, inum, j, nblocks, nsupb, psize;
psize = lfsp->lfs_bsize;
addr = lfsp->lfs_idaddr;
if (!(dpage = malloc(psize)))
err("%s", strerror(errno));
get(fd, addr << daddr_shift, dpage, psize);
for (dip = dpage + INOPB(lfsp) - 1; dip >= dpage; --dip)
if (dip->di_inumber == LFS_IFILE_INUM)
break;
if (dip < dpage)
err("unable to locate ifile inode");
(void)printf("\nIFILE inode\n");
dump_dinode(dip);
(void)printf("\nIFILE contents\n");
nblocks = dip->di_size >> lfsp->lfs_bshift;
block_limit = MIN(nblocks, NDADDR);
/* Get the direct block */
if ((ipage = malloc(psize)) == NULL)
err("%s", strerror(errno));
for (inum = 0, addrp = dip->di_db, i = 0; i < block_limit;
i++, addrp++) {
get(fd, *addrp << daddr_shift, ipage, psize);
if (i < lfsp->lfs_cleansz) {
dump_cleaner_info(lfsp, ipage);
print_suheader;
continue;
}
if (i < (lfsp->lfs_segtabsz + lfsp->lfs_cleansz)) {
inum = dump_ipage_segusage(lfsp, inum, ipage,
lfsp->lfs_sepb);
if (!inum)
if(!do_ientries)
goto e0;
else
print_iheader;
} else
inum = dump_ipage_ifile(inum, ipage, lfsp->lfs_ifpb);
}
if (nblocks <= NDADDR)
goto e0;
/* Dump out blocks off of single indirect block */
if (!(indir = malloc(psize)))
err("%s", strerror(errno));
get(fd, dip->di_ib[0] << daddr_shift, indir, psize);
block_limit = MIN(i + lfsp->lfs_nindir, nblocks);
for (addrp = indir; i < block_limit; i++, addrp++) {
if (*addrp == LFS_UNUSED_DADDR)
break;
get(fd, *addrp << daddr_shift,ipage, psize);
if (i < lfsp->lfs_cleansz) {
dump_cleaner_info(lfsp, ipage);
continue;
} else
i -= lfsp->lfs_cleansz;
if (i < lfsp->lfs_segtabsz) {
inum = dump_ipage_segusage(lfsp, inum, ipage,
lfsp->lfs_sepb);
if (!inum)
if(!do_ientries)
goto e1;
else
print_iheader;
} else
inum = dump_ipage_ifile(inum, ipage, lfsp->lfs_ifpb);
}
if (nblocks <= lfsp->lfs_nindir * lfsp->lfs_ifpb)
goto e1;
/* Get the double indirect block */
if (!(dindir = malloc(psize)))
err("%s", strerror(errno));
get(fd, dip->di_ib[1] << daddr_shift, dindir, psize);
for (iaddrp = dindir, j = 0; j < lfsp->lfs_nindir; j++, iaddrp++) {
if (*iaddrp == LFS_UNUSED_DADDR)
break;
get(fd, *iaddrp << daddr_shift, indir, psize);
block_limit = MIN(i + lfsp->lfs_nindir, nblocks);
for (addrp = indir; i < block_limit; i++, addrp++) {
if (*addrp == LFS_UNUSED_DADDR)
break;
get(fd, *addrp << daddr_shift, ipage, psize);
if (i < lfsp->lfs_cleansz) {
dump_cleaner_info(lfsp, ipage);
continue;
} else
i -= lfsp->lfs_cleansz;
if (i < lfsp->lfs_segtabsz) {
inum = dump_ipage_segusage(lfsp,
inum, ipage, lfsp->lfs_sepb);
if (!inum)
if(!do_ientries)
goto e2;
else
print_iheader;
} else
inum = dump_ipage_ifile(inum,
ipage, lfsp->lfs_ifpb);
}
}
e2: free(dindir);
e1: free(indir);
e0: free(dpage);
free(ipage);
}
static int
dump_ipage_ifile(i, pp, tot)
int i;
IFILE *pp;
int tot;
{
IFILE *ip;
int cnt, max;
max = i + tot;
for (ip = pp, cnt = i; cnt < max; cnt++, ip++)
print_ientry(cnt, ip);
return (max);
}
static int
dump_ipage_segusage(lfsp, i, pp, tot)
struct lfs *lfsp;
int i;
IFILE *pp;
int tot;
{
SEGUSE *sp;
int cnt, max;
max = i + tot;
for (sp = (SEGUSE *)pp, cnt = i;
cnt < lfsp->lfs_nseg && cnt < max; cnt++, sp++)
print_suentry(cnt, sp);
if (max >= lfsp->lfs_nseg)
return (0);
else
return (max);
}
static void
dump_dinode(dip)
struct dinode *dip;
{
int i;
(void)printf("%s%d\t%s%d\t%s%d\t%s%d\t%s%d\n",
"mode ", dip->di_mode,
"nlink ", dip->di_nlink,
"uid ", dip->di_uid,
"gid ", dip->di_gid,
"size ", dip->di_size);
(void)printf("%s%s%s%s%s%s",
"atime ", ctime(&dip->di_atime.ts_sec),
"mtime ", ctime(&dip->di_mtime.ts_sec),
"ctime ", ctime(&dip->di_ctime.ts_sec));
(void)printf("inum %d\n", dip->di_inumber);
(void)printf("Direct Addresses\n");
for (i = 0; i < NDADDR; i++) {
(void)printf("\t0x%X", dip->di_db[i]);
if ((i % 6) == 5)
(void)printf("\n");
}
for (i = 0; i < NIADDR; i++)
(void)printf("\t0x%X", dip->di_ib[i]);
(void)printf("\n");
}
static int
dump_sum(fd, lfsp, sp, segnum, addr)
struct lfs *lfsp;
SEGSUM *sp;
int fd, segnum;
daddr_t addr;
{
FINFO *fp;
long *dp;
int i, j;
int ck;
int numblocks;
struct dinode *inop;
if (sp->ss_sumsum != (ck = cksum(&sp->ss_datasum,
LFS_SUMMARY_SIZE - sizeof(sp->ss_sumsum)))) {
(void)printf("dumplfs: %s %d address 0x%lx\n",
"corrupt summary block; segment", segnum, addr);
return(0);
}
(void)printf("Segment Summary Info at 0x%lx\n", addr);
(void)printf(" %s0x%X\t%s%d\t%s%d\n %s0x%X\t%s0x%X",
"next ", sp->ss_next,
"nfinfo ", sp->ss_nfinfo,
"ninos ", sp->ss_ninos,
"sumsum ", sp->ss_sumsum,
"datasum ", sp->ss_datasum );
(void)printf("\tcreate %s", ctime((time_t *)&sp->ss_create));
numblocks = (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp);
/* Dump out inode disk addresses */
dp = (daddr_t *)sp;
dp += LFS_SUMMARY_SIZE / sizeof(daddr_t);
inop = malloc(1 << lfsp->lfs_bshift);
printf(" Inode addresses:");
for (dp--, i = 0; i < sp->ss_ninos; dp--) {
printf("\t0x%X {", *dp);
get(fd, *dp << (lfsp->lfs_bshift - lfsp->lfs_fsbtodb), inop,
(1 << lfsp->lfs_bshift));
for (j = 0; i < sp->ss_ninos && j < INOPB(lfsp); j++, i++) {
if (j > 0)
(void)printf(", ");
(void)printf("%d", inop[j].di_inumber);
}
(void)printf("}");
if (((i/INOPB(lfsp)) % 4) == 3)
(void)printf("\n");
}
free(inop);
printf("\n");
for (fp = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; i++) {
numblocks += fp->fi_nblocks;
(void)printf(" FINFO for inode: %d version %d nblocks %d\n",
fp->fi_ino, fp->fi_version, fp->fi_nblocks);
dp = &(fp->fi_blocks[0]);
for (j = 0; j < fp->fi_nblocks; j++, dp++) {
(void)printf("\t%d", *dp);
if ((j % 8) == 7)
(void)printf("\n");
}
if ((j % 8) != 0)
(void)printf("\n");
fp = (FINFO *)dp;
}
return (numblocks);
}
static void
dump_segment(fd, segnum, addr, lfsp, dump_sb)
int fd, segnum;
daddr_t addr;
struct lfs *lfsp;
int dump_sb;
{
struct lfs lfs_sb, *sbp;
SEGSUM *sump;
char sumblock[LFS_SUMMARY_SIZE];
int did_one, nblocks, sb;
off_t sum_offset, super_off;
(void)printf("\nSEGMENT %d (Disk Address 0x%X)\n",
addr >> (lfsp->lfs_segshift - daddr_shift), addr);
sum_offset = (addr << (lfsp->lfs_bshift - lfsp->lfs_fsbtodb));
sb = 0;
did_one = 0;
do {
get(fd, sum_offset, sumblock, LFS_SUMMARY_SIZE);
sump = (SEGSUM *)sumblock;
if (sump->ss_sumsum != cksum (&sump->ss_datasum,
LFS_SUMMARY_SIZE - sizeof(sump->ss_sumsum))) {
sbp = (struct lfs *)sump;
if (sb = (sbp->lfs_magic == LFS_MAGIC)) {
super_off = sum_offset;
sum_offset += LFS_SBPAD;
} else if (did_one)
break;
else {
printf("Segment at 0x%X corrupt\n", addr);
break;
}
} else {
nblocks = dump_sum(fd, lfsp, sump, segnum, sum_offset >>
(lfsp->lfs_bshift - lfsp->lfs_fsbtodb));
if (nblocks)
sum_offset += LFS_SUMMARY_SIZE +
(nblocks << lfsp->lfs_bshift);
else
sum_offset = 0;
did_one = 1;
}
} while (sum_offset);
if (dump_sb && sb) {
get(fd, super_off, &lfs_sb, sizeof(struct lfs));
dump_super(&lfs_sb);
}
return;
}
static void
dump_super(lfsp)
struct lfs *lfsp;
{
int i;
(void)printf("%s0x%X\t%s0x%X\t%s%d\t%s%d\n",
"magic ", lfsp->lfs_magic,
"version ", lfsp->lfs_version,
"size ", lfsp->lfs_size,
"ssize ", lfsp->lfs_ssize);
(void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n",
"dsize ", lfsp->lfs_dsize,
"bsize ", lfsp->lfs_bsize,
"fsize ", lfsp->lfs_fsize,
"frag ", lfsp->lfs_frag);
(void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n",
"minfree ", lfsp->lfs_minfree,
"inopb ", lfsp->lfs_inopb,
"ifpb ", lfsp->lfs_ifpb,
"nindir ", lfsp->lfs_nindir);
(void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n",
"nseg ", lfsp->lfs_nseg,
"nspf ", lfsp->lfs_nspf,
"cleansz ", lfsp->lfs_cleansz,
"segtabsz ", lfsp->lfs_segtabsz);
(void)printf("%s0x%X\t%s%d\t%s0x%X\t%s%d\n",
"segmask ", lfsp->lfs_segmask,
"segshift ", lfsp->lfs_segshift,
"bmask ", lfsp->lfs_bmask,
"bshift ", lfsp->lfs_bshift);
(void)printf("%s0x%X\t\t%s%d\t%s0x%X\t%s%d\n",
"ffmask ", lfsp->lfs_ffmask,
"ffshift ", lfsp->lfs_ffshift,
"fbmask ", lfsp->lfs_fbmask,
"fbshift ", lfsp->lfs_fbshift);
(void)printf("%s%d\t%s%d\t%s0x%X\t%s0x%qx\n",
"sushift ", lfsp->lfs_sushift,
"fsbtodb ", lfsp->lfs_fsbtodb,
"cksum ", lfsp->lfs_cksum,
"maxfilesize ", lfsp->lfs_maxfilesize);
(void)printf("Superblock disk addresses:\t");
for (i = 0; i < LFS_MAXNUMSB; i++) {
(void)printf(" 0x%X", lfsp->lfs_sboffs[i]);
if ( i == (LFS_MAXNUMSB >> 1))
(void)printf("\n\t\t\t\t");
}
(void)printf("\n");
(void)printf("Checkpoint Info\n");
(void)printf("%s%d\t%s0x%X\t%s%d\n",
"free ", lfsp->lfs_free,
"idaddr ", lfsp->lfs_idaddr,
"ifile ", lfsp->lfs_ifile);
(void)printf("%s%d\t%s%d\t%s%d\n",
"bfree ", lfsp->lfs_bfree,
"avail ", lfsp->lfs_avail,
"uinodes ", lfsp->lfs_uinodes);
(void)printf("%s%d\t%s0x%X\t%s0x%X\n%s0x%X\t%s0x%X\t",
"nfiles ", lfsp->lfs_nfiles,
"lastseg ", lfsp->lfs_lastseg,
"nextseg ", lfsp->lfs_nextseg,
"curseg ", lfsp->lfs_curseg,
"offset ", lfsp->lfs_offset);
(void)printf("tstamp %s", ctime((time_t *)&lfsp->lfs_tstamp));
(void)printf("\nIn-Memory Information\n");
(void)printf("%s%d\t%s0x%X\t%s%d%s%d\t%s%d\n",
"seglock ", lfsp->lfs_seglock,
"iocount ", lfsp->lfs_iocount,
"writer ", lfsp->lfs_writer,
"dirops ", lfsp->lfs_dirops,
"doifile ", lfsp->lfs_doifile);
(void)printf("%s%d\t%s%d\t%s0x%X\t%s%d\n",
"nactive ", lfsp->lfs_nactive,
"fmod ", lfsp->lfs_fmod,
"clean ", lfsp->lfs_clean,
"ronly ", lfsp->lfs_ronly);
}
static void
addseg(arg)
char *arg;
{
SEGLIST *p;
if ((p = malloc(sizeof(SEGLIST))) == NULL)
err("%s", strerror(errno));
p->next = seglist;
p->num = atoi(arg);
seglist = p;
}
static void
dump_cleaner_info(lfsp, ipage)
struct lfs *lfsp;
void *ipage;
{
CLEANERINFO *cip;
cip = (CLEANERINFO *)ipage;
(void)printf("segments clean\t%d\tsegments dirty\t%d\n\n",
cip->clean, cip->dirty);
}
static void
usage()
{
(void)fprintf(stderr, "usage: dumplfs [-ai] [-s segnum] file\n");
exit(1);
}

40
usr.sbin/dumplfs/extern.h Normal file
View File

@ -0,0 +1,40 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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: @(#)extern.h 8.1 (Berkeley) 6/5/93
* $Id: extern.h,v 1.1 1994/06/08 18:58:51 mycroft Exp $
*/
void err __P((const char *, ...));
void get __P((int, off_t, void *, size_t));
extern char *special;

91
usr.sbin/dumplfs/misc.c Normal file
View File

@ -0,0 +1,91 @@
/*-
* Copyright (c) 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)misc.c 8.1 (Berkeley) 6/5/93";*/
static char *rcsid = "$Id: misc.c,v 1.1 1994/06/08 18:58:52 mycroft Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "extern.h"
void
get(fd, off, p, len)
int fd;
off_t off;
void *p;
size_t len;
{
int rbytes;
if (lseek(fd, off, SEEK_SET) < 0)
err("%s: %s", special, strerror(errno));
if ((rbytes = read(fd, p, len)) < 0)
err("%s: %s", special, strerror(errno));
if (rbytes != len)
err("%s: short read (%d, not %d)", special, rbytes, len);
}
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
void
#if __STDC__
err(const char *fmt, ...)
#else
err(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
(void)fprintf(stderr, "dumplfs: ");
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
(void)fprintf(stderr, "\n");
exit(1);
/* NOTREACHED */
}