mirror of https://github.com/vitalif/e2fsprogs
commit
3839e65723
|
@ -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.
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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>.
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
||||
|
||||
|
||||
|
|
@ -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)
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,42 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Test script for e2fsck
|
||||
#
|
||||
|
||||
FSCK=../e2fsck
|
||||
SECOND_FSCK=$FSCK
|
||||
FSCK_OPT=-yft
|
||||
SECOND_FSCK_OPT=$FSCK_OPT
|
||||
|
||||
#
|
||||
# Uncomment to test against original e2fsck
|
||||
#
|
||||
#FSCK=/u4/src/e2fsprogs-0.3c/e2fsck
|
||||
#FSCK_OPT=-af
|
||||
|
||||
OUTFILE=test_script.log
|
||||
|
||||
cp /dev/null $OUTFILE
|
||||
|
||||
for i in *.img.gz
|
||||
do
|
||||
echo -n "Testing $i... "
|
||||
echo "Testing $i..." >> $OUTFILE
|
||||
gunzip < $i > /tmp/$i.$$
|
||||
echo $FSCK $FSCK_OPT /tmp/$i.$$ >> $OUTFILE
|
||||
$FSCK $FSCK_OPT /tmp/$i.$$ >> $OUTFILE 2>&1
|
||||
status=$?
|
||||
echo Exit status is $status >> $OUTFILE
|
||||
echo " " >> $OUTFILE
|
||||
echo -n "Exit status $status "
|
||||
echo Running e2fsck again.... >> $OUTFILE
|
||||
echo $SECOND_FSCK $SECOND_FSCK_OPT /tmp/$i.$$ >> $OUTFILE
|
||||
$SECOND_FSCK $SECOND_FSCK_OPT /tmp/$i.$$ >> $OUTFILE 2>&1
|
||||
status=$?
|
||||
echo Exit status is $status >> $OUTFILE
|
||||
echo Exit status $status
|
||||
rm /tmp/$i.$$
|
||||
echo "---------------------------------------------------" >> $OUTFILE
|
||||
done
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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];
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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)");
|
||||
}
|
||||
}
|
|
@ -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, "-");
|
||||
}
|
|
@ -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");
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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".
|
|
@ -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;
|
||||
}
|
|
@ -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) */
|
|
@ -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
|
|
@ -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".
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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.
|
||||
|
||||
*/
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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…
Reference in New Issue