Imported reiserfsprogs-3.6.20

This commit is contained in:
Jeff Mahoney committed 2012-10-11 11:32:09 -04:00
1 parent 0ed773997f
commit dac518d099
189 files changed
+43353 -29787

No files matched your search

-5
View File
@@ -1,5 +0,0 @@
noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = io.c misc.c
##reiserfs.c
-375
View File
@@ -1,375 +0,0 @@
# Makefile.in generated by automake 1.7.6 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_triplet = @host@
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
UUID_LIBS = @UUID_LIBS@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = io.c misc.c
subdir = lib
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
libmisc_a_AR = $(AR) cru
libmisc_a_LIBADD =
am_libmisc_a_OBJECTS = io.$(OBJEXT) misc.$(OBJEXT)
libmisc_a_OBJECTS = $(am_libmisc_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/io.Po ./$(DEPDIR)/misc.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DIST_SOURCES = $(libmisc_a_SOURCES)
DIST_COMMON = Makefile.am Makefile.in
SOURCES = $(libmisc_a_SOURCES)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu lib/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
AR = ar
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libmisc.a: $(libmisc_a_OBJECTS) $(libmisc_a_DEPENDENCIES)
-rm -f libmisc.a
$(libmisc_a_AR) libmisc.a $(libmisc_a_OBJECTS) $(libmisc_a_LIBADD)
$(RANLIB) libmisc.a
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
distclean-depend:
-rm -rf ./$(DEPDIR)
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`
uninstall-info-am:
ETAGS = etags
ETAGSFLAGS =
CTAGS = ctags
CTAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
distclean: distclean-am
distclean-am: clean-am distclean-compile distclean-depend \
distclean-generic distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-noinstLIBRARIES ctags distclean distclean-compile \
distclean-depend distclean-generic distclean-tags distdir dvi \
dvi-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
-960
View File
@@ -1,960 +0,0 @@
/*
* Copyright 1996-2004 by Hans Reiser, licensing governed by
* reiserfsprogs/README
*/
#include "io.h"
#include <string.h>
#include <errno.h>
#include <asm/types.h>
void check_memory_msg (void) {
fprintf(stderr,
"\nThe problem has occurred looks like a hardware problem (perhaps\n"
"memory). Send us the bug report only if the second run dies at\n"
"the same place with the same block number.\n");
}
void check_hd_msg (void) {
fprintf(stderr,
"\nThe problem has occurred looks like a hardware problem. If you have\n"
"bad blocks, we advise you to get a new hard drive, because once you\n"
"get one bad block that the disk drive internals cannot hide from\n"
"your sight,the chances of getting more are generally said to become\n"
"much higher (precise statistics are unknown to us), and this disk\n"
"drive is probably not expensive enough for you to you to risk your\n"
"time and data on it. If you don't want to follow that follow that\n"
"advice then if you have just a few bad blocks, try writing to the\n"
"bad blocks and see if the drive remaps the bad blocks (that means\n"
"it takes a block it has in reserve and allocates it for use for\n"
"of that block number). If it cannot remap the block, use badblock\n"
"option (-B) with reiserfs utils to handle this block correctly.\n");
}
static int is_bad_block (unsigned long block)
{
#ifdef IO_FAILURE_EMULATION
/* this array similates bad blocks on the device */
unsigned long bad_blocks [] =
{
8208, 8209, 8210
/*, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19*/
};
int i;
for (i = 0; i < sizeof (bad_blocks) / sizeof (bad_blocks[0]); i ++)
if (bad_blocks [i] == block)
return 1;
#endif
return 0;
}
/* All buffers are in double linked cycled list. If getblk found buffer with
wanted block number in hash queue it moves buffer to the end of list. */
static int g_nr_buffers;
static unsigned long buffers_memory;
/* create buffers until we spend this fraction of system memory, this
** is a hard limit on the amount of buffer ram used
*/
#define BUFFER_MEMORY_FRACTION 10
/* number of bytes in local buffer cache before we start forcing syncs
** of dirty data and reusing unused buffers instead of allocating new
** ones. If a flush doesn't find reusable buffers, new ones are
** still allocated up to the BUFFER_MEMORY_FRACTION percentage
**
*/
#define BUFFER_SOFT_LIMIT (500 * 1024)
static unsigned long buffer_soft_limit = BUFFER_SOFT_LIMIT;
#define NR_HASH_QUEUES 4096
static struct buffer_head * g_a_hash_queues [NR_HASH_QUEUES];
static struct buffer_head * Buffer_list_head;
static struct buffer_head * g_free_buffers = NULL ;
static struct buffer_head * g_buffer_heads;
static int buffer_hits = 0 ;
static int buffer_misses = 0 ;
static int buffer_reads = 0 ;
static int buffer_writes = 0 ;
static void _show_buffers(struct buffer_head **list, int dev, unsigned long size) {
int all = 0;
int dirty = 0;
int in_use = 0; /* count != 0 */
int free = 0;
struct buffer_head * next;
next = *list;
if (!next)
return ;
for (;;) {
if (next->b_dev == dev && next->b_size == size) {
all ++;
if (next->b_count != 0) {
in_use ++;
}
if (buffer_dirty (next)) {
dirty ++;
}
if (buffer_clean (next) && next->b_count == 0) {
free ++;
}
}
next = next->b_next;
if (next == *list)
break;
}
printf("show_buffers (dev %d, size %lu): free %d, count != 0 %d, dirty %d, "
"all %d\n", dev, size, free, in_use, dirty, all);
}
static void show_buffers (int dev, int size)
{
_show_buffers(&Buffer_list_head, dev, size) ;
_show_buffers(&g_free_buffers, dev, size) ;
}
static void insert_into_hash_queue (struct buffer_head * bh)
{
int index = bh->b_blocknr % NR_HASH_QUEUES;
if (bh->b_hash_prev || bh->b_hash_next)
die ("insert_into_hash_queue: hash queue corrupted");
if (g_a_hash_queues[index]) {
g_a_hash_queues[index]->b_hash_prev = bh;
bh->b_hash_next = g_a_hash_queues[index];
}
g_a_hash_queues[index] = bh;
}
static void remove_from_hash_queue (struct buffer_head * bh)
{
if (bh->b_hash_next == 0 && bh->b_hash_prev == 0 && bh != g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES])
/* (b_dev == -1) ? */
return;
if (bh == g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES]) {
if (bh->b_hash_prev != 0)
die ("remove_from_hash_queue: hash queue corrupted");
g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES] = bh->b_hash_next;
}
if (bh->b_hash_next)
bh->b_hash_next->b_hash_prev = bh->b_hash_prev;
if (bh->b_hash_prev)
bh->b_hash_prev->b_hash_next = bh->b_hash_next;
bh->b_hash_prev = bh->b_hash_next = 0;
}
static void put_buffer_list_end (struct buffer_head **list,
struct buffer_head * bh)
{
struct buffer_head * last = 0;
if (bh->b_prev || bh->b_next)
die ("put_buffer_list_end: buffer list corrupted");
if (*list == 0) {
bh->b_next = bh;
bh->b_prev = bh;
*list = bh;
} else {
last = (*list)->b_prev;
bh->b_next = last->b_next;
bh->b_prev = last;
last->b_next->b_prev = bh;
last->b_next = bh;
}
}
static void remove_from_buffer_list (struct buffer_head **list,
struct buffer_head * bh)
{
if (bh == bh->b_next) {
*list = 0;
} else {
bh->b_prev->b_next = bh->b_next;
bh->b_next->b_prev = bh->b_prev;
if (bh == *list)
*list = bh->b_next;
}
bh->b_next = bh->b_prev = 0;
}
static void put_buffer_list_head (struct buffer_head **list,
struct buffer_head * bh)
{
put_buffer_list_end (list, bh);
*list = bh;
}
/*
#include <sys/mman.h>
static size_t estimate_memory_amount (void)
{
size_t len = 1;
size_t max = 0;
void * addr;
while (len > 0) {
addr = mmap (0, len, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (addr == MAP_FAILED) {
if (errno != ENOMEM)
die ("mmap failed: %s\n", strerror(errno));
break;
}
if (mlock (addr, len) != 0) {
if (errno == EPERM)
die ("No permission to run mlock");
break;
}
munlock (addr, len);
munmap (addr, len);
max = len;
len *= 2;
}
// * If we've looped, we don't want to return 0, we want to return the
// * last successful len before we looped. In the event that mmap/mlock
// * failed for len = 1, max will still be 0, so we don't get an invalid
// * result
return max;
}
*/
#define GROW_BUFFERS__NEW_BUFERS_PER_CALL 10
/* creates number of new buffers and insert them into head of buffer list */
static int grow_buffers (int size)
{
int i;
struct buffer_head * bh, * tmp;
/* get memory for array of buffer heads */
bh = (struct buffer_head *)getmem (GROW_BUFFERS__NEW_BUFERS_PER_CALL *
sizeof (struct buffer_head) + sizeof (struct buffer_head *));
if (g_buffer_heads == 0)
g_buffer_heads = bh;
else {
/* link new array to the end of array list */
tmp = g_buffer_heads;
while (*(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL) != 0)
tmp = *(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL);
*(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL) = bh;
}
for (i = 0; i < GROW_BUFFERS__NEW_BUFERS_PER_CALL; i ++) {
tmp = bh + i;
memset (tmp, 0, sizeof (struct buffer_head));
tmp->b_data = getmem (size);
if (tmp->b_data == 0)
die ("grow_buffers: no memory for new buffer data");
tmp->b_dev = -1;
tmp->b_size = size;
put_buffer_list_head (&g_free_buffers, tmp);
}
buffers_memory += GROW_BUFFERS__NEW_BUFERS_PER_CALL * size;
g_nr_buffers += GROW_BUFFERS__NEW_BUFERS_PER_CALL;
return GROW_BUFFERS__NEW_BUFERS_PER_CALL;
}
struct buffer_head *find_buffer(int dev, unsigned long block, unsigned long size)
{
struct buffer_head * next;
next = g_a_hash_queues[block % NR_HASH_QUEUES];
for (;;) {
struct buffer_head *tmp = next;
if (!next)
break;
next = tmp->b_hash_next;
if (tmp->b_blocknr != block || tmp->b_size != size || tmp->b_dev != dev)
continue;
next = tmp;
break;
}
return next;
}
static struct buffer_head * get_free_buffer (struct buffer_head **list,
unsigned long size)
{
struct buffer_head * next;
next = *list;
if (!next)
return 0;
for (;;) {
if (!next)
die ("get_free_buffer: buffer list is corrupted");
if (next->b_count == 0 && buffer_clean (next) && next->b_size == size) {
remove_from_hash_queue (next);
remove_from_buffer_list (list, next);
return next;
}
next = next->b_next;
if (next == *list)
break;
}
return 0;
}
/* to_write == 0 when all blocks have to be flushed. Otherwise - write only
buffers with b_count == 0 */
static int sync_buffers (struct buffer_head **list, int dev, int to_write) {
struct buffer_head * next;
int written = 0;
restart:
next = *list;
if (!next)
return 0;
for (;;) {
if (!next)
die ("sync_buffers: buffer list is corrupted");
if (next->b_dev == dev && buffer_dirty (next) && buffer_uptodate (next)) {
if ((to_write == 0 || next->b_count == 0) && !buffer_do_not_flush (next)) {
bwrite (next);
}
}
/* if this buffer is reusable, put it onto the end of the free list */
if (next->b_count == 0 && buffer_clean(next)) {
remove_from_hash_queue (next);
remove_from_buffer_list (list, next);
put_buffer_list_end (&g_free_buffers, next);
written++ ;
if (written == to_write)
return written;
goto restart;
}
if (to_write && written >= to_write)
return written;
next = next->b_next;
if (next == *list)
break;
}
return written;
}
void flush_buffers (int dev)
{
if (dev == -1)
die ("flush_buffers: device is not specified");
sync_buffers (&Buffer_list_head, dev, 0/*all*/);
buffer_soft_limit = BUFFER_SOFT_LIMIT;
}
struct buffer_head * getblk (int dev, unsigned long block, int size)
{
struct buffer_head * bh;
bh = find_buffer (dev, block, size);
if (bh) {
/* move the buffer to the end of list */
/*checkmem (bh->b_data, bh->b_size);*/
remove_from_buffer_list (&Buffer_list_head, bh);
put_buffer_list_end (&Buffer_list_head, bh);
bh->b_count ++;
buffer_hits++ ;
return bh;
}
buffer_misses++ ;
bh = get_free_buffer (&g_free_buffers, size);
if (bh == NULL) {
if (buffers_memory >= buffer_soft_limit) {
if (sync_buffers (&Buffer_list_head, dev, 32) == 0) {
grow_buffers(size);
buffer_soft_limit = buffers_memory +
GROW_BUFFERS__NEW_BUFERS_PER_CALL * size;
}
} else {
if (grow_buffers(size) == 0)
sync_buffers (&Buffer_list_head, dev, 32);
}
bh = get_free_buffer (&g_free_buffers, size);
if (bh == NULL) {
show_buffers (dev, size);
die ("getblk: no free buffers after grow_buffers "
"and refill (%d)", g_nr_buffers);
}
}
bh->b_count = 1;
bh->b_dev = dev;
bh->b_size = size;
bh->b_blocknr = block;
bh->b_end_io = NULL ;
memset (bh->b_data, 0, size);
misc_clear_bit(BH_Dirty, &bh->b_state);
misc_clear_bit(BH_Uptodate, &bh->b_state);
put_buffer_list_end (&Buffer_list_head, bh);
insert_into_hash_queue (bh);
/*checkmem (bh->b_data, bh->b_size);*/
return bh;
}
void brelse (struct buffer_head * bh)
{
if (bh == 0)
return;
if (bh->b_count == 0)
die ("brelse: can not free a free buffer %lu", bh->b_blocknr);
/*checkmem (bh->b_data, get_mem_size (bh->b_data));*/
bh->b_count --;
}
void bforget (struct buffer_head * bh)
{
if (bh) {
bh->b_state = 0;
brelse (bh);
remove_from_hash_queue (bh);
remove_from_buffer_list(&Buffer_list_head, bh);
put_buffer_list_head(&Buffer_list_head, bh);
}
}
/* Returns 0 on success; 1 - end of file; 0 - OK. */
static int f_read(struct buffer_head * bh)
{
unsigned long long offset;
ssize_t bytes;
buffer_reads++ ;
offset = (unsigned long long)bh->b_size * bh->b_blocknr;
if (lseek (bh->b_dev, offset, SEEK_SET) < 0)
return -1;
bytes = read (bh->b_dev, bh->b_data, bh->b_size);
return bytes < 0 ? -1 : (bytes != (ssize_t)bh->b_size ? 1 : 0);
}
struct buffer_head * bread (int dev, unsigned long block, size_t size)
{
struct buffer_head * bh;
int ret;
if (is_bad_block (block))
return 0;
bh = getblk (dev, block, size);
/*checkmem (bh->b_data, get_mem_size(bh->b_data));*/
if (buffer_uptodate (bh))
return bh;
ret = f_read(bh);
if (ret > 0) {
die ("%s: End of file, cannot read the block (%lu).\n",
__FUNCTION__, block);
} else if (ret < 0) {
/* BAD BLOCK LIST SUPPORT
* die ("%s: Cannot read a block # %lu. Specify list of badblocks\n",*/
if (errno == EIO) {
check_hd_msg();
die ("%s: Cannot read the block (%lu): (%s).\n",
__FUNCTION__, block, strerror(errno));
} else {
fprintf (stderr, "%s: Cannot read the block (%lu): (%s).\n",
__FUNCTION__, block, strerror(errno));
return NULL;
}
}
mark_buffer_uptodate (bh, 0);
return bh;
}
#define ROLLBACK_FILE_START_MAGIC "_RollBackFileForReiserfsFSCK"
static struct block_handler * rollback_blocks_array;
static __u32 rollback_blocks_number = 0;
static FILE * s_rollback_file = 0;
static FILE * log_file;
static int do_rollback = 0;
static char * rollback_data;
static int rollback_blocksize;
void init_rollback_file (char * rollback_file, int *blocksize, FILE * log) {
char * string;
struct stat buf;
if (rollback_file == NULL)
return;
stat(rollback_file, &buf);
s_rollback_file = fopen (rollback_file, "w+");
if (s_rollback_file == NULL) {
fprintf (stderr, "Cannot create file %s, work without a rollback file\n", rollback_file);
return;
}
rollback_blocksize = *blocksize;
string = ROLLBACK_FILE_START_MAGIC;
fwrite (string, 28, 1, s_rollback_file);
fwrite (&rollback_blocksize, sizeof (rollback_blocksize), 1, s_rollback_file);
fwrite (&rollback_blocks_number, sizeof (rollback_blocks_number), 1, s_rollback_file);
fflush(s_rollback_file);
rollback_data = getmem(rollback_blocksize);
// printf("\ncheckmem1");
// fflush (stdout);
// checkmem (rollback_data, get_mem_size((char *)rollback_data));
// printf(" OK");
log_file = log;
if (log_file)
fprintf (log_file, "rollback: file (%s) initialize\n", rollback_file);
do_rollback = 0;
}
#if 0
static void erase_rollback_file (char * rollback_file) {
close_rollback_file ();
unlink (rollback_file);
}
#endif
int open_rollback_file (char * rollback_file, FILE * log) {
char string [28];
struct stat buf;
if (rollback_file == NULL)
return -1;
if (stat(rollback_file, &buf)) {
fprintf (stderr, "Cannot stat rollback file (%s)\n", rollback_file);
return -1;
}
s_rollback_file = fopen (rollback_file, "r+");
if (s_rollback_file == NULL) {
fprintf (stderr, "Cannot open file (%s)\n", rollback_file);
return -1;
}
fread (string, 28, 1, s_rollback_file);
if (!strcmp (string, ROLLBACK_FILE_START_MAGIC)) {
fprintf (stderr, "Specified file (%s) does not look like a rollback file\n", rollback_file);
fclose (s_rollback_file);
s_rollback_file = 0;
return -1;
}
fread (&rollback_blocksize, sizeof (rollback_blocksize), 1, s_rollback_file);
if (rollback_blocksize <= 0) {
fprintf(stderr, "rollback: wrong rollback blocksize, exit\n");
return -1;
}
log_file = log;
if (log_file)
fprintf (log_file, "rollback: file (%s) opened\n", rollback_file);
do_rollback = 1;
return 0;
}
void close_rollback_file () {
if (s_rollback_file == 0)
return;
if (!do_rollback) {
if (fseek (s_rollback_file, 28 + sizeof(int), SEEK_SET) == (loff_t)-1)
return;
fwrite (&rollback_blocks_number, sizeof (rollback_blocksize), 1, s_rollback_file);
if (log_file != 0)
fprintf (log_file, "rollback: %d blocks backed up\n", rollback_blocks_number);
}
fclose (s_rollback_file);
freemem (rollback_data);
freemem (rollback_blocks_array);
// fprintf (stdout, "rollback: (%u) blocks saved, \n", rollback_blocks_number);
/* for (i = 0; i < rollback_blocks_number; i++)
fprintf(stdout, "device (%Lu), block number (%u)\n",
rollback_blocks_array [i].device,
rollback_blocks_array [i].blocknr);
fprintf(stdout, "\n");
*/
}
void do_fsck_rollback (int fd_device, int fd_journal_device, FILE * progress) {
long long int offset;
struct stat buf;
int descriptor;
ssize_t retval;
int count_failed = 0;
int count_rollbacked = 0;
int b_dev;
int n_dev = 0;
int n_journal_dev = 0;
unsigned long total, done = 0;
if (fd_device == 0) {
fprintf(stderr, "rollback: unspecified device, exit\n");
return;
}
if (fd_journal_device) {
if (!fstat (fd_journal_device, &buf)) {
n_journal_dev = buf.st_rdev;
} else {
fprintf(stderr, "rollback: specified journal device cannot be stated\n");
}
}
if (!fstat (fd_device, &buf)) {
n_dev = buf.st_rdev;
} else {
fprintf(stderr, "rollback: specified device cannot be stated, exit\n");
return;
}
rollback_data = getmem (rollback_blocksize);
// printf("\ncheckmem2");
// fflush (stdout);
// checkmem (rollback_data, get_mem_size((char *)rollback_data));
// printf(" OK");
fread (&rollback_blocks_number, sizeof (rollback_blocks_number), 1, s_rollback_file);
total = rollback_blocks_number;
while (1) {
print_how_far (progress, &done, rollback_blocks_number, 1, 0/*not quiet*/);
descriptor = 0;
if ((retval = fread (&b_dev, sizeof (b_dev), 1, s_rollback_file)) <= 0) {
if (retval)
fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
break;
}
if ((retval = fread (&offset, sizeof (offset), 1, s_rollback_file)) <= 0) {
if (retval)
fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
break;
}
if ((retval = fread (rollback_data, rollback_blocksize, 1, s_rollback_file)) <= 0) {
if (retval)
fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
break;
}
if (n_dev == b_dev)
descriptor = fd_device;
if ((n_journal_dev) && (n_journal_dev == b_dev))
descriptor = fd_journal_device;
if (descriptor == 0) {
fprintf(stderr, "rollback: block from unknown device, skip block\n");
count_failed ++;
continue;
}
if (lseek (descriptor, offset, SEEK_SET) == (loff_t)-1) {
fprintf(stderr, "device cannot be lseeked, skip block\n");
count_failed ++;
continue;
}
if (write (descriptor, rollback_data, rollback_blocksize) == -1) {
fprintf (stderr, "rollback: write %d bytes returned error "
"(block=%lld, dev=%d): %s\n", rollback_blocksize,
offset/rollback_blocksize, b_dev, strerror (errno));
count_failed ++;
} else {
count_rollbacked ++;
/*if you want to know what gets rollbacked, uncomment it*/
/* if (log_file != 0 && log_file != stdout)
fprintf (log_file, "rollback: block %Lu of device %Lu was restored\n",
(loff_t)offset/rollback_blocksize, b_dev);
*/
// fprintf (stdout, "rollback: block (%Ld) written\n", (loff_t)offset/rollback_blocksize);
}
}
printf ("\n");
if (log_file != 0)
fprintf (log_file, "rollback: (%u) blocks restored\n", count_rollbacked);
}
/*
static void rollback__mark_block_saved (struct block_handler * rb_e) {
if (rollback_blocks_array == NULL)
rollback_blocks_array = getmem (ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e));
if (rollback_blocks_number == get_mem_size ((void *)rollback_blocks_array) / sizeof (*rb_e))
rollback_blocks_array = expandmem (rollback_blocks_array, get_mem_size((void *)rollback_blocks_array),
ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e));
// checkmem ((char *)rollback_blocks_array, get_mem_size((char *)rollback_blocks_array));
rollback_blocks_array[rollback_blocks_number] = *rb_e;
rollback_blocks_number ++;
qsort (rollback_blocks_array, rollback_blocks_number, sizeof (*rb_e), rollback_compare);
// printf("\ncheckmem3");
// fflush (stdout);
// checkmem ((char *)rollback_blocks_array, get_mem_size((char *)rollback_blocks_array));
// printf(" OK");
}
*/
/* for now - just make sure that bad blocks did not get here */
int bwrite (struct buffer_head * bh)
{
unsigned long long offset;
long long bytes, size;
if (is_bad_block (bh->b_blocknr)) {
fprintf (stderr, "bwrite: bad block is going to be written: %lu\n",
bh->b_blocknr);
exit(8);
}
if (!buffer_dirty (bh) || !buffer_uptodate (bh))
return 0;
buffer_writes++ ;
if (bh->b_start_io)
/* this is used by undo feature of reiserfsck */
bh->b_start_io (bh->b_blocknr);
size = bh->b_size;
offset = (loff_t)size * (loff_t)bh->b_blocknr;
if (lseek (bh->b_dev, offset, SEEK_SET) == (loff_t)-1){
fprintf (stderr, "bwrite: lseek to position %llu (block=%lu, dev=%d): %s\n",
offset, bh->b_blocknr, bh->b_dev, strerror(errno));
exit(8); /* File system errors left uncorrected */
}
if (s_rollback_file != NULL && bh->b_size == (unsigned long)rollback_blocksize) {
struct stat buf;
__u32 position;
struct block_handler block_h;
/*log previous content into the log*/
if (!fstat (bh->b_dev, &buf)) {
block_h.blocknr = bh->b_blocknr;
block_h.device = buf.st_rdev;
if (reiserfs_bin_search(&block_h, rollback_blocks_array,
rollback_blocks_number, sizeof (block_h),
&position, blockdev_list_compare)
!= POSITION_FOUND)
{
/*read initial data from the disk*/
if (read(bh->b_dev, rollback_data, bh->b_size) == (long long)bh->b_size) {
fwrite(&buf.st_rdev, sizeof (buf.st_rdev), 1, s_rollback_file);
fwrite(&offset, sizeof (offset), 1, s_rollback_file);
fwrite(rollback_data, rollback_blocksize, 1, s_rollback_file);
fflush(s_rollback_file);
blocklist__insert_in_position(&block_h, (void *)(&rollback_blocks_array),
&rollback_blocks_number, sizeof(block_h), &position);
/*if you want to know what gets saved, uncomment it*/
/* if (log_file != 0 && log_file != stdout) {
fprintf (log_file, "rollback: block %lu of device %Lu was "
"backed up\n", bh->b_blocknr, buf.st_rdev);
}
*/
} else {
fprintf (stderr, "bwrite: read (block=%lu, dev=%d): %s\n",
bh->b_blocknr, bh->b_dev, strerror (errno));
exit(8);
}
if (lseek (bh->b_dev, offset, SEEK_SET) == (loff_t)-1) {
fprintf (stderr, "bwrite: lseek to position %llu (block=%lu, "
"dev=%d): %s\n", offset, bh->b_blocknr, bh->b_dev,
strerror(errno));
exit(8);
}
}
} else {
fprintf (stderr, "bwrite: fstat of (%d) returned -1: %s\n",
bh->b_dev, strerror(errno));
}
} else if (s_rollback_file != NULL) {
fprintf (stderr, "rollback: block (%lu) has the size different from "
"the fs uses, block skipped\n", bh->b_blocknr);
}
bytes = write(bh->b_dev, bh->b_data, size);
if (bytes != size) {
fprintf (stderr, "bwrite: write %lld bytes returned %lld (block=%ld, "
"dev=%d): %s\n", size, bytes, bh->b_blocknr, bh->b_dev,
strerror(errno));
exit(8);
}
mark_buffer_clean (bh);
if (bh->b_end_io) {
bh->b_end_io(bh, 1) ;
}
return 0;
}
static int _check_and_free_buffer_list(struct buffer_head *list) {
struct buffer_head *next = list ;
int count = 0 ;
if (!list)
return 0 ;
for(;;) {
if (next->b_count != 0)
fprintf (stderr, "check_and_free_buffer_mem: not free buffer "
"(%d, %ld, %ld, %d)\n", next->b_dev, next->b_blocknr,
next->b_size, next->b_count);
if (buffer_dirty (next) && buffer_uptodate (next))
fprintf (stderr, "check_and_free_buffer_mem: dirty buffer "
"(%d %lu) found\n", next->b_dev, next->b_blocknr);
freemem (next->b_data);
count++;
next = next->b_next;
if (next == list)
break;
}
return count;
}
static void check_and_free_buffer_mem (void)
{
int count = 0;
struct buffer_head * next ;
// printf("check and free buffer mem, hits %d misses %d reads %d writes %d\n",
// buffer_hits, buffer_misses, buffer_reads, buffer_writes) ;
/*sync_buffers (0, 0);*/
count = _check_and_free_buffer_list(Buffer_list_head);
count += _check_and_free_buffer_list(g_free_buffers);
if (count != g_nr_buffers)
die ("check_and_free_buffer_mem: found %d buffers, must be %d",
count, g_nr_buffers);
/* free buffer heads */
while ((next = g_buffer_heads)) {
g_buffer_heads = *(struct buffer_head **)
(next + GROW_BUFFERS__NEW_BUFERS_PER_CALL);
freemem (next);
}
return;
}
/* */
void free_buffers (void)
{
check_and_free_buffer_mem ();
}
static void _invalidate_buffer_list(struct buffer_head *list, int dev)
{
struct buffer_head * next;
if (!list)
return;
next = list;
for (;;) {
if (next->b_dev == dev) {
if (buffer_dirty (next) || next->b_count)
fprintf (stderr, "invalidate_buffers: dirty buffer or used buffer (%d %lu) found\n",
next->b_count, next->b_blocknr);
next->b_state = 0;
remove_from_hash_queue (next);
}
next = next->b_next;
if (next == list)
break;
}
}
/* forget all buffers of the given device */
void invalidate_buffers (int dev)
{
_invalidate_buffer_list(Buffer_list_head, dev) ;
_invalidate_buffer_list(g_free_buffers, dev) ;
}
-986
View File
@@ -1,986 +0,0 @@
/*
* Copyright 1996-2004 by Hans Reiser, licensing governed by
* reiserfsprogs/README
*/
#define _GNU_SOURCE
#include "misc.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <mntent.h>
#include <sys/vfs.h>
#include <time.h>
#include <utime.h>
#include <ctype.h>
#include <linux/hdreg.h>
#include <dirent.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <signal.h>
/* Debian modifications by Ed Boraas <ed@debian.org> */
#include <sys/mount.h>
/* End Debian mods */
#define STAT_FIELD(Field, Type) \
inline Type misc_device_##Field(char *device) { \
struct stat st; \
\
if (stat(device, &st) == 0) \
return st.st_##Field; \
\
fprintf(stderr, "Stat of the device '%s' failed.", device); \
exit(8); \
}
STAT_FIELD(mode, mode_t);
STAT_FIELD(rdev, dev_t);
STAT_FIELD(size, off_t);
STAT_FIELD(blocks, blkcnt_t);
void die (char * fmt, ...)
{
static char buf[1024];
va_list args;
va_start (args, fmt);
vsprintf (buf, fmt, args);
va_end (args);
fprintf (stderr, "\n%s\n", buf);
abort ();
}
#define MEM_BEGIN "_mem_begin_"
#define MEM_END "mem_end"
#define MEM_FREED "__free_"
#define CONTROL_SIZE (strlen (MEM_BEGIN) + 1 + sizeof (int) + strlen (MEM_END) + 1)
unsigned int get_mem_size(char *p) {
char *begin;
begin = p - strlen (MEM_BEGIN) - 1 - sizeof(int);
return *(int *)(begin + strlen (MEM_BEGIN) + 1);
}
void checkmem (char * p, int size)
{
char * begin;
char * end;
begin = p - strlen (MEM_BEGIN) - 1 - sizeof (int);
if (strcmp (begin, MEM_BEGIN))
die ("checkmem: memory corrupted - invalid head sign");
if (*(int *)(begin + strlen (MEM_BEGIN) + 1) != size)
die ("checkmem: memory corrupted - invalid size");
end = begin + size + CONTROL_SIZE - strlen (MEM_END) - 1;
if (strcmp (end, MEM_END))
die ("checkmem: memory corrupted - invalid end sign");
}
void *getmem (int size)
{
char * mem;
if ((mem = mem_alloc(size)) == NULL)
die ("getmem: no more memory (%d)", size);
memset (mem, 0, size);
// checkmem (mem, size);
return mem;
}
void *mem_alloc(int size) {
char * p;
char * mem;
p = (char *)malloc (CONTROL_SIZE + size);
if (!p)
die ("getmem: no more memory (%d)", size);
/* Write the MEM_BEGIN magic in the beginning of allocated memory. */
strcpy (p, MEM_BEGIN);
p += strlen (MEM_BEGIN) + 1;
/* Write the size after the magic. */
*(int *)p = size;
p += sizeof (int);
mem = p;
p += size;
strcpy (p, MEM_END);
return mem;
}
void * expandmem (void * vp, int size, int by)
{
int allocated;
char * mem, * p = vp;
int expand_by = by;
if (p) {
checkmem (p, size);
allocated = CONTROL_SIZE + size;
p -= (strlen (MEM_BEGIN) + 1 + sizeof (int));
} else {
allocated = 0;
/* add control bytes to the new allocated area */
expand_by += CONTROL_SIZE;
}
p = realloc (p, allocated + expand_by);
if (!p)
die ("expandmem: no more memory (%d)", size);
if (!vp) {
strcpy (p, MEM_BEGIN);
}
mem = p + strlen (MEM_BEGIN) + 1 + sizeof (int);
*(int *)(p + strlen (MEM_BEGIN) + 1) = size + by;
/* fill new allocated area by 0s */
if(by > 0)
memset (mem + size, 0, by);
strcpy (mem + size + by, MEM_END);
// checkmem (mem, size + by);
return mem;
}
void freemem (void * vp)
{
char * p = vp;
int size;
if (!p)
return;
size = get_mem_size (vp);
checkmem (p, size);
p -= (strlen (MEM_BEGIN) + 1 + sizeof (int));
strcpy (p, MEM_FREED);
strcpy (p + size + CONTROL_SIZE - strlen (MEM_END) - 1, MEM_FREED);
free (p);
}
typedef int (*func_t) (char *);
/* Lookup the @file in the @mntfile. @file is mntent.mnt_fsname if @fsname
is set; mntent.mnt_dir otherwise. Return the mnt entry from the @mntfile.
Warning: if the root fs is mounted RO, the content of /etc/mtab may be
not correct. */
static struct mntent *misc_mntent_lookup(char *mntfile,
char *file,
int path)
{
struct mntent *mnt;
int name_match = 0;
struct stat st;
dev_t rdev = 0;
dev_t dev = 0;
ino_t ino = 0;
char *name;
FILE *fp;
assert(mntfile != NULL);
assert(file != NULL);
if (stat(file, &st) == 0) {
/* Devices is stated. */
if (S_ISBLK(st.st_mode)) {
rdev = st.st_rdev;
} else {
dev = st.st_dev;
ino = st.st_ino;
}
}
if ((fp = setmntent(mntfile, "r")) == NULL)
return INVAL_PTR;
while ((mnt = getmntent(fp)) != NULL) {
/* Check if names match. */
name = path ? mnt->mnt_dir : mnt->mnt_fsname;
if (strcmp(file, name) == 0)
name_match = 1;
if (stat(name, &st))
continue;
/* If names do not match, check if stats match. */
if (!name_match) {
if (rdev && S_ISBLK(st.st_mode)) {
if (rdev != st.st_rdev)
continue;
} else if (dev && !S_ISBLK(st.st_mode)) {
if (dev != st.st_dev ||
ino != st.st_ino)
continue;
} else {
continue;
}
}
/* If not path and not block device do not check anything more. */
if (!path && !rdev)
break;
if (path) {
/* Either names or stats match. Make sure the st_dev of
the path is same as @mnt_fsname device rdev. */
if (stat(mnt->mnt_fsname, &st) == 0 &&
dev == st.st_rdev)
break;
} else {
/* Either names or stats match. Make sure the st_dev of
the mount entry is same as the given device rdev. */
if (stat(mnt->mnt_dir, &st) == 0 &&
rdev == st.st_dev)
break;
}
}
endmntent (fp);
return mnt;
}
static int misc_root_mounted(char *device) {
struct stat rootst, devst;
assert(device != NULL);
if (stat("/", &rootst) != 0)
return -1;
if (stat(device, &devst) != 0)
return -1;
if (!S_ISBLK(devst.st_mode) ||
devst.st_rdev != rootst.st_dev)
return 0;
return 1;
}
static int misc_file_ro(char *file) {
if (utime(file, 0) == -1) {
if (errno == EROFS)
return 1;
}
return 0;
}
struct mntent *misc_mntent(char *device) {
int proc = 0, path = 0, root = 0;
struct mntent *mnt;
struct statfs stfs;
assert(device != NULL);
/* Check if the root. */
if (misc_root_mounted(device) == 1)
root = 1;
#ifdef __linux__
/* Check if /proc is procfs. */
if (statfs("/proc", &stfs) == 0 && stfs.f_type == 0x9fa0) {
proc = 1;
if (root) {
/* Lookup the "/" entry in /proc/mounts. Special
case as root entry can present as:
rootfs / rootfs rw 0 0
Look up the mount point in this case. */
mnt = misc_mntent_lookup("/proc/mounts", "/", 1);
} else {
/* Lookup the @device /proc/mounts */
mnt = misc_mntent_lookup("/proc/mounts", device, 0);
}
if (mnt == INVAL_PTR)
proc = 0;
else if (mnt)
return mnt;
}
#endif /* __linux__ */
#if defined(MOUNTED) || defined(_PATH_MOUNTED)
#ifndef MOUNTED
#define MOUNTED _PATH_MOUNTED
#endif
/* Check in MOUNTED (/etc/mtab) if RW. */
if (!misc_file_ro(MOUNTED)) {
path = 1;
if (root) {
mnt = misc_mntent_lookup(MOUNTED, "/", 1);
} else {
mnt = misc_mntent_lookup(MOUNTED, device, 0);
}
if (mnt == INVAL_PTR)
path = 0;
else if (mnt)
return mnt;
}
#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
/* If has not been checked in neither /proc/mounts nor /etc/mtab (or
errors have occured), return INVAL_PTR, NULL otherwise. */
return (!proc && !path) ? INVAL_PTR : NULL;
}
int misc_device_mounted(char *device) {
struct mntent *mnt;
/* Check for the "/" first to avoid any possible problem with
reflecting the root fs info in mtab files. */
if (misc_root_mounted(device) == 1) {
return misc_file_ro("/") ? MF_RO : MF_RW;
}
/* Lookup the mount entry. */
if ((mnt = misc_mntent(device)) == NULL) {
return MF_NOT_MOUNTED;
} else if (mnt == INVAL_PTR) {
return 0;
}
return hasmntopt(mnt, MNTOPT_RO) ? MF_RO : MF_RW;
}
char buf1 [100];
char buf2 [100];
void print_how_fast (unsigned long passed, unsigned long total,
int cursor_pos, int reset_time)
{
static time_t t0 = 0, t1 = 0, t2 = 0;
int speed;
int indent;
if (reset_time)
time (&t0);
time (&t1);
if (t1 != t0) {
speed = passed / (t1 - t0);
if (total - passed) {
if (t1 - t2 < 1)
return;
t2 = t1;
}
} else
speed = 0;
/* what has to be written */
if (total)
sprintf (buf1, "left %lu, %d /sec", total - passed, speed);
else {
/*(*passed) ++;*/
sprintf (buf1, "done %lu, %d /sec", passed, speed);
}
/* make indent */
indent = 79 - cursor_pos - strlen (buf1);
memset (buf2, ' ', indent);
buf2[indent] = 0;
fprintf (stderr, "%s%s", buf2, buf1);
memset (buf2, '\b', indent + strlen (buf1));
buf2 [indent + strlen (buf1)] = 0;
fprintf (stderr, "%s", buf2);
fflush (stderr);
}
static char * strs[] =
{"0%",".",".",".",".","20%",".",".",".",".","40%",".",".",".",".","60%",".",".",".",".","80%",".",".",".",".","100%"};
static char progress_to_be[1024];
static char current_progress[1024];
static void str_to_be (char * buf, int prosents)
{
int i;
prosents -= prosents % 4;
buf[0] = 0;
for (i = 0; i <= prosents / 4; i ++)
strcat (buf, strs[i]);
}
void print_how_far (FILE * fp,
unsigned long * passed, unsigned long total,
unsigned int inc, int quiet)
{
int percent;
if (*passed == 0)
current_progress[0] = 0;
(*passed) += inc;
if (*passed > total) {
/* fprintf (fp, "\nprint_how_far: total %lu has been reached already. cur=%lu\n",
total, *passed);*/
return;
}
percent = ((*passed) * 100) / total;
str_to_be (progress_to_be, percent);
if (strlen (current_progress) != strlen (progress_to_be)) {
fprintf (fp, "%s", progress_to_be + strlen (current_progress));
}
strcat (current_progress, progress_to_be + strlen (current_progress));
if (!quiet) {
print_how_fast(*passed /* - inc*/, total, strlen (progress_to_be),
(*passed == inc) ? 1 : 0);
}
fflush (fp);
}
#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
/* Note! Despite this call being called with *64, it must be encoded to
* return only sizeof(size_t), since in earlier kernel versions it was
* declared _IOR(0x12, 114, sizeof(u64)), making it use sizeof(sizeof(u64)).
*
* However, the call itself does always return 64bit!
*/
# define BLKGETSIZE64 _IOR(0x12, 114, size_t)
#endif
/* To not have problem with last sectors on the block device when switching
to smaller one. */
#define MAX_BS (64 * 1024)
int valid_offset( int fd, loff_t offset) {
char ch;
loff_t res;
/*res = reiserfs_llseek (fd, offset, 0);*/
res = lseek (fd, offset, SEEK_SET);
if (res < 0)
return 0;
/* if (read (fd, &ch, 1) < 0) does not wirk on files */
if (read (fd, &ch, 1) < 1)
return 0;
return 1;
}
/* calculates number of blocks in a file. Returns 0 for "sparse"
regular files and files other than regular files and block devices */
unsigned long count_blocks (char * filename, int blocksize)
{
loff_t high, low;
unsigned long sz;
__u64 size;
int fd;
if (!S_ISBLK(misc_device_mode(filename)) &&
!S_ISREG(misc_device_mode(filename)))
return 0;
fd = open (filename, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Failed to open '%s': %s.\n", filename, strerror(errno));
return 0;
}
#ifdef BLKGETSIZE64
{
if (ioctl (fd, BLKGETSIZE64, &size) >= 0) {
size = (size / MAX_BS) * MAX_BS / blocksize;
sz = size;
if ((__u64)sz != size)
die ("count_blocks: block device too large");
close(fd);
return sz;
}
}
#endif
#ifdef BLKGETSIZE
{
if (ioctl (fd, BLKGETSIZE, &sz) >= 0) {
size = sz;
close(fd);
return (size * 512 / MAX_BS) * MAX_BS / blocksize;
}
}
#endif
low = 0;
for( high = 1; valid_offset (fd, high); high *= 2 )
low = high;
while (low < high - 1) {
const loff_t mid = ( low + high ) / 2;
if (valid_offset (fd, mid))
low = mid;
else
high = mid;
}
valid_offset (fd, 0);
close (fd);
return (low + 1) * MAX_BS / MAX_BS / blocksize;
}
/* there are masks for certain bits */
__u16 mask16 (int from, int count)
{
__u16 mask;
mask = (0xffff >> from);
mask <<= from;
mask <<= (16 - from - count);
mask >>= (16 - from - count);
return mask;
}
__u32 mask32 (int from, int count)
{
__u32 mask;
mask = (0xffffffff >> from);
mask <<= from;
mask <<= (32 - from - count);
mask >>= (32 - from - count);
return mask;
}
__u64 mask64 (int from, int count)
{
__u64 mask;
mask = (0xffffffffffffffffLL >> from);
mask <<= from;
mask <<= (64 - from - count);
mask >>= (64 - from - count);
return mask;
}
__u32 get_random (void)
{
srandom (time (0));
return random ();
}
/* this implements binary search in the array 'base' among 'num' elements each
of those is 'width' bytes long. 'comp_func' is used to compare keys */
int reiserfs_bin_search (void * key, void * base, __u32 num, int width,
__u32 * ppos, comparison_fn_t comp_func)
{
__u32 rbound, lbound, j;
int ret;
if (num == 0 || base == NULL) {
/* objectid map may be 0 elements long */
*ppos = 0;
return POSITION_NOT_FOUND;
}
lbound = 0;
rbound = num - 1;
for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) {
ret = comp_func ((void *)((char *)base + j * width), key ) ;
if (ret < 0) { /* second is greater */
lbound = j + 1;
continue;
} else if (ret > 0) { /* first is greater */
if (j == 0)
break;
rbound = j - 1;
continue;
} else { /* equal */
*ppos = j;
return POSITION_FOUND;
}
}
*ppos = lbound;
return POSITION_NOT_FOUND;
}
#define BLOCKLIST__ELEMENT_NUMBER 10
/*element is block number and device*/
int blockdev_list_compare (const void * block1, const void * block2) {
if (*(__u32 *)block1 < *(__u32 *)block2)
return -1;
if (*(__u32 *)block1 > *(__u32 *)block2)
return 1;
if (*((__u32 *)block1 + 1) < *((__u32 *)block2 + 1))
return -1;
if (*((__u32 *)block1 + 1) > *((__u32 *)block2 + 1))
return 1;
return 0;
}
void blocklist__insert_in_position (void *elem, void **base, __u32 *count,
int elem_size, __u32 *position)
{
if (elem_size == 0)
return;
if (*base == NULL)
*base = getmem (BLOCKLIST__ELEMENT_NUMBER * elem_size);
if (*count == get_mem_size((void *)*base) / elem_size)
*base = expandmem (*base, get_mem_size((void *)*base),
BLOCKLIST__ELEMENT_NUMBER * elem_size);
if (*position < *count) {
memmove (*base + (*position + 1),
*base + (*position),
(*count - *position) * elem_size);
}
memcpy (*base + (char) *position * elem_size, elem, elem_size);
*count+=1;
}
/* 0 - dma is not supported, scsi or regular file */
/* 1 - xt drive */
/* 2 - ide drive */
static void get_dma_support(dma_info_t *dma_info){
if (S_ISREG(dma_info->st.st_mode))
dma_info->st.st_rdev = dma_info->st.st_dev;
if (IDE_DISK_MAJOR(major(dma_info->st.st_rdev))) {
dma_info->support_type = 2;
return;
}
#ifdef XT_DISK_MAJOR
if (major(dma_info->st.st_rdev) == XT_DISK_MAJOR) {
dma_info->support_type = 1;
return;
}
#endif
dma_info->support_type = 0;
}
/*
* Return values:
* 0 - ok;
* 1 - preparation cannot be done
* -1 - preparation failed
*/
int prepare_dma_check(dma_info_t *dma_info) {
DIR *dir;
struct dirent *dirent;
struct stat st;
dev_t rdev;
int rem;
char buf[256];
#ifndef HDIO_GET_DMA
return -1;
#endif
if (fstat(dma_info->fd, &dma_info->st))
die("stat on device failed\n");
get_dma_support(dma_info);
/* dma should be supported */
if (dma_info->support_type == 0)
return 1;
if (dma_info->support_type == 2) {
rdev = dma_info->st.st_rdev;
if ((rem = (minor(rdev) % 64)) != 0) {
rdev -= rem;
if(!(dir = opendir("/dev/"))) {
dma_info->support_type = 1;
return 0;
}
while ((dirent = readdir(dir)) != NULL) {
if (strncmp(dirent->d_name, ".", 1) == 0 || strncmp(dirent->d_name, "..", 2) == 0)
continue;
memset(buf, 0, 256);
strncat(buf, "/dev/", 5);
strncat(buf, dirent->d_name, strlen(dirent->d_name));
if (stat(buf, &st))
break;
if (S_ISBLK(st.st_mode) && st.st_rdev == rdev)
{
dma_info->st = st;
dma_info->fd = open(buf, O_RDONLY
#if defined(O_LARGEFILE)
| O_LARGEFILE
#endif
);
closedir(dir);
return 0;
}
}
closedir(dir);
dma_info->support_type = 1;
return 1;
}
}
return 0;
}
static int is_dma_on (int fd) {
#ifdef HDIO_GET_DMA
static long parm;
if (ioctl(fd, HDIO_GET_DMA, &parm))
return -1;
else
return parm;
#endif
return 0;
}
static __u64 dma_speed(int fd, int support_type) {
static struct hd_driveid id;
__u64 speed = 0;
if (support_type != 2)
return 0;
#ifdef HDIO_OBSOLETE_IDENTITY
if (!ioctl(fd, HDIO_GET_IDENTITY, &id) ||
!ioctl(fd, HDIO_OBSOLETE_IDENTITY)) {
#else
if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) {
#endif
speed |= (__u64)id.dma_1word & ~(__u64)0xff;
speed |= ((__u64)id.dma_mword & ~(__u64)0xff) << 16;
speed |= ((__u64)id.dma_ultra & ~(__u64)0xff) << 32;
} else if (errno == -ENOMSG)
return -1;
else
return -1;
return speed;
}
int get_dma_info(dma_info_t *dma_info) {
if ((dma_info->dma = is_dma_on(dma_info->fd)) == -1)
return -1;
if ((dma_info->speed = dma_speed(dma_info->fd, dma_info->support_type)) == (__u64)-1)
return -1;
return 0;
}
void clean_after_dma_check(int fd, dma_info_t *dma_info) {
signal(SIGALRM, SIG_IGN);
if (dma_info->fd && fd != dma_info->fd)
close(dma_info->fd);
}
/* Only le bitops operations are used. */
inline int misc_set_bit (unsigned long long nr, void * addr) {
__u8 * p, mask;
int retval;
p = (__u8 *)addr;
p += nr >> 3;
mask = 1 << (nr & 0x7);
/*cli();*/
retval = (mask & *p) != 0;
*p |= mask;
/*sti();*/
return retval;
}
inline int misc_clear_bit (unsigned long long nr, void * addr) {
__u8 * p, mask;
int retval;
p = (__u8 *)addr;
p += nr >> 3;
mask = 1 << (nr & 0x7);
/*cli();*/
retval = (mask & *p) != 0;
*p &= ~mask;
/*sti();*/
return retval;
}
inline int misc_test_bit(unsigned long long nr, const void * addr) {
__u8 * p, mask;
p = (__u8 *)addr;
p += nr >> 3;
mask = 1 << (nr & 0x7);
return ((mask & *p) != 0);
}
inline unsigned long long misc_find_first_zero_bit (const void *vaddr,
unsigned long long size)
{
const __u8 *p = vaddr, *addr = vaddr;
unsigned long long res;
if (!size)
return 0;
size = (size >> 3) + ((size & 0x7) > 0);
while (*p++ == 255) {
if (--size == 0)
return (unsigned long long)(p - addr) << 3;
}
--p;
for (res = 0; res < 8; res++)
if (!misc_test_bit (res, p))
break;
return res + (p - addr) * 8;
}
inline unsigned long long misc_find_next_zero_bit (const void *vaddr,
unsigned long long size, unsigned long long offset)
{
const __u8 *addr = vaddr;
const __u8 *p = addr + (offset >> 3);
int bit = offset & 7;
unsigned long long res;
if (offset >= size)
return size;
if (bit) {
/* Look for zero in first char */
for (res = bit; res < 8; res++)
if (!misc_test_bit (res, p))
return res + (p - addr) * 8;
p++;
}
/* No zero yet, search remaining full bytes for a zero */
res = misc_find_first_zero_bit (p, size - 8 * (p - addr));
return res + (p - addr) * 8;
}
inline unsigned long long misc_find_first_set_bit (const void *vaddr,
unsigned long long size)
{
const __u8 *p = vaddr, *addr = vaddr;
unsigned long long res;
if (!size)
return 0;
size = (size >> 3) + ((size & 0x7) > 0);
while (*p++ == 0) {
if (--size == 0)
return (unsigned long long)(p - addr) << 3;
}
--p;
for (res = 0; res < 8; res++)
if (misc_test_bit (res, p))
break;
return res + (p - addr) * 8;
}
inline unsigned long long misc_find_next_set_bit(const void *vaddr,
unsigned long long size, unsigned long long offset)
{
const __u8 *addr = vaddr;
const __u8 *p = addr + (offset >> 3);
int bit = offset & 7;
unsigned long long res;
if (offset >= size)
return size;
if (bit) {
/* Look for zero in first char */
for (res = bit; res < 8; res++)
if (misc_test_bit (res, p))
return res + (p - addr) * 8;
p++;
}
/* No set bit yet, search remaining full bytes for a 1 */
res = misc_find_first_set_bit (p, size - 8 * (p - addr));
return res + (p - addr) * 8;
}
#include "credits.h"
/* Reads the "CREDITS" file and prints one paragraph from it. */
void misc_print_credit(FILE *out) {
char *line;
__u32 num1, num2;
fprintf(out, "A pair of credits:\n");
srandom (time (0));
num1 = random() % CREDITS_COUNT;
line = credits[num1];
fprintf(out, "%s\n", line);
while ((num1 == (num2 = random() % CREDITS_COUNT))) {}
line = credits[num2];
fprintf(out, "%s\n", line);
}
int user_confirmed (FILE * fp, char * q, char * yes) {
char * answer = 0;
size_t n = 0;
fprintf (fp, "%s", q);
if (getline (&answer, &n, stdin) != (ssize_t)strlen (yes) || strcmp (yes, answer))
return 0;
return 1;
}