Many files:

Checkin of e2fsprogs 0.5b
bitmap-optimize
Theodore Ts'o 1997-04-26 13:21:57 +00:00
commit 3839e65723
163 changed files with 22904 additions and 0 deletions

34
INSTALL Normal file
View File

@ -0,0 +1,34 @@
To install the second extended file system management program,
just follow the steps:
1) Edit the file MCONFIG
This file contains definitions used in the various makefiles. These
definitions have reasonable default value but you may want to adjust them to
your system configuration.
2) Create the dependencies files
Run `make depend' to create the dependencies files. Note that this
is not strictly necessary since the makefiles automagically recreates them
if they do not exist.
3) Compile the programs
Run `make' to compile the libraries and the programs.
4) Install the programs
Run `make install'
5) Install the include files and libraries
You can run `make install-libs' to install the include files and
libraries. Please note that this installation is not needed for the
programs to work. It is only needed if you expect to develop other
programs using the libraries.
You can run `make world' as an alternative to steps 2 and 3. This
will create the dependencies files, compile the programs and run e2fsck on
a test suite contained in e2fsck/images.

57
MCONFIG Normal file
View File

@ -0,0 +1,57 @@
#
# C Compiler
#
CC= gcc
#
# Optimization flags
#
#OPT= -g -O -fno-inline
OPT= -O2 -fomit-frame-pointer
#
# Warning flags
#
WFLAGS= -ansi -D_POSIX_SOURCE -pedantic \
-Wall -Wwrite-strings -Wpointer-arith \
-Wcast-qual -Wenum-clash -Wcast-align -Wtraditional \
-Wstrict-prototypes -Wmissing-prototypes \
-Wnested-externs -Winline -Wshadow
#
# Installation user and groups
#
BINGRP= bin
BINOWN= bin
BINMODE= 555
INCGRP= bin
INCOWN= bin
INCMODE= 444
LIBOWN= bin
LIBGRP= bin
LIBMODE= 444
MANGRP= bin
MANOWN= bin
MANMODE= 444
#
# Installation programs
#
CHMOD= chmod
INSTALL= install -c
INSTALLBIN= $(INSTALL) -o $(BINOWN) -g $(BINGRP) -m $(BINMODE) -s
INSTALLINC= $(INSTALL) -o $(INCOWN) -g $(INCGRP) -m $(INCMODE)
INSTALLLIB= $(INSTALL) -o $(LIBOWN) -g $(LIBGRP) -m $(LIBMODE)
INSTALLMAN= $(INSTALL) -o $(MANOWN) -g $(MANGRP) -m $(MANMODE)
#
# Destination directories
#
ETCDIR= /etc
INCLDIR= /usr/include
LIBDIR= /usr/lib
SBINDIR= /sbin
SMANDIR= /usr/man/man8
UMANDIR= /usr/man/man1
USRBINDIR= /usr/bin
USRSBINDIR= /usr/sbin

61
Makefile Normal file
View File

@ -0,0 +1,61 @@
all: libs
(cd e2fsck; $(MAKE))
(cd debugfs ; $(MAKE))
(cd misc ; $(MAKE))
libs:
(cd lib/et; $(MAKE))
(cd lib/ss; $(MAKE))
(cd lib/ext2fs; $(MAKE))
(cd lib/e2p; $(MAKE))
install:
(cd e2fsck; $(MAKE) install)
(cd debugfs; $(MAKE) install)
(cd misc ; $(MAKE) install)
install-libs:
(cd lib/et; $(MAKE) install)
(cd lib/ss; $(MAKE) install)
(cd lib/ext2fs; $(MAKE) install)
(cd lib/e2p; $(MAKE) install)
clean:
rm -f $(PROGS) \#* *.s *.o *.a *~ core MAKELOG
(cd lib/et; $(MAKE) clean)
(cd lib/ss; $(MAKE) clean)
(cd lib/ext2fs; $(MAKE) clean)
(cd lib/e2p; $(MAKE) clean)
(cd e2fsck; $(MAKE) clean)
(cd debugfs; $(MAKE) clean)
(cd misc ; $(MAKE) clean)
really-clean: clean
rm -f .depend
(cd lib/et; $(MAKE) really-clean)
(cd lib/ss; $(MAKE) really-clean)
(cd lib/ext2fs; $(MAKE) really-clean)
(cd lib/e2p; $(MAKE) really-clean)
(cd e2fsck; $(MAKE) really-clean)
(cd debugfs; $(MAKE) really-clean)
(cd misc ; $(MAKE) really-clean)
dep depend:
(cd lib/et; cp /dev/null .depend; $(MAKE) depend)
(cd lib/ss; cp /dev/null .depend; $(MAKE) depend)
(cd lib/ext2fs; cp /dev/null .depend; $(MAKE) depend)
(cd lib/e2p; cp /dev/null .depend; $(MAKE) depend)
(cd debugfs; cp /dev/null .depend; $(MAKE) depend)
(cd e2fsck; cp /dev/null .depend; $(MAKE) depend)
(cd misc ; cp /dev/null .depend; $(MAKE) depend)
world:
@date
$(MAKE) depend
@date
$(MAKE) all
@date
(cd e2fsck/images; ./test_script)
@date

42
README Normal file
View File

@ -0,0 +1,42 @@
This is the new version (0.5) of the second extended file system
management programs. You need to run Linux 1.0 or above to use it since
some programs used some ext2fs features that where not available in
previous kernel versions.
This version contains programs written by Theodore T'so and Remy Card.
This distribution was packaged by Ted and Remy with the help of Stephen Tweedie
and Alexy Vovenko.
The programs written or rewritten by Ted are:
- libext2fs: a new library containing entries to access the control
structures of a second extended file system.
- e2fsck: a new file system checker which uses optimized routines.
This new checker is much more efficient and safer than the old
e2fsck.
- mke2fs: a new file system creator which uses the ext2fs library.
- debugfs: a file system debugger which can be used to examine and
change the state of a file system. Use it with caution since it
can corrupt file systems if you are not careful.
- fsck: a new fsck front-end. This new fsck can run multiple
several file system checks simultanously if they are on different
disks.
The programs written by Remy are:
- badblocks: a new bad blocks checker. It can be run by the super
user to search for bad blocks on a device and can also be called
by e2fsck and mke2fs.
- dumpe2fs: a new program which displays the control structure of
a file system. To understand the output of this program, one needs
to know the physical structure of a second extended file system.
- mklost+found: re-creates a lost+found directory if it has been
deleted.
- tune2fs: adjusts tunable paramaters on a file system.
- chattr: changes files attributes and version.
- lsattr: lists files attributes and version.
Manual pages are included in this package.
See the file INSTALL for installation instructions.
In case of bugs in these programs, please contact Ted <tytso@mit.edu>
and Remy <card@masi.ibp.fr>.

36
debugfs/.depend Normal file
View File

@ -0,0 +1,36 @@
debugfs.o : debugfs.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h \
/usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/alloca.h /usr/include/ctype.h /usr/include/string.h /usr/include/time.h \
/usr/include/getopt.h /usr/include/sys/stat.h /usr/include/linux/stat.h ../lib/et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../lib/ss/ss.h ../lib/ss/mit-sipb-copyright.h \
../lib/ss/ss_err.h debugfs.h /usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h \
../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
icheck.o : icheck.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h \
/usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/alloca.h /usr/include/ctype.h /usr/include/string.h /usr/include/time.h \
/usr/include/getopt.h /usr/include/sys/stat.h /usr/include/linux/stat.h debugfs.h \
/usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h ../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
ncheck.o : ncheck.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h \
/usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/alloca.h /usr/include/ctype.h /usr/include/string.h /usr/include/time.h \
/usr/include/getopt.h /usr/include/sys/stat.h /usr/include/linux/stat.h debugfs.h \
/usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h ../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
util.o : util.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h \
/usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/alloca.h /usr/include/ctype.h /usr/include/string.h debugfs.h /usr/include/linux/ext2_fs.h \
../lib/ext2fs/ext2fs.h ../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h

42
debugfs/Makefile Normal file
View File

@ -0,0 +1,42 @@
include ../MCONFIG
CFLAGS= $(OPT) -Wall -I../lib
LDFLAGS= $(OPT)
PROGS= debugfs
BINDIR= $(USRSBINDIR)
MANPAGES= debugfs.8
MANDIR= $(SMANDIR)
MK_CMDS= ../lib/ss/mk_cmds
DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o
LIBS= -L../lib -lss -lcom_err -lext2fs
DEPLIBS= ../lib/libss.a ../lib/libcom_err.a ../lib/libext2fs.a
debugfs: $(DEBUG_OBJS) $(DEPLIBS)
cc $(LDFLAGS) -o debugfs $(DEBUG_OBJS) $(LIBS)
debug_cmds.c debug_cmds.h: debug_cmds.ct
$(MK_CMDS) debug_cmds.ct
install:: $(PROGS)
for i in $(PROGS); do \
$(INSTALLBIN) $$i $(BINDIR)/$$i; \
done
install:: $(MANPAGES)
for i in $(MANPAGES); do \
$(INSTALLMAN) $$i $(MANDIR)/$$i; \
done
clean:
rm -f debugfs \#* *.s *.o *.a *~ debug_cmds.c core
really-clean: clean
rm -f debug_cmds.c .depend
dep depend .depend:
$(CPP) $(CFLAGS) -M *.c >.depend
include .depend

98
debugfs/debug_cmds.ct Normal file
View File

@ -0,0 +1,98 @@
#
# Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
# under the terms of the GNU Public License.
#
command_table debug_cmds;
request do_show_debugfs_params, "Show debugfs parameters",
show_debugfs_params, params;
request do_open_filesys, "Open a filesystem",
open_filesys, open;
request do_close_filesys, "Close a filesystem",
close_filesys, close;
request do_init_filesys, "Initalize a filesystem (DESTROYS DATA)",
init_filesys;
request do_show_super_stats, "Show superblock statistics",
show_super_stats, stats;
request do_ncheck, "Do inode->name translation",
ncheck;
request do_icheck, "Do block->inode translation",
icheck;
request do_chroot, "Change root directory",
change_root_directory, chroot;
request do_change_working_dir, "Change working directory",
change_working_directory, cd;
request do_list_dir, "List directory",
list_directory, ls;
request do_stat, "Show inode information ",
show_inode_info, stat;
request do_link, "Create directory link",
link, ln;
request do_unlink, "Delete a directory link",
unlink;
request do_mkdir, "Create a directory",
mkdir;
request do_rmdir, "Remove a directory",
rmdir;
request do_rm, "Remove a file (unlink and kill_file, if appropriate)",
rm;
request do_kill_file, "Deallocate an inode and its blocks",
kill_file;
request do_clri, "Clear an inode's contents",
clri;
request do_freei, "Clear an inode's in-use flag",
freei;
request do_seti, "Set an inode's in-use flag",
seti;
request do_testi, "Test an inode's in-use flag",
testi;
request do_freeb, "Clear a block's in-use flag",
freeb;
request do_setb, "Set a block's in-use flag",
setb;
request do_testb, "Test a block's in-use flag",
testb;
request do_modify_inode, "Modify an inode by structure",
modify_inode, mi;
request do_find_free_block, "Find free block(s)",
find_free_block, ffb;
request do_find_free_inode, "Find free inode(s)",
find_free_inode, ffi;
request do_print_working_directory, "Print current working directory",
print_working_directory, pwd;
request do_expand_dir, "Expand directory",
expand_dir, expand;
end;

133
debugfs/debugfs.8 Normal file
View File

@ -0,0 +1,133 @@
.\" -*- nroff -*-
.TH DEBUGFS 8 "March 1994" "Version 0.4b"
.SH NAME
debugfs \- ext2 file system debugger
.SH SYNOPSIS
.B debugfs
[
[
.B \-w
]
device
]
.SH DESCRIPTION
.B debugfs
is a file system debugger. It can be used to examine and change the
state of an ext2 file system.
.br
.I device
is the special file corresponding to the device containing the ext2
file system (e.g /dev/hdXX).
.SH OPTIONS
.TP
.I -w
Specify that the file system should be open in read-write mode. Without this
option, the file system is open in read-only mode.
.SH COMMANDS
.B debugfs
is an interactive debugger. It understands a number of commands.
.TP
.I cd file
.TP
.I chroot file
.TP
.I close
Close the currently open file system.
.TP
.I clri file
Clear the contents of the inode corresponding to
.I file
.TP
.I expand_dir, file
Expand a directory.
.TP
.I find_free_block [goal]
Find the first free block, starting from
.I goal
and allocates it.
.TP
.I find_free_inode [dir [mode]]
Find a free inode and allocates it.
.TP
.I freeb block
Mark the block as not allocated.
.TP
.I freei file
Free the inode corresponding to
.I file
.TP
.I help
.TP
.I iname inode
Print the file name corresponding to
.I inode
(currently not implemented).
.TP
.I initialize device blocksize
Create an ext2 file system on
.I device
.TP
.I kill_file file
Remove a file and deallocates its blocks.
.TP
.I ln source_file dest_file
Create a link.
.TP
.I ls [pathname]
Emulate the
.BR ls (1)
command.
.TP
.I modify_inode file
Modify the contents of the inode corresponding to
.I file
.TP
.I mkdir file
Make a directory.
.TP
.I open [-w] device
Open a file system.
.TP
.I pwd
.TP
.I quit
Quit
.B debugfs
.TP
.I rm file
Remove a file.
.TP
.I rmdir file
Remove a directory.
.TP
.I setb block
Mark the block as allocated.
.TP
.I seti file
Mark in use the inode corresponding to
.I file
.TP
.I show_super_stats
List the contents of the super block.
.TP
.I stat file
Dump the contents of the inode corresponding to
.I file
.TP
.I testb block
Test if the block is marked as allocated.
.TP
.I testi file
Test if the inode correponding to
.I file
is marked as allocated.
.TP
.I unlink file
Remove a link.
.SH AUTHOR
.B debugfs
has been written by Theodore T'so <tytso@mit.edu>.
.SH SEE ALSO
.BR dumpe2fs (8),
.BR e2fsck (8),
.BR mke2fs (8)

1142
debugfs/debugfs.c Normal file

File diff suppressed because it is too large Load Diff

18
debugfs/debugfs.h Normal file
View File

@ -0,0 +1,18 @@
/*
* debugfs.h --- header file for the debugfs program
*/
#include <linux/ext2_fs.h>
#include "ext2fs/ext2fs.h"
extern ext2_filsys fs;
extern ino_t root, cwd;
extern FILE *open_pager(void);
extern void close_pager(FILE *stream);
extern int check_fs_open(char *name);
extern int check_fs_not_open(char *name);
extern ino_t string_to_inode(char *str);

157
debugfs/icheck.c Normal file
View File

@ -0,0 +1,157 @@
/*
* icheck.c --- given a list of blocks, generate a list of inodes
*
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "debugfs.h"
struct block_info {
blk_t blk;
ino_t ino;
};
struct block_walk_struct {
struct block_info *barray;
int blocks_left;
int num_blocks;
ino_t inode;
};
int icheck_proc(ext2_filsys fs,
blk_t *block_nr,
int blockcnt,
void *private)
{
struct block_walk_struct *bw = (struct block_walk_struct *) private;
int i;
for (i=0; i < bw->num_blocks; i++) {
if (bw->barray[i].blk == *block_nr) {
bw->barray[i].ino = bw->inode;
bw->blocks_left--;
}
}
if (!bw->blocks_left)
return BLOCK_ABORT;
return 0;
}
void do_icheck(int argc, char **argv)
{
struct block_walk_struct bw;
struct block_info *binfo;
int i;
ext2_inode_scan scan = 0;
ino_t ino;
struct ext2_inode inode;
errcode_t retval;
char *tmp;
char *block_buf;
if (argc < 2) {
com_err(argv[0], 0, "Usage: icheck <block number> ...");
return;
}
if (check_fs_open(argv[0]))
return;
bw.barray = malloc(sizeof(struct block_info) * argc);
if (!bw.barray) {
com_err("icheck", ENOMEM,
"while allocating inode info array");
return;
}
memset(bw.barray, 0, sizeof(struct block_info) * argc);
block_buf = malloc(fs->blocksize * 3);
if (!block_buf) {
com_err("icheck", ENOMEM, "while allocating block buffer");
goto error_out;
}
for (i=1; i < argc; i++) {
bw.barray[i-1].blk = strtol(argv[i], &tmp, 0);
if (*tmp) {
com_err(argv[0], 0, "Bad block - %s", argv[i]);
return;
}
}
bw.num_blocks = bw.blocks_left = argc-1;
retval = ext2fs_open_inode_scan(fs, 0, &scan);
if (retval) {
com_err("icheck", retval, "while opening inode scan");
goto error_out;
}
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval) {
com_err("icheck", retval, "while starting inode scan");
goto error_out;
}
while (ino) {
if (!inode.i_links_count)
goto next;
/*
* To handle filesystems touched by 0.3c extfs; can be
* removed later.
*/
if (inode.i_dtime)
goto next;
bw.inode = ino;
retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
icheck_proc, &bw);
if (retval) {
com_err("icheck", retval,
"while calling ext2_block_iterate");
goto next;
}
if (bw.blocks_left == 0)
break;
next:
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval) {
com_err("icheck", retval,
"while doing inode scan");
goto error_out;
}
}
printf("Block\tInode number\n");
for (i=0, binfo = bw.barray; i < bw.num_blocks; i++, binfo++) {
if (binfo->ino == 0) {
printf("%ld\t<block not found>\n", binfo->blk);
continue;
}
printf("%ld\t%ld\n", binfo->blk, binfo->ino);
}
error_out:
free(bw.barray);
free(block_buf);
if (scan)
ext2fs_close_inode_scan(scan);
return;
}

173
debugfs/ncheck.c Normal file
View File

@ -0,0 +1,173 @@
/*
* ncheck.c --- given a list of inodes, generate a list of names
*
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "debugfs.h"
struct inode_info {
ino_t ino;
ino_t parent;
char *pathname;
};
struct inode_walk_struct {
struct inode_info *iarray;
int inodes_left;
int num_inodes;
int position;
ino_t parent;
};
int ncheck_proc(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private)
{
struct inode_walk_struct *iw = (struct inode_walk_struct *) private;
int i;
iw->position++;
if (iw->position <= 2)
return 0;
for (i=0; i < iw->num_inodes; i++) {
if (iw->iarray[i].ino == dirent->inode) {
iw->iarray[i].parent = iw->parent;
iw->inodes_left--;
}
}
if (!iw->inodes_left)
return DIRENT_ABORT;
return 0;
}
void do_ncheck(int argc, char **argv)
{
struct inode_walk_struct iw;
struct inode_info *iinfo;
int i;
ext2_inode_scan scan = 0;
ino_t ino;
struct ext2_inode inode;
errcode_t retval;
char *tmp;
if (argc < 2) {
com_err(argv[0], 0, "Usage: ncheck <inode number> ...");
return;
}
if (check_fs_open(argv[0]))
return;
iw.iarray = malloc(sizeof(struct inode_info) * argc);
if (!iw.iarray) {
com_err("do_ncheck", ENOMEM,
"while allocating inode info array");
return;
}
memset(iw.iarray, 0, sizeof(struct inode_info) * argc);
for (i=1; i < argc; i++) {
iw.iarray[i-1].ino = strtol(argv[i], &tmp, 0);
if (*tmp) {
com_err(argv[0], 0, "Bad inode - %s", argv[i]);
return;
}
}
iw.num_inodes = iw.inodes_left = argc-1;
retval = ext2fs_open_inode_scan(fs, 0, &scan);
if (retval) {
com_err("ncheck", retval, "while opening inode scan");
goto error_out;
}
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval) {
com_err("ncheck", retval, "while starting inode scan");
goto error_out;
}
while (ino) {
if (!inode.i_links_count)
goto next;
/*
* To handle filesystems touched by 0.3c extfs; can be
* removed later.
*/
if (inode.i_dtime)
goto next;
/* Ignore anything that isn't a directory */
if (!S_ISDIR(inode.i_mode))
goto next;
iw.position = 0;
iw.parent = ino;
retval = ext2fs_dir_iterate(fs, ino, 0, 0,
ncheck_proc, &iw);
if (retval) {
com_err("ncheck", retval,
"while calling ext2_dir_iterate");
goto next;
}
if (iw.inodes_left == 0)
break;
next:
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval) {
com_err("ncheck", retval,
"while doing inode scan");
goto error_out;
}
}
for (i=0, iinfo = iw.iarray; i < iw.num_inodes; i++, iinfo++) {
if (iinfo->parent == 0)
continue;
retval = ext2fs_get_pathname(fs, iinfo->parent,
iinfo->ino, &iinfo->pathname);
if (retval)
com_err("ncheck", retval,
"while resolving pathname for inode %d (%d)",
iinfo->parent, iinfo->ino);
}
printf("Inode\tPathname\n");
for (i=0, iinfo = iw.iarray; i < iw.num_inodes; i++, iinfo++) {
if (iinfo->parent == 0) {
printf("%ld\t<inode not found>\n", iinfo->ino);
continue;
}
printf("%ld\t%s\n", iinfo->ino, iinfo->pathname ?
iinfo->pathname : "<unknown pathname>");
if (iinfo->pathname)
free(iinfo->pathname);
}
error_out:
free(iw.iarray);
if (scan)
ext2fs_close_inode_scan(scan);
return;
}

94
debugfs/util.c Normal file
View File

@ -0,0 +1,94 @@
/*
* util.c --- utilities for the debugfs program
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "debugfs.h"
FILE *open_pager(void)
{
FILE *outfile;
char *pager = getenv("PAGER");
if (!pager)
outfile = stdout;
else {
outfile = popen(pager, "w");
if (!outfile) outfile = stdout;
}
return (outfile);
}
void close_pager(FILE *stream)
{
if (stream && stream != stdout) fclose(stream);
}
/*
* This routine is used whenever a command needs to turn a string into
* an inode.
*/
ino_t string_to_inode(char *str)
{
ino_t ino;
int len = strlen(str);
int i;
int retval;
/*
* If the string is of the form <ino>, then treat it as an
* inode number.
*/
if ((len > 2) && (str[0] == '<') && (str[len-1] == '>')) {
for (i = 1; i < len-1; i++)
if (!isdigit(str[i]))
break;
if (i == len-1)
return(atoi(str+1));
}
retval = ext2fs_namei(fs, root, cwd, str, &ino);
if (retval) {
com_err(str, retval, "");
return 0;
}
return ino;
}
/*
* This routine returns 1 if the filesystem is not open, and prints an
* error message to that effect.
*/
int check_fs_open(char *name)
{
if (!fs) {
com_err(name, 0, "Filesystem not open");
return 1;
}
return 0;
}
/*
* This routine returns 1 if a filesystem is open, and prints an
* error message to that effect.
*/
int check_fs_not_open(char *name)
{
if (fs) {
com_err(name, 0,
"Filesystem %s is still open. Close it first.\n",
fs->device_name);
return 1;
}
return 0;
}

229
e2fsck/.depend Normal file
View File

@ -0,0 +1,229 @@
badblocks.o : badblocks.c /usr/include/time.h /usr/include/features.h /usr/include/sys/cdefs.h \
../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h e2fsck.h \
/usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/sys/time.h /usr/include/linux/time.h \
/usr/include/linux/fs.h /usr/include/linux/linkage.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/net.h /usr/include/linux/socket.h /usr/include/linux/sockios.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h \
/usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
/usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h \
../lib/ext2fs/ext2fs.h ../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
dirinfo.o : dirinfo.c ../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
e2fsck.h /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/sys/stat.h /usr/include/linux/stat.h \
/usr/include/sys/time.h /usr/include/linux/time.h /usr/include/time.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h \
../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
e2fsck.o : e2fsck.c /usr/include/string.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/fcntl.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/linux/fcntl.h /usr/include/ctype.h /usr/include/termios.h \
/usr/include/linux/termios.h /usr/include/time.h /usr/include/getopt.h /usr/include/unistd.h \
/usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/mntent.h /usr/include/stdio.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/sys/ioctl.h /usr/include/linux/ioctl.h \
/usr/include/malloc.h ../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
e2fsck.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/sys/stat.h /usr/include/linux/stat.h \
/usr/include/sys/time.h /usr/include/linux/time.h /usr/include/linux/fs.h /usr/include/linux/linkage.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/net.h /usr/include/linux/socket.h \
/usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h \
/usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h \
/usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h \
/usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h ../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h \
../lib/ext2fs/bitops.h ../version.h
ehandler.o : ehandler.c /usr/include/stdlib.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/string.h /usr/include/ctype.h /usr/include/termios.h /usr/include/linux/termios.h \
/usr/include/sys/resource.h /usr/include/sys/time.h /usr/include/linux/time.h \
/usr/include/time.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/limits.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/syslimits.h \
/usr/include/limits.h /usr/include/posix1_lim.h /usr/include/linux/limits.h \
/usr/include/linux/resource.h e2fsck.h /usr/include/stdio.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/net.h /usr/include/linux/socket.h \
/usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h \
/usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h \
/usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h \
/usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h ../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
flushb.o : flushb.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/fcntl.h /usr/include/linux/fcntl.h \
/usr/include/sys/ioctl.h /usr/include/linux/ioctl.h /usr/include/termios.h /usr/include/linux/termios.h \
/usr/include/linux/fs.h /usr/include/linux/linkage.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/net.h /usr/include/linux/socket.h /usr/include/linux/sockios.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h \
/usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
/usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h
mtrace.o : mtrace.c ./malloc.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/limits.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/syslimits.h /usr/include/limits.h \
/usr/include/posix1_lim.h /usr/include/linux/limits.h /usr/include/stdlib.h \
/usr/include/errno.h /usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h
pass1.o : pass1.c /usr/include/time.h /usr/include/features.h /usr/include/sys/cdefs.h \
../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h e2fsck.h \
/usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/sys/time.h /usr/include/linux/time.h \
/usr/include/linux/fs.h /usr/include/linux/linkage.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/net.h /usr/include/linux/socket.h /usr/include/linux/sockios.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h \
/usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
/usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h \
../lib/ext2fs/ext2fs.h ../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
pass1b.o : pass1b.c /usr/include/time.h /usr/include/features.h /usr/include/sys/cdefs.h \
../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h e2fsck.h \
/usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/sys/time.h /usr/include/linux/time.h \
/usr/include/linux/fs.h /usr/include/linux/linkage.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/net.h /usr/include/linux/socket.h /usr/include/linux/sockios.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h \
/usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
/usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h \
../lib/ext2fs/ext2fs.h ../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
pass2.o : pass2.c ../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
e2fsck.h /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/sys/stat.h /usr/include/linux/stat.h \
/usr/include/sys/time.h /usr/include/linux/time.h /usr/include/time.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h \
../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
pass3.o : pass3.c ../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
e2fsck.h /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/sys/stat.h /usr/include/linux/stat.h \
/usr/include/sys/time.h /usr/include/linux/time.h /usr/include/time.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h \
../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
pass4.o : pass4.c e2fsck.h /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/sys/stat.h /usr/include/linux/stat.h \
/usr/include/sys/time.h /usr/include/linux/time.h /usr/include/time.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h \
../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../lib/ext2fs/io.h \
../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
pass5.o : pass5.c ../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
e2fsck.h /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/sys/stat.h /usr/include/linux/stat.h \
/usr/include/sys/time.h /usr/include/linux/time.h /usr/include/time.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h \
../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h
util.o : util.c /usr/include/stdlib.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/string.h /usr/include/ctype.h /usr/include/termios.h /usr/include/linux/termios.h \
/usr/include/sys/resource.h /usr/include/sys/time.h /usr/include/linux/time.h \
/usr/include/time.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/limits.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/syslimits.h \
/usr/include/limits.h /usr/include/posix1_lim.h /usr/include/linux/limits.h \
/usr/include/linux/resource.h e2fsck.h /usr/include/stdio.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/net.h /usr/include/linux/socket.h \
/usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h \
/usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h \
/usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h \
/usr/include/linux/ext2_fs.h ../lib/ext2fs/ext2fs.h ../lib/et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../lib/ext2fs/io.h ../lib/ext2fs/ext2_err.h ../lib/ext2fs/bitops.h

53
e2fsck/CHANGES Normal file
View File

@ -0,0 +1,53 @@
[tytso:19940101.1200EST]
Add new options -l and -L, to append to and modify the bad-blocks list.
Fix bugs in bad-block cloning.
[tytso:19931230.1832EST]
Clean up e2fsck and library to be clean even when compiling with full
warnings enabled.
Make e2fsck deal with zero-length directories correctly.
Deleted inodes from old ext2fs code (inodes with dtime set but
non-zero link count) are detected, and the user is given the
opportunity to clear them.
The last bit in the last group of the block bitmap badding was not
being checked; now fixed.
The free_blocks and free_inodes count in the last group weren't being
checked. Now fixed.
[tytso:19931101.0007EST]
Fixed bugs with root reallocation; previously the parent pointers in
the dirinfo structure would get corrupted, causing many different '..'
links to be wrong. Also, the inode link count for the root directory
wasn't always being set correctly. (All of this would be fixed on
the second e2fsck, however).
Fixed to recognize filesystem corruption caused by mke2fs 0.2b (where
/ and /lost+found had non-zero dtime entries). Offers to fix /'s
dtime entry.
e2fsck will now expand the /lost+found directory if it runs out of room.
Fixed dependency on BLOCK_SIZE in pass2. e2fsck will now handle 4k
filesystems w/o problems.
e2fsck will now move bad blocks found in the inode bitmaps, block
bitmaps, and in the inode tables. (Can't handle bad blocks found in
the superblock and the group descriptors.) (Doesn't update alternate
superblocks, group descriptors.)
e2fsck now supports the -b option, to allow a user to specify an
alternate superblock.
The -B option now specifies the blocksize of the filesystem. (If not
specified, and the -b option is specified, e2fsck will attempt to
search through various blocksizes to find the correct one.)
Added manual page.

82
e2fsck/Makefile Normal file
View File

@ -0,0 +1,82 @@
#
# Makefile for e2fsck
#
include ../MCONFIG
MK_CMDS= ../lib/ss/mk_cmds
CFLAGS= $(PROF) $(OPT) $(MTRACE) $(MCHECK) $(WFLAGS) -I../lib
LDFLAGS= $(PROF) $(OPT)
PROGS= e2fsck flushb
MANPAGES= e2fsck.8
BINDIR= $(SBINDIR)
MANDIR= $(SMANDIR)
LIBS= -L../lib -lss -lcom_err -lext2fs $(CHECKLIB)
DEPLIBS= ../lib/libss.a ../lib/libcom_err.a ../lib/libext2fs.a
#
# Flags for using Checker
# Note: The optimization flags must include -g
#
#MCHECK= -checker
#LIBS= -L../lib -lss -lcom_err -lext2fs $(CHECKLIB)
#DEPLIBS= ../lib/libss.a ../lib/libcom_err.a ../lib/libext2fs.a
#CHECKLIB= /usr/lib/libchecker.o
#
# Flags for doing mtrace --- uncomment to produce mtracing e2fsck
# Note: The optimization flags must include -g
#
#MTRACE= -DMTRACE
#MTRACE_OBJ= mtrace.o
#OPT= -g
#
# Flags for doing mcheck --- uncomment to produce mchecking e2fsck
# Note: The optimization flags must include -g
#
#MCHECK= -DMCHECK
#
# Flags for profiling --- uncomment to produce profiling e2fsck
#
#PROF= -pg
#LIBS= -L../lib -lss -lcom_err_p -lext2fs_p
#DEPLIBS= ../lib/libss.a ../lib/libcom_err_p.a ../lib/libext2fs_p.a
OBJS= e2fsck.o pass1.o pass1b.o pass2.o pass3.o pass4.o pass5.o \
badblocks.o util.o dirinfo.o ehandler.o $(MTRACE_OBJ)
all: $(PROGS)
#e2fsck: $(OBJS) $(DEPLIBS)
# cc $(LDFLAGS) -o e2fsck $(OBJS) $(LIBS)
e2fsck: $(OBJS) $(DEPLIBS)
cc $(LDFLAGS) -static -o e2fsck $(OBJS) $(LIBS)
flushb: flushb.o
cc $(LDFLAGS) -o flushb flushb.o $(CHECKLIB)
install:: $(PROGS)
for i in $(PROGS); do \
$(INSTALLBIN) $$i $(BINDIR)/$$i; \
done
ln -sf e2fsck $(BINDIR)/fsck.ext2
install:: $(MANPAGES)
for i in $(MANPAGES); do \
$(INSTALLMAN) $$i $(MANDIR)/$$i; \
done
clean:
rm -f $(PROGS) \#* *\# *.s *.o *.a *~ core
really-clean:
rm -f .depend
dep depend .depend:
$(CPP) $(CFLAGS) -M *.c >.depend
include .depend

126
e2fsck/badblocks.c Normal file
View File

@ -0,0 +1,126 @@
/*
* badblocks.c --- replace/append bad blocks to the bad block inode
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*/
#include <time.h>
#include <et/com_err.h>
#include "e2fsck.h"
static void invalid_block(ext2_filsys fs, blk_t blk)
{
printf("Bad block %lu out of range; ignored.\n", blk);
return;
}
void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
int replace_bad_blocks)
{
errcode_t retval;
badblocks_list bb_list = 0;
FILE *f;
read_bitmaps(fs);
/*
* If we're appending to the bad blocks inode, read in the
* current bad blocks.
*/
if (!replace_bad_blocks) {
retval = ext2fs_read_bb_inode(fs, &bb_list);
if (retval) {
com_err("ext2fs_read_bb_inode", retval,
"while reading the bad blocks inode");
fatal_error(0);
}
}
/*
* Now read in the bad blocks from the file.
*/
f = fopen(bad_blocks_file, "r");
if (!f) {
com_err("read_bad_blocks_file", errno,
"while trying to open %s", bad_blocks_file);
fatal_error(0);
}
retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block);
fclose (f);
if (retval) {
com_err("ext2fs_read_bb_FILE", retval,
"while reading in list of bad blocks from file");
fatal_error(0);
}
/*
* Finally, update the bad blocks from the bad_block_map
*/
retval = ext2fs_update_bb_inode(fs, bb_list);
if (retval) {
com_err("ext2fs_update_bb_inode", retval,
"while updating bad block inode");
fatal_error(0);
}
badblocks_list_free(bb_list);
return;
}
void test_disk(ext2_filsys fs)
{
errcode_t retval;
badblocks_list bb_list = 0;
FILE *f;
char buf[1024];
read_bitmaps(fs);
/*
* Always read in the current list of bad blocks.
*/
retval = ext2fs_read_bb_inode(fs, &bb_list);
if (retval) {
com_err("ext2fs_read_bb_inode", retval,
"while reading the bad blocks inode");
fatal_error(0);
}
/*
* Now run the bad blocks program
*/
sprintf(buf, "badblocks %s%s %ld", preen ? "" : "-s ",
fs->device_name,
fs->super->s_blocks_count);
if (verbose)
printf("Running command: %s\n", buf);
f = popen(buf, "r");
if (!f) {
com_err("popen", errno,
"while trying to run %s", buf);
fatal_error(0);
}
retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block);
fclose (f);
if (retval) {
com_err("ext2fs_read_bb_FILE", retval,
"while processing list of bad blocks from program");
fatal_error(0);
}
/*
* Finally, update the bad blocks from the bad_block_map
*/
retval = ext2fs_update_bb_inode(fs, bb_list);
if (retval) {
com_err("ext2fs_update_bb_inode", retval,
"while updating bad block inode");
fatal_error(0);
}
badblocks_list_free(bb_list);
return;
}

120
e2fsck/dirinfo.c Normal file
View File

@ -0,0 +1,120 @@
/*
* dirinfo.c --- maintains the directory information table for e2fsck.
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <et/com_err.h>
#include "e2fsck.h"
static int dir_info_count = 0;
static int dir_info_size = 0;
static struct dir_info *dir_info = 0;
int get_num_dirs(ext2_filsys fs)
{
int i, num_dirs;
num_dirs = 0;
for (i = 0; i < fs->group_desc_count; i++)
num_dirs += fs->group_desc[i].bg_used_dirs_count;
return num_dirs;
}
/*
* This subroutine is called during pass1 to stash away the block
* numbers for the directory, which we will need later. The idea is
* to avoid reading directory inodes twice.
*/
void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent,
struct ext2_inode *inode)
{
struct dir_info *dir;
int i, j;
#if 0
printf("add_dir_info for inode %d...\n", ino);
#endif
if (!dir_info) {
dir_info_count = 0;
dir_info_size = get_num_dirs(fs) + 10;
dir_info = allocate_memory(dir_info_size *
sizeof (struct dir_info),
"directory map");
}
if (dir_info_count >= dir_info_size) {
dir_info_size += 10;
dir_info = realloc(dir_info,
dir_info_size * sizeof(struct dir_info));
}
/*
* Normally, add_dir_info is called with each inode in
* sequential order; but once in a while (like when pass 3
* needs to recreate the root directory or lost+found
* directory) it is called out of order. In those cases, we
* need to move the dir_info entries down to make room, since
* the dir_info array needs to be sorted by inode number for
* get_dir_info()'s sake.
*/
if (dir_info_count && dir_info[dir_info_count-1].ino > ino) {
for (i = dir_info_count-1; i > 0; i--)
if (dir_info[i-1].ino < ino)
break;
dir = &dir_info[i];
if (dir->ino != ino)
for (j = dir_info_count++; j > i; j--)
dir_info[j] = dir_info[j-1];
} else
dir = &dir_info[dir_info_count++];
dir->ino = ino;
dir->dotdot = parent;
dir->parent = parent;
}
/*
* get_dir_info() --- given an inode number, try to find the directory
* information entry for it.
*/
struct dir_info *get_dir_info(ino_t ino)
{
int low, high, mid;
low = 0;
high = dir_info_count-1;
if (ino == dir_info[low].ino)
return &dir_info[low];
if (ino == dir_info[high].ino)
return &dir_info[high];
while (low < high) {
mid = (low+high)/2;
if (mid == low || mid == high)
break;
if (ino == dir_info[mid].ino)
return &dir_info[mid];
if (ino < dir_info[mid].ino)
high = mid;
else
low = mid;
}
return 0;
}
/*
* Free the dir_info structure when it isn't needed any more.
*/
void free_dir_info(ext2_filsys fs)
{
if (dir_info) {
free(dir_info);
dir_info = 0;
}
dir_info_size = 0;
dir_info_count = 0;
}

127
e2fsck/e2fsck.8 Normal file
View File

@ -0,0 +1,127 @@
.\" -*- nroff -*-
.\" Copyright 1993, 1994 by Theodore Ts'o. All Rights Reserved.
.\" This file may be copied under the terms of the GNU Public License.
.\"
.TH NEW-E2FSCK 8 "March 1994" "Version 0.5"
.SH NAME
e2fsck \- check a Linux second extended file system
.SH SYNOPSIS
.B e2fsck
[
.B \-panyrdfvtFV
]
[
.B \-b
.I superblock
]
[
.B \-B
.I blocksize
]
[
.B \-l|-L
.I bad_blocks_file
]
.I device
.SH DESCRIPTION
.B e2fsck
is used to check a Linux second extended file system.
.TP
.I device
is the special file corresponding to the device (e.g /dev/hdXX).
.SH OPTIONS
.TP
.I -b superblock
Instead of using the normal superblock, use the alternative superblock
specified by
.IR superblock .
.TP
.I -d
Print debugging output (useless unless you are debugging
.B e2fsck
).
.TP
.I -f
Force checking even if the file system seems clean.
.TP
.I -F
Flush the filesystem device's buffer caches before beginning. Only
really useful for doing e2fsck time trials.
.TP
.I -l filename
Add the blocks listed in the file specified by
.I filename
to the list of bad blocks.
.TP
.I -L filename
Set the bad blocks list to be the list of blocks specified by
.IR filename .
(This option is the same as the
.I -l
option, except the bad blocks list is cleared before the blocks listed
in the file are added to the bad blocks list.)
.TP
.I -n
Open the filesystem read-only, and assume an answer of ``no'' to all
questions. Allows
.B e2fsck
to be used non-interactively. (Note: if the
.I -l
or
.I -L
options are specified in addition to the
.I -n
option, then the filesystem will be opened read-write, to permit the
bad-blocks list to be updated. However, no other changes will be made
to the filesystem.)
.TP
.I -p
Automatically repair ("preen") the file system without any questions.
The
.I -a
option is provided for backwards compatibility.
.TP
.I -t
Print timing statistics for
.BR e2fsck .
If this option is used twice, additional timing statistics are printed
on a pass by pass basis.
.TP
.I -v
Verbose mode.
.TP
.I -V
Print version information and exit.
.TP
.I -y
Assume an answer of ``yes'' to all questions; allows
.B e2fsck
to be used non-interactively.
.SH EXIT CODE
The exit code returned by
.B e2fsck
is the sum of the following conditions:
.br
\ 0\ \-\ No errors
.br
\ 1\ \-\ File system errors corrected
.br
\ 2\ \-\ File system errors corrected, system should
.br
\ \ \ \ be rebooted if file system was mounted
.br
\ 4\ \-\ File system errors left uncorrected
.br
\ 8\ \-\ Operational error
.br
\ 16\ \-\ Usage or syntax error
.br
\ 128\ \-\ Shared library error
.br
.SH AUTHOR
This version of
.B e2fsck
is written by Theodore Ts'o <tytso@mit.edu>.
.SH SEE ALSO
.BR mke2fs (8),
.BR tune2fs (8)

481
e2fsck/e2fsck.c Normal file
View File

@ -0,0 +1,481 @@
/*
* e2fsck.c - a consistency checker for the new extended file system.
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*/
/* Usage: e2fsck [-dfpnsvy] device
* -d -- debugging this program
* -f -- check the fs even if it is marked valid
* -p -- "preen" the filesystem
* -n -- open the filesystem r/o mode; never try to fix problems
* -v -- verbose (tells how many files)
* -y -- always answer yes to questions
*
* The device may be a block device or a image of one, but this isn't
* enforced (but it's not much fun on a character device :-).
*/
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <time.h>
#include <getopt.h>
#include <unistd.h>
#include <mntent.h>
#include <sys/ioctl.h>
#include <malloc.h>
#include "et/com_err.h"
#include "e2fsck.h"
#include "../version.h"
extern int isatty(int);
const char * program_name = "e2fsck";
const char * device_name = NULL;
/* Command line options */
int nflag = 0;
int yflag = 0;
int tflag = 0; /* Do timing */
int cflag = 0; /* check disk */
int preen = 0;
int rwflag = 1;
int inode_buffer_blocks = 0;
blk_t superblock;
int blocksize = 0;
int verbose = 0;
int list = 0;
int debug = 0;
int force = 0;
static int show_version_only = 0;
static int replace_bad_blocks = 0;
static char *bad_blocks_file = 0;
static int possible_block_sizes[] = { 1024, 2048, 4096, 8192, 0};
struct resource_track global_rtrack;
static int root_filesystem = 0;
static int read_only_root = 0;
static void usage(NOARGS)
{
fprintf(stderr,
"Usage: %s [-panyrdfvtFV] [-b superblock] [-B blocksize]\n"
"\t\tdevice\n", program_name);
exit(FSCK_USAGE);
}
static void show_stats(ext2_filsys fs)
{
int inodes, inodes_used, blocks, blocks_used;
int dir_links;
int num_files, num_links;
dir_links = 2 * fs_directory_count - 1;
num_files = fs_total_count - dir_links;
num_links = fs_links_count - dir_links;
inodes = fs->super->s_inodes_count;
inodes_used = (fs->super->s_inodes_count -
fs->super->s_free_inodes_count);
blocks = fs->super->s_blocks_count;
blocks_used = (fs->super->s_blocks_count -
fs->super->s_free_blocks_count);
if (!verbose) {
printf("%s: %d/%d files, %d/%d blocks\n", device_name,
inodes_used, inodes, blocks_used, blocks);
return;
}
printf ("\n%6d inode%s used (%d%%)\n", inodes_used,
(inodes_used != 1) ? "s" : "",
100 * inodes_used / inodes);
printf ("%6d block%s used (%d%%)\n"
"%6d bad block%s\n", blocks_used,
(blocks_used != 1) ? "s" : "",
100 * blocks_used / blocks, fs_badblocks_count,
fs_badblocks_count != 1 ? "s" : "");
printf ("\n%6d regular file%s\n"
"%6d director%s\n"
"%6d character device file%s\n"
"%6d block device file%s\n"
"%6d fifo%s\n"
"%6d link%s\n"
"%6d symbolic link%s (%d fast symbolic link%s)\n"
"%6d socket%s\n"
"------\n"
"%6d file%s\n",
fs_regular_count, (fs_regular_count != 1) ? "s" : "",
fs_directory_count, (fs_directory_count != 1) ? "ies" : "y",
fs_chardev_count, (fs_chardev_count != 1) ? "s" : "",
fs_blockdev_count, (fs_blockdev_count != 1) ? "s" : "",
fs_fifo_count, (fs_fifo_count != 1) ? "s" : "",
fs_links_count - dir_links,
((fs_links_count - dir_links) != 1) ? "s" : "",
fs_symlinks_count, (fs_symlinks_count != 1) ? "s" : "",
fs_fast_symlinks_count, (fs_fast_symlinks_count != 1) ? "s" : "",
fs_sockets_count, (fs_sockets_count != 1) ? "s" : "",
fs_total_count - dir_links,
((fs_total_count - dir_links) != 1) ? "s" : "");
}
static void check_mount(NOARGS)
{
FILE * f;
struct mntent * mnt;
int cont;
int fd;
if ((f = setmntent (MOUNTED, "r")) == NULL)
return;
while ((mnt = getmntent (f)) != NULL)
if (strcmp (device_name, mnt->mnt_fsname) == 0)
break;
endmntent (f);
if (!mnt)
return;
if (!strcmp(mnt->mnt_dir, "/"))
root_filesystem = 1;
/*
* If the root is mounted read-only, then /etc/mtab is
* probably not correct; so we won't issue a warning based on
* it.
*/
fd = open(MOUNTED, O_RDWR);
if (fd < 0) {
if (errno == EROFS) {
read_only_root = 1;
return;
}
} else
close(fd);
if (!rwflag) {
printf("Warning! %s is mounted.\n", device_name);
return;
}
printf ("%s is mounted. ", device_name);
if (isatty (0) && isatty (1))
cont = ask_yn("Do you really want to continue", -1);
else
cont = 0;
if (!cont) {
printf ("check aborted.\n");
exit (0);
}
return;
}
static void sync_disks(NOARGS)
{
sync();
sync();
sleep(1);
sync();
}
static void check_super_block(ext2_filsys fs)
{
blk_t first_block, last_block;
int blocks_per_group = fs->super->s_blocks_per_group;
int i;
first_block = fs->super->s_first_data_block;
last_block = first_block + blocks_per_group;
for (i = 0; i < fs->group_desc_count; i++) {
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
printf("Block bitmap %ld for group %d not in group.\n",
fs->group_desc[i].bg_block_bitmap, i);
fatal_error(0);
}
if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
printf("Inode bitmap %ld for group %d not in group.\n",
fs->group_desc[i].bg_inode_bitmap, i);
fatal_error(0);
}
if ((fs->group_desc[i].bg_inode_table < first_block) ||
((fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group - 1) >= last_block)) {
printf("Inode table %ld for group %d not in group.\n",
fs->group_desc[i].bg_inode_table, i);
fatal_error(0);
}
first_block += fs->super->s_blocks_per_group;
last_block += fs->super->s_blocks_per_group;
}
return;
}
/*
* This routine checks to see if a filesystem can be skipped; if so,
* it will exit with E2FSCK_OK. Under some conditions it will print a
* message explaining why a check is being forced.
*/
static void check_if_skip(ext2_filsys fs)
{
const char *reason = NULL;
if (force || bad_blocks_file || cflag)
return;
if (fs->super->s_state & EXT2_ERROR_FS)
reason = "contains a file system with errors";
else if (fs->super->s_mnt_count >=
(unsigned) fs->super->s_max_mnt_count)
reason = "has reached maximal mount count";
else if (fs->super->s_checkinterval &&
time(0) >= (fs->super->s_lastcheck +
fs->super->s_checkinterval))
reason = "has gone too long without being checked";
if (reason) {
printf("%s %s, check forced.\n", device_name, reason);
return;
}
if (fs->super->s_state & EXT2_VALID_FS) {
printf("%s is clean, no check.\n", device_name);
exit(FSCK_OK);
}
}
static void PRS(int argc, char *argv[])
{
int flush = 0;
char c;
#ifdef MTRACE
extern void *mallwatch;
#endif
char *oldpath, newpath[PATH_MAX];
/* Update our PATH to include /sbin */
strcpy(newpath, "PATH=/sbin:");
if ((oldpath = getenv("PATH")) != NULL)
strcat(newpath, oldpath);
putenv(newpath);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
initialize_ext2_error_table();
if (argc && *argv)
program_name = *argv;
while ((c = getopt (argc, argv, "panyrcB:dfvtFVM:b:I:P:l:L:")) != EOF)
switch (c) {
case 'p':
case 'a':
preen = 1;
yflag = nflag = 0;
break;
case 'n':
nflag = 1;
preen = yflag = 0;
break;
case 'y':
yflag = 1;
preen = nflag = 0;
break;
case 't':
tflag++;
break;
case 'c':
cflag++;
break;
case 'r':
/* What we do by default, anyway! */
break;
case 'b':
superblock = atoi(optarg);
break;
case 'B':
blocksize = atoi(optarg);
break;
case 'I':
inode_buffer_blocks = atoi(optarg);
break;
case 'P':
process_inode_size = atoi(optarg);
break;
case 'L':
replace_bad_blocks++;
case 'l':
bad_blocks_file = malloc(strlen(optarg)+1);
if (!bad_blocks_file)
fatal_error("Couldn't malloc bad_blocks_file");
strcpy(bad_blocks_file, optarg);
break;
case 'd':
debug = 1;
break;
case 'f':
force = 1;
break;
case 'F':
flush = 1;
break;
case 'v':
verbose = 1;
break;
case 'V':
show_version_only = 1;
break;
#ifdef MTRACE
case 'M':
mallwatch = (void *) strtol(optarg, NULL, 0);
break;
#endif
default:
usage ();
}
if (show_version_only)
return;
if (optind != argc - 1)
usage ();
if (nflag && !bad_blocks_file && !cflag)
rwflag = 0;
device_name = argv[optind];
if (flush) {
int fd = open(device_name, O_RDONLY, 0);
if (fd < 0) {
com_err("open", errno, "while opening %s for flushing",
device_name);
exit(FSCK_ERROR);
}
if (ioctl(fd, BLKFLSBUF, 0) < 0) {
com_err("BLKFLSBUF", errno, "while trying to flush %s",
device_name);
exit(FSCK_ERROR);
}
close(fd);
}
}
int main (int argc, char *argv[])
{
errcode_t retval = 0;
int exit_value = FSCK_OK;
int i;
ext2_filsys fs;
#ifdef MTRACE
mtrace();
#endif
#ifdef MCHECK
mcheck(0);
#endif
init_resource_track(&global_rtrack);
PRS(argc, argv);
if (!preen)
fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
E2FSPROGS_VERSION, E2FSPROGS_DATE,
EXT2FS_VERSION, EXT2FS_DATE);
if (show_version_only)
exit(0);
check_mount();
if (!preen && !nflag && !yflag) {
if (!isatty (0) || !isatty (1))
die ("need terminal for interactive repairs");
}
sync_disks();
if (superblock && blocksize) {
retval = ext2fs_open(device_name, rwflag ? EXT2_FLAG_RW : 0,
superblock, blocksize, unix_io_manager,
&fs);
} else if (superblock) {
for (i=0; possible_block_sizes[i]; i++) {
retval = ext2fs_open(device_name,
rwflag ? EXT2_FLAG_RW : 0,
superblock,
possible_block_sizes[i],
unix_io_manager, &fs);
if (!retval)
break;
}
} else
retval = ext2fs_open(device_name, rwflag ? EXT2_FLAG_RW : 0,
0, 0, unix_io_manager, &fs);
if (retval) {
com_err(program_name, retval, "while trying to open %s",
device_name);
printf("Couldn't find valid filesystem superblock.\n");
fatal_error(0);
}
/*
* If the user specified a specific superblock, presumably the
* master superblock has been trashed. So we mark the
* superblock as dirty, so it can be written out.
*/
if (superblock && rwflag)
ext2fs_mark_super_dirty(fs);
ehandler_init(fs->io);
check_super_block(fs);
check_if_skip(fs);
if (bad_blocks_file)
read_bad_blocks_file(fs, bad_blocks_file, replace_bad_blocks);
else if (cflag)
test_disk(fs);
/*
* Mark the system as valid, 'til proven otherwise
*/
ext2fs_mark_valid(fs);
pass1(fs);
pass2(fs);
pass3(fs);
pass4(fs);
pass5(fs);
#ifdef MTRACE
mtrace_print("Cleanup");
#endif
if (ext2fs_test_changed(fs)) {
exit_value = FSCK_NONDESTRUCT;
if (!preen)
printf("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n",
device_name);
if (root_filesystem && !read_only_root) {
printf("%s: ***** REBOOT LINUX *****\n", device_name);
exit_value = FSCK_REBOOT;
}
}
if (!ext2fs_test_valid(fs))
exit_value = FSCK_UNCORRECTED;
if (rwflag) {
if (ext2fs_test_valid(fs))
fs->super->s_state = EXT2_VALID_FS;
else
fs->super->s_state &= ~EXT2_VALID_FS;
fs->super->s_mnt_count = 0;
fs->super->s_lastcheck = time(NULL);
ext2fs_mark_super_dirty(fs);
}
show_stats(fs);
write_bitmaps(fs);
ext2fs_close(fs);
sync_disks();
if (tflag)
print_resource_track(&global_rtrack);
return exit_value;
}

176
e2fsck/e2fsck.h Normal file
View File

@ -0,0 +1,176 @@
/*
* e2fsck.h
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include "ext2fs/ext2fs.h"
#ifdef __STDC__
#define NOARGS void
#else
#define NOARGS
#define const
#endif
/*
* Exit codes used by fsck-type programs
*/
#define FSCK_OK 0 /* No errors */
#define FSCK_NONDESTRUCT 1 /* File system errors corrected */
#define FSCK_REBOOT 2 /* System should be rebooted */
#define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */
#define FSCK_ERROR 8 /* Operational error */
#define FSCK_USAGE 16 /* Usage or syntax error */
#define FSCK_LIBRARY 128 /* Shared library error */
/*
* Inode count arrays
*/
extern unsigned short * inode_count;
extern unsigned short * inode_link_info;
/*
* The directory information structure; stores directory information
* collected in earlier passes, to avoid disk i/o in fetching the
* directoryt information.
*/
struct dir_info {
ino_t ino; /* Inode number */
ino_t dotdot; /* Parent according to '..' */
ino_t parent; /* Parent according to treewalk */
};
struct dir_block_struct {
ino_t ino;
blk_t blk;
int blockcnt;
};
struct dir_block_struct *dir_blocks;
int dir_block_count;
int dir_block_size;
/*
* This structure is used for keeping track of how much resources have
* been used for a particular pass of e2fsck.
*/
struct resource_track {
struct timeval time_start;
struct timeval user_start;
struct timeval system_start;
void *brk_start;
};
/*
* Variables
*/
extern const char * program_name;
extern const char * device_name;
extern char * inode_used_map; /* Inodes which are in use */
extern char * inode_bad_map; /* Inodes which are bad in some way */
extern char * inode_dir_map; /* Inodes which are directories */
extern char * block_found_map; /* Blocks which are used by an inode */
extern char * block_dup_map; /* Blocks which are used by more than once */
extern const char *fix_msg[2]; /* Fixed or ignored! */
extern const char *clear_msg[2]; /* Cleared or ignored! */
/* Command line options */
extern int nflag;
extern int yflag;
extern int tflag;
extern int preen;
extern int verbose;
extern int list;
extern int debug;
extern int force;
extern int rwflag;
extern int inode_buffer_blocks;
extern int process_inode_size;
extern int directory_blocks;
extern int no_bad_inode;
extern int no_lpf;
extern int lpf_corrupted;
/* Files counts */
extern int fs_directory_count;
extern int fs_regular_count;
extern int fs_blockdev_count;
extern int fs_chardev_count;
extern int fs_links_count;
extern int fs_symlinks_count;
extern int fs_fast_symlinks_count;
extern int fs_fifo_count;
extern int fs_total_count;
extern int fs_badblocks_count;
extern int fs_sockets_count;
extern struct resource_track global_rtrack;
/*
* Procedure declarations
*/
extern void pass1(ext2_filsys fs);
extern void pass1_dupblocks(ext2_filsys fs, char *block_buf);
extern void pass2(ext2_filsys fs);
extern void pass3(ext2_filsys fs);
extern void pass4(ext2_filsys fs);
extern void pass5(ext2_filsys fs);
/* badblock.c */
extern void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
int replace_bad_blocks);
extern void test_disk(ext2_filsys fs);
/* dirinfo.c */
extern void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent,
struct ext2_inode *inode);
extern struct dir_info *get_dir_info(ino_t ino);
extern void free_dir_info(ext2_filsys fs);
extern int get_num_dirs(ext2_filsys fs);
/* ehandler.c */
extern const char *ehandler_operation(const char *op);
extern void ehandler_init(io_channel channel);
/* util.c */
extern void *allocate_memory(int size, const char *description);
extern int ask(const char * string, int def);
extern int ask_yn(const char * string, int def);
extern void fatal_error (const char * fmt_string);
extern void read_bitmaps(ext2_filsys fs);
extern void write_bitmaps(ext2_filsys fs);
extern void preenhalt(NOARGS);
extern void print_resource_track(struct resource_track *track);
extern void init_resource_track(struct resource_track *track);
extern int inode_has_valid_blocks(struct ext2_inode *inode);
#ifdef MTRACE
extern void mtrace_print(char *mesg);
#endif
#define die(str) fatal_error(str)
/*
* pass3.c
*/
extern int reconnect_file(ext2_filsys fs, ino_t inode);

111
e2fsck/ehandler.c Normal file
View File

@ -0,0 +1,111 @@
/*
* ehandler.c --- handle bad block errors which come up during the
* course of an e2fsck session.
*
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <termios.h>
#include <sys/resource.h>
#include "e2fsck.h"
static const char *operation;
static errcode_t e2fsck_handle_read_error(io_channel channel,
unsigned long block,
int count,
void *data,
size_t size,
int actual,
errcode_t error)
{
int i;
char *p;
/*
* If more than one block was read, try reading each block
* separately. We could use the actual bytes read to figure
* out where to start, but we don't bother.
*/
if (count > 1) {
p = (char *) data;
for (i=0; i < count; i++, p += channel->block_size, block++) {
error = io_channel_read_blk(channel, block,
1, p);
if (error)
return error;
}
return 0;
}
if (operation)
printf("Error reading block %ld (%s) while %s. ", block,
error_message(error), operation);
else
printf("Error reading block %ld (%s). ", block,
error_message(error));
preenhalt();
if (ask("Ignore error", 1))
return 0;
return error;
}
static errcode_t e2fsck_handle_write_error(io_channel channel,
unsigned long block,
int count,
const void *data,
size_t size,
int actual,
errcode_t error)
{
int i;
const char *p;
/*
* If more than one block was written, try writing each block
* separately. We could use the actual bytes read to figure
* out where to start, but we don't bother.
*/
if (count > 1) {
p = (const char *) data;
for (i=0; i < count; i++, p += channel->block_size, block++) {
error = io_channel_write_blk(channel, block,
1, p);
if (error)
return error;
}
return 0;
}
if (operation)
printf("Error writing block %ld (%s) while %s. ", block,
error_message(error), operation);
else
printf("Error writing block %ld (%s). ", block,
error_message(error));
preenhalt();
if (ask("Ignore error", 1))
return 0;
return error;
}
const char *ehandler_operation(const char *op)
{
const char *ret = operation;
operation = op;
return ret;
}
void ehandler_init(io_channel channel)
{
channel->read_error = e2fsck_handle_read_error;
channel->write_error = e2fsck_handle_write_error;
}

51
e2fsck/flushb.c Normal file
View File

@ -0,0 +1,51 @@
/*
* flushb.c --- This routine flushes the disk buffers for a disk
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#ifdef __STDC__
#define NOARGS void
#else
#define NOARGS
#define const
#endif
const char *progname;
static void usage(NOARGS)
{
fprintf(stderr, "Usage: %s disk\n", progname);
exit(1);
}
int main(int argc, char **argv)
{
int fd;
progname = argv[0];
if (argc != 2)
usage();
fd = open(argv[1], O_RDONLY, 0);
if (fd < 0) {
perror("open");
exit(1);
}
/*
* Note: to reread the partition table, use the ioctl
* BLKRRPART instead of BLKFSLBUF.
*/
if (ioctl(fd, BLKFLSBUF, 0) < 0) {
perror("ioctl");
exit(1);
}
return 0;
}

59
e2fsck/images/README Normal file
View File

@ -0,0 +1,59 @@
These images contain various forms of corrupted filesystem which
e2fsck will correct. They are used as a regression test for e2fsck.
The test_script program will automatically run e2fsck against the
filesystem images. It will run them two times, and display the exit
status for each run. The meaning of the exit status codes are as
follows:
0 No filesystem errors were detected
1 Filesystem errors detected, but corrected
2 System should be rebooted
4 Filesystem errors left uncorrected
8 Operational error (generally means internal error,
or filesystem error that the e2fsck was not
prepared to deal with)
16 Usage or syntax error
During the regression test, the first exit code should be 1 (with the
exception of the empty filesystem, empty.img, which will have an exit
code of 0), and the second exit code should be 0. In other words, all
of the test filesystems in this directory (with the exception of
empty.img) have some sort of filesystem corruption, which e2fsck
should fix on the first pass. After the first pass, e2fsck should
leave a fully consistent filesystem with no detectable errors found in
the second pass.
NOTE: It appears that at least some versions of the original e2fsck do
not exit with an exit status code of 1 after correcting filesystem
errors. So if you modify the test_script to try running these
filesystems against the original e2fsck, you will have to inspect the
test_script.log file manually.
--------------------------------------------------------------
Here's a one-line descriptons of the various test images in this
directory:
baddir.img Filesystem with a corrupted directory
badinode.img Filesystem with various different corrupted inode
entries.
badlkcnt.img Filesystem with deleted files with non-zero link count
badroot.img Filesystem with a file for a root directory
badtable.img Filesystem with blocks shared between the bitmaps and
inode table blocks and the bad block inode
bbfile.img Filesystem with files containing bad blocks
bitmaps.img Filesystem with corrupted inode and block bitmaps
dirlink.img Filesystem with a hard link to a directory
dup.img Filesystem with blocks claimed by two different files
dup2.img Filesystem with blocks claimed by three different files
end-bitmap.img Filesystem with corruption at the end of the block
bitmap
expand.img Tests e2fsck's ability to expand lost+found if
necessary
lpf.img Filesystem with disconnected files and no /lost+found
directory
mke2fs2b.img Filesystem with corruption similar to that
created by mke2fs version 0.2b
noroot.img Filesystem with a deleted root directory.

BIN
e2fsck/images/baddir.img.gz Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
e2fsck/images/bbfile.img.gz Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
e2fsck/images/dup.img.gz Normal file

Binary file not shown.

BIN
e2fsck/images/dup2.img.gz Normal file

Binary file not shown.

Binary file not shown.

BIN
e2fsck/images/expand.img.gz Normal file

Binary file not shown.

BIN
e2fsck/images/lpf.img.gz Normal file

Binary file not shown.

Binary file not shown.

BIN
e2fsck/images/noroot.img.gz Normal file

Binary file not shown.

42
e2fsck/images/test_script Normal file
View File

@ -0,0 +1,42 @@
#!/bin/sh
#
# Test script for e2fsck
#
FSCK=../e2fsck
SECOND_FSCK=$FSCK
FSCK_OPT=-yft
SECOND_FSCK_OPT=$FSCK_OPT
#
# Uncomment to test against original e2fsck
#
#FSCK=/u4/src/e2fsprogs-0.3c/e2fsck
#FSCK_OPT=-af
OUTFILE=test_script.log
cp /dev/null $OUTFILE
for i in *.img.gz
do
echo -n "Testing $i... "
echo "Testing $i..." >> $OUTFILE
gunzip < $i > /tmp/$i.$$
echo $FSCK $FSCK_OPT /tmp/$i.$$ >> $OUTFILE
$FSCK $FSCK_OPT /tmp/$i.$$ >> $OUTFILE 2>&1
status=$?
echo Exit status is $status >> $OUTFILE
echo " " >> $OUTFILE
echo -n "Exit status $status "
echo Running e2fsck again.... >> $OUTFILE
echo $SECOND_FSCK $SECOND_FSCK_OPT /tmp/$i.$$ >> $OUTFILE
$SECOND_FSCK $SECOND_FSCK_OPT /tmp/$i.$$ >> $OUTFILE 2>&1
status=$?
echo Exit status is $status >> $OUTFILE
echo Exit status $status
rm /tmp/$i.$$
echo "---------------------------------------------------" >> $OUTFILE
done

File diff suppressed because it is too large Load Diff

231
e2fsck/malloc.h Normal file
View File

@ -0,0 +1,231 @@
/* Declarations for `malloc' and friends.
Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
Written May 1989 by Mike Haertel.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
#ifndef _MALLOC_H
#define _MALLOC_H 1
#ifdef __cplusplus
extern "C"
{
#endif
#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
#undef __P
#define __P(args) args
#undef __ptr_t
#define __ptr_t void *
#else /* Not C++ or ANSI C. */
#undef __P
#define __P(args) ()
#undef const
#define const
#undef __ptr_t
#define __ptr_t char *
#endif /* C++ or ANSI C. */
#ifndef NULL
#define NULL 0
#endif
#ifdef __STDC__
#include <stddef.h>
#else
#undef size_t
#define size_t unsigned int
#undef ptrdiff_t
#define ptrdiff_t int
#endif
/* Allocate SIZE bytes of memory. */
extern __ptr_t malloc __P ((size_t __size));
/* Re-allocate the previously allocated block
in __ptr_t, making the new block SIZE bytes long. */
extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size));
/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
extern __ptr_t calloc __P ((size_t __nmemb, size_t __size));
/* Free a block allocated by `malloc', `realloc' or `calloc'. */
extern void free __P ((__ptr_t __ptr));
/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
extern __ptr_t memalign __P ((size_t __alignment, size_t __size));
/* Allocate SIZE bytes on a page boundary. */
extern __ptr_t valloc __P ((size_t __size));
#ifdef _MALLOC_INTERNAL
#include <stdio.h> /* Harmless, gets __GNU_LIBRARY__ defined. */
#if defined(__GNU_LIBRARY__) || defined(STDC_HEADERS) || defined(USG)
#include <string.h>
#else
#ifndef memset
#define memset(s, zero, n) bzero ((s), (n))
#endif
#ifndef memcpy
#define memcpy(d, s, n) bcopy ((s), (d), (n))
#endif
#endif
#if defined(__GNU_LIBRARY__) || defined(__STDC__)
#include <limits.h>
#else
#define CHAR_BIT 8
#endif
/* The allocator divides the heap into blocks of fixed size; large
requests receive one or more whole blocks, and small requests
receive a fragment of a block. Fragment sizes are powers of two,
and all fragments of a block are the same size. When all the
fragments in a block have been freed, the block itself is freed. */
#define INT_BIT (CHAR_BIT * sizeof(int))
#define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
#define BLOCKSIZE (1 << BLOCKLOG)
#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
/* Determine the amount of memory spanned by the initial heap table
(not an absolute limit). */
#define HEAP (INT_BIT > 16 ? 4194304 : 65536)
/* Number of contiguous free blocks allowed to build up at the end of
memory before they will be returned to the system. */
#define FINAL_FREE_BLOCKS 8
/* Data structure giving per-block information. */
typedef union
{
/* Heap information for a busy block. */
struct
{
/* Zero for a large block, or positive giving the
logarithm to the base two of the fragment size. */
int type;
union
{
struct
{
size_t nfree; /* Free fragments in a fragmented block. */
size_t first; /* First free fragment of the block. */
} frag;
/* Size (in blocks) of a large cluster. */
size_t size;
} info;
} busy;
/* Heap information for a free block
(that may be the first of a free cluster). */
struct
{
size_t size; /* Size (in blocks) of a free cluster. */
size_t next; /* Index of next free cluster. */
size_t prev; /* Index of previous free cluster. */
} free;
} malloc_info;
/* Pointer to first block of the heap. */
extern char *_heapbase;
/* Table indexed by block number giving per-block information. */
extern malloc_info *_heapinfo;
/* Address to block number and vice versa. */
#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
#define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
/* Current search index for the heap table. */
extern size_t _heapindex;
/* Limit of valid info table indices. */
extern size_t _heaplimit;
/* Doubly linked lists of free fragments. */
struct list
{
struct list *next;
struct list *prev;
};
/* Free list headers for each fragment size. */
extern struct list _fraghead[];
/* List of blocks allocated with `memalign' (or `valloc'). */
struct alignlist
{
struct alignlist *next;
__ptr_t aligned; /* The address that memaligned returned. */
__ptr_t exact; /* The address that malloc returned. */
};
extern struct alignlist *_aligned_blocks;
/* Instrumentation. */
extern size_t _chunks_used;
extern size_t _bytes_used;
extern size_t _chunks_free;
extern size_t _bytes_free;
/* Internal version of `free' used in `morecore' (malloc.c). */
extern void _free_internal __P ((__ptr_t __ptr));
#endif /* _MALLOC_INTERNAL. */
/* Underlying allocation function; successive calls should
return contiguous pieces of memory. */
extern __ptr_t (*__morecore) __P ((ptrdiff_t __size));
/* Default value of `__morecore'. */
extern __ptr_t __default_morecore __P ((ptrdiff_t __size));
/* Nonzero if `malloc' has been called and done its initialization. */
extern int __malloc_initialized;
/* Hooks for debugging versions. */
extern void (*__free_hook) __P ((__ptr_t __ptr));
extern __ptr_t (*__malloc_hook) __P ((size_t __size));
extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size));
/* Activate a standard collection of debugging hooks. */
extern void mcheck __P ((void (*__func) __P ((void))));
/* Activate a standard collection of tracing hooks. */
extern void mtrace __P ((void));
/* Statistics available to the user. */
struct mstats
{
size_t bytes_total; /* Total size of the heap. */
size_t chunks_used; /* Chunks allocated by the user. */
size_t bytes_used; /* Byte total of user-allocated chunks. */
size_t chunks_free; /* Chunks in the free list. */
size_t bytes_free; /* Byte total of chunks in the free list. */
};
/* Pick up the current statistics. */
extern struct mstats mstats __P ((void));
#ifdef __cplusplus
}
#endif
#endif /* malloc.h */

37
e2fsck/mtrace.awk Normal file
View File

@ -0,0 +1,37 @@
#!/usr/bin/awk -f
#
# Awk program to analyze mtrace.c output.
#
$1 == "+" { if (allocated[$2] != "")
print "+", $2, "Alloc", NR, "duplicate:", allocated[$2];
else
allocated[$2] = $3;
}
$1 == "-" { if (allocated[$2] != "") {
allocated[$2] = "";
if (allocated[$2] != "")
print "DELETE FAILED", $2, allocated[$2];
} else
print "-", $2, "Free", NR, "was never alloc'd";
}
$1 == "<" { if (allocated[$2] != "")
allocated[$2] = "";
else
print "-", $2, "Realloc", NR, "was never alloc'd";
}
$1 == ">" { if (allocated[$2] != "")
print "+", $2, "Realloc", NR, "duplicate:", allocated[$2];
else
allocated[$2] = $3;
}
# Ignore "= Start"
$1 == "=" { }
# Ignore failed realloc attempts for now
$1 == "!" { }
END { for (x in allocated)
if (allocated[x] != "")
print "+", x, allocated[x];
}

158
e2fsck/mtrace.c Normal file
View File

@ -0,0 +1,158 @@
/* More debugging hooks for `malloc'.
Copyright (C) 1991, 1992 Free Software Foundation, Inc.
Written April 2, 1991 by John Gilmore of Cygnus Support.
Based on mcheck.c by Mike Haertel.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
The author may be reached (Email) at the address mike@ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
#ifndef _MALLOC_INTERNAL
#define _MALLOC_INTERNAL
#include "./malloc.h"
#endif
#include <stdio.h>
#ifndef __GNU_LIBRARY__
extern char *getenv ();
#else
#include <stdlib.h>
#endif
static FILE *mallstream;
static char mallenv[]= "MALLOC_TRACE";
static char mallbuf[BUFSIZ]; /* Buffer for the output. */
/* Address to breakpoint on accesses to... */
__ptr_t mallwatch;
/* Old hook values. */
static void (*tr_old_free_hook) __P ((__ptr_t ptr));
static __ptr_t (*tr_old_malloc_hook) __P ((size_t size));
static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr, size_t size));
/*
* Added by TYT, 10/10/93 --- so that we can print
*/
FILE *malloc_get_mallstream()
{
return mallstream;
}
/* This function is called when the block being alloc'd, realloc'd, or
freed has an address matching the variable "mallwatch". In a debugger,
set "mallwatch" to the address of interest, then put a breakpoint on
tr_break. */
void tr_break __P ((void));
void
tr_break ()
{
}
static void tr_freehook __P ((__ptr_t));
static void
tr_freehook (ptr)
__ptr_t ptr;
{
fprintf (mallstream, "- %p\n", ptr); /* Be sure to print it first. */
if (ptr == mallwatch)
tr_break ();
__free_hook = tr_old_free_hook;
free (ptr);
__free_hook = tr_freehook;
}
static __ptr_t tr_mallochook __P ((size_t));
static __ptr_t
tr_mallochook (size)
size_t size;
{
__ptr_t hdr;
__malloc_hook = tr_old_malloc_hook;
hdr = (__ptr_t) malloc (size);
__malloc_hook = tr_mallochook;
/* We could be printing a NULL here; that's OK. */
fprintf (mallstream, "+ %p %d\n", hdr, size);
if (hdr == mallwatch)
tr_break ();
return hdr;
}
static __ptr_t tr_reallochook __P ((__ptr_t, size_t));
static __ptr_t
tr_reallochook (ptr, size)
__ptr_t ptr;
size_t size;
{
__ptr_t hdr;
if (ptr == mallwatch)
tr_break ();
__free_hook = tr_old_free_hook;
__malloc_hook = tr_old_malloc_hook;
__realloc_hook = tr_old_realloc_hook;
hdr = (__ptr_t) realloc (ptr, size);
__free_hook = tr_freehook;
__malloc_hook = tr_mallochook;
__realloc_hook = tr_reallochook;
if (hdr == NULL)
/* Failed realloc. */
fprintf (mallstream, "! %p %d\n", ptr, size);
else
fprintf (mallstream, "< %p\n> %p %d\n", ptr, hdr, size);
if (hdr == mallwatch)
tr_break ();
return hdr;
}
/* We enable tracing if either the environment variable MALLOC_TRACE
is set, or if the variable mallwatch has been patched to an address
that the debugging user wants us to stop on. When patching mallwatch,
don't forget to set a breakpoint on tr_break! */
void
mtrace ()
{
char *mallfile;
mallfile = getenv (mallenv);
if (mallfile != NULL || mallwatch != NULL)
{
mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w");
if (mallstream != NULL)
{
/* Be sure it doesn't malloc its buffer! */
setbuf (mallstream, mallbuf);
fprintf (mallstream, "= Start\n");
tr_old_free_hook = __free_hook;
__free_hook = tr_freehook;
tr_old_malloc_hook = __malloc_hook;
__malloc_hook = tr_mallochook;
tr_old_realloc_hook = __realloc_hook;
__realloc_hook = tr_reallochook;
}
}
}

894
e2fsck/pass1.c Normal file
View File

@ -0,0 +1,894 @@
/*
* pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*
* Pass 1 of e2fsck iterates over all the inodes in the filesystems,
* and applies the following tests to each inode:
*
* - The mode field of the inode must be legal.
* - The size and block count fields of the inode are correct.
* - A data block must not be used by another inode
*
* Pass 1 also gathers the collects the following information:
*
* - A bitmap of which inodes are in use. (inode_used_map)
* - A bitmap of which inodes are directories. (inode_dir_map)
* - A bitmap of which inodes have bad fields. (inode_bad_map)
* - A bitmap of which blocks are in use. (block_found_map)
* - A bitmap of which blocks are in use by two inodes (block_dup_map)
* - The data blocks of the directory inodes. (dir_map)
*
* Pass 1 is designed to stash away enough information so that the
* other passes should not need to read in the inode information
* during the normal course of a filesystem check. (Althogh if an
* inconsistency is detected, other passes may need to read in an
* inode to fix it.)
*
* Note that pass 1B will be invoked if there are any duplicate blocks
* found.
*/
#include <time.h>
#include <et/com_err.h>
#include "e2fsck.h"
/* Files counts */
int fs_directory_count = 0;
int fs_regular_count = 0;
int fs_blockdev_count = 0;
int fs_chardev_count = 0;
int fs_links_count = 0;
int fs_symlinks_count = 0;
int fs_fast_symlinks_count = 0;
int fs_fifo_count = 0;
int fs_total_count = 0;
int fs_badblocks_count = 0;
int fs_sockets_count = 0;
char * inode_used_map = 0; /* Inodes which are in use */
char * inode_bad_map = 0; /* Inodes which are bad in some way */
char * inode_dir_map = 0; /* Inodes which are directories */
char * block_found_map = 0;
char * block_dup_map = 0;
static char * bad_fs_block_map = 0;
static int fix_link_count = -1;
unsigned short * inode_link_info = NULL;
static int process_block(ext2_filsys fs, blk_t *blocknr,
int blockcnt, void *private);
static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
int blockcnt, void *private);
static int process_fs_bad_block(ext2_filsys fs, blk_t *block_nr,
int blockcnt, void *private);
static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
char *block_buf);
static void mark_table_blocks(ext2_filsys fs);
static errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino);
static errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks);
static void alloc_bad_map(ext2_filsys fs);
static void handle_fs_bad_blocks(ext2_filsys fs, char *block_buf);
static void process_inodes(ext2_filsys fs, char *block_buf);
static int process_inode_cmp(const void *a, const void *b);
static int dir_block_cmp(const void *a, const void *b);
struct process_block_struct {
ino_t ino;
int is_dir;
int num_blocks;
int last_block;
int fix;
};
struct process_inode_block {
ino_t ino;
struct ext2_inode inode;
};
/*
* For pass1_check_directory and pass1_get_blocks
*/
ino_t stashed_ino;
struct ext2_inode *stashed_inode;
/*
* For the inodes to process list.
*/
static struct process_inode_block *inodes_to_process;
static int process_inode_count;
int process_inode_size = 128;
/*
* For the directory blocks list.
*/
struct dir_block_struct *dir_blocks = 0;
int dir_block_count = 0;
int dir_block_size = 0;
void pass1(ext2_filsys fs)
{
ino_t ino;
struct ext2_inode inode;
ext2_inode_scan scan;
char *block_buf;
errcode_t retval;
struct resource_track rtrack;
init_resource_track(&rtrack);
if (!preen)
printf("Pass 1: Checking inodes, blocks, and sizes\n");
#ifdef MTRACE
mtrace_print("Pass 1");
#endif
/*
* Allocate bitmaps structures
*/
retval = ext2fs_allocate_inode_bitmap(fs, &inode_used_map);
if (retval) {
com_err("ext2fs_allocate_inode_bitmap", retval,
"while allocating inode_used_map");
fatal_error(0);
}
retval = ext2fs_allocate_inode_bitmap(fs, &inode_dir_map);
if (retval) {
com_err("ext2fs_allocate_inode_bitmap", retval,
"while allocating inode_dir_map");
fatal_error(0);
}
retval = ext2fs_allocate_block_bitmap(fs, &block_found_map);
if (retval) {
com_err("ext2fs_allocate_block_bitmap", retval,
"while allocating block_found_map");
fatal_error(0);
}
inode_link_info = allocate_memory((fs->super->s_inodes_count + 1) *
sizeof(unsigned short),
"inode link count array");
inodes_to_process = allocate_memory(process_inode_size *
sizeof(struct process_inode_block),
"array of inodes to process");
process_inode_count = 0;
dir_block_size = get_num_dirs(fs) * 4;
dir_block_count = 0;
dir_blocks = allocate_memory(sizeof(struct dir_block_struct) *
dir_block_size,
"directory block information");
mark_table_blocks(fs);
block_buf = allocate_memory(fs->blocksize * 3, "block interate buffer");
fs->get_blocks = pass1_get_blocks;
fs->check_directory = pass1_check_directory;
ehandler_operation("doing inode scan");
retval = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan);
if (retval) {
com_err(program_name, retval, "while opening inode scan");
fatal_error(0);
}
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval) {
com_err(program_name, retval, "while starting inode scan");
fatal_error(0);
}
stashed_inode = &inode;
while (ino) {
stashed_ino = ino;
inode_link_info[ino] = inode.i_links_count;
if (ino == EXT2_BAD_INO) {
struct process_block_struct pb;
pb.ino = EXT2_BAD_INO;
pb.num_blocks = pb.last_block = 0;
pb.is_dir = 0;
pb.fix = -1;
retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
process_bad_block, &pb);
if (retval)
com_err(program_name, retval, "while calling e2fsc_block_interate in pass 1");
ext2fs_mark_inode_bitmap(fs, inode_used_map, ino);
goto next;
}
if (ino == EXT2_ROOT_INO) {
/*
* Make sure the root inode is a directory; if
* not, offer to clear it. It will be
* regnerated in pass #3.
*/
if (!S_ISDIR(inode.i_mode)) {
printf("Root inode is not a directory. ");
preenhalt();
if (ask("Clear", 1)) {
inode.i_dtime = time(0);
inode.i_links_count = 0;
ext2fs_write_inode(fs, ino, &inode);
} else
ext2fs_unmark_valid(fs);
}
/*
* If dtime is set, offer to clear it. mke2fs
* version 0.2b created filesystems with the
* dtime field set for the root and lost+found
* directories. We won't worry about
* /lost+found, since that can be regenerated
* easily. But we will fix the root directory
* as a special case.
*/
if (inode.i_dtime && inode.i_links_count) {
if (ask("Root inode has dtime set "
"(probably due to old mke2fs). Fix",
1)) {
inode.i_dtime = 0;
ext2fs_write_inode(fs, ino, &inode);
printf("Note: /lost+found will "
"probably be deleted as well, "
"due to the mke2fs bug.\n"
"Be sure to run mklost+found "
"to recreate it after e2fsck "
"finishes.\n\n");
} else
ext2fs_unmark_valid(fs);
}
}
if ((ino != EXT2_ROOT_INO) && (ino < EXT2_FIRST_INO)) {
ext2fs_mark_inode_bitmap(fs, inode_used_map, ino);
check_blocks(fs, ino, &inode, block_buf);
goto next;
}
/*
* This code assumes that deleted inodes have
* i_links_count set to 0.
*/
if (!inode.i_links_count) {
if (!inode.i_dtime && inode.i_mode) {
printf("Deleted inode %ld has zero dtime.\n",
ino);
if (ask("Set dtime", 1)) {
inode.i_dtime = time(0);
ext2fs_write_inode(fs, ino, &inode);
} else
ext2fs_unmark_valid(fs);
}
goto next;
}
/*
* 0.3c ext2fs code didn't clear i_links_count for
* deleted files. Oops.
*
* In the future, when the new ext2fs behavior is the
* norm, we may want to handle the case of a non-zero
* i_links_count and non-zero dtime by clearing dtime
* and assuming the inode is in use, instead of
* assuming the inode is not in use.
*/
if (inode.i_dtime) {
if (fix_link_count == -1) {
printf("\nDeleted inode detected with non-zero link count.\n");
printf("This is probably due to old ext2fs kernel code. \n");
fix_link_count = ask("Fix inode(s)", 1);
}
printf("Inode %ld is deleted w/ non-zero link_count. %s\n",
ino, clear_msg[fix_link_count]);
if (fix_link_count) {
inode.i_links_count = 0;
ext2fs_write_inode(fs, ino, &inode);
} else
ext2fs_unmark_valid(fs);
goto next;
}
ext2fs_mark_inode_bitmap(fs, inode_used_map, ino);
if (inode.i_faddr || inode.i_frag || inode.i_fsize ||
inode.i_file_acl || inode.i_dir_acl) {
if (!inode_bad_map)
alloc_bad_map(fs);
ext2fs_mark_inode_bitmap(fs, inode_bad_map, ino);
}
if (S_ISDIR(inode.i_mode)) {
ext2fs_mark_inode_bitmap(fs, inode_dir_map, ino);
add_dir_info(fs, ino, 0, &inode);
fs_directory_count++;
} else if (S_ISREG (inode.i_mode))
fs_regular_count++;
else if (S_ISCHR (inode.i_mode))
fs_chardev_count++;
else if (S_ISBLK (inode.i_mode))
fs_blockdev_count++;
else if (S_ISLNK (inode.i_mode)) {
fs_symlinks_count++;
if (!inode.i_blocks)
fs_fast_symlinks_count++;
}
else if (S_ISFIFO (inode.i_mode))
fs_fifo_count++;
else if (S_ISSOCK (inode.i_mode))
fs_sockets_count++;
else {
if (!inode_bad_map)
alloc_bad_map(fs);
ext2fs_mark_inode_bitmap(fs, inode_bad_map, ino);
}
if (inode.i_block[EXT2_IND_BLOCK] ||
inode.i_block[EXT2_DIND_BLOCK] ||
inode.i_block[EXT2_TIND_BLOCK]) {
inodes_to_process[process_inode_count].ino = ino;
inodes_to_process[process_inode_count].inode = inode;
process_inode_count++;
} else
check_blocks(fs, ino, &inode, block_buf);
inode_link_info[ino] = inode.i_links_count;
if (process_inode_count >= process_inode_size)
process_inodes(fs, block_buf);
next:
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval) {
com_err(program_name, retval,
"while doing inode scan");
fatal_error(0);
}
}
process_inodes(fs, block_buf);
ext2fs_close_inode_scan(scan);
ehandler_operation(0);
qsort(dir_blocks, dir_block_count, sizeof(struct dir_block_struct),
dir_block_cmp);
if (block_dup_map) {
if (preen) {
printf("Duplicate or bad blocks in use!\n");
preenhalt();
}
pass1_dupblocks(fs, block_buf);
}
fs->get_blocks = 0;
fs->check_directory = 0;
free(inodes_to_process);
if (bad_fs_block_map) {
handle_fs_bad_blocks(fs, block_buf);
free(bad_fs_block_map);
}
free(block_buf);
if (tflag > 1) {
printf("Pass 1: ");
print_resource_track(&rtrack);
}
}
/*
* Process the inodes in the "inodes to process" list.
*/
static void process_inodes(ext2_filsys fs, char *block_buf)
{
int i;
struct ext2_inode *old_stashed_inode;
ino_t ino;
const char *old_operation;
char buf[80];
#if 0
printf("process_inodes: ");
#endif
old_operation = ehandler_operation(0);
old_stashed_inode = stashed_inode;
qsort(inodes_to_process, process_inode_count,
sizeof(struct process_inode_block), process_inode_cmp);
for (i=0; i < process_inode_count; i++) {
stashed_inode = &inodes_to_process[i].inode;
ino = inodes_to_process[i].ino;
stashed_ino = ino;
#if 0
printf("%d ", ino);
#endif
sprintf(buf, "reading indirect blocks of inode %ld", ino);
ehandler_operation(buf);
check_blocks(fs, ino, stashed_inode, block_buf);
}
stashed_inode = old_stashed_inode;
process_inode_count = 0;
#if 0
printf("\n");
#endif
ehandler_operation(old_operation);
}
static int process_inode_cmp(const void *a, const void *b)
{
const struct process_inode_block *ib_a =
(const struct process_inode_block *) a;
const struct process_inode_block *ib_b =
(const struct process_inode_block *) b;
return (ib_a->inode.i_block[EXT2_IND_BLOCK] -
ib_b->inode.i_block[EXT2_IND_BLOCK]);
}
static int dir_block_cmp(const void *a, const void *b)
{
const struct dir_block_struct *db_a =
(const struct dir_block_struct *) a;
const struct dir_block_struct *db_b =
(const struct dir_block_struct *) b;
return (db_a->blk - db_b->blk);
}
/*
* This procedure will allocate the inode bad map table
*/
static void alloc_bad_map(ext2_filsys fs)
{
errcode_t retval;
retval = ext2fs_allocate_inode_bitmap(fs, &inode_bad_map);
if (retval) {
com_err("ext2fs_allocate_inode_bitmap", retval,
"while allocating inode_bad_map");
fatal_error(0);
}
}
/*
* Marks a block as in use, setting the dup_map if it's been set
* already. Called by process_block and process_bad_block.
*/
static void mark_block_used(ext2_filsys fs, blk_t block)
{
errcode_t retval;
if (ext2fs_test_block_bitmap(fs, block_found_map, block)) {
if (!block_dup_map) {
retval = ext2fs_allocate_block_bitmap(fs,
&block_dup_map);
if (retval) {
com_err("ext2fs_allocate_block_bitmap", retval,
"while allocating block_dup_map");
fatal_error(0);
}
}
ext2fs_mark_block_bitmap(fs, block_dup_map, block);
} else {
ext2fs_mark_block_bitmap(fs, block_found_map, block);
}
}
/*
* This subroutine is called on each inode to account for all of the
* blocks used by that inode.
*/
static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
char *block_buf)
{
struct process_block_struct pb;
errcode_t retval;
if (!inode_has_valid_blocks(inode))
return;
pb.ino = ino;
pb.num_blocks = pb.last_block = 0;
pb.is_dir = S_ISDIR(inode->i_mode);
pb.fix = -1;
retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
process_block, &pb);
if (retval)
com_err(program_name, retval,
"while calling ext2fs_block_iterate in check_blocks");
pb.num_blocks *= (fs->blocksize / 512);
#if 0
printf("inode %d, i_size = %d, last_block = %d, i_blocks=%d, num_blocks = %d\n",
ino, inode->i_size, pb.last_block, inode->i_blocks,
pb.num_blocks);
#endif
if (!pb.num_blocks && pb.is_dir) {
printf("Inode %ld is a zero length directory. ", ino);
if (ask("Clear", 1)) {
inode->i_links_count = 0;
inode->i_dtime = time(0);
ext2fs_write_inode(fs, ino, inode);
ext2fs_unmark_inode_bitmap(fs, inode_dir_map, ino);
ext2fs_unmark_inode_bitmap(fs, inode_used_map, ino);
fs_directory_count--;
} else
ext2fs_unmark_valid(fs);
}
if (inode->i_size < pb.last_block * fs->blocksize) {
printf ("Inode %ld, incorrect size, %ld (counted = %d). ",
ino, inode->i_size,
(pb.last_block+1) * fs->blocksize);
if (ask ("Set size to counted", 1)) {
inode->i_size = (pb.last_block+1) * fs->blocksize;
ext2fs_write_inode(fs, ino, inode);
} else
ext2fs_unmark_valid(fs);
}
if (pb.num_blocks != inode->i_blocks) {
printf ("Inode %ld, i_blocks wrong %ld (counted=%d) .",
ino, inode->i_blocks, pb.num_blocks);
if (ask ("Set i_blocks to counted", 1)) {
inode->i_blocks = pb.num_blocks;
ext2fs_write_inode(fs, ino, inode);
} else
ext2fs_unmark_valid(fs);
}
}
/*
* This is a helper function for check_blocks().
*/
int process_block(ext2_filsys fs,
blk_t *block_nr,
int blockcnt,
void *private)
{
struct process_block_struct *p;
int group;
int illegal_block = 0;
char problem[80];
blk_t firstblock;
blk_t blk = *block_nr;
if (!blk)
return 0;
p = (struct process_block_struct *) private;
#if 0
printf("Process_block, inode %d, block %d, #%d\n", p->ino, blk,
blockcnt);
#endif
p->num_blocks++;
if (blockcnt > 0)
p->last_block = blockcnt;
firstblock = fs->super->s_first_data_block;
group = (blk - firstblock) / fs->super->s_blocks_per_group;
if (blk < firstblock) {
sprintf(problem, "< FIRSTBLOCK (%ld)", firstblock);
illegal_block++;
} else if (blk >= fs->super->s_blocks_count) {
sprintf(problem, "> BLOCKS (%ld)", fs->super->s_blocks_count);
illegal_block++;
} else if (blk == fs->group_desc[group].bg_block_bitmap) {
sprintf(problem, "is the block bitmap of group %d", group);
illegal_block++;
} else if (blk == fs->group_desc[group].bg_inode_bitmap) {
sprintf(problem, "is the inode bitmap of group %d", group);
illegal_block++;
} else if (blk >= fs->group_desc[group].bg_inode_table &&
blk < fs->group_desc[group].bg_inode_table + fs->inode_blocks_per_group) {
sprintf(problem, "is in the inode table of group %d", group);
illegal_block++;
}
if (illegal_block) {
if (preen) {
printf("Block %ld of inode %ld %s\n", blk, p->ino,
problem);
preenhalt();
}
if (p->fix == -1) {
printf("Remove illegal block(s) in inode %ld", p->ino);
p->fix = ask("", 1);
}
printf("Block #%d (%ld) %s. %s\n", blockcnt, blk, problem,
clear_msg[p->fix]);
if (p->fix) {
*block_nr = 0;
return BLOCK_CHANGED;
} else {
ext2fs_unmark_valid(fs);
return 0;
}
}
mark_block_used(fs, blk);
if (p->is_dir && (blockcnt >= 0)) {
if (dir_block_count >= dir_block_size) {
dir_block_size += 100;
dir_blocks = realloc(dir_blocks,
dir_block_size *
sizeof(struct dir_block_struct));
}
dir_blocks[dir_block_count].blk = blk;
dir_blocks[dir_block_count].ino = p->ino;
dir_blocks[dir_block_count].blockcnt = blockcnt;
dir_block_count++;
}
#if 0
printf("process block, inode %d, block #%d is %d\n",
p->ino, blockcnt, blk);
#endif
return 0;
}
int process_bad_block(ext2_filsys fs,
blk_t *block_nr,
int blockcnt,
void *private)
{
struct process_block_struct *p;
errcode_t retval;
blk_t blk = *block_nr;
if (!blk)
return 0;
p = (struct process_block_struct *) private;
if ((blk < fs->super->s_first_data_block) ||
(blk >= fs->super->s_blocks_count)) {
if (preen) {
printf("Illegal block %ld in bad block inode\n", blk);
preenhalt();
}
if (p->fix == -1)
p->fix = ask("Remove illegal block(s) in bad block inode", 1);
printf("Illegal block %ld in bad block inode. %s\n", blk,
clear_msg[p->fix]);
if (p->fix) {
*block_nr = 0;
return BLOCK_CHANGED;
} else {
ext2fs_unmark_valid(fs);
return 0;
}
}
if (blockcnt < 0) {
mark_block_used(fs, blk);
return 0;
}
#if 0
printf ("DEBUG: Marking %d as bad.\n", blk);
#endif
fs_badblocks_count++;
/*
* If the block is not used, then mark it as used and return.
* If it is already marked as found, this must mean that
* there's an overlap between the filesystem table blocks
* (bitmaps and inode table) and the bad block list.
*/
if (!ext2fs_test_block_bitmap(fs, block_found_map, blk)) {
ext2fs_mark_block_bitmap(fs, block_found_map, blk);
return 0;
}
if (!bad_fs_block_map) {
retval = ext2fs_allocate_inode_bitmap(fs, &bad_fs_block_map);
if (retval) {
com_err("ext2fs_allocate_block_bitmap", retval,
"while allocating bad_fs_block_map");
fatal_error(0);
}
}
ext2fs_mark_block_bitmap(fs, bad_fs_block_map, blk);
return 0;
}
/*
* This routine gets called at the end of pass 1 if bad blocks are
* detected in the superblock, group descriptors, inode_bitmaps, or
* block bitmaps. At this point, all of the blocks have been mapped
* out, so we can try to allocate new block(s) to replace the bad
* blocks.
*/
static void handle_fs_bad_blocks(ext2_filsys fs, char *block_buf)
{
errcode_t retval;
printf("Warning: Bad block(s) found in filesystem-reserved blocks.\n");
retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, block_buf,
process_fs_bad_block, 0);
}
static void new_table_block(ext2_filsys fs, blk_t first_block,
const char *name, int num, blk_t *new_block)
{
errcode_t retval;
blk_t old_block = *new_block;
int i;
char *buf;
retval = ext2fs_get_free_blocks(fs, first_block,
first_block + fs->super->s_blocks_per_group,
num, block_found_map, new_block);
if (retval) {
printf("Could not allocate %d block(s) for %s: %s\n",
num, name, error_message(retval));
ext2fs_unmark_valid(fs);
return;
}
buf = malloc(fs->blocksize);
if (!buf) {
printf("Could not allocate block buffer for relocating %s\n",
name);
ext2fs_unmark_valid(fs);
return;
}
ext2fs_mark_super_dirty(fs);
for (i = 0; i < num; i++) {
ext2fs_mark_block_bitmap(fs, block_found_map, (*new_block)+i);
retval = io_channel_read_blk(fs->io, old_block + i,
1, buf);
if (retval)
printf("Warning: could not read block %ld of %s: %s\n",
old_block + i, name, error_message(retval));
retval = io_channel_write_blk(fs->io, (*new_block) + i,
1, buf);
if (retval)
printf("Warning: could not write block %ld for %s: %s\n",
(*new_block) + i, name, error_message(retval));
/*
* If this particular block is not marked as bad, then
* clear its bit in the block_found map. Otherwise,
* leave it set, since it is included in the bad
* blocks inode.
*/
if (!ext2fs_test_block_bitmap(fs, bad_fs_block_map,
old_block + i))
ext2fs_unmark_block_bitmap(fs, block_found_map,
old_block + i);
/*
* Clear the bitmap since this block has now been moved.
*/
ext2fs_unmark_block_bitmap(fs, bad_fs_block_map,
old_block + i);
}
free(buf);
}
/*
* Helper function for handle_fs_bad_blocks()
*/
static int process_fs_bad_block(ext2_filsys fs, blk_t *block_nr,
int blockcnt, void *private)
{
int i;
blk_t block = *block_nr;
int first_block = fs->super->s_first_data_block;
/*
* If this block isn't one that is marked as a bad block in
* the filesystem tables, return
*/
if (!ext2fs_test_block_bitmap(fs, bad_fs_block_map, block))
return 0;
for (i = 0; i < fs->group_desc_count; i++) {
if (block == first_block)
printf("Bad block %ld in group %d's superblock.\n",
block, i);
if (block == fs->group_desc[i].bg_block_bitmap) {
printf("Bad block %ld in group %d's block bitmap. ",
block, i);
if (ask("Relocate", 1)) {
new_table_block(fs, first_block,
"block bitmap", 1,
&fs->group_desc[i].bg_block_bitmap);
} else
ext2fs_unmark_valid(fs);
}
if (block == fs->group_desc[i].bg_inode_bitmap) {
printf("Bad block %ld in group %d's inode bitmap. ",
block, i);
if (ask("Relocate", 1)) {
new_table_block(fs, first_block,
"inode bitmap", 1,
&fs->group_desc[i].bg_inode_bitmap);
} else
ext2fs_unmark_valid(fs);
}
if ((block >= fs->group_desc[i].bg_inode_table) &&
(block < (fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group))) {
printf("WARNING: Severe data loss possible!!!!\n");
printf("Bad block %ld in group %d's inode table. ",
block, i);
if (ask("Relocate", 1)) {
new_table_block(fs, first_block,
"inode table",
fs->inode_blocks_per_group,
&fs->group_desc[i].bg_inode_table);
} else
ext2fs_unmark_valid(fs);
}
if ((block > first_block) &&
(block <= first_block + fs->desc_blocks))
printf("Bad block %ld in group %d's copy of the descriptors.\n",
block, i);
first_block += fs->super->s_blocks_per_group;
}
return 0;
}
/*
* This routine marks all blocks which are used by the superblock,
* group descriptors, inode bitmaps, and block bitmaps.
*/
static void mark_table_blocks(ext2_filsys fs)
{
blk_t block;
int i,j;
block = fs->super->s_first_data_block;
for (i = 0; i < fs->group_desc_count; i++) {
/*
* Mark block used for the block bitmap
*/
ext2fs_mark_block_bitmap(fs, block_found_map,
fs->group_desc[i].bg_block_bitmap);
/*
* Mark block used for the inode bitmap
*/
ext2fs_mark_block_bitmap(fs, block_found_map,
fs->group_desc[i].bg_inode_bitmap);
/*
* Mark the blocks used for the inode table
*/
for (j = 0; j < fs->inode_blocks_per_group; j++)
ext2fs_mark_block_bitmap(fs, block_found_map,
fs->group_desc[i].bg_inode_table + j);
/*
* Mark this group's copy of the superblock
*/
ext2fs_mark_block_bitmap(fs, block_found_map, block);
/*
* Mark this group's copy of the descriptors
*/
for (j = 0; j < fs->desc_blocks; j++)
ext2fs_mark_block_bitmap(fs, block_found_map,
block + j + 1);
block += fs->super->s_blocks_per_group;
}
}
/*
* This subroutines short circuits ext2fs_get_blocks and
* ext2fs_check_directory; we use them since we already have the inode
* structure, so there's no point in letting the ext2fs library read
* the inode again.
*/
static errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks)
{
int i;
if (ino == stashed_ino) {
for (i=0; i < EXT2_N_BLOCKS; i++)
blocks[i] = stashed_inode->i_block[i];
return 0;
}
printf("INTERNAL ERROR: pass1_get_blocks: unexpected inode #%ld\n",
ino);
printf("\t(was expecting %ld)\n", stashed_ino);
exit(FSCK_ERROR);
}
static errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino)
{
if (ino == stashed_ino) {
if (!S_ISDIR(stashed_inode->i_mode))
return ENOTDIR;
return 0;
}
printf("INTERNAL ERROR: pass1_check_directory: unexpected inode #%ld\n",
ino);
printf("\t(was expecting %ld)\n", stashed_ino);
exit(FSCK_ERROR);
}

640
e2fsck/pass1b.c Normal file
View File

@ -0,0 +1,640 @@
/*
* pass1b.c --- Pass #1b of e2fsck
*
* This file contains pass1B, pass1C, and pass1D of e2fsck. They are
* only invoked if pass 1 discovered blocks which are in use by more
* than one inode.
*
* Pass1B scans the data blocks of all the inodes again, generating a
* complete list of duplicate blocks and which inodes have claimed
* them.
*
* Pass1C does a tree-traversal of the filesystem, to determine the
* parent directories of these inodes. This step is necessary so that
* e2fsck can print out the pathnames of affected inodes.
*
* Pass1D is a reconciliation pass. For each inode with duplicate
* blocks, the user is prompted if s/he would like to clone the file
* (so that the file gets a fresh copy of the duplicated blocks) or
* simply to delete the file.
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*
*/
#include <time.h>
#include <et/com_err.h>
#include "e2fsck.h"
/*
* This is structure is allocated for each time that a block is
* claimed by more than one file. So if a particular block is claimed
* by 3 files, then three copies of this structure will be allocated,
* one for each conflict.
*
* The linked list structure is as follows:
*
* dup_blk --> block #34 --> block #35 --> block #47
* inode #12 inode #14 inode #17
* num_bad = 3 num_bad = 2 num_bad = 2
* | | |
* V V V
* block #34 block #35 block #47
* inode #14 inode #15 inode #23
* |
* V
* block #34
* inode #15
*
* The num_bad field indicates how many inodes are sharing a
* particular block, and is only stored in the first element of the
* linked list for a particular block. As the block conflicts are
* resolved, num_bad is decremented; when it reaches 1, then we no
* longer need to worry about that block.
*/
struct dup_block {
blk_t block; /* Block number */
ino_t ino; /* Inode number */
int num_bad;
/* Pointer to next dup record with different block */
struct dup_block *next_block;
/* Pointer to next dup record with different inode */
struct dup_block *next_inode;
};
/*
* This structure stores information about a particular inode which
* is sharing blocks with other inodes. This information is collected
* to display to the user, so that the user knows what files he or she
* is dealing with, when trying to decide how to resolve the conflict
* of multiply-claimed blocks.
*/
struct dup_inode {
ino_t ino;
time_t mtime;
char *pathname;
int num_dupblocks;
int flags;
struct dup_inode *next;
};
#define DUP_INODE_DONT_FREE_PATHNAME 0x1
static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
int blockcnt, void *private);
static void delete_file(ext2_filsys fs, struct dup_inode *dp,
char *block_buf);
static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf);
static void pass1b(ext2_filsys fs, char *block_buf);
static void pass1c(ext2_filsys fs, char *block_buf);
static void pass1d(ext2_filsys fs, char *block_buf);
static struct dup_block *dup_blk = 0;
static struct dup_inode *dup_ino = 0;
static int dup_inode_count = 0;
/*
* For pass1_check_directory and pass1_get_blocks
*/
extern ino_t stashed_ino;
extern struct ext2_inode *stashed_inode;
static char *inode_dup_map;
/*
* Main procedure for handling duplicate blocks
*/
void pass1_dupblocks(ext2_filsys fs, char *block_buf)
{
errcode_t retval;
struct dup_block *p, *q, *next_p, *next_q;
struct dup_inode *r, *next_r;
retval = ext2fs_allocate_inode_bitmap(fs, &inode_dup_map);
if (retval) {
com_err("ext2fs_allocate_inode_bitmap", retval,
"while allocating inode_dup_map");
fatal_error(0);
}
pass1b(fs, block_buf);
pass1c(fs, block_buf);
pass1d(fs, block_buf);
/*
* Time to free all of the accumulated data structures that we
* don't need anymore.
*/
free(inode_dup_map); inode_dup_map = 0;
free(block_dup_map); block_dup_map = 0;
for (p = dup_blk; p; p = next_p) {
next_p = p->next_block;
for (q = p; q; q = next_q) {
next_q = q->next_inode;
free(q);
}
}
for (r = dup_ino; r; r = next_r) {
next_r = r->next;
if (r->pathname && !(r->flags & DUP_INODE_DONT_FREE_PATHNAME))
free(r->pathname);
free(r);
}
}
/*
* Scan the inodes looking for inodes that contain duplicate blocks.
*/
struct process_block_struct {
ino_t ino;
int dup_blocks;
};
void pass1b(ext2_filsys fs, char *block_buf)
{
ino_t ino;
struct ext2_inode inode;
ext2_inode_scan scan;
errcode_t retval;
struct process_block_struct pb;
struct dup_inode *dp;
printf("Duplicate blocks found... invoking duplicate block passes.\n");
printf("Pass 1B: Rescan for duplicate/bad blocks\n");
retval = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan);
if (retval) {
com_err(program_name, retval, "while opening inode scan");
fatal_error(0);
}
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval) {
com_err(program_name, retval, "while starting inode scan");
fatal_error(0);
}
stashed_inode = &inode;
while (ino) {
stashed_ino = ino;
if ((ino != EXT2_BAD_INO) &&
(!ext2fs_test_inode_bitmap(fs, inode_used_map, ino) ||
!inode_has_valid_blocks(&inode)))
goto next;
pb.ino = ino;
pb.dup_blocks = 0;
retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
process_pass1b_block, &pb);
if (pb.dup_blocks) {
if (ino != EXT2_BAD_INO)
printf("\n");
dp = allocate_memory(sizeof(struct dup_inode),
"duplicate inode record");
dp->ino = ino;
dp->mtime = inode.i_mtime;
dp->num_dupblocks = pb.dup_blocks;
dp->pathname = 0;
dp->flags = 0;
dp->next = dup_ino;
dup_ino = dp;
if (ino != EXT2_BAD_INO)
dup_inode_count++;
}
if (retval)
com_err(program_name, retval,
"while calling ext2fs_block_iterate in pass1b");
next:
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval) {
com_err(program_name, retval,
"while doing inode scan");
fatal_error(0);
}
}
ext2fs_close_inode_scan(scan);
fs->get_blocks = 0;
fs->check_directory = 0;
}
int process_pass1b_block(ext2_filsys fs,
blk_t *block_nr,
int blockcnt,
void *private)
{
struct process_block_struct *p;
struct dup_block *dp, *q, *r;
int i;
if (!*block_nr)
return 0;
p = (struct process_block_struct *) private;
if (ext2fs_test_block_bitmap(fs, block_dup_map, *block_nr)) {
/* OK, this is a duplicate block */
if (p->ino != EXT2_BAD_INO) {
if (!p->dup_blocks)
printf("Duplicate/bad block(s) in inode %ld:",
p->ino);
printf(" %ld", *block_nr);
}
p->dup_blocks++;
ext2fs_mark_block_bitmap(fs, block_dup_map, *block_nr);
ext2fs_mark_inode_bitmap(fs, inode_dup_map, p->ino);
dp = allocate_memory(sizeof(struct dup_block),
"duplicate block record");
dp->block = *block_nr;
dp->ino = p->ino;
dp->num_bad = 0;
q = dup_blk;
while (q) {
if (q->block == *block_nr)
break;
q = q->next_block;
}
if (q) {
dp->next_inode = q->next_inode;
q->next_inode = dp;
} else {
dp->next_block = dup_blk;
dup_blk = dp;
}
}
/*
* Set the num_bad field
*/
for (q = dup_blk; q; q = q->next_block) {
i = 0;
for (r = q; r; r = r->next_inode)
i++;
q->num_bad = i;
}
return 0;
}
/*
* Used by pass1c to name the "special" inodes. They are declared as
* writeable strings to prevent const problems.
*/
#define num_special_inodes 7
char special_inode_name[num_special_inodes][40] =
{
"<The NULL inode>", /* 0 */
"<The bad blocks inode>", /* 1 */
"/", /* 2 */
"<The ACL index inode>", /* 3 */
"<The ACL data inode>", /* 4 */
"<The boot loader inode>", /* 5 */
"<The undelete directory inode>" /* 6 */
};
/*
* Pass 1c: Scan directories for inodes with duplicate blocks. This
* is used so that we can print pathnames when prompting the user for
* what to do.
*/
struct process_dir_struct {
ext2_filsys fs;
ino_t dir_ino;
int count;
};
void pass1c(ext2_filsys fs, char *block_buf)
{
int i;
struct dup_inode *p;
errcode_t retval;
char buf[80];
int inodes_left = dup_inode_count;
int offset, entry;
struct ext2_dir_entry *dirent;
printf("Pass 1C: Scan directories for inodes with dup blocks.\n");
/*
* First check to see if any of the inodes with dup blocks is
* the bad block inode or the root inode; handle them as
* special cases.
*/
for (p = dup_ino; p; p = p->next) {
if (p->ino < num_special_inodes) {
p->pathname = special_inode_name[p->ino];
p->flags |= DUP_INODE_DONT_FREE_PATHNAME;
inodes_left--;
}
}
/*
* Search through all directories to translate inodes to names
* (by searching for the containing directory for that inode.)
*/
for (i=0; inodes_left && i < dir_block_count; i++) {
retval = io_channel_read_blk(fs->io, dir_blocks[i].blk,
1, block_buf);
entry = offset = 0;
while (offset < fs->blocksize) {
entry++;
dirent = (struct ext2_dir_entry *)
(block_buf + offset);
if (!dirent->inode ||
((dir_blocks[i].blockcnt == 0) && (entry <= 2)))
goto next;
if (!ext2fs_test_inode_bitmap(fs, inode_dup_map,
dirent->inode))
goto next;
for (p = dup_ino; p; p = p->next) {
if (p->ino == dirent->inode)
break;
}
if (!p || p->pathname)
goto next;
(void) ext2fs_get_pathname(fs, dir_blocks[i].ino,
p->ino, &p->pathname);
inodes_left--;
next:
if (dirent->rec_len < 8)
break;
offset += dirent->rec_len;
}
}
/*
* If we can't get a name, then put in a generic one.
*/
for (p = dup_ino; p; p = p->next) {
if (!p->pathname) {
sprintf(buf, "<Unknown inode #%ld>", p->ino);
p->pathname = malloc(strlen(buf)+1);
if (!p->pathname) {
fprintf(stderr, "pass1c: couldn't malloc "
"generic pathname\n");
fatal_error(0);
}
strcpy(p->pathname, buf);
}
}
}
static void pass1d(ext2_filsys fs, char *block_buf)
{
struct dup_inode *p, *s;
struct dup_block *q, *r;
ino_t *shared;
int shared_len;
int i;
errcode_t retval;
char *time_str;
int file_ok;
printf("Pass 1D: Reconciling duplicate blocks\n");
read_bitmaps(fs);
printf("(There are %d inodes containing duplicate/bad blocks.)\n\n",
dup_inode_count);
shared = allocate_memory(sizeof(ino_t) * dup_inode_count,
"Shared inode list");
for (p = dup_ino; p; p = p->next) {
shared_len = 0;
file_ok = 1;
if (p->ino == EXT2_BAD_INO)
continue;
/*
* Search through the duplicate records to see which
* inodes share blocks with this one
*/
for (q = dup_blk; q; q = q->next_block) {
/*
* See if this block is used by this inode.
* If it isn't, continue.
*/
for (r = q; r; r = r->next_inode)
if (r->ino == p->ino)
break;
if (!r)
continue;
if (q->num_bad > 1)
file_ok = 0;
/*
* Add all inodes used by this block to the
* shared[] --- which is a unique list, so
* if an inode is already in shared[], don't
* add it again.
*/
for (r = q; r; r = r->next_inode) {
if (r->ino == p->ino)
continue;
for (i = 0; i < shared_len; i++)
if (shared[i] == r->ino)
break;
if (i == shared_len) {
shared[shared_len++] = r->ino;
}
}
}
time_str = ctime(&p->mtime);
time_str[24] = 0;
printf("File %s (inode #%ld, mod time %s) \n",
p->pathname, p->ino, time_str);
printf(" has %d duplicate blocks, shared with %d file%s:\n",
p->num_dupblocks, shared_len,
(shared_len>1) ? "s" : "");
for (i = 0; i < shared_len; i++) {
for (s = dup_ino; s; s = s->next)
if (s->ino == shared[i])
break;
if (!s)
continue;
time_str = ctime(&s->mtime);
time_str[24] = 0;
printf("\t%s (inode #%ld, mod time %s)\n",
s->pathname, s->ino, time_str);
}
if (file_ok) {
printf("Duplicated blocks already reassigned or cloned.\n\n");
continue;
}
if (ask("Clone duplicate/bad blocks", 1)) {
retval = clone_file(fs, p, block_buf);
if (retval)
printf("Couldn't clone file: %s\n",
error_message(retval));
else {
printf("\n");
continue;
}
}
if (ask("Delete file", 1))
delete_file(fs, p, block_buf);
else
ext2fs_unmark_valid(fs);
printf("\n");
}
}
static int delete_file_block(ext2_filsys fs,
blk_t *block_nr,
int blockcnt,
void *private)
{
struct dup_block *p;
if (!*block_nr)
return 0;
if (ext2fs_test_block_bitmap(fs, block_dup_map, *block_nr)) {
for (p = dup_blk; p; p = p->next_block)
if (p->block == *block_nr)
break;
if (p) {
p->num_bad--;
if (p->num_bad == 1)
ext2fs_unmark_block_bitmap(fs, block_dup_map,
*block_nr);
} else
com_err("delete_file_block", 0,
"internal error; can't find dup_blk for %d\n",
*block_nr);
} else {
ext2fs_unmark_block_bitmap(fs, block_found_map, *block_nr);
ext2fs_unmark_block_bitmap(fs, fs->block_map, *block_nr);
}
return 0;
}
static void delete_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
{
errcode_t retval;
struct process_block_struct pb;
struct ext2_inode inode;
pb.ino = dp->ino;
pb.dup_blocks = dp->num_dupblocks;
retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf,
delete_file_block, &pb);
if (retval)
com_err("delete_file", retval,
"while calling ext2fs_block_iterate for inode %d",
dp->ino);
ext2fs_unmark_inode_bitmap(fs, inode_used_map, dp->ino);
ext2fs_unmark_inode_bitmap(fs, inode_dir_map, dp->ino);
if (inode_bad_map)
ext2fs_unmark_inode_bitmap(fs, inode_bad_map, dp->ino);
ext2fs_unmark_inode_bitmap(fs, fs->inode_map, dp->ino);
ext2fs_mark_ib_dirty(fs);
ext2fs_mark_bb_dirty(fs);
retval = ext2fs_read_inode(fs, dp->ino, &inode);
if (retval) {
com_err("delete_file", retval, "while reading inode %d",
dp->ino);
return;
}
inode.i_links_count = 0;
inode.i_dtime = time(0);
retval = ext2fs_write_inode(fs, dp->ino, &inode);
if (retval) {
com_err("delete_file", retval, "while writing inode %d",
dp->ino);
return;
}
}
struct clone_struct {
errcode_t errcode;
char *buf;
};
static int clone_file_block(ext2_filsys fs,
blk_t *block_nr,
int blockcnt,
void *private)
{
struct dup_block *p;
blk_t new_block;
errcode_t retval;
struct clone_struct *cs = (struct clone_struct *) private;
if (!*block_nr)
return 0;
if (ext2fs_test_block_bitmap(fs, block_dup_map, *block_nr)) {
for (p = dup_blk; p; p = p->next_block)
if (p->block == *block_nr)
break;
if (p) {
retval = ext2fs_new_block(fs, 0, block_found_map,
&new_block);
if (retval) {
cs->errcode = retval;
return BLOCK_ABORT;
}
retval = io_channel_read_blk(fs->io, *block_nr, 1,
cs->buf);
if (retval) {
cs->errcode = retval;
return BLOCK_ABORT;
}
retval = io_channel_write_blk(fs->io, new_block, 1,
cs->buf);
if (retval) {
cs->errcode = retval;
return BLOCK_ABORT;
}
p->num_bad--;
if (p->num_bad == 1)
ext2fs_unmark_block_bitmap(fs, block_dup_map,
*block_nr);
*block_nr = new_block;
ext2fs_mark_block_bitmap(fs, block_found_map,
new_block);
ext2fs_mark_block_bitmap(fs, fs->block_map, new_block);
return BLOCK_CHANGED;
} else
com_err("clone_file_block", 0,
"internal error; can't find dup_blk for %d\n",
*block_nr);
}
return 0;
}
static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
{
errcode_t retval;
struct clone_struct cs;
cs.errcode = 0;
cs.buf = malloc(fs->blocksize);
if (!cs.buf)
return ENOMEM;
retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf,
clone_file_block, &cs);
ext2fs_mark_bb_dirty(fs);
free(cs.buf);
if (retval) {
com_err("clone_file", retval,
"while calling ext2fs_block_iterate for inode %d",
dp->ino);
return retval;
}
if (cs.errcode) {
com_err("clone_file", retval,
"returned from clone_file_block");
return retval;
}
return 0;
}

631
e2fsck/pass2.c Normal file
View File

@ -0,0 +1,631 @@
/*
* pass2.c --- check directory structure
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*
* Pass 2 of e2fsck iterates through all active directory inodes, and
* applies to following tests to each directory entry in the directory
* blocks in the inodes:
*
* - The length of the directory entry (rec_len) should be at
* least 8 bytes, and no more than the remaining space
* left in the directory block.
* - The length of the name in the directory entry (name_len)
* should be less than (rec_len - 8).
* - The inode number in the directory entry should be within
* legal bounds.
* - The inode number should refer to a in-use inode.
* - The first entry should be '.', and its inode should be
* the inode of the directory.
* - The second entry should be '..'.
*
* To minimize disk seek time, the directory blocks are processed in
* sorted order of block numbers.
*
* Pass 2 also collects the following information:
* - The inode numbers of the subdirectories for each directory.
*
* Pass 2 relies on the following information from previous passes:
* - The directory information collected in pass 1.
* - The inode_used_map bitmap
* - The inode_bad_map bitmap
* - The inode_dir_map bitmap
* - The block_dup_map bitmap
*
* Pass 2 frees the following data structures
* - The inode_bad_map bitmap
*/
#include "et/com_err.h"
#include "e2fsck.h"
/*
* Keeps track of how many times an inode is referenced.
*/
unsigned short * inode_count;
static void deallocate_inode(ext2_filsys fs, ino_t ino,
char* block_buf);
static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino);
static int check_dir_block(ext2_filsys fs,
struct dir_block_struct *dir_blocks_info,
char *buf);
void pass2(ext2_filsys fs)
{
int i;
char *buf;
struct resource_track rtrack;
init_resource_track(&rtrack);
#ifdef MTRACE
mtrace_print("Pass 2");
#endif
if (!preen)
printf("Pass 2: Checking directory structure\n");
inode_count = allocate_memory((fs->super->s_inodes_count + 1) *
sizeof(unsigned short),
"buffer for inode count");
buf = allocate_memory(fs->blocksize, "directory scan buffer");
for (i=0; i < dir_block_count; i++)
check_dir_block(fs, &dir_blocks[i], buf);
free(buf);
free(dir_blocks);
if (inode_bad_map) {
free(inode_bad_map);
inode_bad_map = 0;
}
if (tflag > 1) {
printf("Pass 2: ");
print_resource_track(&rtrack);
}
}
/*
* Make sure the first entry in the directory is '.', and that the
* directory entry is sane.
*/
static int check_dot(ext2_filsys fs,
struct ext2_dir_entry *dirent,
ino_t ino)
{
struct ext2_dir_entry *nextdir;
int status = 0;
int created = 0;
int new_len;
char name[BLOCK_SIZE];
if (!dirent->inode) {
printf("Missing '.' in directory inode %ld.\n", ino);
if (dirent->rec_len < 12)
fatal_error("Cannot fix, insufficient space to add '.'");
preenhalt();
if (ask("Fix", 1)) {
dirent->inode = ino;
dirent->name_len = 1;
dirent->name[0] = '.';
status = 1;
created = 1;
} else {
ext2fs_unmark_valid(fs);
return 0;
}
}
if ((dirent->name_len != 1) ||
strncmp(dirent->name, ".", dirent->name_len)) {
strncpy(name, dirent->name, dirent->name_len);
name[dirent->name_len] = '\0';
printf("Missing '.' in directory inode %ld.\n", ino);
printf("Cannot fix, first entry in directory contains '%s'\n",
name);
exit(FSCK_ERROR);
}
if (dirent->inode != ino) {
printf("Bad inode number for '.' in directory inode %ld.\n",
ino);
preenhalt();
if (ask("Fix", 1)) {
dirent->inode = ino;
status = 1;
} else
ext2fs_unmark_valid(fs);
}
if (dirent->rec_len > 12) {
new_len = dirent->rec_len - 12;
if (new_len > 12) {
preenhalt();
if (created ||
ask("Directory entry for '.' is big. Split", 1)) {
nextdir = (struct ext2_dir_entry *)
((char *) dirent + 12);
dirent->rec_len = 12;
nextdir->rec_len = new_len;
nextdir->inode = 0;
nextdir->name_len = 0;
status = 1;
}
}
}
return status;
}
/*
* Make sure the second entry in the directory is '..', and that the
* directory entry is sane. We do not check the inode number of '..'
* here; this gets done in pass 3.
*/
static int check_dotdot(ext2_filsys fs,
struct ext2_dir_entry *dirent,
struct dir_info *dir)
{
char name[BLOCK_SIZE];
int ino = dir->ino;
if (!dirent->inode) {
printf("Missing '..' in directory inode %d.\n", ino);
if (dirent->rec_len < 12)
fatal_error("Cannot fix, insufficient space to add '..'");
preenhalt();
if (ask("Fix", 1)) {
/*
* Note: we don't have the parent inode just
* yet, so we will fill it in with the root
* inode. This will get fixed in pass 3.
*/
dirent->inode = EXT2_ROOT_INO;
dirent->name_len = 2;
dirent->name[0] = '.';
dirent->name[1] = '.';
return 1;
} else
ext2fs_unmark_valid(fs);
return 0;
}
if ((dirent->name_len != 2) ||
strncmp(dirent->name, "..", dirent->name_len)) {
strncpy(name, dirent->name, dirent->name_len);
name[dirent->name_len] = '\0';
printf("Missing '..' in directory inode %d.\n", ino);
printf("Cannot fix, first entry in directory contains %s\n",
name);
exit(FSCK_ERROR);
}
dir->dotdot = dirent->inode;
return 0;
}
/*
* Check to make sure a directory entry doesn't contain any illegal
* characters.
*/
static int check_name(ext2_filsys fs,
struct ext2_dir_entry *dirent,
ino_t dir_ino,
char *name)
{
int i;
int fixup = -1;
char *pathname;
int ret = 0;
errcode_t retval;
for ( i = 0; i < dirent->name_len; i++) {
if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
if (fixup < 0) {
retval = ext2fs_get_pathname(fs, dir_ino,
0, &pathname);
if (retval) {
com_err(program_name, retval, "while getting pathname in check_name");
fatal_error(0);
}
printf ("Bad file name '%s' (contains '/' or "
" null) in directory '%s'",
pathname, name);
free(pathname);
preenhalt();
fixup = ask("Replace '/' or null by '.'", 1);
}
if (fixup) {
dirent->name[i] = '.';
ret = 1;
} else
ext2fs_unmark_valid(fs);
}
}
return ret;
}
static int check_dir_block(ext2_filsys fs,
struct dir_block_struct *db,
char *buf)
{
struct dir_info *subdir, *dir;
struct ext2_dir_entry *dirent;
char name[BLOCK_SIZE];
int offset = 0;
int dir_modified = 0;
errcode_t retval;
char *path1, *path2;
int dot_state;
blk_t block_nr = db->blk;
ino_t ino = db->ino;
static char unknown[] = "???";
/*
* Make sure the inode is still in use (could have been
* deleted in the duplicate/bad blocks pass.
*/
if (!(ext2fs_test_inode_bitmap(fs, inode_used_map, ino)))
return 0;
if (db->blockcnt)
dot_state = 2;
else
dot_state = 0;
#if 0
printf("In process_dir_block block %d, #%d, inode %d\n", block_nr,
db->blockcnt, ino);
#endif
retval = io_channel_read_blk(fs->io, block_nr, 1, buf);
if (retval) {
com_err(program_name, retval,
"while reading directory block %d", block_nr);
}
do {
dot_state++;
dirent = (struct ext2_dir_entry *) (buf + offset);
if (((offset + dirent->rec_len) > fs->blocksize) ||
(dirent->rec_len < 8) ||
((dirent->name_len+8) > dirent->rec_len)) {
printf("Directory inode %ld, block %d, offset %d: directory corrupted\n",
ino, db->blockcnt, offset);
preenhalt();
if (ask("Salvage", 1)) {
dirent->rec_len = fs->blocksize - offset;
dirent->name_len = 0;
dirent->inode = 0;
dir_modified++;
} else {
ext2fs_unmark_valid(fs);
return DIRENT_ABORT;
}
}
strncpy(name, dirent->name, dirent->name_len);
name[dirent->name_len] = '\0';
if (dot_state == 1) {
if (check_dot(fs, dirent, ino))
dir_modified++;
} else if (dot_state == 2) {
dir = get_dir_info(ino);
if (!dir) {
printf("Internal error: couldn't find dir_info for %ld\n",
ino);
fatal_error(0);
}
if (check_dotdot(fs, dirent, dir))
dir_modified++;
} else if (dirent->inode == ino) {
retval = ext2fs_get_pathname(fs, ino, 0, &path1);
if (retval)
path1 = unknown;
printf("Entry '%s' in %s (%ld) is a link to '.' ",
name, path1, ino);
if (path1 != unknown)
free(path1);
preenhalt();
if (ask("Clear", 1)) {
dirent->inode = 0;
dir_modified++;
}
}
if (!dirent->inode)
goto next;
#if 0
printf("Entry '%s', name_len %d, rec_len %d, inode %d... ",
name, dirent->name_len, dirent->rec_len, dirent->inode);
#endif
if (check_name(fs, dirent, ino, name))
dir_modified++;
/*
* Make sure the inode listed is a legal one.
*/
if (((dirent->inode != EXT2_ROOT_INO) &&
(dirent->inode < EXT2_FIRST_INO)) ||
(dirent->inode > fs->super->s_inodes_count)) {
retval = ext2fs_get_pathname(fs, ino, 0, &path1);
if (retval)
path1 = unknown;
printf("Entry '%s' in %s (%ld) has bad inode #: %ld.\n",
name, path1, ino, dirent->inode);
if (path1 != unknown)
free(path1);
preenhalt();
if (ask("Clear", 1)) {
dirent->inode = 0;
dir_modified++;
goto next;
} else
ext2fs_unmark_valid(fs);
}
/*
* If the inode is unusued, offer to clear it.
*/
if (!(ext2fs_test_inode_bitmap(fs, inode_used_map,
dirent->inode))) {
retval = ext2fs_get_pathname(fs, ino, 0, &path1);
if (retval)
path1 = unknown;
printf("Entry '%s' in %s (%ld) has deleted/unused inode %ld.\n",
name, path1, ino, dirent->inode);
if (path1 != unknown)
free(path1);
if (ask("Clear", 1)) {
dirent->inode = 0;
dir_modified++;
goto next;
} else
ext2fs_unmark_valid(fs);
}
/*
* If the inode was marked as having bad fields in
* pass1, process it and offer to fix/clear it.
* (We wait until now so that we can display the
* pathname to the user.)
*/
if (inode_bad_map &&
ext2fs_test_inode_bitmap(fs, inode_bad_map,
dirent->inode)) {
if (process_bad_inode(fs, ino, dirent->inode)) {
dirent->inode = 0;
dir_modified++;
goto next;
}
}
/*
* If this is a directory, then mark its parent in its
* dir_info structure. If the parent field is already
* filled in, then this directory has more than one
* hard link. We assume the first link is correct,
* and ask the user if he/she wants to clear this one.
*/
if ((dot_state > 2) &&
(ext2fs_test_inode_bitmap(fs, inode_dir_map,
dirent->inode))) {
subdir = get_dir_info(dirent->inode);
if (!subdir) {
printf("INTERNAL ERROR: missing dir %ld\n",
dirent->inode);
fatal_error(0);
}
if (subdir->parent) {
retval = ext2fs_get_pathname(fs, ino,
0, &path1);
if (retval)
path1 = unknown;
retval = ext2fs_get_pathname(fs,
subdir->parent,
dirent->inode,
&path2);
if (retval)
path2 = unknown;
printf("Entry '%s' in %s (%ld) is a link to directory %s (%ld).\n",
name, path1, ino, path2,
dirent->inode);
if (path1 != unknown)
free(path1);
if (path2 != unknown)
free(path2);
if (ask("Clear", 1)) {
dirent->inode = 0;
dir_modified++;
goto next;
} else
ext2fs_unmark_valid(fs);
}
subdir->parent = ino;
}
if (inode_count[dirent->inode]++ > 0)
fs_links_count++;
fs_total_count++;
next:
offset += dirent->rec_len;
} while (offset < fs->blocksize);
#if 0
printf("\n");
#endif
if (offset != fs->blocksize) {
printf("Final rec_len is %d, should be %d\n",
dirent->rec_len,
dirent->rec_len - fs->blocksize + offset);
}
if (dir_modified) {
retval = io_channel_write_blk(fs->io, block_nr,
1, buf);
if (retval) {
com_err(program_name, retval,
"while writing directory block %d", block_nr);
}
ext2fs_mark_changed(fs);
}
return 0;
}
/*
* This function is called to deallocate a block, and is an interator
* functioned called by deallocate inode via ext2fs_iterate_block().
*/
static int deallocate_inode_block(ext2_filsys fs,
blk_t *block_nr,
int blockcnt,
void *private)
{
if (!*block_nr)
return 0;
ext2fs_unmark_block_bitmap(fs, block_found_map, *block_nr);
ext2fs_unmark_block_bitmap(fs, fs->block_map, *block_nr);
return 0;
}
/*
* This fuction deallocates an inode
*/
static void deallocate_inode(ext2_filsys fs, ino_t ino,
char* block_buf)
{
errcode_t retval;
struct ext2_inode inode;
retval = ext2fs_read_inode(fs, ino, &inode);
if (retval) {
com_err("deallocate_inode", retval, "while reading inode %d",
ino);
return;
}
inode.i_links_count = 0;
inode.i_dtime = time(0);
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval) {
com_err("deallocate_inode", retval, "while writing inode %d",
ino);
return;
}
/*
* Fix up the bitmaps...
*/
read_bitmaps(fs);
ext2fs_unmark_inode_bitmap(fs, inode_used_map, ino);
ext2fs_unmark_inode_bitmap(fs, inode_dir_map, ino);
if (inode_bad_map)
ext2fs_unmark_inode_bitmap(fs, inode_bad_map, ino);
ext2fs_unmark_inode_bitmap(fs, fs->inode_map, ino);
ext2fs_mark_ib_dirty(fs);
if (!inode_has_valid_blocks(&inode))
return;
ext2fs_mark_bb_dirty(fs);
retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
deallocate_inode_block, 0);
if (retval)
com_err("deallocate_inode", retval,
"while calling ext2fs_block_iterate for inode %d",
ino);
}
/*
* These two subroutines are used by process_bad_inode; it is used to
* make sure that certain reserved fields are really zero. If not,
* prompt the user if he/she wants us to zeroize them.
*/
static void check_for_zero_long(ext2_filsys fs, ino_t ino, char *pathname,
const char *name, unsigned long *val,
int *modified)
{
char prompt[80];
if (*val) {
printf("%s for inode %ld (%s) is %ld, should be zero.\n",
name, ino, pathname, *val);
preenhalt();
sprintf(prompt, "Clear %s", name);
if (ask(prompt, 1)) {
*val = 0;
*modified = 1;
} else
ext2fs_unmark_valid(fs);
}
}
static void check_for_zero_char(ext2_filsys fs, ino_t ino, char *pathname,
const char *name, unsigned char *val,
int *modified)
{
char prompt[80];
if (*val) {
printf("%s for inode %ld (%s) is %d, should be zero.\n",
name, ino, pathname, *val);
preenhalt();
sprintf(prompt, "Clear %s", name);
if (ask(prompt, 1)) {
*val = 0;
*modified = 1;
} else
ext2fs_unmark_valid(fs);
}
}
static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
{
struct ext2_inode inode;
errcode_t retval;
int inode_modified = 0;
char *pathname;
retval = ext2fs_read_inode(fs, ino, &inode);
if (retval) {
com_err("process_bad_inode", retval, "while reading inode %d",
ino);
return 0;
}
retval = ext2fs_get_pathname(fs, dir, ino, &pathname);
if (retval) {
com_err("process_bad_inode", retval,
"while getting pathname for inode %d",
ino);
return 0;
}
if (!S_ISDIR(inode.i_mode) && !S_ISREG(inode.i_mode) &&
!S_ISCHR(inode.i_mode) && !S_ISBLK(inode.i_mode) &&
!S_ISLNK(inode.i_mode) && !S_ISFIFO(inode.i_mode) &&
!(S_ISSOCK(inode.i_mode))) {
printf("Inode %ld (%s) has a bad mode (0%o).\n",
ino, pathname, inode.i_mode);
preenhalt();
if (ask("Clear", 1)) {
deallocate_inode(fs, ino, 0);
return 1;
} else
ext2fs_unmark_valid(fs);
}
check_for_zero_long(fs, ino, pathname, "i_faddr", &inode.i_faddr,
&inode_modified);
check_for_zero_char(fs, ino, pathname, "i_frag", &inode.i_frag,
&inode_modified);
check_for_zero_char(fs, ino, pathname, "i_fsize", &inode.i_fsize,
&inode_modified);
check_for_zero_long(fs, ino, pathname, "i_file_acl", &inode.i_file_acl,
&inode_modified);
check_for_zero_long(fs, ino, pathname, "i_dir_acl", &inode.i_dir_acl,
&inode_modified);
free(pathname);
if (inode_modified) {
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval) {
com_err("process_bad_inode", retval,
"while writing inode %d",
ino);
return 0;
}
}
return 0;
}

684
e2fsck/pass3.c Normal file
View File

@ -0,0 +1,684 @@
/*
* pass3.c -- pass #3 of e2fsck: Check for directory connectivity
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*
* Pass #3 assures that all directories are connected to the
* filesystem tree, using the following algorithm:
*
* First, the root directory is checked to make sure it exists; if
* not, e2fsck will offer to create a new one. It is then marked as
* "done".
*
* Then, pass3 interates over all directory inodes; for each directory
* it attempts to trace up the filesystem tree, using dirinfo.parent
* until it reaches a directory which has been marked "done". If it
* can not do so, then the directory must be disconnected, and e2fsck
* will offer to reconnect it to /lost+found. While it is chasing
* parent pointers up the filesystem tree, if pass3 sees a directory
* twice, then it has detected a filesystem loop, and it will again
* offer to reconnect the directory to /lost+found in to break the
* filesystem loop.
*
* Pass 3 also contains the subroutine, reconnect_file() to reconnect
* inodes to /lost+found; this subroutine is also used by pass 4.
* reconnect_file() calls get_lost_and_found(), which is responsible
* for creating /lost+found if it does not exist.
*
* Pass 3 frees the following data structures:
* - The dirinfo directory information cache.
*/
#include "et/com_err.h"
#include "e2fsck.h"
static void check_root(ext2_filsys fs, ino_t root_ino);
static void check_directory(ext2_filsys fs, ino_t dir);
static ino_t get_lost_and_found(ext2_filsys fs);
static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent);
static int adjust_inode_count(ext2_filsys fs, ino_t ino, int adj);
static errcode_t expand_directory(ext2_filsys fs, ino_t dir);
static ino_t lost_and_found = 0;
static int bad_lost_and_found = 0;
static char *inode_loop_detect;
static char *inode_done_map;
void pass3(ext2_filsys fs)
{
int i;
errcode_t retval;
struct resource_track rtrack;
init_resource_track(&rtrack);
#ifdef MTRACE
mtrace_print("Pass 3");
#endif
if (!preen)
printf("Pass 3: Checking directory connectivity\n");
/*
* Allocate some bitmaps to do loop detection.
*/
retval = ext2fs_allocate_inode_bitmap(fs, &inode_loop_detect);
if (retval) {
com_err("ext2fs_allocate_inode_bitmap", retval,
"while allocating inode_loop_detect");
fatal_error(0);
}
retval = ext2fs_allocate_inode_bitmap(fs, &inode_done_map);
if (retval) {
com_err("ext2fs_allocate_inode_bitmap", retval,
"while allocating inode_done_map");
fatal_error(0);
}
if (tflag) {
printf("Peak memory: ");
print_resource_track(&global_rtrack);
}
check_root(fs, EXT2_ROOT_INO);
ext2fs_mark_inode_bitmap(fs, inode_done_map, EXT2_ROOT_INO);
for (i=1; i <= fs->super->s_inodes_count; i++) {
if (ext2fs_test_inode_bitmap(fs, inode_dir_map, i))
check_directory(fs, i);
}
free_dir_info(fs);
free(inode_loop_detect);
free(inode_done_map);
if (tflag > 1) {
printf("Pass 3: ");
print_resource_track(&rtrack);
}
}
/*
* This makes sure the root inode is present; if not, we ask if the
* user wants us to create it. Not creating it is a fatal error.
*/
void check_root(ext2_filsys fs, ino_t root_ino)
{
blk_t blk;
errcode_t retval;
struct ext2_inode inode;
char * block;
struct dir_info *dir;
if (ext2fs_test_inode_bitmap(fs, inode_used_map, root_ino)) {
/*
* If the root inode is a directory, die here. The
* user must have answered 'no' in pass1 when we
* offered to clear it.
*/
if (!(ext2fs_test_inode_bitmap(fs, inode_dir_map, root_ino)))
fatal_error("Root inode not directory");
/*
* Set up the parent pointer for the root; this isn't
* done anywhere else, so we do it here.
*/
dir = get_dir_info(root_ino);
dir->parent = root_ino;
return;
}
printf("Root inode not allocated. ");
preenhalt();
if (!ask("Rellocate", 1)) {
ext2fs_unmark_valid(fs);
fatal_error("Cannot proceed without a root inode.");
}
read_bitmaps(fs);
/*
* First, find a free block
*/
retval = ext2fs_new_block(fs, 0, block_found_map, &blk);
if (retval) {
com_err("ext2fs_new_block", retval,
"while trying to create root directory");
fatal_error(0);
}
ext2fs_mark_block_bitmap(fs, block_found_map, blk);
ext2fs_mark_block_bitmap(fs, fs->block_map, blk);
ext2fs_mark_bb_dirty(fs);
/*
* Now let's create the actual data block for the inode
*/
retval = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
&block);
if (retval) {
com_err("ext2fs_new_dir_block", retval,
"while creating new root directory");
fatal_error(0);
}
retval = io_channel_write_blk(fs->io, blk, 1, block);
if (retval) {
com_err("io_channel_write_blk", retval,
"while writing the root directory block");
fatal_error(0);
}
free(block);
/*
* Set up the inode structure
*/
memset(&inode, 0, sizeof(inode));
inode.i_mode = 040755;
inode.i_size = fs->blocksize;
inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
inode.i_links_count = 2;
inode.i_blocks = fs->blocksize / 512;
inode.i_block[0] = blk;
/*
* Write out the inode.
*/
retval = ext2fs_write_inode(fs, EXT2_ROOT_INO, &inode);
if (retval) {
com_err("ext2fs_write_inode", retval,
"While trying to create /lost+found");
fatal_error(0);
}
/*
* Miscellaneous bookkeeping...
*/
add_dir_info(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, &inode);
inode_count[EXT2_ROOT_INO] = 2;
inode_link_info[EXT2_ROOT_INO] = 2;
ext2fs_mark_inode_bitmap(fs, inode_used_map, EXT2_ROOT_INO);
ext2fs_mark_inode_bitmap(fs, inode_dir_map, EXT2_ROOT_INO);
ext2fs_mark_inode_bitmap(fs, fs->inode_map, EXT2_ROOT_INO);
ext2fs_mark_ib_dirty(fs);
}
/*
* This subroutine is responsible for making sure that a particular
* directory is connected to the root; if it isn't we trace it up as
* far as we can go, and then offer to connect the resulting parent to
* the lost+found. We have to do loop detection; if we ever discover
* a loop, we treat that as a disconnected directory and offer to
* reparent it to lost+found.
*/
static void check_directory(ext2_filsys fs, ino_t ino)
{
struct dir_info *dir;
struct dir_info *p;
errcode_t retval;
char *path1, *path2, *path3;
static char unknown[] = "???";
dir = get_dir_info(ino);
if (!dir) {
printf("Internal error: couldn't find dir_info for %ld\n",
ino);
fatal_error(0);
}
memset(inode_loop_detect, 0, (fs->super->s_inodes_count / 8) + 1);
p = dir;
while (p) {
/*
* If we find a parent which we've already checked,
* then stop; we know it's either already connected to
* the directory tree, or it isn't but the user has
* already told us he doesn't want us to reconnect the
* disconnected subtree.
*/
if (ext2fs_test_inode_bitmap(fs, inode_done_map, p->ino))
goto check_dot_dot;
/*
* Mark this inode as being "done"; by the time we
* return from this function, the inode we either be
* verified as being connected to the directory tree,
* or we will have offered to reconnect this to
* lost+found.
*/
ext2fs_mark_inode_bitmap(fs, inode_done_map, p->ino);
/*
* If this directory doesn't have a parent, or we've
* seen the parent once already, then offer to
* reparent it to lost+found
*/
if (!p->parent ||
(ext2fs_test_inode_bitmap(fs, inode_loop_detect,
p->parent)))
break;
ext2fs_mark_inode_bitmap(fs, inode_loop_detect,
p->parent);
p = get_dir_info(p->parent);
}
/*
* If we've reached here, we've hit a detached directory
* inode; offer to reconnect it to lost+found.
*/
retval = ext2fs_get_pathname(fs, p->ino, 0, &path1);
if (retval)
path1 = unknown;
printf("Unconnected directory inode %li (%s)\n", p->ino, path1);
if (path1 != unknown)
free(path1);
preenhalt();
if (ask("Connect to /lost+found", 1)) {
if (reconnect_file(fs, p->ino))
ext2fs_unmark_valid(fs);
else {
p->parent = lost_and_found;
fix_dotdot(fs, p, lost_and_found);
}
} else
ext2fs_unmark_valid(fs);
/*
* Make sure that .. and the parent directory are the same;
* offer to fix it if not.
*/
check_dot_dot:
if (dir->parent != dir->dotdot) {
retval = ext2fs_get_pathname(fs, dir->parent, ino,
&path1);
if (retval)
path1 = unknown;
retval = ext2fs_get_pathname(fs, dir->dotdot, 0, &path2);
if (retval)
path2 = unknown;
retval = ext2fs_get_pathname(fs, dir->parent, 0, &path3);
if (retval)
path3 = unknown;
printf("'..' in %s (%ld) is %s (%ld), should be %s (%ld).\n",
path1, ino, path2, dir->dotdot,
path3, dir->parent);
if (path1 != unknown)
free(path1);
if (path2 != unknown)
free(path2);
if (path3 != unknown)
free(path3);
if (ask("Fix", 1))
fix_dotdot(fs, dir, dir->parent);
else
ext2fs_unmark_valid(fs);
}
}
/*
* This routine gets the lost_and_found inode, making it a directory
* if necessary
*/
ino_t get_lost_and_found(ext2_filsys fs)
{
ino_t ino;
blk_t blk;
errcode_t retval;
struct ext2_inode inode;
char * block;
const char * name = "lost+found";
retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino);
if (!retval)
return ino;
if (retval != ENOENT)
printf("Error while trying to find /lost+found: %s",
error_message(retval));
else
printf("/lost+found not found. ");
preenhalt();
if (!ask("Create", 1)) {
ext2fs_unmark_valid(fs);
return 0;
}
/*
* Read the inode and block bitmaps in; we'll be messing with
* them.
*/
read_bitmaps(fs);
/*
* First, find a free block
*/
retval = ext2fs_new_block(fs, 0, block_found_map, &blk);
if (retval) {
com_err("ext2fs_new_block", retval,
"while trying to create /lost+found directory");
return 0;
}
ext2fs_mark_block_bitmap(fs, block_found_map, blk);
ext2fs_mark_block_bitmap(fs, fs->block_map, blk);
ext2fs_mark_bb_dirty(fs);
/*
* Next find a free inode.
*/
retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040755, inode_used_map,
&ino);
if (retval) {
com_err("ext2fs_new_inode", retval,
"while trying to create /lost+found directory");
return 0;
}
ext2fs_mark_inode_bitmap(fs, inode_used_map, ino);
ext2fs_mark_inode_bitmap(fs, inode_dir_map, ino);
ext2fs_mark_inode_bitmap(fs, fs->inode_map, ino);
ext2fs_mark_ib_dirty(fs);
/*
* Now let's create the actual data block for the inode
*/
retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
if (retval) {
com_err("ext2fs_new_dir_block", retval,
"while creating new directory block");
return 0;
}
retval = io_channel_write_blk(fs->io, blk, 1, block);
if (retval) {
com_err("io_channel_write_blk", retval,
"while writing the directory block for /lost+found");
return 0;
}
free(block);
/*
* Set up the inode structure
*/
memset(&inode, 0, sizeof(inode));
inode.i_mode = 040755;
inode.i_size = fs->blocksize;
inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
inode.i_links_count = 2;
inode.i_blocks = fs->blocksize / 512;
inode.i_block[0] = blk;
/*
* Next, write out the inode.
*/
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval) {
com_err("ext2fs_write_inode", retval,
"While trying to create /lost+found");
return 0;
}
/*
* Finally, create the directory link
*/
retval = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, 0);
if (retval) {
com_err("ext2fs_link", retval, "While creating /lost+found");
return 0;
}
/*
* Miscellaneous bookkeeping that needs to be kept straight.
*/
add_dir_info(fs, ino, EXT2_ROOT_INO, &inode);
adjust_inode_count(fs, EXT2_ROOT_INO, +1);
inode_count[ino] = 2;
inode_link_info[ino] = 2;
#if 0
printf("/lost+found created; inode #%d\n", ino);
#endif
return ino;
}
/*
* This routine will connect a file to lost+found
*/
int reconnect_file(ext2_filsys fs, ino_t inode)
{
errcode_t retval;
char name[80];
if (bad_lost_and_found) {
printf("Bad or nonexistent /lost+found. Cannot reconnect.\n");
return 1;
}
if (!lost_and_found) {
lost_and_found = get_lost_and_found(fs);
if (!lost_and_found) {
printf("Bad or nonexistent /lost+found. Cannot reconnect.\n");
bad_lost_and_found++;
return 1;
}
}
sprintf(name, "#%ld", inode);
retval = ext2fs_link(fs, lost_and_found, name, inode, 0);
if (retval == EXT2_ET_DIR_NO_SPACE) {
if (!ask("No room in /lost+found; expand /lost+found", 1))
return 1;
retval = expand_directory(fs, lost_and_found);
if (retval) {
printf("Could not expand /lost+found: %s\n",
error_message(retval));
return 1;
}
retval = ext2fs_link(fs, lost_and_found, name, inode, 0);
}
if (retval) {
printf("Could not reconnect %ld: %s\n", inode,
error_message(retval));
return 1;
}
adjust_inode_count(fs, inode, +1);
return 0;
}
/*
* Utility routine to adjust the inode counts on an inode.
*/
static int adjust_inode_count(ext2_filsys fs, ino_t ino, int adj)
{
errcode_t retval;
struct ext2_inode inode;
if (!ino)
return 0;
retval = ext2fs_read_inode(fs, ino, &inode);
if (retval)
return retval;
#if 0
printf("Adjusting link count for inode %d by %d (from %d)\n", ino, adj,
inode.i_links_count);
#endif
inode.i_links_count += adj;
inode_count[ino] += adj;
inode_link_info[ino] += adj;
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval)
return retval;
return 0;
}
/*
* Fix parent --- this routine fixes up the parent of a directory.
*/
struct fix_dotdot_struct {
ext2_filsys fs;
ino_t parent;
int done;
};
static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private)
{
struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) private;
errcode_t retval;
if (dirent->name_len != 2)
return 0;
if (strncmp(dirent->name, "..", 2))
return 0;
retval = adjust_inode_count(fp->fs, dirent->inode, -1);
if (retval)
printf("Error while adjusting inode count on inode %ld\n",
dirent->inode);
retval = adjust_inode_count(fp->fs, fp->parent, 1);
if (retval)
printf("Error while adjusting inode count on inode %ld\n",
fp->parent);
dirent->inode = fp->parent;
fp->done++;
return DIRENT_ABORT | DIRENT_CHANGED;
}
static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent)
{
errcode_t retval;
struct fix_dotdot_struct fp;
fp.fs = fs;
fp.parent = parent;
fp.done = 0;
#if 0
printf("Fixing '..' of inode %d to be %d...\n", dir->ino, parent);
#endif
retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
0, fix_dotdot_proc, &fp);
if (retval || !fp.done) {
printf("Couldn't fix parent of inode %ld: %s\n\n",
dir->ino, retval ? error_message(retval) :
"Couldn't find parent direntory entry");
ext2fs_unmark_valid(fs);
}
dir->dotdot = parent;
return;
}
/*
* These routines are responsible for expanding a /lost+found if it is
* too small.
*/
struct expand_dir_struct {
int done;
errcode_t err;
};
static int expand_dir_proc(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
void *private)
{
struct expand_dir_struct *es = (struct expand_dir_struct *) private;
blk_t new_blk;
static blk_t last_blk = 0;
char *block;
errcode_t retval;
if (*blocknr) {
last_blk = *blocknr;
return 0;
}
retval = ext2fs_new_block(fs, last_blk, block_found_map, &new_blk);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
if (blockcnt > 0) {
retval = ext2fs_new_dir_block(fs, 0, 0, &block);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
es->done = 1;
} else {
block = malloc(fs->blocksize);
if (!block) {
es->err = ENOMEM;
return BLOCK_ABORT;
}
memset(block, 0, fs->blocksize);
}
retval = io_channel_write_blk(fs->io, new_blk, 1, block);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
free(block);
*blocknr = new_blk;
ext2fs_mark_block_bitmap(fs, block_found_map, new_blk);
ext2fs_mark_block_bitmap(fs, fs->block_map, new_blk);
ext2fs_mark_bb_dirty(fs);
if (es->done)
return (BLOCK_CHANGED | BLOCK_ABORT);
else
return BLOCK_CHANGED;
}
static errcode_t expand_directory(ext2_filsys fs, ino_t dir)
{
errcode_t retval;
struct expand_dir_struct es;
struct ext2_inode inode;
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
retval = ext2fs_check_directory(fs, dir);
if (retval)
return retval;
es.done = 0;
es.err = 0;
retval = ext2fs_block_iterate(fs, dir, BLOCK_FLAG_APPEND,
0, expand_dir_proc, &es);
if (es.err)
return es.err;
if (!es.done)
return EXT2_ET_EXPAND_DIR_ERR;
/*
* Update the size and block count fields in the inode.
*/
retval = ext2fs_read_inode(fs, dir, &inode);
if (retval)
return retval;
inode.i_size += fs->blocksize;
inode.i_blocks += fs->blocksize / 512;
retval = ext2fs_write_inode(fs, dir, &inode);
if (retval)
return retval;
return 0;
}

70
e2fsck/pass4.c Normal file
View File

@ -0,0 +1,70 @@
/*
* pass4.c -- pass #4 of e2fsck: Check reference counts
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*
*/
#include "e2fsck.h"
void pass4(ext2_filsys fs)
{
int i;
struct ext2_inode inode;
struct resource_track rtrack;
init_resource_track(&rtrack);
#ifdef MTRACE
mtrace_print("Pass 4");
#endif
if (!preen)
printf("Pass 4: Check reference counts.\n");
for (i=1; i <= fs->super->s_inodes_count; i++) {
if (i == EXT2_BAD_INO ||
(i > EXT2_ROOT_INO && i < EXT2_FIRST_INO))
continue;
if (!(ext2fs_test_inode_bitmap(fs, inode_used_map, i)))
continue;
if (inode_count[i] == 0) {
/*
* Inode isn't attached to the filesystem;
* prompt to reconnect.
*/
printf("Unattached inode %d\n", i);
preenhalt();
if (ask("Connect to /lost+found", 1)) {
if (reconnect_file(fs, i))
ext2fs_unmark_valid(fs);
} else
ext2fs_unmark_valid(fs);
}
if (inode_count[i] != inode_link_info[i]) {
ext2fs_read_inode(fs, i, &inode);
if (inode_link_info[i] != inode.i_links_count) {
printf("WARNING: PROGRAMMING BUG IN E2FSCK!\n");
printf("inode_link_info[%d] is %d, "
"inode.i_links_count is %d. "
"They should be the same!\n",
i, inode_link_info[i],
inode.i_links_count);
}
printf("Inode %d has ref count %d, expecting %d.\n",
i, inode.i_links_count, inode_count[i]);
if (ask("Set i_nlinks to count", 1)) {
inode.i_links_count = inode_count[i];
ext2fs_write_inode(fs, i, &inode);
} else
ext2fs_unmark_valid(fs);
}
}
free(inode_link_info); inode_link_info = 0;
free(inode_count); inode_count = 0;
if (tflag > 1) {
printf("Pass 4: ");
print_resource_track(&rtrack);
}
}

328
e2fsck/pass5.c Normal file
View File

@ -0,0 +1,328 @@
/*
* pass5.c --- check block and inode bitmaps against on-disk bitmaps
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*
*/
#include "et/com_err.h"
#include "e2fsck.h"
static void check_block_bitmaps(ext2_filsys fs);
static void check_inode_bitmaps(ext2_filsys fs);
static void check_inode_end(ext2_filsys fs);
static void check_block_end(ext2_filsys fs);
static int do_fix = -1;
static const char *fix_question = "Fix summary information";
void pass5(ext2_filsys fs)
{
struct resource_track rtrack;
#ifdef MTRACE
mtrace_print("Pass 5");
#endif
init_resource_track(&rtrack);
if (!preen)
printf("Pass 5: Checking group summary information.\n");
read_bitmaps(fs);
check_block_bitmaps(fs);
check_inode_bitmaps(fs);
check_inode_end(fs);
check_block_end(fs);
free(inode_used_map);
free(inode_dir_map);
free(block_found_map);
if (tflag > 1) {
printf("Pass 5: ");
print_resource_track(&rtrack);
}
}
static void check_block_bitmaps(ext2_filsys fs)
{
int i;
int *free_array;
int group = 0;
int blocks = 0;
int free_blocks = 0;
int group_free = 0;
int actual, bitmap;
const char *print_header = "Block bitmap differences:";
free_array = allocate_memory(fs->group_desc_count * sizeof(int),
"free block count array");
for (i = fs->super->s_first_data_block;
i < fs->super->s_blocks_count;
i++) {
actual = ext2fs_test_block_bitmap(fs, block_found_map, i);
bitmap = ext2fs_test_block_bitmap(fs, fs->block_map, i);
if (actual == bitmap)
goto do_counts;
if (do_fix < 0)
do_fix = ask(fix_question, 1);
if (print_header) {
printf(print_header);
print_header = 0;
}
if (!actual && bitmap) {
/*
* Block not used, but marked in use in the bitmap.
*/
printf(" -%d", i);
if (do_fix)
ext2fs_unmark_block_bitmap(fs, fs->block_map,
i);
} else {
/*
* Block used, but not marked in use in the bitmap.
*/
printf(" +%d", i);
if (do_fix)
ext2fs_mark_block_bitmap(fs, fs->block_map,
i);
}
if (do_fix) {
ext2fs_mark_bb_dirty(fs);
bitmap = actual;
} else
ext2fs_unmark_valid(fs);
do_counts:
if (!bitmap) {
group_free++;
free_blocks++;
}
blocks ++;
if ((blocks == fs->super->s_blocks_per_group) ||
(i == fs->super->s_blocks_count-1)) {
free_array[group] = group_free;
group ++;
blocks = 0;
group_free = 0;
}
}
if (!print_header)
printf(". %s\n", fix_msg[do_fix]);
for (i = 0; i < fs->group_desc_count; i++) {
if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
if (do_fix < 0)
do_fix = ask(fix_question, 1);
printf("Free blocks count wrong for group %d (%d, counted=%d). %s\n",
i, fs->group_desc[i].bg_free_blocks_count,
free_array[i], fix_msg[do_fix]);
if (do_fix) {
fs->group_desc[i].bg_free_blocks_count =
free_array[i];
ext2fs_mark_super_dirty(fs);
} else
ext2fs_unmark_valid(fs);
}
}
if (free_blocks != fs->super->s_free_blocks_count) {
if (do_fix < 0)
do_fix = ask(fix_question, 1);
printf("Free blocks count wrong (%ld, counted=%d). %s\n",
fs->super->s_free_blocks_count, free_blocks,
fix_msg[do_fix]);
if (do_fix) {
fs->super->s_free_blocks_count = free_blocks;
ext2fs_mark_super_dirty(fs);
} else
ext2fs_unmark_valid(fs);
}
}
static void check_inode_bitmaps(ext2_filsys fs)
{
int i;
int free_inodes = 0;
int group_free = 0;
int dirs_count = 0;
int group = 0;
int inodes = 0;
int *free_array;
int *dir_array;
int actual, bitmap;
const char *print_header = "Inode bitmap differences:";
free_array = allocate_memory(fs->group_desc_count * sizeof(int),
"free inode count array");
dir_array = allocate_memory(fs->group_desc_count * sizeof(int),
"directory count array");
for (i = 1; i <= fs->super->s_inodes_count; i++) {
actual = ext2fs_test_inode_bitmap(fs, inode_used_map, i);
bitmap = ext2fs_test_inode_bitmap(fs, fs->inode_map, i);
if (actual == bitmap)
goto do_counts;
if (do_fix < 0)
do_fix = ask(fix_question, 1);
if (print_header) {
printf(print_header);
print_header = 0;
}
if (!actual && bitmap) {
/*
* Inode wasn't used, but marked in bitmap
*/
printf(" -%d", i);
if (do_fix)
ext2fs_unmark_inode_bitmap(fs, fs->inode_map,
i);
} else if (actual && !bitmap) {
/*
* Inode used, but not in bitmap
*/
printf (" +%d", i);
if (do_fix)
ext2fs_mark_inode_bitmap(fs, fs->inode_map, i);
}
if (do_fix) {
ext2fs_mark_ib_dirty(fs);
bitmap = actual;
} else
ext2fs_unmark_valid(fs);
do_counts:
if (!bitmap) {
group_free++;
free_inodes++;
} else {
if (ext2fs_test_inode_bitmap(fs, inode_dir_map, i))
dirs_count++;
}
inodes++;
if ((inodes == fs->super->s_inodes_per_group) ||
(i == fs->super->s_inodes_count)) {
free_array[group] = group_free;
dir_array[group] = dirs_count;
group ++;
inodes = 0;
group_free = 0;
dirs_count = 0;
}
}
if (!print_header)
printf(". %s\n", fix_msg[do_fix]);
for (i = 0; i < fs->group_desc_count; i++) {
if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
if (do_fix < 0)
do_fix = ask(fix_question, 1);
printf ("Free inodes count wrong for group #%d (%d, counted=%d). %s\n",
i, fs->group_desc[i].bg_free_inodes_count,
free_array[i], fix_msg[do_fix]);
if (do_fix) {
fs->group_desc[i].bg_free_inodes_count =
free_array[i];
ext2fs_mark_super_dirty(fs);
} else
ext2fs_unmark_valid(fs);
}
if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
if (do_fix < 0)
do_fix = ask(fix_question, 1);
printf ("Directories count wrong for group #%d (%d, counted=%d). %s\n",
i, fs->group_desc[i].bg_used_dirs_count,
dir_array[i], fix_msg[do_fix]);
if (do_fix) {
fs->group_desc[i].bg_used_dirs_count =
dir_array[i];
ext2fs_mark_super_dirty(fs);
} else
ext2fs_unmark_valid(fs);
}
}
if (free_inodes != fs->super->s_free_inodes_count) {
if (do_fix < 0)
do_fix = ask(fix_question, 1);
printf("Free inodes count wrong (%ld, counted=%d). %s\n",
fs->super->s_free_inodes_count, free_inodes,
fix_msg[do_fix]);
if (do_fix) {
fs->super->s_free_inodes_count = free_inodes;
ext2fs_mark_super_dirty(fs);
} else
ext2fs_unmark_valid(fs);
}
}
static void check_inode_end(ext2_filsys fs)
{
ino_t end;
ino_t save_inodes_count = fs->super->s_inodes_count;
ino_t i;
end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
if (save_inodes_count == end)
return;
fs->super->s_inodes_count = end;
for (i = save_inodes_count + 1; i <= end; i++) {
if (!ext2fs_test_inode_bitmap(fs, fs->inode_map, i)) {
printf("Padding at end of inode bitmap is not set. ");
if (ask("Fix", 1)) {
for (i = save_inodes_count + 1; i <= end; i++)
ext2fs_mark_inode_bitmap(fs,
fs->inode_map,
i);
ext2fs_mark_ib_dirty(fs);
} else
ext2fs_unmark_valid(fs);
break;
}
}
fs->super->s_inodes_count = save_inodes_count;
}
static void check_block_end(ext2_filsys fs)
{
blk_t end;
blk_t save_blocks_count = fs->super->s_blocks_count;
blk_t i;
end = fs->super->s_first_data_block +
(EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count);
if (save_blocks_count == end)
return;
fs->super->s_blocks_count = end;
for (i = save_blocks_count; i < end; i++) {
if (!ext2fs_test_block_bitmap(fs, fs->block_map, i)) {
printf("Padding at end of block bitmap is not set. ");
if (ask("Fix", 1)) {
for (i = save_blocks_count + 1; i < end; i++)
ext2fs_mark_block_bitmap(fs,
fs->block_map,
i);
ext2fs_mark_bb_dirty(fs);
} else
ext2fs_unmark_valid(fs);
break;
}
}
fs->super->s_blocks_count = save_blocks_count;
}

240
e2fsck/util.c Normal file
View File

@ -0,0 +1,240 @@
/*
* util.c --- miscellaneous utilities
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <termios.h>
#include <sys/resource.h>
#include "e2fsck.h"
const char * fix_msg[2] = { "IGNORED", "FIXED" };
const char * clear_msg[2] = { "IGNORED", "CLEARED" };
void fatal_error (const char *msg)
{
if (msg)
fprintf (stderr, "%s: %s\n", program_name, msg);
exit(FSCK_ERROR);
}
void *allocate_memory(int size, const char *description)
{
void *ret;
char buf[256];
#ifdef DEBUG_ALLOCATE_MEMORY
printf("Allocating %d bytes for %s...\n", size, description);
#endif
ret = malloc(size);
if (!ret) {
sprintf(buf, "%%s: Can't allocate %s\n", description);
fatal_error(buf);
}
memset(ret, 0, size);
return ret;
}
int ask_yn(const char * string, int def)
{
int c;
struct termios termios, tmp;
const char *defstr;
tcgetattr (0, &termios);
tmp = termios;
tmp.c_lflag &= ~(ICANON | ECHO);
tcsetattr (0, TCSANOW, &tmp);
if (def == 1)
defstr = "<y>";
else if (def == 0)
defstr = "<n>";
else
defstr = " (y/n)";
printf("%s%s? ", string, defstr);
while (1) {
fflush (stdout);
if ((c = getchar()) == EOF)
break;
c = toupper(c);
if (c == 'Y') {
def = 1;
break;
}
else if (c == 'N') {
def = 0;
break;
}
else if ((c == ' ' || c == '\n') && (def != -1))
break;
}
if (def)
printf ("yes\n\n");
else
printf ("no\n\n");
tcsetattr (0, TCSANOW, &termios);
return def;
}
int ask (const char * string, int def)
{
if (nflag) {
printf ("%s? no\n\n", string);
return 0;
}
if (yflag) {
printf ("%s? yes\n\n", string);
return 1;
}
if (preen) {
printf ("%s? %s\n\n", string, def ? "yes" : "no");
return def;
}
return ask_yn(string, def);
}
void read_bitmaps(ext2_filsys fs)
{
errcode_t retval;
if (!fs->inode_map) {
ehandler_operation("reading inode bitmaps");
retval = ext2fs_read_inode_bitmap(fs);
ehandler_operation(0);
if (retval) {
com_err(program_name, retval,
"while retrying to read inode bitmaps for %s",
device_name);
fatal_error(0);
}
}
if (!fs->block_map) {
ehandler_operation("reading block bitmaps");
retval = ext2fs_read_block_bitmap(fs);
ehandler_operation(0);
if (retval) {
com_err(program_name, retval,
"while retrying to read block bitmaps for %s",
device_name);
fatal_error(0);
}
}
}
void write_bitmaps(ext2_filsys fs)
{
errcode_t retval;
if (ext2fs_test_bb_dirty(fs)) {
ehandler_operation("writing block bitmaps");
retval = ext2fs_write_block_bitmap(fs);
ehandler_operation(0);
if (retval) {
com_err(program_name, retval,
"while retrying to write block bitmaps for %s",
device_name);
fatal_error(0);
}
}
if (ext2fs_test_ib_dirty(fs)) {
ehandler_operation("writing inode bitmaps");
retval = ext2fs_write_inode_bitmap(fs);
ehandler_operation(0);
if (retval) {
com_err(program_name, retval,
"while retrying to write inode bitmaps for %s",
device_name);
fatal_error(0);
}
}
}
void preenhalt(NOARGS)
{
if (!preen)
return;
fprintf(stderr, "\n\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
device_name);
exit(FSCK_UNCORRECTED);
}
void init_resource_track(struct resource_track *track)
{
struct rusage r;
track->brk_start = sbrk(0);
gettimeofday(&track->time_start, 0);
getrusage(RUSAGE_SELF, &r);
track->user_start = r.ru_utime;
track->system_start = r.ru_stime;
}
static __inline__ float timeval_subtract(struct timeval *tv1,
struct timeval *tv2)
{
return ((tv1->tv_sec - tv2->tv_sec) +
((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
}
void print_resource_track(struct resource_track *track)
{
struct rusage r;
struct timeval time_end;
gettimeofday(&time_end, 0);
getrusage(RUSAGE_SELF, &r);
printf("Memory used: %d, elapsed time: %6.3f/%6.3f/%6.3f\n",
(int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
timeval_subtract(&time_end, &track->time_start),
timeval_subtract(&r.ru_utime, &track->user_start),
timeval_subtract(&r.ru_stime, &track->system_start));
}
/*
* This function returns 1 if the inode's block entries actually
* contain block entries.
*/
int inode_has_valid_blocks(struct ext2_inode *inode)
{
/*
* Only directories, regular files, and some symbolic links
* have valid block entries.
*/
if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
!S_ISLNK(inode->i_mode))
return 0;
/*
* If the symbolic link is a "fast symlink", then the symlink
* target is stored in the block entries.
*/
if (S_ISLNK (inode->i_mode) && inode->i_blocks == 0 &&
inode->i_size < EXT2_N_BLOCKS * sizeof (unsigned long))
return 0;
return 1;
}
#ifdef MTRACE
void mtrace_print(char *mesg)
{
FILE *malloc_get_mallstream();
FILE *f = malloc_get_mallstream();
if (f)
fprintf(f, "============= %s\n", mesg);
}
#endif

77
lib/e2p/.depend Normal file
View File

@ -0,0 +1,77 @@
fgetflags.o : fgetflags.c /usr/include/errno.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/linux/errno.h /usr/include/fcntl.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/linux/fcntl.h /usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/sys/ioctl.h \
/usr/include/linux/ioctl.h /usr/include/termios.h /usr/include/linux/termios.h \
/usr/include/linux/ext2_fs.h e2p.h /usr/include/dirent.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h
fgetversion.o : fgetversion.c /usr/include/errno.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/linux/errno.h /usr/include/fcntl.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/linux/fcntl.h /usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/sys/ioctl.h \
/usr/include/linux/ioctl.h /usr/include/termios.h /usr/include/linux/termios.h \
/usr/include/linux/ext2_fs.h e2p.h /usr/include/dirent.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h
fsetflags.o : fsetflags.c /usr/include/errno.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/linux/errno.h /usr/include/fcntl.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/linux/fcntl.h /usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/sys/ioctl.h \
/usr/include/linux/ioctl.h /usr/include/termios.h /usr/include/linux/termios.h \
/usr/include/linux/ext2_fs.h e2p.h /usr/include/dirent.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h
fsetversion.o : fsetversion.c /usr/include/errno.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/linux/errno.h /usr/include/fcntl.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/linux/fcntl.h /usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/sys/ioctl.h \
/usr/include/linux/ioctl.h /usr/include/termios.h /usr/include/linux/termios.h \
/usr/include/linux/ext2_fs.h e2p.h /usr/include/dirent.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h
getflags.o : getflags.c /usr/include/errno.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/linux/errno.h /usr/include/sys/ioctl.h /usr/include/linux/ioctl.h \
/usr/include/termios.h /usr/include/sys/types.h /usr/include/linux/types.h /usr/include/linux/termios.h \
/usr/include/linux/ext2_fs.h e2p.h /usr/include/dirent.h /usr/include/gnu/types.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h
getversion.o : getversion.c /usr/include/errno.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/linux/errno.h /usr/include/sys/ioctl.h /usr/include/linux/ioctl.h \
/usr/include/termios.h /usr/include/sys/types.h /usr/include/linux/types.h /usr/include/linux/termios.h \
/usr/include/linux/ext2_fs.h e2p.h /usr/include/dirent.h /usr/include/gnu/types.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h
iod.o : iod.c /usr/include/dirent.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h e2p.h /usr/include/stdio.h /usr/include/libio.h \
/usr/include/_G_config.h /usr/include/linux/ext2_fs.h
ls.o : ls.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/time.h /usr/include/linux/ext2_fs.h \
e2p.h /usr/include/dirent.h /usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h
pe.o : pe.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/linux/ext2_fs.h e2p.h \
/usr/include/dirent.h /usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h
pf.o : pf.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/linux/ext2_fs.h e2p.h \
/usr/include/dirent.h /usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h
ps.o : ps.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/linux/ext2_fs.h e2p.h \
/usr/include/dirent.h /usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h
setflags.o : setflags.c /usr/include/errno.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/linux/errno.h /usr/include/sys/ioctl.h /usr/include/linux/ioctl.h \
/usr/include/termios.h /usr/include/sys/types.h /usr/include/linux/types.h /usr/include/linux/termios.h \
/usr/include/linux/ext2_fs.h e2p.h /usr/include/dirent.h /usr/include/gnu/types.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h
setversion.o : setversion.c /usr/include/errno.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/linux/errno.h /usr/include/sys/ioctl.h /usr/include/linux/ioctl.h \
/usr/include/termios.h /usr/include/sys/types.h /usr/include/linux/types.h /usr/include/linux/termios.h \
/usr/include/linux/ext2_fs.h e2p.h /usr/include/dirent.h /usr/include/gnu/types.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/linux/limits.h \
/usr/include/linux/dirent.h /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h

66
lib/e2p/Makefile Normal file
View File

@ -0,0 +1,66 @@
# Makefile for the second extended file system utility functions
#
# Copyright (C) 1993 Remy Card (card@masi.ibp.fr)
#
# This file can be redistributed under the terms of the GNU General
# Public License
include ../../MCONFIG
CFLAGS_NO= $(WFLAGS) -I..
CFLAGS= $(OPT) $(CFLAGS_NO)
LDFLAGS= $(OPT)
ARCHIVE=ar r
RANLIB=ranlib
RM=rm -f
MV=mv
LN=ln -s
OBJS= fgetflags.o fsetflags.o fgetversion.o fsetversion.o \
getflags.o getversion.o iod.o ls.o pe.o pf.o ps.o \
setflags.o setversion.o
.c.o:
$(CC) $(CFLAGS) -c $*.c
$(CC) $(CFLAGS_NO) -pg -o profiled/$*.o -c $*.c
# $(CC) $(CFLAGS_NO) -checker -g -o checker/$*.o -c $*.c
all: libe2p.a libe2p_p.a
libe2p.a: $(OBJS)
$(RM) $@.bak
-$(MV) $@ $@.bak
$(ARCHIVE) $@ $(OBJS)
$(RANLIB) $@
$(RM) ../$@
$(LN) e2p/$@ ../$@
libe2p_p.a: $(OBJS)
$(RM) $@.bak
-$(MV) $@ $@.bak
(cd profiled; $(ARCHIVE) ../$@ $(OBJS))
$(RANLIB) $@
$(RM) ../$@
$(LN) e2p/$@ ../$@
libe2p_chk.a: $(OBJS)
$(RM) $@.bak
-$(MV) $@ $@.bak
(cd checker; $(ARCHIVE) ../$@ $(OBJS))
$(RANLIB) $@
$(RM) ../$@
$(LN) e2p/$@ ../$@
install:
clean:
rm -f \#* *.s *.o *.a *~ *.bak core profiled/* checker/*
really-clean: clean
rm -f .depend
dep depend .depend:
$(CC) -M $(CFLAGS) *.c >.depend
include .depend

20
lib/e2p/e2p.h Normal file
View File

@ -0,0 +1,20 @@
#include <dirent.h>
#include <stdio.h>
#include <linux/ext2_fs.h>
int fgetflags (const char * name, unsigned long * flags);
int fgetversion (const char * name, unsigned long * version);
int fsetflags (const char * name, unsigned long flags);
int fsetversion (const char * name, unsigned long version);
int getflags (int fd, unsigned long * flags);
int getversion (int fd, unsigned long * version);
int iterate_on_dir (const char * dir_name,
int (*func) (const char *, struct dirent *, void *),
void * private);
void list_super (struct ext2_super_block * s);
void print_fs_errors (FILE * f, unsigned short errors);
void print_flags (FILE * f, unsigned long flags);
void print_fs_state (FILE * f, unsigned short state);
int setflags (int fd, unsigned long flags);
int setversion (int fd, unsigned long version);

37
lib/e2p/fgetflags.c Normal file
View File

@ -0,0 +1,37 @@
/*
* fgetflags.c - Get a file flags on an ext2 file system
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/10/30 - Creation
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
int fgetflags (const char * name, unsigned long * flags)
{
int fd;
int r;
fd = open (name, O_RDONLY);
if (fd == -1)
return -1;
r = ioctl (fd, EXT2_IOC_GETFLAGS, flags);
close (fd);
return r;
}

37
lib/e2p/fgetversion.c Normal file
View File

@ -0,0 +1,37 @@
/*
* fgetversion.c - Get a file version on an ext2 file system
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/10/30 - Creation
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
int fgetversion (const char * name, unsigned long * version)
{
int fd;
int r;
fd = open (name, O_RDONLY);
if (fd == -1)
return - 1;
r = ioctl (fd, EXT2_IOC_GETVERSION, version);
close (fd);
return r;
}

37
lib/e2p/fsetflags.c Normal file
View File

@ -0,0 +1,37 @@
/*
* fsetflags.c - Set a file flags on an ext2 file system
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/10/30 - Creation
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
int fsetflags (const char * name, unsigned long flags)
{
int fd;
int r;
fd = open (name, O_RDONLY);
if (fd == -1)
return -1;
r = ioctl (fd, EXT2_IOC_SETFLAGS, &flags);
close (fd);
return r;
}

37
lib/e2p/fsetversion.c Normal file
View File

@ -0,0 +1,37 @@
/*
* fsetversion.c - Set a file version on an ext2 file system
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/10/30 - Creation
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
int fsetversion (const char * name, unsigned long version)
{
int fd;
int r;
fd = open (name, O_RDONLY);
if (fd == -1)
return -1;
r = ioctl (fd, EXT2_IOC_SETVERSION, &version);
close (fd);
return r;
}

27
lib/e2p/getflags.c Normal file
View File

@ -0,0 +1,27 @@
/*
* getflags.c - Get a file flags on an ext2 file system
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/10/30 - Creation
*/
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
int getflags (int fd, unsigned long * flags)
{
return ioctl (fd, EXT2_IOC_GETFLAGS, flags);
}

27
lib/e2p/getversion.c Normal file
View File

@ -0,0 +1,27 @@
/*
* getversion.c - Get a file version on an ext2 file system
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/10/30 - Creation
*/
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
int getversion (int fd, unsigned long * version)
{
return ioctl (fd, EXT2_IOC_GETVERSION, version);
}

42
lib/e2p/iod.c Normal file
View File

@ -0,0 +1,42 @@
/*
* iod.c - Iterate a function on each entry of a directory
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/10/30 - Creation
*/
#include <dirent.h>
#include "e2p.h"
int iterate_on_dir (const char * dir_name,
int (*func) (const char *, struct dirent *, void *),
void * private)
{
DIR * dir;
struct dirent de;
struct dirent *dep;
dir = opendir (dir_name);
if (dir == NULL)
return -1;
while ((dep = readdir (dir)))
{
de.d_ino = dep->d_ino;
de.d_off = dep->d_off;
de.d_reclen = dep->d_reclen;
strcpy (de.d_name, dep->d_name);
(*func) (dir_name, &de, private);
}
closedir (dir);
return 0;
}

52
lib/e2p/ls.c Normal file
View File

@ -0,0 +1,52 @@
/*
* ls.c - List the contents of an ext2fs superblock
*
* Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
#include <stdio.h>
#include <time.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
void list_super (struct ext2_super_block * s)
{
printf ("Filesystem magic number: 0x%04X\n", s->s_magic);
printf ("Filesystem state: ");
print_fs_state (stdout, s->s_state);
printf ("\n");
printf ("Errors behavior: ");
print_fs_errors (stdout, s->s_errors);
printf ("\n");
printf ("Inode count: %lu\n", s->s_inodes_count);
printf ("Block count: %lu\n", s->s_blocks_count);
printf ("Reserved block count: %lu\n", s->s_r_blocks_count);
printf ("Free blocks: %lu\n", s->s_free_blocks_count);
printf ("Free inodes: %lu\n", s->s_free_inodes_count);
printf ("First block: %lu\n", s->s_first_data_block);
printf ("Block size: %u\n", EXT2_BLOCK_SIZE(s));
printf ("Fragment size: %u\n", EXT2_FRAG_SIZE(s));
printf ("Blocks per group: %lu\n", s->s_blocks_per_group);
printf ("Fragments per group: %lu\n", s->s_frags_per_group);
printf ("Inodes per group: %lu\n", s->s_inodes_per_group);
printf ("Last mount time: %s", ctime ((time_t *) &s->s_mtime));
printf ("Last write time: %s", ctime ((time_t *) &s->s_wtime));
printf ("Mount count: %u\n", s->s_mnt_count);
printf ("Maximum mount count: %d\n", s->s_max_mnt_count);
printf ("Last checked: %s", ctime ((time_t *) &s->s_lastcheck));
printf ("Check interval: %lu\n", s->s_checkinterval);
if (s->s_checkinterval)
{
time_t next;
next = s->s_lastcheck + s->s_checkinterval;
printf ("Next check after: %s", ctime (&next));
}
}

39
lib/e2p/pe.c Normal file
View File

@ -0,0 +1,39 @@
/*
* pe.c - Print a second extended filesystem errors behavior
*
* Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 94/01/09 - Creation
*/
#include <stdio.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
void print_fs_errors (FILE * f, unsigned short errors)
{
switch (errors)
{
case EXT2_ERRORS_CONTINUE:
fprintf (f, "Continue");
break;
case EXT2_ERRORS_RO:
fprintf (f, "Remount read-only");
break;
case EXT2_ERRORS_PANIC:
fprintf (f, "Panic");
break;
default:
fprintf (f, "Unknown (continue)");
}
}

40
lib/e2p/pf.c Normal file
View File

@ -0,0 +1,40 @@
/*
* pf.c - Print file attributes on an ext2 file system
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/10/30 - Creation
*/
#include <stdio.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
void print_flags (FILE * f, unsigned long flags)
{
if (flags & EXT2_SYNC_FL)
fprintf (f, "S");
else
fprintf (f, "-");
if (flags & EXT2_COMPR_FL)
fprintf (f, "c");
else
fprintf (f, "-");
if (flags & EXT2_SECRM_FL)
fprintf (f, "s");
else
fprintf (f, "-");
if (flags & EXT2_UNRM_FL)
fprintf (f, "u");
else
fprintf (f, "-");
}

31
lib/e2p/ps.c Normal file
View File

@ -0,0 +1,31 @@
/*
* ps.c - Print filesystem state
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/12/22 - Creation
*/
#include <stdio.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
void print_fs_state (FILE * f, unsigned short state)
{
if (state & EXT2_VALID_FS)
fprintf (f, " clean");
else
fprintf (f, " not clean");
if (state & EXT2_ERROR_FS)
fprintf (f, " with errors");
}

27
lib/e2p/setflags.c Normal file
View File

@ -0,0 +1,27 @@
/*
* setflags.c - Set a file flags on an ext2 file system
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/10/30 - Creation
*/
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
int setflags (int fd, unsigned long flags)
{
return ioctl (fd, EXT2_IOC_SETFLAGS, &flags);
}

27
lib/e2p/setversion.c Normal file
View File

@ -0,0 +1,27 @@
/*
* setversion.c - Set a file version on an ext2 file system
*
* Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
/*
* History:
* 93/10/30 - Creation
*/
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/ext2_fs.h>
#include "e2p.h"
int setversion (int fd, unsigned long version)
{
return ioctl (fd, EXT2_IOC_SETVERSION, &version);
}

13
lib/et/.depend Normal file
View File

@ -0,0 +1,13 @@
com_err.o : com_err.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h mit-sipb-copyright.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
error_table.h internal.h /usr/include/errno.h /usr/include/linux/errno.h com_err.h
error_message.o : error_message.c /usr/include/stdio.h /usr/include/features.h \
/usr/include/sys/cdefs.h /usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h error_table.h mit-sipb-copyright.h \
internal.h /usr/include/errno.h /usr/include/linux/errno.h
et_name.o : et_name.c error_table.h mit-sipb-copyright.h internal.h /usr/include/errno.h \
/usr/include/features.h /usr/include/sys/cdefs.h /usr/include/linux/errno.h
init_et.o : init_et.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h error_table.h mit-sipb-copyright.h
vfprintf.o : vfprintf.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/varargs.h

85
lib/et/Makefile Normal file
View File

@ -0,0 +1,85 @@
include ../../MCONFIG
ARCHIVE=ar r
RANLIB=ranlib
RM=rm -f
MV=mv
LN=ln -s
TAGS=etags
CFLAGS_NO=
CFLAGS= $(CFLAGS_NO) $(OPT)
OBJS= error_message.o et_name.o init_et.o com_err.o
SRCS = error_message.c et_name.c init_et.c com_err.c
HFILES= com_err.h
#
# what to build...
#
.c.o:
$(CC) $(CFLAGS) -c $*.c
$(CC) $(CFLAGS_NO) -g -pg -o profiled/$*.o -c $*.c
all: compile_et libcom_err.a libcom_err_p.a
compile_et: compile_et.sh
./config_script compile_et.sh $(AWK) > compile_et
chmod +x compile_et
libcom_err.a: $(OBJS)
$(RM) $@.bak
-$(MV) $@ $@.bak
$(ARCHIVE) $@ $(OBJS)
$(RANLIB) $@
$(RM) ../$@
$(LN) et/$@ ../$@
libcom_err_p.a: $(OBJS)
$(RM) $@.bak
-$(MV) $@ $@.bak
(cd profiled ; $(ARCHIVE) ../$@ $(OBJS))
$(RANLIB) $@
$(RM) ../$@
$(LN) et/$@ ../$@
clean:
$(RM) compile_et libcom_err.a libcom_err_p.a
$(RM) $(OBJS) profiled/*
$(RM) *~ \#* *.bak *.otl *.aux *.toc *.PS *.dvi *.ps TAGS *.ln
really-clean: clean
$(RM) .depend
install:: libcom_err.a
$(INSTALLLIB) libcom_err.a $(DESTDIR)$(LIBDIR)/libcom_err.a
$(CHMOD) 644 $(DESTDIR)$(LIBDIR)/libcom_err.a
$(RANLIB) $(DESTDIR)$(LIBDIR)/libcom_err.a
$(CHMOD) $(LIBMODE) $(DESTDIR)$(LIBDIR)/libcom_err.a
install:: $(HFILES)
@rm -rf ${DESTDIR}$(INCLDIR)/et
@mkdir ${DESTDIR}$(INCLDIR)/et
for i in $(HFILES); do \
$(INSTALLINC) $$i ${DESTDIR}$(INCLDIR)/et/$$i; \
done
##
com_err.ps : com_err.dvi
com_err.dvi: com_err.texinfo
libcom_err.o: $(LIBOBJS)
ld -r -s -o libcom_err.o $(LIBOBJS)
chmod -x libcom_err.o
TAGS: $(SRCS)
$(TAGS) $(SRCS)
dep depend .depend: compile_et
$(CPP) -M $(CFLAGS) *.c >.depend
include .depend

96
lib/et/com_err.3 Normal file
View File

@ -0,0 +1,96 @@
.\" Copyright (c) 1988 Massachusetts Institute of Technology,
.\" Student Information Processing Board. All rights reserved.
.\"
.\" $Header$
.\"
.TH COM_ERR 3 "22 Nov 1988" SIPB
.SH NAME
com_err \- common error display routine
.SH SYNOPSIS
.nf
#include <com_err.h>
.PP
void com_err (whoami, code, format, ...);
const char *whoami;
long code;
const char *format;
.PP
proc = set_com_err_hook (proc);
.fi
void (*
.I proc
) (const char *, long, const char *, va_list);
.nf
.PP
proc = reset_com_err_hook ();
.PP
void initialize_XXXX_error_table ();
.fi
.SH DESCRIPTION
.I Com_err
displays an error message on the standard error stream
.I stderr
(see
.IR stdio (3S))
composed of the
.I whoami
string, which should specify the program name or some subportion of
a program, followed by an error message generated from the
.I code
value (derived from
.IR compile_et (1)),
and a string produced using the
.I format
string and any following arguments, in the same style as
.IR fprintf (3).
The behavior of
.I com_err
can be modified using
.I set_com_err_hook;
this defines a procedure which is called with the arguments passed to
.I com_err,
instead of the default internal procedure which sends the formatted
text to error output. Thus the error messages from a program can all
easily be diverted to another form of diagnostic logging, such as
.IR syslog (3).
.I Reset_com_err_hook
may be used to restore the behavior of
.I com_err
to its default form. Both procedures return the previous ``hook''
value. These ``hook'' procedures must have the declaration given for
.I proc
above in the synopsis.
The
.I initialize_XXXX_error_table
routine is generated mechanically by
.IR compile_et (1)
from a source file containing names and associated strings. Each
table has a name of up to four characters, which is used in place of
the
.B XXXX
in the name of the routine. These routines should be called before
any of the corresponding error codes are used, so that the
.I com_err
library will recognize error codes from these tables when they are
used.
The
.B com_err.h
header file should be included in any source file that uses routines
from the
.I com_err
library; executable files must be linked using
.I ``-lcom_err''
in order to cause the
.I com_err
library to be included.
.\" .IR for manual entries
.\" .PP for paragraph breaks
.SH "SEE ALSO"
compile_et (1), syslog (3).
Ken Raeburn, "A Common Error Description Library for UNIX".

127
lib/et/com_err.c Normal file
View File

@ -0,0 +1,127 @@
/*
* Copyright 1987, 1988 by MIT Student Information Processing Board.
*
* For copyright info, see mit-sipb-copyright.h.
*/
#include <stdio.h>
#include "mit-sipb-copyright.h"
#if __STDC__ || defined(STDARG_PROTOTYPES)
#include <stdarg.h>
#else
#include <varargs.h>
#define VARARGS
#endif
#include "error_table.h"
#include "internal.h"
#ifdef notdef
/*
* Protect us from header version (externally visible) of com_err, so
* we can survive in a <varargs.h> environment. I think.
*/
#define com_err com_err_external
#include "com_err.h"
#undef com_err
#else
#include "com_err.h"
#endif
#if ! lint
static const char rcsid[] =
"$Header$";
#endif /* ! lint */
static void
#ifdef __STDC__
default_com_err_proc (const char *whoami, long code, const char *fmt, va_list args)
#else
default_com_err_proc (whoami, code, fmt, args)
const char *whoami;
long code;
const char *fmt;
va_list args;
#endif
{
if (whoami) {
fputs(whoami, stderr);
fputs(": ", stderr);
}
if (code) {
fputs(error_message(code), stderr);
fputs(" ", stderr);
}
if (fmt) {
vfprintf (stderr, fmt, args);
}
putc('\n', stderr);
/* should do this only on a tty in raw mode */
putc('\r', stderr);
fflush(stderr);
}
#ifdef __STDC__
typedef void (*errf) (const char *, long, const char *, va_list);
#else
typedef void (*errf) ();
#endif
errf com_err_hook = default_com_err_proc;
void com_err_va (whoami, code, fmt, args)
const char *whoami;
long code;
const char *fmt;
va_list args;
{
(*com_err_hook) (whoami, code, fmt, args);
}
#ifndef VARARGS
void com_err (const char *whoami,
long code,
const char *fmt, ...)
{
#else
void com_err (va_alist)
va_dcl
{
const char *whoami, *fmt;
long code;
#endif
va_list pvar;
if (!com_err_hook)
com_err_hook = default_com_err_proc;
#ifdef VARARGS
va_start (pvar);
whoami = va_arg (pvar, const char *);
code = va_arg (pvar, long);
fmt = va_arg (pvar, const char *);
#else
va_start(pvar, fmt);
#endif
com_err_va (whoami, code, fmt, pvar);
va_end(pvar);
}
errf set_com_err_hook (new_proc)
errf new_proc;
{
errf x = com_err_hook;
if (new_proc)
com_err_hook = new_proc;
else
com_err_hook = default_com_err_proc;
return x;
}
errf reset_com_err_hook () {
errf x = com_err_hook;
com_err_hook = default_com_err_proc;
return x;
}

38
lib/et/com_err.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Header file for common error description library.
*
* Copyright 1988, Student Information Processing Board of the
* Massachusetts Institute of Technology.
*
* For copyright and distribution info, see the documentation supplied
* with this package.
*/
#ifndef __COM_ERR_H
typedef long errcode_t;
#ifdef __STDC__
#ifndef __HIGHC__ /* gives us STDC but not stdarg */
#include <stdarg.h>
#else
#include <varargs.h>
#endif
/* ANSI C -- use prototypes etc */
void com_err (const char *, long, const char *, ...);
char const *error_message (long);
void (*com_err_hook) (const char *, long, const char *, va_list);
void (*set_com_err_hook (void (*) (const char *, long, const char *, va_list)))
(const char *, long, const char *, va_list);
void (*reset_com_err_hook (void)) (const char *, long, const char *, va_list);
#else
/* no prototypes */
void com_err ();
char *error_message ();
void (*com_err_hook) ();
void (*set_com_err_hook ()) ();
void (*reset_com_err_hook ()) ();
#endif
#define __COM_ERR_H
#endif /* ! defined(__COM_ERR_H) */

554
lib/et/com_err.texinfo Normal file
View File

@ -0,0 +1,554 @@
\input texinfo @c -*-texinfo-*-
@c $Header$
@c $Source$
@c $Locker$
@c Note that although this source file is in texinfo format (more
@c or less), it is not yet suitable for turning into an ``info''
@c file. Sorry, maybe next time.
@c
@c In order to produce hardcopy documentation from a texinfo file,
@c run ``tex com_err.texinfo'' which will load in texinfo.tex,
@c provided in this distribution. (texinfo.tex is from the Free
@c Software Foundation, and is under different copyright restrictions
@c from the rest of this package.)
@ifinfo
@barfo
@end ifinfo
@iftex
@tolerance 10000
@c Mutate section headers...
@begingroup
@catcode#=6
@gdef@secheading#1#2#3{@secheadingi {#3@enspace #1}}
@endgroup
@end iftex
@setfilename com_err
@settitle A Common Error Description Library for UNIX
@ifinfo
This file documents the use of the Common Error Description library.
Copyright (C) 1987, 1988 Student Information Processing Board of the
Massachusetts Institute of Technology.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
used in advertising or publicity pertaining to distribution of the software
without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
make no representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied warranty.
Note that the file texinfo.tex, provided with this distribution, is from
the Free Software Foundation, and is under different copyright restrictions
from the remainder of this package.
@end ifinfo
@ignore
Permission is granted to process this file through Tex and print the
results, provided the printed document carries copying permission
notice identical to this one except for the removal of this paragraph
(this paragraph not being relevant to the printed manual).
@end ignore
@setchapternewpage odd
@titlepage
@center @titlefont{A Common Error Description}
@center @titlefont{Library for UNIX}
@sp 2
@center Ken Raeburn
@center Bill Sommerfeld
@sp 1
@center MIT Student Information Processing Board
@sp 3
@center last updated 1 January 1989
@center for version 1.2
@center ***DRAFT COPY ONLY***
@vskip 2in
@center @b{Abstract}
UNIX has always had a clean and simple system call interface, with a
standard set of error codes passed between the kernel and user
programs. Unfortunately, the same cannot be said of many of the
libraries layered on top of the primitives provided by the kernel.
Typically, each one has used a different style of indicating errors to
their callers, leading to a total hodgepodge of error handling, and
considerable amounts of work for the programmer. This paper describes
a library and associated utilities which allows a more uniform way for
libraries to return errors to their callers, and for programs to
describe errors and exceptional conditions to their users.
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1987, 1988 by the Student Information Processing
Board of the Massachusetts Institute of Technology.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
used in advertising or publicity pertaining to distribution of the software
without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
make no representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied warranty.
Note that the file texinfo.tex, provided with this distribution, is from
the Free Software Foundation, and is under different copyright restrictions
from the remainder of this package.
@end titlepage
@ifinfo
@c should put a menu here someday....
@end ifinfo
@page
@section Why com_err?
In building application software packages, a programmer often has to
deal with a number of libraries, each of which can use a different
error-reporting mechanism. Sometimes one of two values is returned,
indicating simply SUCCESS or FAILURE, with no description of errors
encountered. Sometimes it is an index into a table of text strings,
where the name of the table used is dependent on the library being
used when the error is generated; since each table starts numbering at
0 or 1, additional information as to the source of the error code is
needed to determine which table to look at. Sometimes no text messages are
supplied at all, and the programmer must supply them at any point at which
he may wish to report error conditions.
Often, a global variable is assigned some value describing the error, but
the programmer has to know in each case whether to look at @code{errno},
@code{h_errno}, the return value from @code{hes_err()}, or whatever other
variables or routines are specified.
And what happens if something
in the procedure of
examining or reporting the error changes the same variable?
The package we have developed is an attempt to present a common
error-handling mechanism to manipulate the most common form of error code
in a fashion that does not have the problems listed above.
A list of up to 256 text messages is supplied to a translator we have
written, along with the three- to four-character ``name'' of the error
table. The library using this error table need only call a routine
generated from this error-table source to make the table ``known'' to the
com_err library, and any error code the library generates can be converted
to the corresponding error message. There is also a default format for
error codes accidentally returned before making the table known, which is
of the form @samp{unknown code foo 32}, where @samp{foo} would be the name
of the table.
@section Error codes
Error codes themselves are 32 bit (signed) integers, of which the high
order 24 bits are an identifier of which error table the error code is
from, and the low order 8 bits are a sequential error number within
the table. An error code may thus be easily decomposed into its component
parts. Only the lowest 32 bits of an error code are considered significant
on systems which support wider values.
Error table 0 is defined to match the UNIX system call error table
(@code{sys_errlist}); this allows @code{errno} values to be used directly
in the library (assuming that @code{errno} is of a type with the same width
as @t{long}). Other error table numbers are formed by compacting together
the first four characters of the error table name. The mapping between
characters in the name and numeric values in the error code are defined in
a system-independent fashion, so that two systems that can pass integral
values between them can reliably pass error codes without loss of meaning;
this should work even if the character sets used are not the same.
(However, if this is to be done, error table 0 should be avoided, since the
local system call error tables may differ.)
Any variable which is to contain an error code should be declared @t{long}.
The draft proposed American National Standard for C (as of May, 1988)
requires that @t{long} variables be at least 32 bits; any system which does
not support 32-bit @t{long} values cannot make use of this package (nor
much other software that assumes an ANSI-C environment base) without
significant effort.
@section Error table source file
The error table source file begins with the declaration of the table name,
as
@example
error_table @var{tablename}
@end example
Individual error codes are
specified with
@example
error_code @var{ERROR_NAME}, @var{"text message"}
@end example
where @samp{ec} can also be used as a short form of @samp{error_code}. To
indicate the end of the table, use @samp{end}. Thus, a (short) sample
error table might be:
@example
error_table dsc
error_code DSC_DUP_MTG_NAME,
"Meeting already exists"
ec DSC_BAD_PATH,
"A bad meeting pathname was given"
ec DSC_BAD_MODES,
"Invalid mode for this access control list"
end
@end example
@section The error-table compiler
The error table compiler is named @code{compile_et}. It takes one
argument, the pathname of a file (ending in @samp{.et}, e.g.,
@samp{dsc_err.et}) containing an error table source file. It parses the
error table, and generates two output files -- a C header file
(@samp{discuss_err.h}) which contains definitions of the numerical values
of the error codes defined in the error table, and a C source file which
should be compiled and linked with the executable. The header file must be
included in the source of a module which wishes to reference the error
codes defined; the object module generated from the C code may be linked in
to a program which wishes to use the printed forms of the error codes.
This translator accepts a @kbd{-language @var{lang}} argument, which
determines for which language (or language variant) the output should be
written. At the moment, @var{lang} is currently limited to @kbd{ANSI-C}
and @kbd{K&R-C}, and some abbreviated forms of each. Eventually, this will
be extended to include some support for C++. The default is currently
@kbd{K&R-C}, though the generated sources will have ANSI-C code
conditionalized on the symbol @t{__STDC__}.
@section Run-time support routines
Any source file which uses the routines supplied with or produced by the
com_err package should include the header file @file{<com_err.h>}. It
contains declarations and definitions which may be needed on some systems.
(Some functions cannot be referenced properly without the return type
declarations in this file. Some functions may work properly on most
architectures even without the header file, but relying on this is not
recommended.)
The run-time support routines and variables provided via this package
include the following:
@example
void initialize_@var{xxxx}_error_table (void);
@end example
One of these routines is built by the error compiler for each error table.
It makes the @var{xxxx} error table ``known'' to the error reporting
system. By convention, this routine should be called in the initialization
routine of the @var{xxxx} library. If the library has no initialization
routine, some combination of routines which form the core of the library
should ensure that this routine is called. It is not advised to leave it
the caller to make this call.
There is no harm in calling this routine more than once.
@example
#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L
@end example
This symbol contains the value of the first error code entry in the
specified table.
This rarely needs be used by the
programmer.
@example
const char *error_message (long code);
@end example
This routine returns the character string error message associated
with @code{code}; if this is associated with an unknown error table, or
if the code is associated with a known error table but the code is not
in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is
returned, where @var{xxxx} is the error table name produced by
reversing the compaction performed on the error table number implied
by that error code, and @var{nn} is the offset from that base value.
Although this routine is available for use when needed, its use should be
left to circumstances which render @code{com_err} (below) unusable.
@example
void com_err (const char *whoami, /* module reporting error */
long code, /* error code */
const char *format, /* format for additional detail */
...); /* (extra parameters) */
@end example
This routine provides an alternate way to print error messages to
standard error; it allows the error message to be passed in as a
parameter, rather than in an external variable. @emph{Provide grammatical
context for ``message.''}
If @var{format} is @code{(char *)NULL}, the formatted message will not be
printed. @var{format} may not be omitted.
@example
#include <stdarg.h>
void com_err_va (const char *whoami,
long code,
const char *format,
va_list args);
@end example
This routine provides an interface, equivalent to @code{com_err} above,
which may be used by higher-level variadic functions (functions which
accept variable numbers of arguments).
@example
#include <stdarg.h>
void (*set_com_err_hook (void (*proc) ())) ();
void (*@var{proc}) (const char *whoami, long code, va_list args);
void reset_com_err_hook ();
@end example
These two routines allow a routine to be dynamically substituted for
@samp{com_err}. After @samp{set_com_err_hook} has been called,
calls to @samp{com_err} will turn into calls to the new hook routine.
@samp{reset_com_err_hook} turns off this hook. This may intended to
be used in daemons (to use a routine which calls @var{syslog(3)}), or
in a window system application (which could pop up a dialogue box).
If a program is to be used in an environment in which simply printing
messages to the @code{stderr} stream would be inappropriate (such as in a
daemon program which runs without a terminal attached),
@code{set_com_err_hook} may be used to redirect output from @code{com_err}.
The following is an example of an error handler which uses @var{syslog(3)}
as supplied in BSD 4.3:
@example
#include <stdio.h>
#include <stdarg.h>
#include <syslog.h>
/* extern openlog (const char * name, int logopt, int facility); */
/* extern syslog (int priority, char * message, ...); */
void hook (const char * whoami, long code,
const char * format, va_list args)
@{
char buffer[BUFSIZ];
static int initialized = 0;
if (!initialized) @{
openlog (whoami,
LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY,
LOG_DAEMON);
initialized = 1;
@}
vsprintf (buffer, format, args);
syslog (LOG_ERR, "%s %s", error_message (code), buffer);
@}
@end example
After making the call
@code{set_com_err_hook (hook);},
any calls to @code{com_err} will result in messages being sent to the
@var{syslogd} daemon for logging.
The name of the program, @samp{whoami}, is supplied to the
@samp{openlog()} call, and the message is formatted into a buffer and
passed to @code{syslog}.
Note that since the extra arguments to @code{com_err} are passed by
reference via the @code{va_list} value @code{args}, the hook routine may
place any form of interpretation on them, including ignoring them. For
consistency, @code{printf}-style interpretation is suggested, via
@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for
the ANSI C library).
@section Coding Conventions
The following conventions are just some general stylistic conventions
to follow when writing robust libraries and programs. Conventions
similar to this are generally followed inside the UNIX kernel and most
routines in the Multics operating system. In general, a routine
either succeeds (returning a zero error code, and doing some side
effects in the process), or it fails, doing minimal side effects; in
any event, any invariant which the library assumes must be maintained.
In general, it is not in the domain of non user-interface library
routines to write error messages to the user's terminal, or halt the
process. Such forms of ``error handling'' should be reserved for
failures of internal invariants and consistancy checks only, as it
provides the user of the library no way to clean up for himself in the
event of total failure.
Library routines which can fail should be set up to return an error
code. This should usually be done as the return value of the
function; if this is not acceptable, the routine should return a
``null'' value, and put the error code into a parameter passed by
reference.
Routines which use the first style of interface can be used from
user-interface levels of a program as follows:
@example
@{
if ((code = initialize_world(getuid(), random())) != 0) @{
com_err("demo", code,
"when trying to initialize world");
exit(1);
@}
if ((database = open_database("my_secrets", &code))==NULL) @{
com_err("demo", code,
"while opening my_secrets");
exit(1);
@}
@}
@end example
A caller which fails to check the return status is in error. It is
possible to look for code which ignores error returns by using lint;
look for error messages of the form ``foobar returns value which is
sometimes ignored'' or ``foobar returns value which is always
ignored.''
Since libraries may be built out of other libraries, it is often necessary
for the success of one routine to depend on another. When a lower level
routine returns an error code, the middle level routine has a few possible
options. It can simply return the error code to its caller after doing
some form of cleanup, it can substitute one of its own, or it can take
corrective action of its own and continue normally. For instance, a
library routine which makes a ``connect'' system call to make a network
connection may reflect the system error code @code{ECONNREFUSED}
(Connection refused) to its caller, or it may return a ``server not
available, try again later,'' or it may try a different server.
Cleanup which is typically necessary may include, but not be limited
to, freeing allocated memory which will not be needed any more,
unlocking concurrancy locks, dropping reference counts, closing file
descriptors, or otherwise undoing anything which the procedure did up
to this point. When there are a lot of things which can go wrong, it
is generally good to write one block of error-handling code which is
branched to, using a goto, in the event of failure. A common source
of errors in UNIX programs is failing to close file descriptors on
error returns; this leaves a number of ``zombied'' file descriptors
open, which eventually causes the process to run out of file
descriptors and fall over.
@example
@{
FILE *f1=NULL, *f2=NULL, *f3=NULL;
int status = 0;
if ( (f1 = fopen(FILE1, "r")) == NULL) @{
status = errno;
goto error;
@}
/*
* Crunch for a while
*/
if ( (f2 = fopen(FILE2, "w")) == NULL) @{
status = errno;
goto error;
@}
if ( (f3 = fopen(FILE3, "a+")) == NULL) @{
status = errno;
goto error;
@}
/*
* Do more processing.
*/
fclose(f1);
fclose(f2);
fclose(f3);
return 0;
error:
if (f1) fclose(f1);
if (f2) fclose(f2);
if (f3) fclose(f3);
return status;
@}
@end example
@section Building and Installation
The distribution of this package will probably be done as a compressed
``tar''-format file available via anonymous FTP from SIPB.MIT.EDU.
Retrieve @samp{pub/com_err.tar.Z} and extract the contents. A subdirectory
@t{profiled} should be created to hold objects compiled for profiling.
Running ``make all'' should then be sufficient to build the library and
error-table compiler. The files @samp{libcom_err.a},
@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be
installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be
installed as manual pages.
Potential problems:
@itemize @bullet
@item Use of @code{strcasecmp}, a routine provided in BSD for
case-insensitive string comparisons. If an equivalent routine is
available, you can modify @code{CFLAGS} in the makefile to define
@code{strcasecmp} to the name of that routine.
@item Compilers that defined @code{__STDC__} without providing the header
file @code{<stdarg.h>}. One such example is Metaware's High ``C''
compiler, as provided at Project Athena on the IBM RT/PC workstation; if
@code{__HIGHC__} is defined, it is assumed that @code{<stdarg.h>} is not
available, and therefore @code{<varargs.h>} must be used. If the symbol
@code{VARARGS} is defined (e.g., in the makefile), @code{<varargs.h>} will
be used.
@item If your linker rejects symbols that are simultaneously defined in two
library files, edit @samp{Makefile} to remove @samp{perror.c} from the
library. This file contains a version of @var{perror(3)} which calls
@code{com_err} instead of calling @code{write} directly.
@end itemize
As I do not have access to non-BSD systems, there are probably
bugs present that may interfere with building or using this package on
other systems. If they are reported to me, they can probably be fixed for
the next version.
@section Bug Reports
Please send any comments or bug reports to the principal author: Ken
Raeburn, @t{Raeburn@@Athena.MIT.EDU}.
@section Acknowledgements
I would like to thank: Bill Sommerfeld, for his help with some of this
documentation, and catching some of the bugs the first time around;
Honeywell Information Systems, for not killing off the @emph{Multics}
operating system before I had an opportunity to use it; Honeywell's
customers, who persuaded them not to do so, for a while; Ted Anderson of
CMU, for catching some problems before version 1.2 left the nest; Stan
Zanarotti and several others of MIT's Student Information Processing Board,
for getting us started with ``discuss,'' for which this package was
originally written; and everyone I've talked into --- I mean, asked to read
this document and the ``man'' pages.
@bye

79
lib/et/compile_et.1 Normal file
View File

@ -0,0 +1,79 @@
.\" Copyright (c) 1988 Massachusetts Institute of Technology,
.\" Student Information Processing Board. All rights reserved.
.\"
.\" $Header$
.\"
.TH COMPILE_ET 1 "22 Nov 1988" SIPB
.SH NAME
compile_et \- error table compiler
.SH SYNOPSIS
.B compile_et
file
.SH DESCRIPTION
.B Compile_et
converts a table listing error-code names and associated messages into
a C source file suitable for use with the
.IR com_err (3)
library.
The source file name must end with a suffix of ``.et''; the file
consists of a declaration supplying the name (up to four characters
long) of the error-code table:
.B error_table
.I name
followed by up to 256 entries of the form:
.B error_code
.I name,
"
.I string
"
and a final
.B end
to indicate the end of the table.
The name of the table is used to construct the name of a subroutine
.I initialize_XXXX_error_table
which must be called in order for the
.I com_err
library to recognize the error table.
The various error codes defined are assigned sequentially increasing
numbers (starting with a large number computed as a hash function of
the name of the table); thus for compatibility it is suggested that
new codes be added only to the end of an existing table, and that no
codes be removed from tables.
The names defined in the table are placed into a C header file with
preprocessor directives defining them as integer constants of up to
32 bits in magnitude.
A C source file is also generated which should be compiled and linked
with the object files which reference these error codes; it contains
the text of the messages and the initialization subroutine. Both C
files have names derived from that of the original source file, with
the ``.et'' suffix replaced by ``.c'' and ``.h''.
A ``#'' in the source file is treated as a comment character, and all
remaining text to the end of the source line will be ignored.
.SH BUGS
Since
.B compile_et
uses a very simple parser based on
.IR yacc (1),
its error recovery leaves much to be desired.
.\" .IR for manual entries
.\" .PP for paragraph breaks
.SH "SEE ALSO"
com_err (3).
Ken Raeburn, "A Common Error Description Library for UNIX".

11
lib/et/compile_et.sh Normal file
View File

@ -0,0 +1,11 @@
#!/bin/sh
#
#
AWK=@AWK@
DIR=@DIR@
ROOT=`echo $1 | sed -e s/.et$//`
BASE=`basename $ROOT`
$AWK -f ${DIR}/et_h.awk outfile=${BASE}.h $ROOT.et
$AWK -f ${DIR}/et_c.awk outfile=${BASE}.c $ROOT.et

25
lib/et/config_script Normal file
View File

@ -0,0 +1,25 @@
#!/bin/sh
#
# This program takes a shell script and configures for the following
# variables: @DIR@
# @AWK@
# @SED@
#
# Usage: config_script <filename> [<awk>] [<sed>]
#
FILE=$1
AWK=$2
SED=$3
# Grr.... not all Unix's have the dirname command
TMP=`echo $1 | sed -e 's;[^/]*$;;' -e 's/^$/./'`
DIR=`cd ${TMP}; pwd`
if test "${AWK}x" = "x" ; then
AWK=awk
fi
if test "${SED}x" = "x" ; then
SED=sed
fi
sed -e "s;@DIR@;${DIR};" -e "s;@AWK@;${AWK};" -e "s;@SED@;${SED};" $FILE

72
lib/et/error_message.c Normal file
View File

@ -0,0 +1,72 @@
/*
* $Header$
* $Source$
* $Locker$
*
* Copyright 1987 by the Student Information Processing Board
* of the Massachusetts Institute of Technology
*
* For copyright info, see "mit-sipb-copyright.h".
*/
#include <stdio.h>
#include <string.h>
#include "error_table.h"
#include "mit-sipb-copyright.h"
#include "internal.h"
static const char rcsid[] =
"$Header$";
static const char copyright[] =
"Copyright 1986, 1987, 1988 by the Student Information Processing Board\nand the department of Information Systems\nof the Massachusetts Institute of Technology";
static char buffer[25];
struct et_list * _et_list = (struct et_list *) NULL;
const char * error_message (code)
long code;
{
int offset;
struct et_list *et;
int table_num;
int started = 0;
char *cp;
offset = code & ((1<<ERRCODE_RANGE)-1);
table_num = code - offset;
if (!table_num) {
if (offset < sys_nerr)
return(sys_errlist[offset]);
else
goto oops;
}
for (et = _et_list; et; et = et->next) {
if (et->table->base == table_num) {
/* This is the right table */
if (et->table->n_msgs <= offset)
goto oops;
return(et->table->msgs[offset]);
}
}
oops:
strcpy (buffer, "Unknown code ");
if (table_num) {
strcat (buffer, error_table_name (table_num));
strcat (buffer, " ");
}
for (cp = buffer; *cp; cp++)
;
if (offset >= 100) {
*cp++ = '0' + offset / 100;
offset %= 100;
started++;
}
if (started || offset >= 10) {
*cp++ = '0' + offset / 10;
offset %= 10;
}
*cp++ = '0' + offset;
*cp = '\0';
return(buffer);
}

30
lib/et/error_table.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright 1988 by the Student Information Processing Board of the
* Massachusetts Institute of Technology.
*
* For copyright info, see mit-sipb-copyright.h.
*/
#ifndef _ET_H
/* Are we using ANSI C? */
#ifndef __STDC__
#define const
#endif
extern int errno;
struct error_table {
char const * const * msgs;
long base;
int n_msgs;
};
struct et_list {
struct et_list *next;
const struct error_table *table;
};
extern struct et_list * _et_list;
#define ERRCODE_RANGE 8 /* # of bits to shift table number */
#define BITS_PER_CHAR 6 /* # bits to shift per character in name */
extern const char *error_table_name();
#define _ET_H
#endif

185
lib/et/et_c.awk Normal file
View File

@ -0,0 +1,185 @@
BEGIN {
char_shift=64
## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
c2n["A"]=1
c2n["B"]=2
c2n["C"]=3
c2n["D"]=4
c2n["E"]=5
c2n["F"]=6
c2n["G"]=7
c2n["H"]=8
c2n["I"]=9
c2n["J"]=10
c2n["K"]=11
c2n["L"]=12
c2n["M"]=13
c2n["N"]=14
c2n["O"]=15
c2n["P"]=16
c2n["Q"]=17
c2n["R"]=18
c2n["S"]=19
c2n["T"]=20
c2n["U"]=21
c2n["V"]=22
c2n["W"]=23
c2n["X"]=24
c2n["Y"]=25
c2n["Z"]=26
c2n["a"]=27
c2n["b"]=28
c2n["c"]=29
c2n["d"]=30
c2n["e"]=31
c2n["f"]=32
c2n["g"]=33
c2n["h"]=34
c2n["i"]=35
c2n["j"]=36
c2n["k"]=37
c2n["l"]=38
c2n["m"]=39
c2n["n"]=40
c2n["o"]=41
c2n["p"]=42
c2n["q"]=43
c2n["r"]=44
c2n["s"]=45
c2n["t"]=46
c2n["u"]=47
c2n["v"]=48
c2n["w"]=49
c2n["x"]=50
c2n["y"]=51
c2n["z"]=52
c2n["0"]=53
c2n["1"]=54
c2n["2"]=55
c2n["3"]=56
c2n["4"]=57
c2n["5"]=58
c2n["6"]=59
c2n["7"]=60
c2n["8"]=61
c2n["9"]=62
c2n["_"]=63
}
/^#/ { next }
/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
table_number = 0
table_name = $2
mod_base = 1000000
for(i=1; i<=length(table_name); i++) {
table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
}
# We start playing *_high, *low games here because the some
# awk programs do not have the necessary precision (sigh)
tab_base_low = table_number % mod_base
tab_base_high = int(table_number / mod_base)
tab_base_sign = 1;
# figure out: table_number_base=table_number*256
tab_base_low = tab_base_low * 256
tab_base_high = (tab_base_high * 256) + \
int(tab_base_low / mod_base)
tab_base_low = tab_base_low % mod_base
if (table_number > 128*256*256) {
# figure out: table_number_base -= 256*256*256*256
# sub_high, sub_low is 256*256*256*256
sub_low = 256*256*256 % mod_base
sub_high = int(256*256*256 / mod_base)
sub_low = sub_low * 256
sub_high = (sub_high * 256) + int(sub_low / mod_base)
sub_low = sub_low % mod_base
tab_base_low = sub_low - tab_base_low;
tab_base_high = sub_high - tab_base_high;
tab_base_sign = -1;
if (tab_base_low < 0) {
tab_base_low = tab_base_low + mod_base
tab_base_high--
}
}
print "/*" > outfile
print " * " outfile ":" > outfile
print " * This file is automatically generated; please do not edit it." > outfile
print " */" > outfile
print "#ifdef __STDC__" > outfile
print "#define NOARGS void" > outfile
print "#else" > outfile
print "#define NOARGS" > outfile
print "#define const" > outfile
print "#endif" > outfile
print "" > outfile
print "static const char * const text[] = {" > outfile
table_item_count = 0
}
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*$/ {
skipone=1
next
}
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*"[ \t]*$/ {
text=""
for (i=3; i<=NF; i++) {
text = text FS $i
}
text=substr(text,2,length(text)-1);
printf "\t%s,\n", text > outfile
table_item_count++
}
{
if (skipone) {
printf "\t%s,\n", $0 > outfile
table_item_count++
}
skipone=0
}
END {
print " 0" > outfile
print "};" > outfile
print "" > outfile
print "struct error_table {" > outfile
print " char const * const * msgs;" > outfile
print " long base;" > outfile
print " int n_msgs;" > outfile
print "};" > outfile
print "struct et_list {" > outfile
print " struct et_list *next;" > outfile
print " const struct error_table * table;" > outfile
print "};" > outfile
print "extern struct et_list *_et_list;" > outfile
print "" > outfile
if (tab_base_high == 0) {
print "static const struct error_table et = { text, " \
sprintf("%dL, %d };", tab_base_sign*tab_base_low, \
table_item_count) > outfile
} else {
print "static const struct error_table et = { text, " \
sprintf("%d%06dL, %d };", tab_base_sign*tab_base_high, \
tab_base_low, table_item_count) > outfile
}
print "" > outfile
print "static struct et_list link = { 0, 0 };" > outfile
print "" > outfile
print "void initialize_" table_name "_error_table (NOARGS);" > outfile
print "" > outfile
print "void initialize_" table_name "_error_table (NOARGS) {" > outfile
print " if (!link.table) {" > outfile
print " link.next = _et_list;" > outfile
print " link.table = &et;" > outfile
print " _et_list = &link;" > outfile
print " }" > outfile
print "}" > outfile
}

157
lib/et/et_h.awk Normal file
View File

@ -0,0 +1,157 @@
BEGIN {
char_shift=64
## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
c2n["A"]=1
c2n["B"]=2
c2n["C"]=3
c2n["D"]=4
c2n["E"]=5
c2n["F"]=6
c2n["G"]=7
c2n["H"]=8
c2n["I"]=9
c2n["J"]=10
c2n["K"]=11
c2n["L"]=12
c2n["M"]=13
c2n["N"]=14
c2n["O"]=15
c2n["P"]=16
c2n["Q"]=17
c2n["R"]=18
c2n["S"]=19
c2n["T"]=20
c2n["U"]=21
c2n["V"]=22
c2n["W"]=23
c2n["X"]=24
c2n["Y"]=25
c2n["Z"]=26
c2n["a"]=27
c2n["b"]=28
c2n["c"]=29
c2n["d"]=30
c2n["e"]=31
c2n["f"]=32
c2n["g"]=33
c2n["h"]=34
c2n["i"]=35
c2n["j"]=36
c2n["k"]=37
c2n["l"]=38
c2n["m"]=39
c2n["n"]=40
c2n["o"]=41
c2n["p"]=42
c2n["q"]=43
c2n["r"]=44
c2n["s"]=45
c2n["t"]=46
c2n["u"]=47
c2n["v"]=48
c2n["w"]=49
c2n["x"]=50
c2n["y"]=51
c2n["z"]=52
c2n["0"]=53
c2n["1"]=54
c2n["2"]=55
c2n["3"]=56
c2n["4"]=57
c2n["5"]=58
c2n["6"]=59
c2n["7"]=60
c2n["8"]=61
c2n["9"]=62
c2n["_"]=63
}
/^#/ { next }
/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
table_number = 0
table_name = $2
mod_base = 1000000
for(i=1; i<=length(table_name); i++) {
table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
}
# We start playing *_high, *low games here because the some
# awk programs do not have the necessary precision (sigh)
tab_base_low = table_number % mod_base
tab_base_high = int(table_number / mod_base)
tab_base_sign = 1;
# figure out: table_number_base=table_number*256
tab_base_low = tab_base_low * 256
tab_base_high = (tab_base_high * 256) + \
int(tab_base_low / mod_base)
tab_base_low = tab_base_low % mod_base
if (table_number > 128*256*256) {
# figure out: table_number_base -= 256*256*256*256
# sub_high, sub_low is 256*256*256*256
sub_low = 256*256*256 % mod_base
sub_high = int(256*256*256 / mod_base)
sub_low = sub_low * 256
sub_high = (sub_high * 256) + int(sub_low / mod_base)
sub_low = sub_low % mod_base
tab_base_low = sub_low - tab_base_low;
tab_base_high = sub_high - tab_base_high;
tab_base_sign = -1;
if (tab_base_low < 0) {
tab_base_low = tab_base_low + mod_base
tab_base_high--
}
}
curr_low = tab_base_low
curr_high = tab_base_high
curr_sign = tab_base_sign
print "/*" > outfile
print " * " outfile ":" > outfile
print " * This file is automatically generated; please do not edit it." > outfile
print " */" > outfile
print "#ifdef __STDC__" > outfile
print "#define NOARGS void" > outfile
print "#else" > outfile
print "#define NOARGS" > outfile
print "#define const" > outfile
print "#endif" > outfile
print "" > outfile
}
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,/ {
tag=substr($2,1,length($2)-1)
if (curr_high == 0) {
printf "#define %-40s (%dL)\n", tag, \
curr_sign*curr_low > outfile
} else {
printf "#define %-40s (%d%06dL)\n", tag, curr_high*curr_sign, \
curr_low > outfile
}
curr_low += curr_sign;
if (curr_low >= mod_base) {
curr_low -= mod_base;
curr_high++
}
if (curr_low < 0) {
cur_low += mod_base
cur_high--
}
}
END {
print "extern void initialize_" table_name "_error_table (NOARGS);" > outfile
if (tab_base_high == 0) {
print "#define ERROR_TABLE_BASE_" table_name " (" \
sprintf("%d", tab_base_sign*tab_base_low) \
"L)" > outfile
} else {
print "#define ERROR_TABLE_BASE_" table_name " (" \
sprintf("%d%06d", tab_base_sign*tab_base_high, \
tab_base_low) "L)" > outfile
}
print "" > outfile
print "/* for compatibility with older versions... */" > outfile
print "#define init_" table_name "_err_tbl initialize_" table_name "_error_table" > outfile
print "#define " table_name "_err_base ERROR_TABLE_BASE_" table_name > outfile
}

43
lib/et/et_name.c Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright 1987 by MIT Student Information Processing Board
*
* For copyright info, see mit-sipb-copyright.h.
*/
#include "error_table.h"
#include "mit-sipb-copyright.h"
#include "internal.h"
#ifndef lint
static const char copyright[] =
"Copyright 1987,1988 by Student Information Processing Board, Massachusetts Institute of Technology";
static const char rcsid_et_name_c[] =
"$Header$";
#endif
static const char char_set[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
static char buf[6];
const char * error_table_name(num)
int num;
{
int ch;
int i;
char *p;
/* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
p = buf;
num >>= ERRCODE_RANGE;
/* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
num &= 077777777;
/* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
for (i = 4; i >= 0; i--) {
ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
if (ch != 0)
*p++ = char_set[ch-1];
}
*p = '\0';
return(buf);
}

55
lib/et/init_et.c Normal file
View File

@ -0,0 +1,55 @@
/*
* $Header$
* $Source$
* $Locker$
*
* Copyright 1986, 1987, 1988 by MIT Information Systems and
* the MIT Student Information Processing Board.
*
* For copyright info, see mit-sipb-copyright.h.
*/
#include <stdio.h>
#include "error_table.h"
#include "mit-sipb-copyright.h"
#ifndef __STDC__
#define const
#endif
#ifndef lint
static const char rcsid_init_et_c[] =
"$Header$";
#endif
extern char *malloc(), *realloc();
struct foobar {
struct et_list etl;
struct error_table et;
};
extern struct et_list * _et_list;
int init_error_table(msgs, base, count)
const char * const * msgs;
int base;
int count;
{
struct foobar * new_et;
if (!base || !count || !msgs)
return 0;
new_et = (struct foobar *) malloc(sizeof(struct foobar));
if (!new_et)
return errno; /* oops */
new_et->etl.table = &new_et->et;
new_et->et.msgs = msgs;
new_et->et.base = base;
new_et->et.n_msgs= count;
new_et->etl.next = _et_list;
_et_list = &new_et->etl;
return 0;
}

22
lib/et/internal.h Normal file
View File

@ -0,0 +1,22 @@
/*
* internal include file for com_err package
*/
#include "mit-sipb-copyright.h"
#ifndef __STDC__
#undef const
#define const
#endif
#include <errno.h>
#ifdef NEED_SYS_ERRLIST
extern char const * const sys_errlist[];
extern const int sys_nerr;
#endif
/* AIX and Ultrix have standard conforming header files. */
#if !defined(ultrix) && !defined(_AIX)
#ifdef __STDC__
void perror (const char *);
#endif
#endif

View File

@ -0,0 +1,19 @@
/*
Copyright 1987, 1988 by the Student Information Processing Board
of the Massachusetts Institute of Technology
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is
hereby granted, provided that the above copyright notice
appear in all copies and that both that copyright notice and
this permission notice appear in supporting documentation,
and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
used in advertising or publicity pertaining to distribution
of the software without specific, written prior permission.
M.I.T. and the M.I.T. S.I.P.B. make no representations about
the suitability of this software for any purpose. It is
provided "as is" without express or implied warranty.
*/

2077
lib/et/texinfo.tex Normal file

File diff suppressed because it is too large Load Diff

47
lib/et/vfprintf.c Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)vfprintf.c 5.2 (Berkeley) 6/27/88";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <varargs.h>
int
vfprintf(iop, fmt, ap)
FILE *iop;
char *fmt;
va_list ap;
{
int len;
char localbuf[BUFSIZ];
if (iop->_flag & _IONBF) {
iop->_flag &= ~_IONBF;
iop->_ptr = iop->_base = localbuf;
len = _doprnt(fmt, ap, iop);
(void) fflush(iop);
iop->_flag |= _IONBF;
iop->_base = NULL;
iop->_bufsiz = 0;
iop->_cnt = 0;
} else
len = _doprnt(fmt, ap, iop);
return (ferror(iop) ? EOF : len);
}

350
lib/ext2fs/.depend Normal file
View File

@ -0,0 +1,350 @@
alloc.o : alloc.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h \
/usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/time.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../ext2fs/io.h ../ext2fs/ext2_err.h \
../ext2fs/bitops.h
badblocks.o : badblocks.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/fcntl.h /usr/include/linux/fcntl.h \
/usr/include/time.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../ext2fs/io.h ../ext2fs/ext2_err.h \
../ext2fs/bitops.h
bb_inode.o : bb_inode.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/fcntl.h /usr/include/linux/fcntl.h \
/usr/include/time.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../ext2fs/io.h ../ext2fs/ext2_err.h \
../ext2fs/bitops.h
bitmaps.o : bitmaps.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/fcntl.h /usr/include/linux/fcntl.h \
/usr/include/time.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../ext2fs/io.h ../ext2fs/ext2_err.h \
../ext2fs/bitops.h
bitops.o : bitops.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/linux/fs.h /usr/include/linux/linkage.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/net.h /usr/include/linux/socket.h /usr/include/linux/sockios.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h \
/usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
/usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h \
ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
block.o : block.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/linux/fs.h /usr/include/linux/linkage.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/net.h /usr/include/linux/socket.h \
/usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h \
/usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h \
/usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h \
/usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
closefs.o : closefs.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h \
/usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/time.h /usr/include/linux/fs.h /usr/include/linux/linkage.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/net.h /usr/include/linux/socket.h /usr/include/linux/sockios.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h \
/usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
/usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h \
ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
expanddir.o : expanddir.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/linux/fs.h /usr/include/linux/linkage.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/net.h /usr/include/linux/socket.h \
/usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h \
/usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h \
/usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h \
/usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
ext2_err.o : ext2_err.c
freefs.o : freefs.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/sys/types.h /usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h \
/usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/linux/fs.h /usr/include/linux/linkage.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/net.h /usr/include/linux/socket.h /usr/include/linux/sockios.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h \
/usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
/usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h \
ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
get_pathname.o : get_pathname.c /usr/include/stdio.h /usr/include/features.h \
/usr/include/sys/cdefs.h /usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/linux/fs.h /usr/include/linux/linkage.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/net.h /usr/include/linux/socket.h /usr/include/linux/sockios.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h \
/usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
/usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h \
ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
initialize.o : initialize.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/fcntl.h /usr/include/linux/fcntl.h \
/usr/include/time.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../ext2fs/io.h ../ext2fs/ext2_err.h \
../ext2fs/bitops.h
inline.o : inline.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/fcntl.h /usr/include/linux/fcntl.h \
/usr/include/time.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../ext2fs/io.h ../ext2fs/ext2_err.h \
../ext2fs/bitops.h
inode.o : inode.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/sys/stat.h /usr/include/linux/stat.h \
/usr/include/linux/fs.h /usr/include/linux/linkage.h /usr/include/linux/limits.h \
/usr/include/linux/wait.h /usr/include/linux/dirent.h /usr/include/linux/vfs.h \
/usr/include/linux/net.h /usr/include/linux/socket.h /usr/include/linux/sockios.h \
/usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h \
/usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h \
/usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h \
/usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h \
/usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h \
/usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h \
/usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h \
ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
link.o : link.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/linux/fs.h /usr/include/linux/linkage.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/net.h /usr/include/linux/socket.h \
/usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h \
/usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h \
/usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h \
/usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
mkdir.o : mkdir.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/fcntl.h /usr/include/linux/fcntl.h \
/usr/include/time.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../ext2fs/io.h ../ext2fs/ext2_err.h \
../ext2fs/bitops.h
namei.o : namei.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/linux/fs.h /usr/include/linux/linkage.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/net.h /usr/include/linux/socket.h \
/usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h \
/usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h \
/usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h \
/usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
newdir.o : newdir.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/linux/fs.h /usr/include/linux/linkage.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/net.h /usr/include/linux/socket.h \
/usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h \
/usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h \
/usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h \
/usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
openfs.o : openfs.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/fcntl.h /usr/include/linux/fcntl.h \
/usr/include/time.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../ext2fs/io.h ../ext2fs/ext2_err.h \
../ext2fs/bitops.h
read_bb.o : read_bb.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/fcntl.h /usr/include/linux/fcntl.h \
/usr/include/time.h /usr/include/sys/stat.h /usr/include/linux/stat.h /usr/include/linux/fs.h \
/usr/include/linux/linkage.h /usr/include/linux/limits.h /usr/include/linux/wait.h \
/usr/include/linux/dirent.h /usr/include/linux/vfs.h /usr/include/linux/net.h \
/usr/include/linux/socket.h /usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h \
/usr/include/linux/minix_fs_i.h /usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h \
/usr/include/linux/hpfs_fs_i.h /usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h \
/usr/include/linux/nfs_fs_i.h /usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h \
/usr/include/linux/sysv_fs_i.h /usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h \
/usr/include/linux/ext2_fs_sb.h /usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h \
/usr/include/linux/iso_fs_sb.h /usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h \
/usr/include/linux/sysv_fs_sb.h /usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ../ext2fs/io.h ../ext2fs/ext2_err.h \
../ext2fs/bitops.h
read_bb_file.o : read_bb_file.c /usr/include/stdio.h /usr/include/features.h \
/usr/include/sys/cdefs.h /usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h /usr/include/unistd.h /usr/include/posix_opt.h \
/usr/include/gnu/types.h /usr/include/sys/types.h /usr/include/linux/types.h \
/usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h \
/usr/include/fcntl.h /usr/include/linux/fcntl.h /usr/include/time.h /usr/include/sys/stat.h \
/usr/include/linux/stat.h /usr/include/linux/fs.h /usr/include/linux/linkage.h \
/usr/include/linux/limits.h /usr/include/linux/wait.h /usr/include/linux/dirent.h \
/usr/include/linux/vfs.h /usr/include/linux/net.h /usr/include/linux/socket.h \
/usr/include/linux/sockios.h /usr/include/linux/pipe_fs_i.h /usr/include/linux/minix_fs_i.h \
/usr/include/linux/ext_fs_i.h /usr/include/linux/ext2_fs_i.h /usr/include/linux/hpfs_fs_i.h \
/usr/include/linux/msdos_fs_i.h /usr/include/linux/iso_fs_i.h /usr/include/linux/nfs_fs_i.h \
/usr/include/linux/nfs.h /usr/include/linux/xia_fs_i.h /usr/include/linux/sysv_fs_i.h \
/usr/include/linux/minix_fs_sb.h /usr/include/linux/ext_fs_sb.h /usr/include/linux/ext2_fs_sb.h \
/usr/include/linux/hpfs_fs_sb.h /usr/include/linux/msdos_fs_sb.h /usr/include/linux/iso_fs_sb.h \
/usr/include/linux/nfs_fs_sb.h /usr/include/linux/xia_fs_sb.h /usr/include/linux/sysv_fs_sb.h \
/usr/include/linux/ext2_fs.h ext2fs.h ../et/com_err.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h \
../ext2fs/io.h ../ext2fs/ext2_err.h ../ext2fs/bitops.h
unix_io.o : unix_io.c /usr/include/stdio.h /usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/string.h /usr/lib/gcc-lib/i486-linux/2.5.8/include/stddef.h \
/usr/include/unistd.h /usr/include/posix_opt.h /usr/include/gnu/types.h /usr/include/sys/types.h \
/usr/include/linux/types.h /usr/include/stdlib.h /usr/include/errno.h /usr/include/linux/errno.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/float.h /usr/include/fcntl.h /usr/include/linux/fcntl.h \
/usr/include/time.h /usr/include/sys/stat.h /usr/include/linux/stat.h ../et/com_err.h \
/usr/lib/gcc-lib/i486-linux/2.5.8/include/stdarg.h ext2_err.h io.h

80
lib/ext2fs/Makefile Normal file
View File

@ -0,0 +1,80 @@
include ../../MCONFIG
COMPILE_ET=../et/compile_et
CFLAGS_NO= $(WFLAGS) -I..
CFLAGS= $(OPT) $(CFLAGS_NO)
LDFLAGS= $(OPT)
ARCHIVE=ar r
RANLIB=ranlib
RM=rm -f
MV=mv
LN=ln -s
OBJS= ext2_err.o openfs.o freefs.o closefs.o bitmaps.o inode.o unix_io.o \
block.o namei.o newdir.o mkdir.o \
get_pathname.o bitops.o link.o alloc.o expanddir.o inline.o \
initialize.o badblocks.o read_bb.o bb_inode.o read_bb_file.o
HFILES= bitops.h ext2_err.h ext2fs.h io.h
DISTFILES= Makefile *.c *.h image
.c.o:
$(CC) $(CFLAGS) -c $*.c
$(CC) $(CFLAGS_NO) -pg -o profiled/$*.o -c $*.c
# $(CC) $(CFLAGS_NO) -checker -g -o checker/$*.o -c $*.c
all: libext2fs.a libext2fs_p.a
libext2fs.a: $(OBJS)
$(RM) $@.bak
-$(MV) $@ $@.bak
$(ARCHIVE) $@ $(OBJS)
$(RANLIB) $@
$(RM) ../$@
$(LN) ext2fs/$@ ../$@
libext2fs_p.a: $(OBJS)
$(RM) $@.bak
-$(MV) $@ $@.bak
(cd profiled; $(ARCHIVE) ../$@ $(OBJS))
$(RANLIB) $@
$(RM) ../$@
$(LN) ext2fs/$@ ../$@
libext2fs_chk.a: $(OBJS)
$(RM) $@.bak
-$(MV) $@ $@.bak
(cd checker; $(ARCHIVE) ../$@ $(OBJS))
$(RANLIB) $@
$(RM) ../$@
$(LN) ext2fs/$@ ../$@
ext2_err.c ext2_err.h: ext2_err.et
$(COMPILE_ET) ext2_err.et
install:: all
$(INSTALLLIB) libext2fs.a ${DESTDIR}$(LIBDIR)/libext2fs.a
$(CHMOD) 644 ${DESTDIR}$(LIBDIR)/libext2fs.a
$(RANLIB) ${DESTDIR}$(LIBDIR)/libext2fs.a
$(CHMOD) $(LIBMODE) ${DESTDIR}$(LIBDIR)/libext2fs.a
install:: $(HFILES)
@rm -rf ${DESTDIR}$(INCLDIR)/ext2fs
@mkdir ${DESTDIR}$(INCLDIR)/ext2fs
for i in $(HFILES); do \
$(INSTALLINC) $$i ${DESTDIR}$(INCLDIR)/ext2fs/$$i; \
done
clean:
rm -f \#* *.s *.o *.a *~ *.bak core profiled/* checker/*
really-clean: clean
rm -f .depend ext2_err.c ext2_err.h
dep depend .depend: ext2_err.h
$(CC) -M $(CFLAGS) *.c >.depend
include .depend

125
lib/ext2fs/alloc.c Normal file
View File

@ -0,0 +1,125 @@
/*
* alloc.c --- allocate new inodes, blocks for ext2fs
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include "ext2fs.h"
/*
* Right now, just search forward from the parent directory's block
* group to find the next free inode.
*
* Should have a special policy for directories.
*/
errcode_t ext2fs_new_inode(ext2_filsys fs, ino_t dir, int mode, char *map,
ino_t *ret)
{
int dir_group = 0;
ino_t i;
ino_t start_inode;
if (!map)
map = fs->inode_map;
if (!map)
return EXT2_ET_NO_INODE_BITMAP;
if (dir > 0)
dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super);
start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1;
i = start_inode;
if (i < EXT2_FIRST_INO)
i = EXT2_FIRST_INO;
do {
if (!ext2fs_test_inode_bitmap(fs, map, i))
break;
i++;
if (i > fs->super->s_inodes_count)
i = EXT2_FIRST_INO;
} while (i != start_inode);
if (ext2fs_test_inode_bitmap(fs, map, i))
return ENOSPC;
*ret = i;
return 0;
}
/*
* Stupid algorithm --- we now just search forward starting from the
* goal. Should put in a smarter one someday....
*/
errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal, char *map, blk_t *ret)
{
blk_t i = goal;
if (!map)
map = fs->block_map;
if (!map)
return EXT2_ET_NO_BLOCK_BITMAP;
if (!i)
i = fs->super->s_first_data_block;
do {
if (!ext2fs_test_block_bitmap(fs, map, i)) {
*ret = i;
return 0;
}
i++;
if (i > fs->super->s_blocks_count)
i = fs->super->s_first_data_block;
} while (i != goal);
return ENOSPC;
}
static int check_blocks_free(ext2_filsys fs, char *map, blk_t blk, int num)
{
int i;
for (i=0; i < num; i++) {
if ((blk+i) > fs->super->s_blocks_count)
return 0;
if (ext2fs_test_block_bitmap(fs, map, blk+i))
return 0;
}
return 1;
}
errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
int num, char *map, blk_t *ret)
{
blk_t b = start;
if (!map)
map = fs->block_map;
if (!map)
return EXT2_ET_NO_BLOCK_BITMAP;
if (!b)
b = fs->super->s_first_data_block;
if (!finish)
finish = start;
if (!num)
num = 1;
do {
if (check_blocks_free(fs, map, b, num)) {
*ret = b;
return 0;
}
b++;
if (b > fs->super->s_blocks_count)
b = fs->super->s_first_data_block;
} while (b != finish);
return ENOSPC;
}

130
lib/ext2fs/badblocks.c Normal file
View File

@ -0,0 +1,130 @@
/*
* badblocks.c --- routines to manipulate the bad block structure
*
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include "ext2fs.h"
/*
* This procedure create an empty badblocks list.
*/
errcode_t badblocks_list_create(badblocks_list *ret, int size)
{
badblocks_list bb;
bb = malloc(sizeof(struct struct_badblocks_list));
if (!bb)
return ENOMEM;
memset(bb, 0, sizeof(struct struct_badblocks_list));
bb->size = size ? size : 10;
bb->list = malloc(bb->size * sizeof(blk_t));
if (!bb->list) {
free(bb);
return ENOMEM;
}
*ret = bb;
return 0;
}
/*
* This procedure frees a badblocks list.
*/
void badblocks_list_free(badblocks_list bb)
{
if (bb->list)
free(bb->list);
bb->list = 0;
free(bb);
}
/*
* This procedure adds a block to a badblocks list.
*/
errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
{
int i;
for (i=0; i < bb->num; i++)
if (bb->list[i] == blk)
return 0;
if (bb->num >= bb->size) {
bb->size += 10;
bb->list = realloc(bb->list, bb->size * sizeof(blk_t));
if (!bb->list) {
bb->size = 0;
bb->num = 0;
return ENOMEM;
}
}
bb->list[bb->num++] = blk;
return 0;
}
/*
* This procedure tests to see if a particular block is on a badblocks
* list.
*/
int badblocks_list_test(badblocks_list bb, blk_t blk)
{
int i;
for (i=0; i < bb->num; i++)
if (bb->list[i] == blk)
return 1;
return 0;
}
errcode_t badblocks_list_iterate_begin(badblocks_list bb,
badblocks_iterate *ret)
{
badblocks_iterate iter;
iter = malloc(sizeof(struct struct_badblocks_iterate));
if (!iter)
return ENOMEM;
iter->bb = bb;
iter->ptr = 0;
*ret = iter;
return 0;
}
int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
{
badblocks_list bb = iter->bb;
if (iter->ptr < bb->num) {
*blk = bb->list[iter->ptr++];
return 1;
}
*blk = 0;
return 0;
}
void badblocks_list_iterate_end(badblocks_iterate iter)
{
iter->bb = 0;
free(iter);
}

232
lib/ext2fs/bb_inode.c Normal file
View File

@ -0,0 +1,232 @@
/*
* bb_inode.c --- routines to update the bad block inode.
*
* WARNING: This routine modifies a lot of state in the filesystem; if
* this routine returns an error, the bad block inode may be in an
* inconsistent state.
*
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include "ext2fs.h"
struct set_badblock_record {
badblocks_iterate bb_iter;
int bad_block_count;
blk_t *ind_blocks;
int max_ind_blocks;
int ind_blocks_size;
int ind_blocks_ptr;
char *block_buf;
errcode_t err;
};
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
void *private);
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
void *private);
/*
* Given a bad blocks bitmap, update the bad blocks inode to reflect
* the map.
*/
errcode_t ext2fs_update_bb_inode(ext2_filsys fs, badblocks_list bb_list)
{
errcode_t retval;
struct set_badblock_record rec;
struct ext2_inode inode;
if (!fs->block_map)
return EXT2_ET_NO_BLOCK_BITMAP;
rec.bad_block_count = 0;
rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
rec.max_ind_blocks = 10;
rec.ind_blocks = malloc(rec.max_ind_blocks * sizeof(blk_t));
if (!rec.ind_blocks)
return ENOMEM;
memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t));
rec.block_buf = malloc(fs->blocksize);
if (!rec.block_buf) {
retval = ENOMEM;
goto cleanup;
}
memset(rec.block_buf, 0, fs->blocksize);
rec.err = 0;
/*
* First clear the old bad blocks (while saving the indirect blocks)
*/
retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0,
clear_bad_block_proc, &rec);
if (retval)
goto cleanup;
if (rec.err) {
retval = rec.err;
goto cleanup;
}
/*
* Now set the bad blocks!
*/
if (bb_list) {
retval = badblocks_list_iterate_begin(bb_list, &rec.bb_iter);
if (retval)
goto cleanup;
retval = ext2fs_block_iterate(fs, EXT2_BAD_INO,
BLOCK_FLAG_APPEND, 0,
set_bad_block_proc, &rec);
badblocks_list_iterate_end(rec.bb_iter);
if (retval)
goto cleanup;
if (rec.err) {
retval = rec.err;
goto cleanup;
}
}
/*
* Update the bad block inode's mod time and block count
* field.
*/
retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode);
if (retval)
goto cleanup;
inode.i_atime = inode.i_mtime = time(0);
if (!inode.i_ctime)
inode.i_ctime = time(0);
inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512);
inode.i_size = rec.bad_block_count * fs->blocksize;
retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode);
if (retval)
goto cleanup;
cleanup:
free(rec.ind_blocks);
free(rec.block_buf);
return retval;
}
/*
* Helper function for update_bb_inode()
*
* Clear the bad blocks in the bad block inode, while saving the
* indirect blocks.
*/
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
void *private)
{
struct set_badblock_record *rec = (struct set_badblock_record *)
private;
int group;
if (!*block_nr)
return 0;
if (blockcnt < 0) {
if (rec->ind_blocks_size >= rec->max_ind_blocks) {
rec->max_ind_blocks += 10;
rec->ind_blocks = realloc(rec->ind_blocks,
rec->max_ind_blocks *
sizeof(blk_t));
if (!rec->ind_blocks) {
rec->err = ENOMEM;
return BLOCK_ABORT;
}
}
rec->ind_blocks[rec->ind_blocks_size++] = *block_nr;
}
/*
* Mark the block as unused, and update accounting information
*/
ext2fs_unmark_block_bitmap(fs, fs->block_map, *block_nr);
ext2fs_mark_bb_dirty(fs);
group = ext2fs_group_of_blk(fs, *block_nr);
fs->group_desc[group].bg_free_blocks_count++;
fs->super->s_free_blocks_count++;
ext2fs_mark_super_dirty(fs);
*block_nr = 0;
return BLOCK_CHANGED;
}
/*
* Helper function for update_bb_inode()
*
* Set the block list in the bad block inode, using the supplied bitmap.
*/
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
int blockcnt, void *private)
{
struct set_badblock_record *rec = (struct set_badblock_record *)
private;
errcode_t retval;
blk_t blk;
int group;
if (blockcnt >= 0) {
/*
* Get the next bad block.
*/
if (!badblocks_list_iterate(rec->bb_iter, &blk))
return BLOCK_ABORT;
rec->bad_block_count++;
} else if (rec->ind_blocks_ptr < rec->ind_blocks_size)
/*
* An indirect block; fetch a block from the
* previously used indirect block list.
*/
blk = rec->ind_blocks[rec->ind_blocks_ptr++];
else {
/*
* An indirect block, and we're out of reserved
* indirect blocks. Allocate a new one.
*/
retval = ext2fs_new_block(fs, 0, 0, &blk);
if (retval) {
rec->err = retval;
return BLOCK_ABORT;
}
retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf);
if (retval) {
rec->err = retval;
return BLOCK_ABORT;
}
}
/*
* Mark the block as used, and update block counts
*/
ext2fs_mark_block_bitmap(fs, fs->block_map, blk);
ext2fs_mark_bb_dirty(fs);
group = ext2fs_group_of_blk(fs, blk);
fs->group_desc[group].bg_free_blocks_count--;
fs->super->s_free_blocks_count--;
ext2fs_mark_super_dirty(fs);
*block_nr = blk;
return BLOCK_CHANGED;
}

258
lib/ext2fs/bitmaps.c Normal file
View File

@ -0,0 +1,258 @@
/*
* bitmaps.c --- routines to read, write, and manipulate the inode and
* block bitmaps.
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include "ext2fs.h"
errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs)
{
int i;
int nbytes;
errcode_t retval;
char * inode_bitmap = fs->inode_map;
char * bitmap_block = NULL;
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
if (!inode_bitmap)
return 0;
nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
bitmap_block = malloc(fs->blocksize);
if (!bitmap_block)
return ENOMEM;
memset(bitmap_block, 0xff, fs->blocksize);
for (i = 0; i < fs->group_desc_count; i++) {
memcpy(bitmap_block, inode_bitmap, nbytes);
retval = io_channel_write_blk(fs->io,
fs->group_desc[i].bg_inode_bitmap, 1,
bitmap_block);
if (retval)
return EXT2_ET_INODE_BITMAP_WRITE;
inode_bitmap += nbytes;
}
fs->flags |= EXT2_FLAG_CHANGED;
fs->flags &= ~EXT2_FLAG_IB_DIRTY;
free(bitmap_block);
return 0;
}
errcode_t ext2fs_write_block_bitmap (ext2_filsys fs)
{
int i;
int j;
int nbytes;
int nbits;
errcode_t retval;
char * block_bitmap = fs->block_map;
char * bitmap_block = NULL;
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
if (!block_bitmap)
return 0;
nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
bitmap_block = malloc(fs->blocksize);
if (!bitmap_block)
return ENOMEM;
memset(bitmap_block, 0xff, fs->blocksize);
for (i = 0; i < fs->group_desc_count; i++) {
memcpy(bitmap_block, block_bitmap, nbytes);
if (i == fs->group_desc_count - 1) {
/* Force bitmap padding for the last group */
nbits = (fs->super->s_blocks_count
- fs->super->s_first_data_block)
% EXT2_BLOCKS_PER_GROUP(fs->super);
for (j = nbits; j < fs->blocksize * 8; j++)
set_bit(j, bitmap_block);
}
retval = io_channel_write_blk(fs->io,
fs->group_desc[i].bg_block_bitmap, 1,
bitmap_block);
if (retval)
return EXT2_ET_BLOCK_BITMAP_WRITE;
block_bitmap += nbytes;
}
fs->flags |= EXT2_FLAG_CHANGED;
fs->flags &= ~EXT2_FLAG_BB_DIRTY;
free(bitmap_block);
return 0;
}
errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs)
{
int i;
char * inode_bitmap;
char *buf = 0;
errcode_t retval;
int nbytes;
fs->write_bitmaps = ext2fs_write_bitmaps;
if (fs->inode_map)
free(fs->inode_map);
nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
fs->flags &= ~EXT2_FLAG_IB_DIRTY;
fs->inode_map = malloc((nbytes * fs->group_desc_count) + 1);
if (!fs->inode_map)
return ENOMEM;
inode_bitmap = fs->inode_map;
buf = malloc(fs->blocksize);
if (!buf)
return ENOMEM;
for (i = 0; i < fs->group_desc_count; i++) {
retval = io_channel_read_blk(fs->io,
fs->group_desc[i].bg_inode_bitmap, 1,
buf);
if (retval) {
retval = EXT2_ET_INODE_BITMAP_READ;
goto cleanup;
}
memcpy(inode_bitmap, buf, nbytes);
inode_bitmap += nbytes;
}
free(buf);
return 0;
cleanup:
free(fs->inode_map);
fs->inode_map = 0;
if (buf)
free(buf);
return retval;
}
errcode_t ext2fs_read_block_bitmap(ext2_filsys fs)
{
int i;
char * block_bitmap;
char *buf = 0;
errcode_t retval;
int nbytes;
fs->write_bitmaps = ext2fs_write_bitmaps;
if (fs->block_map)
free(fs->block_map);
nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
fs->flags &= ~EXT2_FLAG_BB_DIRTY;
fs->block_map = malloc((nbytes * fs->group_desc_count) + 1);
if (!fs->block_map)
return ENOMEM;
block_bitmap = fs->block_map;
buf = malloc(fs->blocksize);
if (!buf)
return ENOMEM;
for (i = 0; i < fs->group_desc_count; i++) {
retval = io_channel_read_blk(fs->io,
fs->group_desc[i].bg_block_bitmap, 1,
buf);
if (retval) {
retval = EXT2_ET_BLOCK_BITMAP_READ;
goto cleanup;
}
memcpy(block_bitmap, buf, nbytes);
block_bitmap += nbytes;
}
free(buf);
return 0;
cleanup:
free(fs->block_map);
fs->block_map = 0;
if (buf)
free(buf);
return retval;
}
errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, char **ret)
{
char *map;
int size;
fs->write_bitmaps = ext2fs_write_bitmaps;
size = (fs->super->s_inodes_count / 8) + 1;
map = malloc(size);
if (!map)
return ENOMEM;
memset(map, 0, size);
*ret = map;
return 0;
}
errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, char **ret)
{
char *map;
int size;
fs->write_bitmaps = ext2fs_write_bitmaps;
size = (fs->super->s_blocks_count / 8) + 1;
map = malloc(size);
if (!map)
return ENOMEM;
memset(map, 0, size);
*ret = map;
return 0;
}
errcode_t ext2fs_read_bitmaps(ext2_filsys fs)
{
errcode_t retval;
fs->write_bitmaps = ext2fs_write_bitmaps;
if (!fs->inode_map) {
retval = ext2fs_read_inode_bitmap(fs);
if (retval)
return retval;
}
if (!fs->block_map) {
retval = ext2fs_read_block_bitmap(fs);
if (retval)
return retval;
}
return 0;
}
errcode_t ext2fs_write_bitmaps(ext2_filsys fs)
{
errcode_t retval;
if (fs->block_map && ext2fs_test_bb_dirty(fs)) {
retval = ext2fs_write_block_bitmap(fs);
if (retval)
return retval;
}
if (fs->inode_map && ext2fs_test_ib_dirty(fs)) {
retval = ext2fs_write_inode_bitmap(fs);
if (retval)
return retval;
}
return 0;
}

95
lib/ext2fs/bitops.c Normal file
View File

@ -0,0 +1,95 @@
/*
* bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
* routines.
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*
* Taken from <asm/bitops.h>, Copyright 1992, Linus Torvalds.
*/
#include <stdio.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include "ext2fs.h"
#if (!defined(__i386__) && !defined(__i486__) && !defined(__i586__))
/*
* For the benefit of those who are trying to port Linux to another
* architecture, here are some C-language equivalents. You should
* recode these in the native assmebly language, if at all possible.
* To guarantee atomicity, these routines call cli() and sti() to
* disable interrupts while they operate. (You have to provide inline
* routines to cli() and sti().)
*
* Also note, these routines assume that you have 32 bit integers.
* You will have to change this if you are trying to port Linux to the
* Alpha architecture or to a Cray. :-)
*
* C language equivalents written by Theodore Ts'o, 9/26/92
*/
int set_bit(int nr,void * addr)
{
int mask, retval;
int *ADDR = (int *) addr;
ADDR += nr >> 5;
mask = 1 << (nr & 0x1f);
cli();
retval = (mask & *ADDR) != 0;
*ADDR |= mask;
sti();
return retval;
}
int clear_bit(int nr, void * addr)
{
int mask, retval;
int *ADDR = (int *) addr;
ADDR += nr >> 5;
mask = 1 << (nr & 0x1f);
cli();
retval = (mask & *ADDR) != 0;
*ADDR &= ~mask;
sti();
return retval;
}
int test_bit(int nr, const void * addr)
{
int mask;
const int *ADDR = (const int *) addr;
ADDR += nr >> 5;
mask = 1 << (nr & 0x1f);
return ((mask & *ADDR) != 0);
}
#endif /* !i386 */
/*
* These are routines print warning messages; they are called by
* inline routines.
*/
const char *ext2fs_block_string = "block";
const char *ext2fs_inode_string = "inode";
const char *ext2fs_mark_string = "mark";
const char *ext2fs_unmark_string = "unmark";
const char *ext2fs_test_string = "test";
void ext2fs_warn_bitmap(ext2_filsys fs, const char *op, const char *type,
int arg)
{
char func[80];
sprintf(func, "ext2fs_%s_%s_bitmap", op, type);
com_err(func, 0, "INTERNAL ERROR: illegal %s #%d for %s",
type, arg, fs->device_name);
}

172
lib/ext2fs/bitops.h Normal file
View File

@ -0,0 +1,172 @@
/*
* bitops.h --- Bitmap frobbing code.
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*
* Taken from <asm/bitops.h>, Copyright 1992, Linus Torvalds.
*/
extern int set_bit(int nr,void * addr);
extern int clear_bit(int nr, void * addr);
extern int test_bit(int nr, const void * addr);
/*
* EXT2FS bitmap manipulation routines.
*/
/* Support for sending warning messages from the inline subroutines */
extern const char *ext2fs_block_string;
extern const char *ext2fs_inode_string;
extern const char *ext2fs_mark_string;
extern const char *ext2fs_unmark_string;
extern const char *ext2fs_test_string;
extern void ext2fs_warn_bitmap(ext2_filsys fs, const char *op,
const char *type, int arg);
extern void ext2fs_mark_block_bitmap(ext2_filsys fs, char *bitmap, int block);
extern void ext2fs_unmark_block_bitmap(ext2_filsys fs, char *bitmap,
int block);
extern int ext2fs_test_block_bitmap(ext2_filsys fs, const char *bitmap,
int block);
extern void ext2fs_mark_inode_bitmap(ext2_filsys fs, char *bitmap, int inode);
extern void ext2fs_unmark_inode_bitmap(ext2_filsys fs, char *bitmap,
int inode);
extern int ext2fs_test_inode_bitmap(ext2_filsys fs, const char *bitmap,
int inode);
/*
* The inline routines themselves...
*
* If NO_INLINE_FUNCS is defined, then we won't try to do inline
* functions at all!
*/
#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
#ifdef INCLUDE_INLINE_FUNCS
#define _INLINE_ extern
#else
#define _INLINE_ extern __inline__
#endif
#if (defined(__i386__) || defined(__i486__) || defined(__i586__))
/*
* These are done by inline assembly for speed reasons.....
*
* All bitoperations return 0 if the bit was cleared before the
* operation and != 0 if it was not. Bit 0 is the LSB of addr; bit 32
* is the LSB of (addr+1).
*/
/*
* Some hacks to defeat gcc over-optimizations..
*/
struct __dummy_h { unsigned long a[100]; };
#define ADDR (*(struct __dummy_h *) addr)
#define CONST_ADDR (*(const struct __dummy_h *) addr)
_INLINE_ int set_bit(int nr, void * addr)
{
int oldbit;
__asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"r" (nr));
return oldbit;
}
_INLINE_ int clear_bit(int nr, void * addr)
{
int oldbit;
__asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"r" (nr));
return oldbit;
}
_INLINE_ int test_bit(int nr, const void * addr)
{
int oldbit;
__asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit)
:"m" (CONST_ADDR),"r" (nr));
return oldbit;
}
#undef ADDR
#endif /* i386 */
_INLINE_ void ext2fs_mark_block_bitmap(ext2_filsys fs, char *bitmap,
int block)
{
if ((block < fs->super->s_first_data_block) ||
(block >= fs->super->s_blocks_count)) {
ext2fs_warn_bitmap(fs, ext2fs_mark_string,
ext2fs_block_string, block);
return;
}
set_bit(block - fs->super->s_first_data_block, bitmap);
}
_INLINE_ void ext2fs_unmark_block_bitmap(ext2_filsys fs, char *bitmap,
int block)
{
if ((block < fs->super->s_first_data_block) ||
(block >= fs->super->s_blocks_count)) {
ext2fs_warn_bitmap(fs, ext2fs_unmark_string,
ext2fs_block_string, block);
return;
}
clear_bit(block - fs->super->s_first_data_block, bitmap);
}
_INLINE_ int ext2fs_test_block_bitmap(ext2_filsys fs, const char *bitmap,
int block)
{
if ((block < fs->super->s_first_data_block) ||
(block >= fs->super->s_blocks_count)) {
ext2fs_warn_bitmap(fs, ext2fs_test_string,
ext2fs_block_string, block);
return 0;
}
return test_bit(block - fs->super->s_first_data_block, bitmap);
}
_INLINE_ void ext2fs_mark_inode_bitmap(ext2_filsys fs, char *bitmap,
int inode)
{
if ((inode < 1) || (inode > fs->super->s_inodes_count)) {
ext2fs_warn_bitmap(fs, ext2fs_mark_string,
ext2fs_inode_string, inode);
return;
}
set_bit(inode - 1, bitmap);
}
_INLINE_ void ext2fs_unmark_inode_bitmap(ext2_filsys fs, char *bitmap,
int inode)
{
if ((inode < 1) || (inode > fs->super->s_inodes_count)) {
ext2fs_warn_bitmap(fs, ext2fs_unmark_string,
ext2fs_inode_string, inode);
return;
}
clear_bit(inode - 1, bitmap);
}
_INLINE_ int ext2fs_test_inode_bitmap(ext2_filsys fs, const char *bitmap,
int inode)
{
if ((inode < 1) || (inode > fs->super->s_inodes_count)) {
ext2fs_warn_bitmap(fs, ext2fs_test_string,
ext2fs_inode_string, inode);
return 0;
}
return test_bit(inode - 1, bitmap);
}
#undef _INLINE_
#endif

223
lib/ext2fs/block.c Normal file
View File

@ -0,0 +1,223 @@
/*
* block.c --- iterate over all blocks in an inode
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include "ext2fs.h"
struct block_context {
ext2_filsys fs;
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int bcount,
void *private);
int bcount;
int bsize;
int flags;
errcode_t errcode;
char *ind_buf;
char *dind_buf;
char *tind_buf;
void *private;
};
static int block_iterate_ind(blk_t *ind_block, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags;
blk_t *block_nr;
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE))
ret = (*ctx->func)(ctx->fs, ind_block, -1, ctx->private);
if (!*ind_block || (ret & BLOCK_ABORT))
return ret;
ctx->errcode = io_channel_read_blk(ctx->fs->io, *ind_block,
1, ctx->ind_buf);
if (ctx->errcode) {
ret |= BLOCK_ERROR;
return ret;
}
for (i = 0; i < (ctx->fs->blocksize >> 2); i++, ctx->bcount++) {
block_nr = (blk_t *) ctx->ind_buf + i;
if (*block_nr || (ctx->flags & BLOCK_FLAG_APPEND)) {
flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
ctx->private);
changed |= flags & BLOCK_CHANGED;
if (flags & BLOCK_ABORT) {
ret |= BLOCK_ABORT;
break;
}
}
}
if (changed) {
ctx->errcode = io_channel_write_blk(ctx->fs->io, *ind_block,
1, ctx->ind_buf);
if (ctx->errcode)
ret |= BLOCK_ERROR | BLOCK_ABORT;
}
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ret & BLOCK_ABORT))
ret |= (*ctx->func)(ctx->fs, ind_block, -1, ctx->private);
return ret;
}
static int block_iterate_dind(blk_t *dind_block, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags;
blk_t *block_nr;
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE))
ret = (*ctx->func)(ctx->fs, dind_block, -2, ctx->private);
if (!*dind_block || (ret & BLOCK_ABORT))
return ret;
ctx->errcode = io_channel_read_blk(ctx->fs->io, *dind_block,
1, ctx->dind_buf);
if (ctx->errcode) {
ret |= BLOCK_ERROR;
return ret;
}
for (i = 0; i < (ctx->fs->blocksize >> 2); i++) {
block_nr = (blk_t *) ctx->dind_buf + i;
if (*block_nr || (ctx->flags & BLOCK_FLAG_APPEND)) {
flags = block_iterate_ind(block_nr, ctx);
changed |= flags & BLOCK_CHANGED;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
}
}
if (changed) {
ctx->errcode = io_channel_write_blk(ctx->fs->io, *dind_block,
1, ctx->dind_buf);
if (ctx->errcode)
ret |= BLOCK_ERROR | BLOCK_ABORT;
}
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ret & BLOCK_ABORT))
ret |= (*ctx->func)(ctx->fs, dind_block, -2, ctx->private);
return ret;
}
static int block_iterate_tind(blk_t *tind_block, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags;
blk_t *block_nr;
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE))
ret = (*ctx->func)(ctx->fs, tind_block, -3, ctx->private);
if (!*tind_block || (ret & BLOCK_ABORT))
return ret;
ctx->errcode = io_channel_read_blk(ctx->fs->io, *tind_block,
1, ctx->tind_buf);
if (ctx->errcode) {
ret |= BLOCK_ERROR;
return ret;
}
for (i = 0; i < (ctx->fs->blocksize >> 2); i++) {
block_nr = (blk_t *) ctx->tind_buf + i;
if (*block_nr || (ctx->flags & BLOCK_FLAG_APPEND)) {
flags = block_iterate_dind(block_nr, ctx);
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
}
}
if (changed) {
ctx->errcode = io_channel_write_blk(ctx->fs->io, *tind_block,
1, ctx->tind_buf);
if (ctx->errcode)
ret |= BLOCK_ERROR | BLOCK_ABORT;
}
if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ret & BLOCK_ABORT))
ret |= (*ctx->func)(ctx->fs, tind_block, -3, ctx->private);
return ret;
}
errcode_t ext2fs_block_iterate(ext2_filsys fs,
ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
void *private),
void *private)
{
int i;
int ret = 0;
struct block_context ctx;
blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
struct ext2_inode inode;
errcode_t retval;
ret = ext2fs_get_blocks(fs, ino, blocks);
if (ret)
return ret;
ctx.fs = fs;
ctx.func = func;
ctx.private = private;
ctx.bcount = 0;
ctx.flags = flags;
if (block_buf) {
ctx.ind_buf = block_buf;
} else {
ctx.ind_buf = malloc(fs->blocksize * 3);
if (!ctx.ind_buf)
return ENOMEM;
}
ctx.dind_buf = ctx.ind_buf + fs->blocksize;
ctx.tind_buf = ctx.dind_buf + fs->blocksize;
for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
ret |= (*func)(fs, &blocks[i], ctx.bcount, private);
if (ret & BLOCK_ABORT)
goto abort;
}
}
if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort;
}
if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK, &ctx);
if (ret & BLOCK_ABORT)
goto abort;
}
if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND))
ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK, &ctx);
abort:
if (ret & BLOCK_CHANGED) {
retval = ext2fs_read_inode(fs, ino, &inode);
if (retval)
return retval;
for (i=0; i < EXT2_N_BLOCKS; i++)
inode.i_block[i] = blocks[i];
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval)
return retval;
}
if (!block_buf)
free(ctx.ind_buf);
return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
}

88
lib/ext2fs/closefs.c Normal file
View File

@ -0,0 +1,88 @@
/*
* closefs.c --- close an ext2 filesystem
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include "ext2fs.h"
errcode_t ext2fs_flush(ext2_filsys fs)
{
int i,j;
int group_block;
errcode_t retval;
char *group_ptr;
/*
* Write out master superblock. This has to be done
* separately, since it is located at a fixed location
* (SUPERBLOCK_OFFSET).
*/
fs->super->s_wtime = time(NULL);
io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE, fs->super);
if (retval)
return retval;
io_channel_set_blksize(fs->io, fs->blocksize);
/*
* Write out the master group descriptors, and the backup
* superblocks and group descriptors.
*/
group_block = fs->super->s_first_data_block;
for (i = 0; i < fs->group_desc_count; i++) {
if (i !=0 ) {
retval = io_channel_write_blk(fs->io, group_block,
-SUPERBLOCK_SIZE,
fs->super);
if (retval)
return retval;
}
group_ptr = (char *) fs->group_desc;
for (j=0; j < fs->desc_blocks; j++) {
retval = io_channel_write_blk(fs->io,
group_block+1+j, 1,
group_ptr);
if (retval)
return retval;
group_ptr += fs->blocksize;
}
group_block += EXT2_BLOCKS_PER_GROUP(fs->super);
}
/*
* If the write_bitmaps() function is present, call it to
* flush the bitmaps. This is done this way so that a simple
* program that doesn't mess with the bitmaps doesn't need to
* drag in the bitmaps.c code.
*/
if (fs->write_bitmaps) {
retval = fs->write_bitmaps(fs);
if (retval)
return retval;
}
return 0;
}
errcode_t ext2fs_close(ext2_filsys fs)
{
errcode_t retval;
if (fs->flags & EXT2_FLAG_DIRTY) {
retval = ext2fs_flush(fs);
if (retval)
return retval;
}
ext2fs_free(fs);
return 0;
}

116
lib/ext2fs/expanddir.c Normal file
View File

@ -0,0 +1,116 @@
/*
* expand.c --- expand an ext2fs directory
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include "ext2fs.h"
struct expand_dir_struct {
int done;
errcode_t err;
};
static int expand_dir_proc(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
void *private)
{
struct expand_dir_struct *es = (struct expand_dir_struct *) private;
blk_t new_blk;
static blk_t last_blk = 0;
char *block;
errcode_t retval;
int group;
if (*blocknr) {
last_blk = *blocknr;
return 0;
}
retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
if (blockcnt > 0) {
retval = ext2fs_new_dir_block(fs, 0, 0, &block);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
es->done = 1;
} else {
block = malloc(fs->blocksize);
if (!block) {
es->err = ENOMEM;
return BLOCK_ABORT;
}
memset(block, 0, fs->blocksize);
}
retval = io_channel_write_blk(fs->io, new_blk, 1, block);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
free(block);
*blocknr = new_blk;
ext2fs_mark_block_bitmap(fs, fs->block_map, new_blk);
ext2fs_mark_bb_dirty(fs);
group = ext2fs_group_of_blk(fs, new_blk);
fs->group_desc[group].bg_free_blocks_count--;
fs->super->s_free_blocks_count--;
ext2fs_mark_super_dirty(fs);
if (es->done)
return (BLOCK_CHANGED | BLOCK_ABORT);
else
return BLOCK_CHANGED;
}
errcode_t ext2fs_expand_dir(ext2_filsys fs, ino_t dir)
{
errcode_t retval;
struct expand_dir_struct es;
struct ext2_inode inode;
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
retval = ext2fs_check_directory(fs, dir);
if (retval)
return retval;
es.done = 0;
es.err = 0;
retval = ext2fs_block_iterate(fs, dir, BLOCK_FLAG_APPEND,
0, expand_dir_proc, &es);
if (es.err)
return es.err;
if (!es.done)
return EXT2_ET_EXPAND_DIR_ERR;
/*
* Update the size and block count fields in the inode.
*/
retval = ext2fs_read_inode(fs, dir, &inode);
if (retval)
return retval;
inode.i_size += fs->blocksize;
inode.i_blocks += fs->blocksize / 512;
retval = ext2fs_write_inode(fs, dir, &inode);
if (retval)
return retval;
return 0;
}

68
lib/ext2fs/ext2_err.c Normal file
View File

@ -0,0 +1,68 @@
/*
* ext2_err.c:
* This file is automatically generated; please do not edit it.
*/
#ifdef __STDC__
#define NOARGS void
#else
#define NOARGS
#define const
#endif
static const char * const text[] = {
"EXT2FS Library version 0.0",
"Bad magic number in super-block",
"Can't seek to superblock",
"Can't read superblock",
"Can't write superblock",
"Attempt to write to filesystem opened read-only",
"Can't read group descriptors",
"Can't write group descriptors",
"Corrupt group descriptor: bad block for block bitmap",
"Corrupt group descriptor: bad block for inode bitmap",
"Corrupt group descriptor: bad block for inode table",
"Can't write an inode bitmap",
"Can't read an inode bitmap",
"Can't write an block bitmap",
"Can't read an block bitmap",
"Can't write an inode table",
"Can't read an inode table",
"Can't read next inode",
"Filesystem has unexpected block size",
"EXT2 directory corrupted",
"Attempt to read block from filesystem resulted in short read",
"Attempt to write block from filesystem resulted in short write",
"No free space in the directory",
"Inode bitmap not loaded",
"BLOCK bitmap not loaded",
"Illegal inode number",
"Illegal block number",
"Internal error in ext2fs_expand_dir",
"Not enough space to build proposed filesystem",
0
};
struct error_table {
char const * const * msgs;
long base;
int n_msgs;
};
struct et_list {
struct et_list *next;
const struct error_table * table;
};
extern struct et_list *_et_list;
static const struct error_table et = { text, 2133571328L, 29 };
static struct et_list link = { 0, 0 };
void initialize_ext2_error_table (NOARGS);
void initialize_ext2_error_table (NOARGS) {
if (!link.table) {
link.next = _et_list;
link.table = &et;
_et_list = &link;
}
}

95
lib/ext2fs/ext2_err.et Normal file
View File

@ -0,0 +1,95 @@
#
# Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
# under the terms of the GNU Public License.
#
error_table ext2
ec EXT2_ET_BASE,
"EXT2FS Library version 0.0"
ec EXT2_ET_BAD_MAGIC,
"Bad magic number in super-block"
ec EXT2_ET_SB_LSEEK,
"Can't seek to superblock"
ec EXT2_ET_SB_READ,
"Can't read superblock"
ec EXT2_ET_SB_WRITE,
"Can't write superblock"
ec EXT2_ET_RO_FILSYS,
"Attempt to write to filesystem opened read-only"
ec EXT2_ET_GDESC_READ,
"Can't read group descriptors"
ec EXT2_ET_GDESC_WRITE,
"Can't write group descriptors"
ec EXT2_ET_GDESC_BAD_BLOCK_MAP,
"Corrupt group descriptor: bad block for block bitmap"
ec EXT2_ET_GDESC_BAD_INODE_MAP,
"Corrupt group descriptor: bad block for inode bitmap"
ec EXT2_ET_GDESC_BAD_INODE_TABLE,
"Corrupt group descriptor: bad block for inode table"
ec EXT2_ET_INODE_BITMAP_WRITE,
"Can't write an inode bitmap"
ec EXT2_ET_INODE_BITMAP_READ,
"Can't read an inode bitmap"
ec EXT2_ET_BLOCK_BITMAP_WRITE,
"Can't write an block bitmap"
ec EXT2_ET_BLOCK_BITMAP_READ,
"Can't read an block bitmap"
ec EXT2_ET_INODE_TABLE_WRITE,
"Can't write an inode table"
ec EXT2_ET_INODE_TABLE_READ,
"Can't read an inode table"
ec EXT2_ET_NEXT_INODE_READ,
"Can't read next inode"
ec EXT2_ET_UNEXPECTED_BLOCK_SIZE,
"Filesystem has unexpected block size"
ec EXT2_ET_DIR_CORRUPTED,
"EXT2 directory corrupted"
ec EXT2_ET_SHORT_READ,
"Attempt to read block from filesystem resulted in short read"
ec EXT2_ET_SHORT_WRITE,
"Attempt to write block from filesystem resulted in short write"
ec EXT2_ET_DIR_NO_SPACE,
"No free space in the directory"
ec EXT2_ET_NO_INODE_BITMAP,
"Inode bitmap not loaded"
ec EXT2_ET_NO_BLOCK_BITMAP,
"BLOCK bitmap not loaded"
ec EXT2_ET_BAD_INODE_NUM,
"Illegal inode number"
ec EXT2_ET_BAD_BLOCK_NUM,
"Illegal block number"
ec EXT2_ET_EXPAND_DIR_ERR,
"Internal error in ext2fs_expand_dir"
ec EXT2_ET_TOOSMALL,
"Not enough space to build proposed filesystem"
end

46
lib/ext2fs/ext2_err.h Normal file
View File

@ -0,0 +1,46 @@
/*
* ext2_err.h:
* This file is automatically generated; please do not edit it.
*/
#ifdef __STDC__
#define NOARGS void
#else
#define NOARGS
#define const
#endif
#define EXT2_ET_BASE (2133571328L)
#define EXT2_ET_BAD_MAGIC (2133571329L)
#define EXT2_ET_SB_LSEEK (2133571330L)
#define EXT2_ET_SB_READ (2133571331L)
#define EXT2_ET_SB_WRITE (2133571332L)
#define EXT2_ET_RO_FILSYS (2133571333L)
#define EXT2_ET_GDESC_READ (2133571334L)
#define EXT2_ET_GDESC_WRITE (2133571335L)
#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571336L)
#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571337L)
#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571338L)
#define EXT2_ET_INODE_BITMAP_WRITE (2133571339L)
#define EXT2_ET_INODE_BITMAP_READ (2133571340L)
#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571341L)
#define EXT2_ET_BLOCK_BITMAP_READ (2133571342L)
#define EXT2_ET_INODE_TABLE_WRITE (2133571343L)
#define EXT2_ET_INODE_TABLE_READ (2133571344L)
#define EXT2_ET_NEXT_INODE_READ (2133571345L)
#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571346L)
#define EXT2_ET_DIR_CORRUPTED (2133571347L)
#define EXT2_ET_SHORT_READ (2133571348L)
#define EXT2_ET_SHORT_WRITE (2133571349L)
#define EXT2_ET_DIR_NO_SPACE (2133571350L)
#define EXT2_ET_NO_INODE_BITMAP (2133571351L)
#define EXT2_ET_NO_BLOCK_BITMAP (2133571352L)
#define EXT2_ET_BAD_INODE_NUM (2133571353L)
#define EXT2_ET_BAD_BLOCK_NUM (2133571354L)
#define EXT2_ET_EXPAND_DIR_ERR (2133571355L)
#define EXT2_ET_TOOSMALL (2133571356L)
extern void initialize_ext2_error_table (NOARGS);
#define ERROR_TABLE_BASE_ext2 (2133571328L)
/* for compatibility with older versions... */
#define init_ext2_err_tbl initialize_ext2_error_table
#define ext2_err_base ERROR_TABLE_BASE_ext2

Some files were not shown because too many files have changed in this diff Show More