mirror of
https://gitee.com/openharmony/third_party_e2fsprogs
synced 2025-02-25 22:37:39 +00:00
Many files:
Checkin of e2fsprogs 0.5b
This commit is contained in:
commit
3839e65723
34
INSTALL
Normal file
34
INSTALL
Normal 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
57
MCONFIG
Normal 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
61
Makefile
Normal 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
42
README
Normal 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
36
debugfs/.depend
Normal 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
42
debugfs/Makefile
Normal 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
98
debugfs/debug_cmds.ct
Normal 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
133
debugfs/debugfs.8
Normal 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
1142
debugfs/debugfs.c
Normal file
File diff suppressed because it is too large
Load Diff
18
debugfs/debugfs.h
Normal file
18
debugfs/debugfs.h
Normal 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
157
debugfs/icheck.c
Normal 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
173
debugfs/ncheck.c
Normal 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
94
debugfs/util.c
Normal 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
229
e2fsck/.depend
Normal 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
53
e2fsck/CHANGES
Normal 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
82
e2fsck/Makefile
Normal 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
126
e2fsck/badblocks.c
Normal 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
120
e2fsck/dirinfo.c
Normal 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
127
e2fsck/e2fsck.8
Normal 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
481
e2fsck/e2fsck.c
Normal 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
176
e2fsck/e2fsck.h
Normal 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
111
e2fsck/ehandler.c
Normal 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
51
e2fsck/flushb.c
Normal 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
59
e2fsck/images/README
Normal 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
BIN
e2fsck/images/baddir.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/badinode.img.gz
Normal file
BIN
e2fsck/images/badinode.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/badlkcnt.img.gz
Normal file
BIN
e2fsck/images/badlkcnt.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/badroot.img.gz
Normal file
BIN
e2fsck/images/badroot.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/badtable.img.gz
Normal file
BIN
e2fsck/images/badtable.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/bbfile.img.gz
Normal file
BIN
e2fsck/images/bbfile.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/bitmaps.img.gz
Normal file
BIN
e2fsck/images/bitmaps.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/dirlink.img.gz
Normal file
BIN
e2fsck/images/dirlink.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/dup.img.gz
Normal file
BIN
e2fsck/images/dup.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/dup2.img.gz
Normal file
BIN
e2fsck/images/dup2.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/end-bitmap.img.gz
Normal file
BIN
e2fsck/images/end-bitmap.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/expand.img.gz
Normal file
BIN
e2fsck/images/expand.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/lpf.img.gz
Normal file
BIN
e2fsck/images/lpf.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/mke2fs2b.img.gz
Normal file
BIN
e2fsck/images/mke2fs2b.img.gz
Normal file
Binary file not shown.
BIN
e2fsck/images/noroot.img.gz
Normal file
BIN
e2fsck/images/noroot.img.gz
Normal file
Binary file not shown.
42
e2fsck/images/test_script
Normal file
42
e2fsck/images/test_script
Normal 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
|
||||
|
||||
|
1289
e2fsck/images/test_script.log
Normal file
1289
e2fsck/images/test_script.log
Normal file
File diff suppressed because it is too large
Load Diff
231
e2fsck/malloc.h
Normal file
231
e2fsck/malloc.h
Normal 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
37
e2fsck/mtrace.awk
Normal 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
158
e2fsck/mtrace.c
Normal 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
894
e2fsck/pass1.c
Normal 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
640
e2fsck/pass1b.c
Normal 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
631
e2fsck/pass2.c
Normal 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
684
e2fsck/pass3.c
Normal 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
70
e2fsck/pass4.c
Normal 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
328
e2fsck/pass5.c
Normal 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
240
e2fsck/util.c
Normal 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
77
lib/e2p/.depend
Normal 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
66
lib/e2p/Makefile
Normal 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
20
lib/e2p/e2p.h
Normal 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
37
lib/e2p/fgetflags.c
Normal 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
37
lib/e2p/fgetversion.c
Normal 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
37
lib/e2p/fsetflags.c
Normal 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
37
lib/e2p/fsetversion.c
Normal 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
27
lib/e2p/getflags.c
Normal 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
27
lib/e2p/getversion.c
Normal 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
42
lib/e2p/iod.c
Normal 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
52
lib/e2p/ls.c
Normal 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
39
lib/e2p/pe.c
Normal 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
40
lib/e2p/pf.c
Normal 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
31
lib/e2p/ps.c
Normal 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
27
lib/e2p/setflags.c
Normal 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
27
lib/e2p/setversion.c
Normal 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
13
lib/et/.depend
Normal 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
85
lib/et/Makefile
Normal 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
96
lib/et/com_err.3
Normal 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
127
lib/et/com_err.c
Normal 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
38
lib/et/com_err.h
Normal 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
554
lib/et/com_err.texinfo
Normal 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
79
lib/et/compile_et.1
Normal 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
11
lib/et/compile_et.sh
Normal 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
25
lib/et/config_script
Normal 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
72
lib/et/error_message.c
Normal 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
30
lib/et/error_table.h
Normal 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
185
lib/et/et_c.awk
Normal 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
157
lib/et/et_h.awk
Normal 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
43
lib/et/et_name.c
Normal 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
55
lib/et/init_et.c
Normal 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
22
lib/et/internal.h
Normal 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
|
19
lib/et/mit-sipb-copyright.h
Normal file
19
lib/et/mit-sipb-copyright.h
Normal 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
2077
lib/et/texinfo.tex
Normal file
File diff suppressed because it is too large
Load Diff
47
lib/et/vfprintf.c
Normal file
47
lib/et/vfprintf.c
Normal 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
350
lib/ext2fs/.depend
Normal 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
80
lib/ext2fs/Makefile
Normal 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
125
lib/ext2fs/alloc.c
Normal 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
130
lib/ext2fs/badblocks.c
Normal 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
232
lib/ext2fs/bb_inode.c
Normal 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
258
lib/ext2fs/bitmaps.c
Normal 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
95
lib/ext2fs/bitops.c
Normal 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
172
lib/ext2fs/bitops.h
Normal 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
223
lib/ext2fs/block.c
Normal 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
88
lib/ext2fs/closefs.c
Normal 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
116
lib/ext2fs/expanddir.c
Normal 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
68
lib/ext2fs/ext2_err.c
Normal 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
95
lib/ext2fs/ext2_err.et
Normal 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
46
lib/ext2fs/ext2_err.h
Normal 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
Loading…
x
Reference in New Issue
Block a user