Submitted By: Jonathan Norman Date: 2009-01-07 Initial Package Version: 1.4.14 Upstream Status: Unknown Origin: Rocklinux, Jim Gifford, Joe Ciccone, and Blue Square Linux Description: Fixes cross-compilation issues and silo no longer links to libext2fs.so, it is integrated instead. Also allows silo to build and work properly on pure64 systems. Now works with 2.6.25.x kernel headers. Rediffed for 1.4.14 diff -Naur silo-1.4.14.orig/Makefile silo-1.4.14/Makefile --- silo-1.4.14.orig/Makefile 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/Makefile 2009-01-07 15:07:56.000000000 -0800 @@ -3,7 +3,7 @@ # These only get built on Linux ifeq ($(OPSYS),Linux) - SUBDIRS = common first second first-isofs tilo + SUBDIRS = common first libext2fs second first-isofs tilo MANPAGES = maketilo.1 tilo.1 endif diff -Naur silo-1.4.14.orig/Rules.make silo-1.4.14/Rules.make --- silo-1.4.14.orig/Rules.make 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/Rules.make 2009-01-07 15:07:56.000000000 -0800 @@ -2,12 +2,14 @@ IMGVERSION=0.99 SHELL=/bin/bash RM=rm -f -# We want to force 32-bit builds -CC=gcc -m32 -LD=ld -m elf32_sparc -AS=as -STRIP=strip -NM=nm +CC=$(CROSS_COMPILE)gcc +CC-SILO=$(CC) -m32 -Wa,-32 -I../include/emul_32 +BUILD_CC=gcc +LD=$(CROSS_COMPILE)ld -m elf32_sparc +AS=$(CROSS_COMPILE)as +STRIP=$(CROSS_COMPILE)strip +NM=$(CROSS_COMPILE)nm + ELFTOAOUT=elftoaout BIN2H=../common/bin2h diff -Naur silo-1.4.14.orig/common/Makefile silo-1.4.14/common/Makefile --- silo-1.4.14.orig/common/Makefile 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/common/Makefile 2009-01-07 15:07:56.000000000 -0800 @@ -5,19 +5,22 @@ include ../Rules.make .c.o: - $(CC) $(CFLAGS) -c $*.c + $(CC-SILO) $(CFLAGS) -c $*.c .S.o: - $(CC) $(CFLAGS) -c $*.S + $(CC-SILO) $(CFLAGS) -c $*.S OBJS = sdiv.o rem.o udiv.o urem.o jmp.o printf.o console.o prom.o tree.o stringops2.o\ stringops1.o ffs.o divdi3.o udivdi3.o -PROGRAMS = bin2h -all: $(OBJS) $(PROGRAMS) +bin2h: + $(BUILD_CC) $(CFLAGS) -o bin2h bin2h.c + +all: $(OBJS) bin2h prom.o: prom.c - $(CC) $(CFLAGS) -c -Wa,-Av9 -o prom.o prom.c + $(CC-SILO) $(CFLAGS) -c -Wa,-Av9 -o prom.o prom.c clean: - $(RM) $(PROGRAMS) *.o + $(RM) bin2h *.o + diff -Naur silo-1.4.14.orig/first/Makefile silo-1.4.14/first/Makefile --- silo-1.4.14.orig/first/Makefile 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/first/Makefile 2009-01-07 15:13:16.000000000 -0800 @@ -1,4 +1,4 @@ -## +# ## Linux Loader for SPARC ## # @@ -13,7 +13,7 @@ LDFLAGS=-N -Ttext 0x4000 .S.o: - $(CC) $(CFLAGS) -c $*.S + $(CC-SILO) $(CFLAGS) -c $*.S all: first.b first.h ultra.b ultra.h generic.b generic.h fd.b ieee32.b @@ -33,7 +33,7 @@ sed -n 's/^\(000000000000\|0000\)4\([0-9a-f][0-9a-f][0-9a-f]\) .*letter_here.*$$/#define FD_LETTER_OFFSET_TMP 0x\2/p' < fd.map >> fd.h first.o: first.S - $(CC) $(CFLAGS) -c first.S -o first.o + $(CC-SILO) $(CFLAGS) -c first.S -o first.o first: first.o $(LD) $(LDFLAGS) -o first first.o @@ -46,7 +46,7 @@ $(DD) if=/dev/zero of=first.b bs=4 count=1 seek=127 ultra.o: ultra.S - $(CC) $(CFLAGS) -c -Wa,-Av9a ultra.S + $(CC-SILO) $(CFLAGS) -c -Wa,-Av9a ultra.S ultra: ultra.o $(LD) $(LDFLAGS) -o ultra ultra.o @@ -56,11 +56,11 @@ ultra.b: ultra $(ELFTOAOUT) -o ultra.b ultra printf 'SILO'$(IMGVERSION) | $(DD) of=ultra.b bs=8 conv=notrunc seek=3 count=1 - printf '\340' | $(DD) of=ultra.b bs=1 count=1 seek=7 conv=notrunc + printf '\0340' | $(DD) of=ultra.b bs=1 count=1 seek=7 conv=notrunc $(DD) if=/dev/zero of=ultra.b bs=4 count=1 seek=127 generic.o: generic.S - $(CC) $(CFLAGS) -c -Wa,-Av9a generic.S + $(CC-SILO) $(CFLAGS) -c -Wa,-Av9a generic.S generic: generic.o $(LD) $(LDFLAGS) -o generic generic.o @@ -70,11 +70,11 @@ generic.b: generic $(ELFTOAOUT) -o generic.b generic printf 'SILO'$(IMGVERSION) | $(DD) of=generic.b bs=8 conv=notrunc seek=3 count=1 - printf '\340' | $(DD) of=generic.b bs=1 count=1 seek=7 conv=notrunc + printf '\0340' | $(DD) of=generic.b bs=1 count=1 seek=7 conv=notrunc $(DD) if=/dev/zero of=generic.b bs=4 count=1 seek=255 fd.o: fd.S - $(CC) $(CFLAGS) -c -Wa,-Av9a fd.S + $(CC-SILO) $(CFLAGS) -c -Wa,-Av9a fd.S fd: fd.o $(LD) $(LDFLAGS) -o fd fd.o @@ -84,11 +84,11 @@ fd.b: fd $(ELFTOAOUT) -o fd.b fd printf 'SILO'$(IMGVERSION) | $(DD) of=fd.b bs=8 conv=notrunc seek=3 count=1 - printf '\340' | $(DD) of=fd.b bs=1 count=1 seek=7 conv=notrunc + printf '\0340' | $(DD) of=fd.b bs=1 count=1 seek=7 conv=notrunc $(DD) if=/dev/zero of=fd.b bs=4 count=1 seek=255 ieee32.o: ieee32.S ieee32.h - $(CC) $(CFLAGS) -DIMGVERSION='"SILO$(IMGVERSION)"' -c ieee32.S + $(CC-SILO) $(CFLAGS) -DIMGVERSION='"SILO$(IMGVERSION)"' -c ieee32.S ieee32.b: ieee32.o $(LD) $(LDFLAGS) -o ieee32.b ieee32.o diff -Naur silo-1.4.14.orig/first-isofs/Makefile silo-1.4.14/first-isofs/Makefile --- silo-1.4.14.orig/first-isofs/Makefile 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/first-isofs/Makefile 2009-01-07 15:07:56.000000000 -0800 @@ -11,10 +11,10 @@ all: $(NAME).b .c.o: - $(CC) $(CFLAGS) -c $*.c + $(CC-SILO) $(CFLAGS) -c $*.c .S.o: - $(CC) $(CFLAGS) -c $*.S + $(CC-SILO) $(CFLAGS) -c $*.S OBJS_COMMON = ../common/prom.o ../common/console.o ../common/tree.o OBJS = crt0.o $(NAME).o $(OBJS_COMMON) @@ -28,7 +28,7 @@ cat $<.aout >> $@ crt0.o: crt0.S - $(CC) $(CFLAGS) -c -Wa,-Av9 -o $@ $< + $(CC-SILO) $(CFLAGS) -c -Wa,-Av9 -o $@ $< clean: $(RM) *.o $(NAME) $(NAME).b $(NAME).aout diff -Naur silo-1.4.14.orig/include/asm/page.h silo-1.4.14/include/asm/page.h --- silo-1.4.14.orig/include/asm/page.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/include/asm/page.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,15 @@ +/* File autogenerated by 'make headers_install' */ +#ifndef __ASM_STUB_PAGE_H +#define __ASM_STUB_PAGE_H +# if defined __sparc__ && defined __arch64__ +#ifndef _SPARC_PAGE_H +#define _SPARC_PAGE_H +#endif +# elif defined __sparc__ && !defined __arch64__ +#ifndef _SPARC64_PAGE_H +#define _SPARC64_PAGE_H +#endif +# else +# warning This machine appears to be neither sparc64 nor sparc. +# endif +#endif /* __ASM_STUB_PAGE_H */ diff -Naur silo-1.4.14.orig/include/emul_32/asm/elf.h silo-1.4.14/include/emul_32/asm/elf.h --- silo-1.4.14.orig/include/emul_32/asm/elf.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/include/emul_32/asm/elf.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,162 @@ +#ifndef __ASMSPARC_ELF_H +#define __ASMSPARC_ELF_H + +/* + * ELF register definitions.. + */ + + +/* + * Sparc section types + */ +#define STT_REGISTER 13 + +/* + * Sparc ELF relocation types + */ +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 + +/* Bits present in AT_HWCAP, primarily for Sparc32. */ + +#define HWCAP_SPARC_FLUSH 1 /* CPU supports flush instruction. */ +#define HWCAP_SPARC_STBAR 2 +#define HWCAP_SPARC_SWAP 4 +#define HWCAP_SPARC_MULDIV 8 +#define HWCAP_SPARC_V9 16 +#define HWCAP_SPARC_ULTRA3 32 + +/* For the most part we present code dumps in the format + * Solaris does. + */ +typedef unsigned long elf_greg_t; +#define ELF_NGREG 38 +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Format is: + * G0 --> G7 + * O0 --> O7 + * L0 --> L7 + * I0 --> I7 + * PSR, PC, nPC, Y, WIM, TBR + */ +#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \ +do { unsigned long *dest = &(__elf_regs[0]); \ + struct pt_regs *src = (__pt_regs); \ + unsigned long *sp; \ + memcpy(&dest[0], &src->u_regs[0], \ + sizeof(unsigned long) * 16); \ + /* Don't try this at home kids... */ \ + sp = (unsigned long *) src->u_regs[14]; \ + copy_from_user(&dest[16], sp, \ + sizeof(unsigned long) * 16); \ + dest[32] = src->psr; \ + dest[33] = src->pc; \ + dest[34] = src->npc; \ + dest[35] = src->y; \ + dest[36] = dest[37] = 0; /* XXX */ \ +} while(0); /* Janitors: Don't touch this colon. */ + +typedef struct { + union { + unsigned long pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned long __unused; + unsigned long pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; +} elf_fpregset_t; + +#define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \ + ({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread.kregs); 1; }) + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x)->e_machine == EM_SPARC) + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_ARCH EM_SPARC +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB + +#define USE_ELF_CORE_DUMP +#ifndef CONFIG_SUN4 +#define ELF_EXEC_PAGESIZE 4096 +#else +#define ELF_EXEC_PAGESIZE 8192 +#endif + + +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical + use of this is to invoke "./ld.so someprog" to test out a new version of + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE) + +/* This yields a mask that user programs can use to figure out what + instruction set this cpu supports. This can NOT be done in userspace + on Sparc. */ + +/* Sun4c has none of the capabilities, most sun4m's have them all. + * XXX This is gross, set some global variable at boot time. -DaveM + */ +#define ELF_HWCAP ((ARCH_SUN4C_SUN4) ? 0 : \ + (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \ + HWCAP_SPARC_SWAP | \ + ((srmmu_modtype != Cypress && \ + srmmu_modtype != Cypress_vE && \ + srmmu_modtype != Cypress_vD) ? \ + HWCAP_SPARC_MULDIV : 0))) + +/* This yields a string that ld.so will use to load implementation + specific libraries for optimization. This is more specific in + intent than poking at uname or /proc/cpuinfo. */ + +#define ELF_PLATFORM (NULL) + + +#endif /* !(__ASMSPARC_ELF_H) */ diff -Naur silo-1.4.14.orig/include/emul_32/asm/posix_types.h silo-1.4.14/include/emul_32/asm/posix_types.h --- silo-1.4.14.orig/include/emul_32/asm/posix_types.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/include/emul_32/asm/posix_types.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,122 @@ +#ifndef __ARCH_SPARC_POSIX_TYPES_H +#define __ARCH_SPARC_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef long int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_umode_t; +typedef short __kernel_nlink_t; +typedef long __kernel_daddr_t; +typedef long __kernel_off_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; +typedef int __kernel_clockid_t; +typedef int __kernel_timer_t; + +#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || (__STDC_VERSION__ >= 199901L) +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if defined(__KERNEL__) || defined(__USE_ALL) + int val[2]; +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ + int __val[2]; +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ +} __kernel_fsid_t; + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] |= (1UL<<_rem); +} + +#undef __FD_CLR +static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem); +} + +#undef __FD_ISSET +static __inline__ int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant cases (8 or 32 longs, + * for 256 and 1024-bit fd_sets respectively) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set *p) +{ + unsigned long *tmp = p->fds_bits; + int i; + + if (__builtin_constant_p(__FDSET_LONGS)) { + switch (__FDSET_LONGS) { + case 32: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0; + tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0; + tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0; + tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0; + tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0; + tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0; + return; + case 16: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0; + tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0; + return; + case 8: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + return; + case 4: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + return; + } + } + i = __FDSET_LONGS; + while (i) { + i--; + *tmp = 0; + tmp++; + } +} + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ + +#endif /* !(__ARCH_SPARC_POSIX_TYPES_H) */ diff -Naur silo-1.4.14.orig/include/emul_32/asm/types.h silo-1.4.14/include/emul_32/asm/types.h --- silo-1.4.14.orig/include/emul_32/asm/types.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/include/emul_32/asm/types.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,41 @@ +#ifndef _SPARC_TYPES_H +#define _SPARC_TYPES_H + +/* + * _xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space. + */ + +/* + * This file is never included by application software unless + * explicitly requested (e.g., via linux/types.h) in which case the + * application is Linux specific so (user-) name space pollution is + * not a major issue. However, for interoperability, libraries still + * need to be careful to avoid a name clashes. + */ + +#ifndef __ASSEMBLY__ + +typedef unsigned short umode_t; + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || (__STDC_VERSION__ >= 199901L) +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +#if (defined(__STRICT_ANSI__) && !defined(inline)) +#define inline __inline__ +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* defined(_SPARC_TYPES_H) */ diff -Naur silo-1.4.14.orig/include/ext2fs/ext2_err.h silo-1.4.14/include/ext2fs/ext2_err.h --- silo-1.4.14.orig/include/ext2fs/ext2_err.h 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/include/ext2fs/ext2_err.h 2009-01-07 15:07:56.000000000 -0800 @@ -3,6 +3,8 @@ * This file is automatically generated; please do not edit it. */ +#include + #define EXT2_ET_BASE (2133571328L) #define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L) #define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L) @@ -19,8 +21,8 @@ #define EXT2_ET_MAGIC_ICOUNT (2133571341L) #define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L) #define EXT2_ET_MAGIC_EXT2_FILE (2133571343L) -#define EXT2_ET_MAGIC_RESERVED_7 (2133571344L) -#define EXT2_ET_MAGIC_RESERVED_8 (2133571345L) +#define EXT2_ET_MAGIC_E2IMAGE (2133571344L) +#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L) #define EXT2_ET_MAGIC_RESERVED_9 (2133571346L) #define EXT2_ET_BAD_MAGIC (2133571347L) #define EXT2_ET_REV_TOO_HIGH (2133571348L) @@ -86,7 +88,25 @@ #define EXT2_ET_UNIMPLEMENTED (2133571408L) #define EXT2_ET_CANCEL_REQUESTED (2133571409L) #define EXT2_ET_FILE_TOO_BIG (2133571410L) +#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L) +#define EXT2_ET_NO_JOURNAL_SB (2133571412L) +#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L) +#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L) +#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L) +#define EXT2_ET_NO_JOURNAL (2133571416L) +#define EXT2_ET_DIRHASH_UNSUPP (2133571417L) +#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L) +#define EXT2_ET_TOO_MANY_INODES (2133571419L) +#define EXT2_ET_NOT_IMAGE_FILE (2133571420L) +#define EXT2_ET_RES_GDT_BLOCKS (2133571421L) +#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L) +#define EXT2_ET_SET_BMAP_NO_IND (2133571423L) +extern const struct error_table et_ext2_error_table; extern void initialize_ext2_error_table(void); + +/* For compatibility with Heimdal */ +extern void initialize_ext2_error_table_r(struct et_list **list); + #define ERROR_TABLE_BASE_ext2 (2133571328L) /* for compatibility with older versions... */ diff -Naur silo-1.4.14.orig/include/ext2fs/ext2_io.h silo-1.4.14/include/ext2fs/ext2_io.h --- silo-1.4.14.orig/include/ext2fs/ext2_io.h 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/include/ext2fs/ext2_io.h 2009-01-07 15:07:56.000000000 -0800 @@ -27,6 +27,8 @@ typedef struct struct_io_manager *io_manager; typedef struct struct_io_channel *io_channel; +#define CHANNEL_FLAGS_WRITETHROUGH 0x01 + struct struct_io_channel { errcode_t magic; io_manager manager; @@ -47,7 +49,8 @@ int actual_bytes_written, errcode_t error); int refcount; - int reserved[15]; + int flags; + int reserved[14]; void *private_data; void *app_data; }; @@ -63,7 +66,11 @@ errcode_t (*write_blk)(io_channel channel, unsigned long block, int count, const void *data); errcode_t (*flush)(io_channel channel); - int reserved[16]; + errcode_t (*write_byte)(io_channel channel, unsigned long offset, + int count, const void *data); + errcode_t (*set_option)(io_channel channel, const char *option, + const char *arg); + int reserved[14]; }; #define IO_FLAG_RW 1 @@ -78,6 +85,13 @@ #define io_channel_flush(c) ((c)->manager->flush((c))) #define io_channel_bumpcount(c) ((c)->refcount++) +/* io_manager.c */ +extern errcode_t io_channel_set_options(io_channel channel, + const char *options); +extern errcode_t io_channel_write_byte(io_channel channel, + unsigned long offset, + int count, const void *data); + /* unix_io.c */ extern io_manager unix_io_manager; diff -Naur silo-1.4.14.orig/include/linux/ufs_fs.h silo-1.4.14/include/linux/ufs_fs.h --- silo-1.4.14.orig/include/linux/ufs_fs.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/include/linux/ufs_fs.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,953 @@ +/* + * linux/include/linux/ufs_fs.h + * + * Copyright (C) 1996 + * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) + * Laboratory for Computer Science Research Computing Facility + * Rutgers, The State University of New Jersey + * + * Clean swab support by Fare + * just hope no one is using NNUUXXI on __?64 structure elements + * 64-bit clean thanks to Maciej W. Rozycki + * + * 4.4BSD (FreeBSD) support added on February 1st 1998 by + * Niels Kristian Bech Jensen partially based + * on code by Martin von Loewis . + * + * NeXTstep support added on February 5th 1998 by + * Niels Kristian Bech Jensen . + * + * Write support by Daniel Pirkl + * + * HP/UX hfs filesystem support added by + * Martin K. Petersen , August 1999 + * + * UFS2 (of FreeBSD 5.x) support added by + * Niraj Kumar , Jan 2004 + * + */ + +#ifndef __LINUX_UFS_FS_H +#define __LINUX_UFS_FS_H + +#include +#include +#include +#include + +#ifndef __KERNEL__ +typedef __u64 __fs64; +typedef __u32 __fs32; +typedef __u16 __fs16; +#else +#include +typedef __u64 __bitwise __fs64; +typedef __u32 __bitwise __fs32; +typedef __u16 __bitwise __fs16; +#endif + +#define UFS_BBLOCK 0 +#define UFS_BBSIZE 8192 +#define UFS_SBLOCK 8192 +#define UFS_SBSIZE 8192 + +#define UFS_SECTOR_SIZE 512 +#define UFS_SECTOR_BITS 9 +#define UFS_MAGIC 0x00011954 +#define UFS2_MAGIC 0x19540119 +#define UFS_CIGAM 0x54190100 /* byteswapped MAGIC */ + +/* Copied from FreeBSD */ +/* + * Each disk drive contains some number of filesystems. + * A filesystem consists of a number of cylinder groups. + * Each cylinder group has inodes and data. + * + * A filesystem is described by its super-block, which in turn + * describes the cylinder groups. The super-block is critical + * data and is replicated in each cylinder group to protect against + * catastrophic loss. This is done at `newfs' time and the critical + * super-block data does not change, so the copies need not be + * referenced further unless disaster strikes. + * + * For filesystem fs, the offsets of the various blocks of interest + * are given in the super block as: + * [fs->fs_sblkno] Super-block + * [fs->fs_cblkno] Cylinder group block + * [fs->fs_iblkno] Inode blocks + * [fs->fs_dblkno] Data blocks + * The beginning of cylinder group cg in fs, is given by + * the ``cgbase(fs, cg)'' macro. + * + * Depending on the architecture and the media, the superblock may + * reside in any one of four places. For tiny media where every block + * counts, it is placed at the very front of the partition. Historically, + * UFS1 placed it 8K from the front to leave room for the disk label and + * a small bootstrap. For UFS2 it got moved to 64K from the front to leave + * room for the disk label and a bigger bootstrap, and for really piggy + * systems we check at 256K from the front if the first three fail. In + * all cases the size of the superblock will be SBLOCKSIZE. All values are + * given in byte-offset form, so they do not imply a sector size. The + * SBLOCKSEARCH specifies the order in which the locations should be searched. + */ +#define SBLOCK_FLOPPY 0 +#define SBLOCK_UFS1 8192 +#define SBLOCK_UFS2 65536 +#define SBLOCK_PIGGY 262144 +#define SBLOCKSIZE 8192 +#define SBLOCKSEARCH \ + { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 } + + +/* HP specific MAGIC values */ + +#define UFS_MAGIC_LFN 0x00095014 /* fs supports filenames > 14 chars */ +#define UFS_CIGAM_LFN 0x14500900 /* srahc 41 < semanelif stroppus sf */ + +#define UFS_MAGIC_SEC 0x00612195 /* B1 security fs */ +#define UFS_CIGAM_SEC 0x95216100 + +#define UFS_MAGIC_FEA 0x00195612 /* fs_featurebits supported */ +#define UFS_CIGAM_FEA 0x12561900 + +#define UFS_MAGIC_4GB 0x05231994 /* fs > 4 GB && fs_featurebits */ +#define UFS_CIGAM_4GB 0x94192305 + +/* Seems somebody at HP goofed here. B1 and lfs are both 0x2 !?! */ +#define UFS_FSF_LFN 0x00000001 /* long file names */ +#define UFS_FSF_B1 0x00000002 /* B1 security */ +#define UFS_FSF_LFS 0x00000002 /* large files */ +#define UFS_FSF_LUID 0x00000004 /* large UIDs */ + +/* End of HP stuff */ + + +#define UFS_BSIZE 8192 +#define UFS_MINBSIZE 4096 +#define UFS_FSIZE 1024 +#define UFS_MAXFRAG (UFS_BSIZE / UFS_FSIZE) + +#define UFS_NDADDR 12 +#define UFS_NINDIR 3 + +#define UFS_IND_BLOCK (UFS_NDADDR + 0) +#define UFS_DIND_BLOCK (UFS_NDADDR + 1) +#define UFS_TIND_BLOCK (UFS_NDADDR + 2) + +#define UFS_NDIR_FRAGMENT (UFS_NDADDR << uspi->s_fpbshift) +#define UFS_IND_FRAGMENT (UFS_IND_BLOCK << uspi->s_fpbshift) +#define UFS_DIND_FRAGMENT (UFS_DIND_BLOCK << uspi->s_fpbshift) +#define UFS_TIND_FRAGMENT (UFS_TIND_BLOCK << uspi->s_fpbshift) + +#define UFS_ROOTINO 2 +#define UFS_FIRST_INO (UFS_ROOTINO + 1) + +#define UFS_USEEFT ((__u16)65535) + +#define UFS_FSOK 0x7c269d38 +#define UFS_FSACTIVE ((__s8)0x00) +#define UFS_FSCLEAN ((__s8)0x01) +#define UFS_FSSTABLE ((__s8)0x02) +#define UFS_FSOSF1 ((__s8)0x03) /* is this correct for DEC OSF/1? */ +#define UFS_FSBAD ((__s8)0xff) + +/* From here to next blank line, s_flags for ufs_sb_info */ +/* directory entry encoding */ +#define UFS_DE_MASK 0x00000010 /* mask for the following */ +#define UFS_DE_OLD 0x00000000 +#define UFS_DE_44BSD 0x00000010 +/* uid encoding */ +#define UFS_UID_MASK 0x00000060 /* mask for the following */ +#define UFS_UID_OLD 0x00000000 +#define UFS_UID_44BSD 0x00000020 +#define UFS_UID_EFT 0x00000040 +/* superblock state encoding */ +#define UFS_ST_MASK 0x00000700 /* mask for the following */ +#define UFS_ST_OLD 0x00000000 +#define UFS_ST_44BSD 0x00000100 +#define UFS_ST_SUN 0x00000200 /* Solaris */ +#define UFS_ST_SUNOS 0x00000300 +#define UFS_ST_SUNx86 0x00000400 /* Solaris x86 */ +/*cylinder group encoding */ +#define UFS_CG_MASK 0x00003000 /* mask for the following */ +#define UFS_CG_OLD 0x00000000 +#define UFS_CG_44BSD 0x00002000 +#define UFS_CG_SUN 0x00001000 +/* filesystem type encoding */ +#define UFS_TYPE_MASK 0x00010000 /* mask for the following */ +#define UFS_TYPE_UFS1 0x00000000 +#define UFS_TYPE_UFS2 0x00010000 + + +/* fs_inodefmt options */ +#define UFS_42INODEFMT -1 +#define UFS_44INODEFMT 2 + +/* + * MINFREE gives the minimum acceptable percentage of file system + * blocks which may be free. If the freelist drops below this level + * only the superuser may continue to allocate blocks. This may + * be set to 0 if no reserve of free blocks is deemed necessary, + * however throughput drops by fifty percent if the file system + * is run at between 95% and 100% full; thus the minimum default + * value of fs_minfree is 5%. However, to get good clustering + * performance, 10% is a better choice. hence we use 10% as our + * default value. With 10% free space, fragmentation is not a + * problem, so we choose to optimize for time. + */ +#define UFS_MINFREE 5 +#define UFS_DEFAULTOPT UFS_OPTTIME + +/* + * Turn file system block numbers into disk block addresses. + * This maps file system blocks to device size blocks. + */ +#define ufs_fsbtodb(uspi, b) ((b) << (uspi)->s_fsbtodb) +#define ufs_dbtofsb(uspi, b) ((b) >> (uspi)->s_fsbtodb) + +/* + * Cylinder group macros to locate things in cylinder groups. + * They calc file system addresses of cylinder group data structures. + */ +#define ufs_cgbase(c) (uspi->s_fpg * (c)) +#define ufs_cgstart(c) ((uspi)->fs_magic == UFS2_MAGIC ? ufs_cgbase(c) : \ + (ufs_cgbase(c) + uspi->s_cgoffset * ((c) & ~uspi->s_cgmask))) +#define ufs_cgsblock(c) (ufs_cgstart(c) + uspi->s_sblkno) /* super blk */ +#define ufs_cgcmin(c) (ufs_cgstart(c) + uspi->s_cblkno) /* cg block */ +#define ufs_cgimin(c) (ufs_cgstart(c) + uspi->s_iblkno) /* inode blk */ +#define ufs_cgdmin(c) (ufs_cgstart(c) + uspi->s_dblkno) /* 1st data */ + +/* + * Macros for handling inode numbers: + * inode number to file system block offset. + * inode number to cylinder group number. + * inode number to file system block address. + */ +#define ufs_inotocg(x) ((x) / uspi->s_ipg) +#define ufs_inotocgoff(x) ((x) % uspi->s_ipg) +#define ufs_inotofsba(x) (((u64)ufs_cgimin(ufs_inotocg(x))) + ufs_inotocgoff(x) / uspi->s_inopf) +#define ufs_inotofsbo(x) ((x) % uspi->s_inopf) + +/* + * Compute the cylinder and rotational position of a cyl block addr. + */ +#define ufs_cbtocylno(bno) \ + ((bno) * uspi->s_nspf / uspi->s_spc) +#define ufs_cbtorpos(bno) \ + ((((bno) * uspi->s_nspf % uspi->s_spc / uspi->s_nsect \ + * uspi->s_trackskew + (bno) * uspi->s_nspf % uspi->s_spc \ + % uspi->s_nsect * uspi->s_interleave) % uspi->s_nsect \ + * uspi->s_nrpos) / uspi->s_npsect) + +/* + * The following macros optimize certain frequently calculated + * quantities by using shifts and masks in place of divisions + * modulos and multiplications. + */ +#define ufs_blkoff(loc) ((loc) & uspi->s_qbmask) +#define ufs_fragoff(loc) ((loc) & uspi->s_qfmask) +#define ufs_lblktosize(blk) ((blk) << uspi->s_bshift) +#define ufs_lblkno(loc) ((loc) >> uspi->s_bshift) +#define ufs_numfrags(loc) ((loc) >> uspi->s_fshift) +#define ufs_blkroundup(size) (((size) + uspi->s_qbmask) & uspi->s_bmask) +#define ufs_fragroundup(size) (((size) + uspi->s_qfmask) & uspi->s_fmask) +#define ufs_fragstoblks(frags) ((frags) >> uspi->s_fpbshift) +#define ufs_blkstofrags(blks) ((blks) << uspi->s_fpbshift) +#define ufs_fragnum(fsb) ((fsb) & uspi->s_fpbmask) +#define ufs_blknum(fsb) ((fsb) & ~uspi->s_fpbmask) + +#define UFS_MAXNAMLEN 255 +#define UFS_MAXMNTLEN 512 +#define UFS2_MAXMNTLEN 468 +#define UFS2_MAXVOLLEN 32 +#define UFS_MAXCSBUFS 31 +#define UFS_LINK_MAX 32000 +/* +#define UFS2_NOCSPTRS ((128 / sizeof(void *)) - 4) +*/ +#define UFS2_NOCSPTRS 28 + +/* + * UFS_DIR_PAD defines the directory entries boundaries + * (must be a multiple of 4) + */ +#define UFS_DIR_PAD 4 +#define UFS_DIR_ROUND (UFS_DIR_PAD - 1) +#define UFS_DIR_REC_LEN(name_len) (((name_len) + 1 + 8 + UFS_DIR_ROUND) & ~UFS_DIR_ROUND) + +struct ufs_timeval { + __fs32 tv_sec; + __fs32 tv_usec; +}; + +struct ufs_dir_entry { + __fs32 d_ino; /* inode number of this entry */ + __fs16 d_reclen; /* length of this entry */ + union { + __fs16 d_namlen; /* actual length of d_name */ + struct { + __u8 d_type; /* file type */ + __u8 d_namlen; /* length of string in d_name */ + } d_44; + } d_u; + __u8 d_name[UFS_MAXNAMLEN + 1]; /* file name */ +}; + +struct ufs_csum { + __fs32 cs_ndir; /* number of directories */ + __fs32 cs_nbfree; /* number of free blocks */ + __fs32 cs_nifree; /* number of free inodes */ + __fs32 cs_nffree; /* number of free frags */ +}; +struct ufs2_csum_total { + __fs64 cs_ndir; /* number of directories */ + __fs64 cs_nbfree; /* number of free blocks */ + __fs64 cs_nifree; /* number of free inodes */ + __fs64 cs_nffree; /* number of free frags */ + __fs64 cs_numclusters; /* number of free clusters */ + __fs64 cs_spare[3]; /* future expansion */ +}; + +struct ufs_csum_core { + __u64 cs_ndir; /* number of directories */ + __u64 cs_nbfree; /* number of free blocks */ + __u64 cs_nifree; /* number of free inodes */ + __u64 cs_nffree; /* number of free frags */ + __u64 cs_numclusters; /* number of free clusters */ +}; + +/* + * File system flags + */ +#define UFS_UNCLEAN 0x01 /* file system not clean at mount (unused) */ +#define UFS_DOSOFTDEP 0x02 /* file system using soft dependencies */ +#define UFS_NEEDSFSCK 0x04 /* needs sync fsck (FreeBSD compat, unused) */ +#define UFS_INDEXDIRS 0x08 /* kernel supports indexed directories */ +#define UFS_ACLS 0x10 /* file system has ACLs enabled */ +#define UFS_MULTILABEL 0x20 /* file system is MAC multi-label */ +#define UFS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */ + +#if 0 +/* + * This is the actual superblock, as it is laid out on the disk. + * Do NOT use this structure, because of sizeof(ufs_super_block) > 512 and + * it may occupy several blocks, use + * struct ufs_super_block_(first,second,third) instead. + */ +struct ufs_super_block { + union { + struct { + __fs32 fs_link; /* UNUSED */ + } fs_42; + struct { + __fs32 fs_state; /* file system state flag */ + } fs_sun; + } fs_u0; + __fs32 fs_rlink; /* UNUSED */ + __fs32 fs_sblkno; /* addr of super-block in filesys */ + __fs32 fs_cblkno; /* offset of cyl-block in filesys */ + __fs32 fs_iblkno; /* offset of inode-blocks in filesys */ + __fs32 fs_dblkno; /* offset of first data after cg */ + __fs32 fs_cgoffset; /* cylinder group offset in cylinder */ + __fs32 fs_cgmask; /* used to calc mod fs_ntrak */ + __fs32 fs_time; /* last time written -- time_t */ + __fs32 fs_size; /* number of blocks in fs */ + __fs32 fs_dsize; /* number of data blocks in fs */ + __fs32 fs_ncg; /* number of cylinder groups */ + __fs32 fs_bsize; /* size of basic blocks in fs */ + __fs32 fs_fsize; /* size of frag blocks in fs */ + __fs32 fs_frag; /* number of frags in a block in fs */ +/* these are configuration parameters */ + __fs32 fs_minfree; /* minimum percentage of free blocks */ + __fs32 fs_rotdelay; /* num of ms for optimal next block */ + __fs32 fs_rps; /* disk revolutions per second */ +/* these fields can be computed from the others */ + __fs32 fs_bmask; /* ``blkoff'' calc of blk offsets */ + __fs32 fs_fmask; /* ``fragoff'' calc of frag offsets */ + __fs32 fs_bshift; /* ``lblkno'' calc of logical blkno */ + __fs32 fs_fshift; /* ``numfrags'' calc number of frags */ +/* these are configuration parameters */ + __fs32 fs_maxcontig; /* max number of contiguous blks */ + __fs32 fs_maxbpg; /* max number of blks per cyl group */ +/* these fields can be computed from the others */ + __fs32 fs_fragshift; /* block to frag shift */ + __fs32 fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ + __fs32 fs_sbsize; /* actual size of super block */ + __fs32 fs_csmask; /* csum block offset */ + __fs32 fs_csshift; /* csum block number */ + __fs32 fs_nindir; /* value of NINDIR */ + __fs32 fs_inopb; /* value of INOPB */ + __fs32 fs_nspf; /* value of NSPF */ +/* yet another configuration parameter */ + __fs32 fs_optim; /* optimization preference, see below */ +/* these fields are derived from the hardware */ + union { + struct { + __fs32 fs_npsect; /* # sectors/track including spares */ + } fs_sun; + struct { + __fs32 fs_state; /* file system state time stamp */ + } fs_sunx86; + } fs_u1; + __fs32 fs_interleave; /* hardware sector interleave */ + __fs32 fs_trackskew; /* sector 0 skew, per track */ +/* a unique id for this filesystem (currently unused and unmaintained) */ +/* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */ +/* Neither of those fields is used in the Tahoe code right now but */ +/* there could be problems if they are. */ + __fs32 fs_id[2]; /* file system id */ +/* sizes determined by number of cylinder groups and their sizes */ + __fs32 fs_csaddr; /* blk addr of cyl grp summary area */ + __fs32 fs_cssize; /* size of cyl grp summary area */ + __fs32 fs_cgsize; /* cylinder group size */ +/* these fields are derived from the hardware */ + __fs32 fs_ntrak; /* tracks per cylinder */ + __fs32 fs_nsect; /* sectors per track */ + __fs32 fs_spc; /* sectors per cylinder */ +/* this comes from the disk driver partitioning */ + __fs32 fs_ncyl; /* cylinders in file system */ +/* these fields can be computed from the others */ + __fs32 fs_cpg; /* cylinders per group */ + __fs32 fs_ipg; /* inodes per cylinder group */ + __fs32 fs_fpg; /* blocks per group * fs_frag */ +/* this data must be re-computed after crashes */ + struct ufs_csum fs_cstotal; /* cylinder summary information */ +/* these fields are cleared at mount time */ + __s8 fs_fmod; /* super block modified flag */ + __s8 fs_clean; /* file system is clean flag */ + __s8 fs_ronly; /* mounted read-only flag */ + __s8 fs_flags; + union { + struct { + __s8 fs_fsmnt[UFS_MAXMNTLEN];/* name mounted on */ + __fs32 fs_cgrotor; /* last cg searched */ + __fs32 fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */ + __fs32 fs_maxcluster; + __fs32 fs_cpc; /* cyl per cycle in postbl */ + __fs16 fs_opostbl[16][8]; /* old rotation block list head */ + } fs_u1; + struct { + __s8 fs_fsmnt[UFS2_MAXMNTLEN]; /* name mounted on */ + __u8 fs_volname[UFS2_MAXVOLLEN]; /* volume name */ + __fs64 fs_swuid; /* system-wide uid */ + __fs32 fs_pad; /* due to alignment of fs_swuid */ + __fs32 fs_cgrotor; /* last cg searched */ + __fs32 fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */ + __fs32 fs_contigdirs;/*# of contiguously allocated dirs */ + __fs32 fs_csp; /* cg summary info buffer for fs_cs */ + __fs32 fs_maxcluster; + __fs32 fs_active;/* used by snapshots to track fs */ + __fs32 fs_old_cpc; /* cyl per cycle in postbl */ + __fs32 fs_maxbsize;/*maximum blocking factor permitted */ + __fs64 fs_sparecon64[17];/*old rotation block list head */ + __fs64 fs_sblockloc; /* byte offset of standard superblock */ + struct ufs2_csum_total fs_cstotal;/*cylinder summary information*/ + struct ufs_timeval fs_time; /* last time written */ + __fs64 fs_size; /* number of blocks in fs */ + __fs64 fs_dsize; /* number of data blocks in fs */ + __fs64 fs_csaddr; /* blk addr of cyl grp summary area */ + __fs64 fs_pendingblocks;/* blocks in process of being freed */ + __fs32 fs_pendinginodes;/*inodes in process of being freed */ + } fs_u2; + } fs_u11; + union { + struct { + __fs32 fs_sparecon[53];/* reserved for future constants */ + __fs32 fs_reclaim; + __fs32 fs_sparecon2[1]; + __fs32 fs_state; /* file system state time stamp */ + __fs32 fs_qbmask[2]; /* ~usb_bmask */ + __fs32 fs_qfmask[2]; /* ~usb_fmask */ + } fs_sun; + struct { + __fs32 fs_sparecon[53];/* reserved for future constants */ + __fs32 fs_reclaim; + __fs32 fs_sparecon2[1]; + __fs32 fs_npsect; /* # sectors/track including spares */ + __fs32 fs_qbmask[2]; /* ~usb_bmask */ + __fs32 fs_qfmask[2]; /* ~usb_fmask */ + } fs_sunx86; + struct { + __fs32 fs_sparecon[50];/* reserved for future constants */ + __fs32 fs_contigsumsize;/* size of cluster summary array */ + __fs32 fs_maxsymlinklen;/* max length of an internal symlink */ + __fs32 fs_inodefmt; /* format of on-disk inodes */ + __fs32 fs_maxfilesize[2]; /* max representable file size */ + __fs32 fs_qbmask[2]; /* ~usb_bmask */ + __fs32 fs_qfmask[2]; /* ~usb_fmask */ + __fs32 fs_state; /* file system state time stamp */ + } fs_44; + } fs_u2; + __fs32 fs_postblformat; /* format of positional layout tables */ + __fs32 fs_nrpos; /* number of rotational positions */ + __fs32 fs_postbloff; /* (__s16) rotation block list head */ + __fs32 fs_rotbloff; /* (__u8) blocks for each rotation */ + __fs32 fs_magic; /* magic number */ + __u8 fs_space[1]; /* list of blocks for each rotation */ +}; +#endif/*struct ufs_super_block*/ + +/* + * Preference for optimization. + */ +#define UFS_OPTTIME 0 /* minimize allocation time */ +#define UFS_OPTSPACE 1 /* minimize disk fragmentation */ + +/* + * Rotational layout table format types + */ +#define UFS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ +#define UFS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ + +/* + * Convert cylinder group to base address of its global summary info. + */ +#define fs_cs(indx) s_csp[(indx)] + +/* + * Cylinder group block for a file system. + * + * Writable fields in the cylinder group are protected by the associated + * super block lock fs->fs_lock. + */ +#define CG_MAGIC 0x090255 +#define ufs_cg_chkmagic(sb, ucg) \ + (fs32_to_cpu((sb), (ucg)->cg_magic) == CG_MAGIC) +/* + * Macros for access to old cylinder group array structures + */ +#define ufs_ocg_blktot(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_btot) +#define ufs_ocg_blks(sb, ucg, cylno) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_b[cylno]) +#define ufs_ocg_inosused(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_iused) +#define ufs_ocg_blksfree(sb, ucg) fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_free) +#define ufs_ocg_chkmagic(sb, ucg) \ + (fs32_to_cpu((sb), ((struct ufs_old_cylinder_group *)(ucg))->cg_magic) == CG_MAGIC) + +/* + * size of this structure is 172 B + */ +struct ufs_cylinder_group { + __fs32 cg_link; /* linked list of cyl groups */ + __fs32 cg_magic; /* magic number */ + __fs32 cg_time; /* time last written */ + __fs32 cg_cgx; /* we are the cgx'th cylinder group */ + __fs16 cg_ncyl; /* number of cyl's this cg */ + __fs16 cg_niblk; /* number of inode blocks this cg */ + __fs32 cg_ndblk; /* number of data blocks this cg */ + struct ufs_csum cg_cs; /* cylinder summary information */ + __fs32 cg_rotor; /* position of last used block */ + __fs32 cg_frotor; /* position of last used frag */ + __fs32 cg_irotor; /* position of last used inode */ + __fs32 cg_frsum[UFS_MAXFRAG]; /* counts of available frags */ + __fs32 cg_btotoff; /* (__u32) block totals per cylinder */ + __fs32 cg_boff; /* (short) free block positions */ + __fs32 cg_iusedoff; /* (char) used inode map */ + __fs32 cg_freeoff; /* (u_char) free block map */ + __fs32 cg_nextfreeoff; /* (u_char) next available space */ + union { + struct { + __fs32 cg_clustersumoff; /* (u_int32) counts of avail clusters */ + __fs32 cg_clusteroff; /* (u_int8) free cluster map */ + __fs32 cg_nclusterblks; /* number of clusters this cg */ + __fs32 cg_sparecon[13]; /* reserved for future use */ + } cg_44; + struct { + __fs32 cg_clustersumoff;/* (u_int32) counts of avail clusters */ + __fs32 cg_clusteroff; /* (u_int8) free cluster map */ + __fs32 cg_nclusterblks;/* number of clusters this cg */ + __fs32 cg_niblk; /* number of inode blocks this cg */ + __fs32 cg_initediblk; /* last initialized inode */ + __fs32 cg_sparecon32[3];/* reserved for future use */ + __fs64 cg_time; /* time last written */ + __fs64 cg_sparecon[3]; /* reserved for future use */ + } cg_u2; + __fs32 cg_sparecon[16]; /* reserved for future use */ + } cg_u; + __u8 cg_space[1]; /* space for cylinder group maps */ +/* actually longer */ +}; + +/* Historic Cylinder group info */ +struct ufs_old_cylinder_group { + __fs32 cg_link; /* linked list of cyl groups */ + __fs32 cg_rlink; /* for incore cyl groups */ + __fs32 cg_time; /* time last written */ + __fs32 cg_cgx; /* we are the cgx'th cylinder group */ + __fs16 cg_ncyl; /* number of cyl's this cg */ + __fs16 cg_niblk; /* number of inode blocks this cg */ + __fs32 cg_ndblk; /* number of data blocks this cg */ + struct ufs_csum cg_cs; /* cylinder summary information */ + __fs32 cg_rotor; /* position of last used block */ + __fs32 cg_frotor; /* position of last used frag */ + __fs32 cg_irotor; /* position of last used inode */ + __fs32 cg_frsum[8]; /* counts of available frags */ + __fs32 cg_btot[32]; /* block totals per cylinder */ + __fs16 cg_b[32][8]; /* positions of free blocks */ + __u8 cg_iused[256]; /* used inode map */ + __fs32 cg_magic; /* magic number */ + __u8 cg_free[1]; /* free block map */ +/* actually longer */ +}; + +/* + * structure of an on-disk inode + */ +struct ufs_inode { + __fs16 ui_mode; /* 0x0 */ + __fs16 ui_nlink; /* 0x2 */ + union { + struct { + __fs16 ui_suid; /* 0x4 */ + __fs16 ui_sgid; /* 0x6 */ + } oldids; + __fs32 ui_inumber; /* 0x4 lsf: inode number */ + __fs32 ui_author; /* 0x4 GNU HURD: author */ + } ui_u1; + __fs64 ui_size; /* 0x8 */ + struct ufs_timeval ui_atime; /* 0x10 access */ + struct ufs_timeval ui_mtime; /* 0x18 modification */ + struct ufs_timeval ui_ctime; /* 0x20 creation */ + union { + struct { + __fs32 ui_db[UFS_NDADDR];/* 0x28 data blocks */ + __fs32 ui_ib[UFS_NINDIR];/* 0x58 indirect blocks */ + } ui_addr; + __u8 ui_symlink[4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */ + } ui_u2; + __fs32 ui_flags; /* 0x64 immutable, append-only... */ + __fs32 ui_blocks; /* 0x68 blocks in use */ + __fs32 ui_gen; /* 0x6c like ext2 i_version, for NFS support */ + union { + struct { + __fs32 ui_shadow; /* 0x70 shadow inode with security data */ + __fs32 ui_uid; /* 0x74 long EFT version of uid */ + __fs32 ui_gid; /* 0x78 long EFT version of gid */ + __fs32 ui_oeftflag; /* 0x7c reserved */ + } ui_sun; + struct { + __fs32 ui_uid; /* 0x70 File owner */ + __fs32 ui_gid; /* 0x74 File group */ + __fs32 ui_spare[2]; /* 0x78 reserved */ + } ui_44; + struct { + __fs32 ui_uid; /* 0x70 */ + __fs32 ui_gid; /* 0x74 */ + __fs16 ui_modeh; /* 0x78 mode high bits */ + __fs16 ui_spare; /* 0x7A unused */ + __fs32 ui_trans; /* 0x7c filesystem translator */ + } ui_hurd; + } ui_u3; +}; + +#define UFS_NXADDR 2 /* External addresses in inode. */ +struct ufs2_inode { + __fs16 ui_mode; /* 0: IFMT, permissions; see below. */ + __fs16 ui_nlink; /* 2: File link count. */ + __fs32 ui_uid; /* 4: File owner. */ + __fs32 ui_gid; /* 8: File group. */ + __fs32 ui_blksize; /* 12: Inode blocksize. */ + __fs64 ui_size; /* 16: File byte count. */ + __fs64 ui_blocks; /* 24: Bytes actually held. */ + __fs64 ui_atime; /* 32: Last access time. */ + __fs64 ui_mtime; /* 40: Last modified time. */ + __fs64 ui_ctime; /* 48: Last inode change time. */ + __fs64 ui_birthtime; /* 56: Inode creation time. */ + __fs32 ui_mtimensec; /* 64: Last modified time. */ + __fs32 ui_atimensec; /* 68: Last access time. */ + __fs32 ui_ctimensec; /* 72: Last inode change time. */ + __fs32 ui_birthnsec; /* 76: Inode creation time. */ + __fs32 ui_gen; /* 80: Generation number. */ + __fs32 ui_kernflags; /* 84: Kernel flags. */ + __fs32 ui_flags; /* 88: Status flags (chflags). */ + __fs32 ui_extsize; /* 92: External attributes block. */ + __fs64 ui_extb[UFS_NXADDR];/* 96: External attributes block. */ + union { + struct { + __fs64 ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */ + __fs64 ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/ + } ui_addr; + __u8 ui_symlink[2*4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */ + } ui_u2; + __fs64 ui_spare[3]; /* 232: Reserved; currently unused */ +}; + + +/* FreeBSD has these in sys/stat.h */ +/* ui_flags that can be set by a file owner */ +#define UFS_UF_SETTABLE 0x0000ffff +#define UFS_UF_NODUMP 0x00000001 /* do not dump */ +#define UFS_UF_IMMUTABLE 0x00000002 /* immutable (can't "change") */ +#define UFS_UF_APPEND 0x00000004 /* append-only */ +#define UFS_UF_OPAQUE 0x00000008 /* directory is opaque (unionfs) */ +#define UFS_UF_NOUNLINK 0x00000010 /* can't be removed or renamed */ +/* ui_flags that only root can set */ +#define UFS_SF_SETTABLE 0xffff0000 +#define UFS_SF_ARCHIVED 0x00010000 /* archived */ +#define UFS_SF_IMMUTABLE 0x00020000 /* immutable (can't "change") */ +#define UFS_SF_APPEND 0x00040000 /* append-only */ +#define UFS_SF_NOUNLINK 0x00100000 /* can't be removed or renamed */ + +/* + * This structure is used for reading disk structures larger + * than the size of fragment. + */ +struct ufs_buffer_head { + __u64 fragment; /* first fragment */ + __u64 count; /* number of fragments */ + struct buffer_head * bh[UFS_MAXFRAG]; /* buffers */ +}; + +struct ufs_cg_private_info { + struct ufs_buffer_head c_ubh; + __u32 c_cgx; /* number of cylidner group */ + __u16 c_ncyl; /* number of cyl's this cg */ + __u16 c_niblk; /* number of inode blocks this cg */ + __u32 c_ndblk; /* number of data blocks this cg */ + __u32 c_rotor; /* position of last used block */ + __u32 c_frotor; /* position of last used frag */ + __u32 c_irotor; /* position of last used inode */ + __u32 c_btotoff; /* (__u32) block totals per cylinder */ + __u32 c_boff; /* (short) free block positions */ + __u32 c_iusedoff; /* (char) used inode map */ + __u32 c_freeoff; /* (u_char) free block map */ + __u32 c_nextfreeoff; /* (u_char) next available space */ + __u32 c_clustersumoff;/* (u_int32) counts of avail clusters */ + __u32 c_clusteroff; /* (u_int8) free cluster map */ + __u32 c_nclusterblks; /* number of clusters this cg */ +}; + + +struct ufs_sb_private_info { + struct ufs_buffer_head s_ubh; /* buffer containing super block */ + struct ufs_csum_core cs_total; + __u32 s_sblkno; /* offset of super-blocks in filesys */ + __u32 s_cblkno; /* offset of cg-block in filesys */ + __u32 s_iblkno; /* offset of inode-blocks in filesys */ + __u32 s_dblkno; /* offset of first data after cg */ + __u32 s_cgoffset; /* cylinder group offset in cylinder */ + __u32 s_cgmask; /* used to calc mod fs_ntrak */ + __u32 s_size; /* number of blocks (fragments) in fs */ + __u32 s_dsize; /* number of data blocks in fs */ + __u64 s_u2_size; /* ufs2: number of blocks (fragments) in fs */ + __u64 s_u2_dsize; /*ufs2: number of data blocks in fs */ + __u32 s_ncg; /* number of cylinder groups */ + __u32 s_bsize; /* size of basic blocks */ + __u32 s_fsize; /* size of fragments */ + __u32 s_fpb; /* fragments per block */ + __u32 s_minfree; /* minimum percentage of free blocks */ + __u32 s_bmask; /* `blkoff'' calc of blk offsets */ + __u32 s_fmask; /* s_fsize mask */ + __u32 s_bshift; /* `lblkno'' calc of logical blkno */ + __u32 s_fshift; /* s_fsize shift */ + __u32 s_fpbshift; /* fragments per block shift */ + __u32 s_fsbtodb; /* fsbtodb and dbtofsb shift constant */ + __u32 s_sbsize; /* actual size of super block */ + __u32 s_csmask; /* csum block offset */ + __u32 s_csshift; /* csum block number */ + __u32 s_nindir; /* value of NINDIR */ + __u32 s_inopb; /* value of INOPB */ + __u32 s_nspf; /* value of NSPF */ + __u32 s_npsect; /* # sectors/track including spares */ + __u32 s_interleave; /* hardware sector interleave */ + __u32 s_trackskew; /* sector 0 skew, per track */ + __u64 s_csaddr; /* blk addr of cyl grp summary area */ + __u32 s_cssize; /* size of cyl grp summary area */ + __u32 s_cgsize; /* cylinder group size */ + __u32 s_ntrak; /* tracks per cylinder */ + __u32 s_nsect; /* sectors per track */ + __u32 s_spc; /* sectors per cylinder */ + __u32 s_ipg; /* inodes per cylinder group */ + __u32 s_fpg; /* fragments per group */ + __u32 s_cpc; /* cyl per cycle in postbl */ + __s32 s_contigsumsize;/* size of cluster summary array, 44bsd */ + __s64 s_qbmask; /* ~usb_bmask */ + __s64 s_qfmask; /* ~usb_fmask */ + __s32 s_postblformat; /* format of positional layout tables */ + __s32 s_nrpos; /* number of rotational positions */ + __s32 s_postbloff; /* (__s16) rotation block list head */ + __s32 s_rotbloff; /* (__u8) blocks for each rotation */ + + __u32 s_fpbmask; /* fragments per block mask */ + __u32 s_apb; /* address per block */ + __u32 s_2apb; /* address per block^2 */ + __u32 s_3apb; /* address per block^3 */ + __u32 s_apbmask; /* address per block mask */ + __u32 s_apbshift; /* address per block shift */ + __u32 s_2apbshift; /* address per block shift * 2 */ + __u32 s_3apbshift; /* address per block shift * 3 */ + __u32 s_nspfshift; /* number of sector per fragment shift */ + __u32 s_nspb; /* number of sector per block */ + __u32 s_inopf; /* inodes per fragment */ + __u32 s_sbbase; /* offset of NeXTstep superblock */ + __u32 s_bpf; /* bits per fragment */ + __u32 s_bpfshift; /* bits per fragment shift*/ + __u32 s_bpfmask; /* bits per fragment mask */ + + __u32 s_maxsymlinklen;/* upper limit on fast symlinks' size */ + __s32 fs_magic; /* filesystem magic */ + unsigned int s_dirblksize; +}; + +/* + * Sizes of this structures are: + * ufs_super_block_first 512 + * ufs_super_block_second 512 + * ufs_super_block_third 356 + */ +struct ufs_super_block_first { + union { + struct { + __fs32 fs_link; /* UNUSED */ + } fs_42; + struct { + __fs32 fs_state; /* file system state flag */ + } fs_sun; + } fs_u0; + __fs32 fs_rlink; + __fs32 fs_sblkno; + __fs32 fs_cblkno; + __fs32 fs_iblkno; + __fs32 fs_dblkno; + __fs32 fs_cgoffset; + __fs32 fs_cgmask; + __fs32 fs_time; + __fs32 fs_size; + __fs32 fs_dsize; + __fs32 fs_ncg; + __fs32 fs_bsize; + __fs32 fs_fsize; + __fs32 fs_frag; + __fs32 fs_minfree; + __fs32 fs_rotdelay; + __fs32 fs_rps; + __fs32 fs_bmask; + __fs32 fs_fmask; + __fs32 fs_bshift; + __fs32 fs_fshift; + __fs32 fs_maxcontig; + __fs32 fs_maxbpg; + __fs32 fs_fragshift; + __fs32 fs_fsbtodb; + __fs32 fs_sbsize; + __fs32 fs_csmask; + __fs32 fs_csshift; + __fs32 fs_nindir; + __fs32 fs_inopb; + __fs32 fs_nspf; + __fs32 fs_optim; + union { + struct { + __fs32 fs_npsect; + } fs_sun; + struct { + __fs32 fs_state; + } fs_sunx86; + } fs_u1; + __fs32 fs_interleave; + __fs32 fs_trackskew; + __fs32 fs_id[2]; + __fs32 fs_csaddr; + __fs32 fs_cssize; + __fs32 fs_cgsize; + __fs32 fs_ntrak; + __fs32 fs_nsect; + __fs32 fs_spc; + __fs32 fs_ncyl; + __fs32 fs_cpg; + __fs32 fs_ipg; + __fs32 fs_fpg; + struct ufs_csum fs_cstotal; + __s8 fs_fmod; + __s8 fs_clean; + __s8 fs_ronly; + __s8 fs_flags; + __s8 fs_fsmnt[UFS_MAXMNTLEN - 212]; + +}; + +struct ufs_super_block_second { + union { + struct { + __s8 fs_fsmnt[212]; + __fs32 fs_cgrotor; + __fs32 fs_csp[UFS_MAXCSBUFS]; + __fs32 fs_maxcluster; + __fs32 fs_cpc; + __fs16 fs_opostbl[82]; + } fs_u1; + struct { + __s8 fs_fsmnt[UFS2_MAXMNTLEN - UFS_MAXMNTLEN + 212]; + __u8 fs_volname[UFS2_MAXVOLLEN]; + __fs64 fs_swuid; + __fs32 fs_pad; + __fs32 fs_cgrotor; + __fs32 fs_ocsp[UFS2_NOCSPTRS]; + __fs32 fs_contigdirs; + __fs32 fs_csp; + __fs32 fs_maxcluster; + __fs32 fs_active; + __fs32 fs_old_cpc; + __fs32 fs_maxbsize; + __fs64 fs_sparecon64[17]; + __fs64 fs_sblockloc; + __fs64 cs_ndir; + __fs64 cs_nbfree; + } fs_u2; + } fs_un; +}; + +struct ufs_super_block_third { + union { + struct { + __fs16 fs_opostbl[46]; + } fs_u1; + struct { + __fs64 cs_nifree; /* number of free inodes */ + __fs64 cs_nffree; /* number of free frags */ + __fs64 cs_numclusters; /* number of free clusters */ + __fs64 cs_spare[3]; /* future expansion */ + struct ufs_timeval fs_time; /* last time written */ + __fs64 fs_size; /* number of blocks in fs */ + __fs64 fs_dsize; /* number of data blocks in fs */ + __fs64 fs_csaddr; /* blk addr of cyl grp summary area */ + __fs64 fs_pendingblocks;/* blocks in process of being freed */ + __fs32 fs_pendinginodes;/*inodes in process of being freed */ + } __attribute__ ((packed)) fs_u2; + } fs_un1; + union { + struct { + __fs32 fs_sparecon[53];/* reserved for future constants */ + __fs32 fs_reclaim; + __fs32 fs_sparecon2[1]; + __fs32 fs_state; /* file system state time stamp */ + __fs32 fs_qbmask[2]; /* ~usb_bmask */ + __fs32 fs_qfmask[2]; /* ~usb_fmask */ + } fs_sun; + struct { + __fs32 fs_sparecon[53];/* reserved for future constants */ + __fs32 fs_reclaim; + __fs32 fs_sparecon2[1]; + __fs32 fs_npsect; /* # sectors/track including spares */ + __fs32 fs_qbmask[2]; /* ~usb_bmask */ + __fs32 fs_qfmask[2]; /* ~usb_fmask */ + } fs_sunx86; + struct { + __fs32 fs_sparecon[50];/* reserved for future constants */ + __fs32 fs_contigsumsize;/* size of cluster summary array */ + __fs32 fs_maxsymlinklen;/* max length of an internal symlink */ + __fs32 fs_inodefmt; /* format of on-disk inodes */ + __fs32 fs_maxfilesize[2]; /* max representable file size */ + __fs32 fs_qbmask[2]; /* ~usb_bmask */ + __fs32 fs_qfmask[2]; /* ~usb_fmask */ + __fs32 fs_state; /* file system state time stamp */ + } fs_44; + } fs_un2; + __fs32 fs_postblformat; + __fs32 fs_nrpos; + __fs32 fs_postbloff; + __fs32 fs_rotbloff; + __fs32 fs_magic; + __u8 fs_space[1]; +}; + +#endif /* __LINUX_UFS_FS_H */ diff -Naur silo-1.4.14.orig/libext2fs/ChangeLog silo-1.4.14/libext2fs/ChangeLog --- silo-1.4.14.orig/libext2fs/ChangeLog 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/ChangeLog 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,3311 @@ +2006-06-30 Theodore Ts'o + + * Release of E2fsprogs 1.38 + +2005-06-30 Theodore Ts'o + + * bitops.h, bitops.c (ext2fs_set_bit, ext2fs_clear_bit, + ext2fs_test_bit): Change these function prototypes to be + unsigned int's. Negative bit numbers were never allowed + (and never made any sense), so this should be a safe + change. This is needed to allow safe use of block numbers + greater than or equal to 2**31. + +2005-06-27 Stephen Tweedie + + * ext2fs.h (ext2fs_resize_mem): Fix C99 strict type aliasing + problems. Addresses Red Hat Bugzilla #161183. + +2005-06-19 Theodore Ts'o + + * getsectsize.c (BLKSSZGET): Clean up test for when to manually + define the BLKSSZGET ioctl. + +2005-05-29 Theodore Ts'o + + * ismounted.c (ext2fs_check_mount_point): Add test to see if the + device appears to be busy; this only works on Linux 2.6+ + systems, but provides some additional bullet-proofing in + those cases. + +2005-05-08 Theodore Ts'o + + * test_io.c (safe_getenv): Fix bug so it would fetch the right + environment variable. + +2005-04-09 Theodore Ts'o + + * inode.c (ext2fs_write_new_inode), + ind_block.c (ext2fs_read_ind_block): Add missing return + value in error return case. (Otherwise we return garbage + instead of the error code.) + +2005-03-31 Theodore Ts'o + + * test_io.c (test_open): If called by a setuid/setgid or an + otherwise privileged program, be paranoid and ignore the + TEST_IO_* environment variables. + +2005-03-21 Theodore Ts'o + + * Release of E2fsprogs 1.37 + +2005-03-21 Theodore Ts'o + + * ext2_ext_attr.h (EXT2_XATTR_LEN, EXT2_XATTR_SIZE): Add new + convenience cpp macros. + +2005-03-20 Theodore Ts'o + + * mkdir.c (ext2fs_mkdir): Call ext2fs_write_new_inode() instead of + ext2fs_write_inode(). + + * inode.c (ext2fs_write_new_inode): New function which should be + used when the caller is writing an inode for the first + time. It makes sure that the extra portion of the large + inode is initialized properly. + +2005-03-18 Theodore Ts'o + + * Makefile.in: Fix clean target to remove tst_getsectsize. + + * getsize.c (ext2fs_get_device_size): Check to see if the number + of blocks is greater than 2**32 when we are doing a binary + search to determine the device size. Thanks to Stephen + Tweedie for the patch. + +2006-02-05 Theodore Ts'o + + * Release of E2fsprogs 1.36 + +2005-02-05 Theodore Ts'o + + * Makefile.in: Remove ext2fs.pc on a "make distclean" + +2005-02-04 Theodore Ts'o + + * Makefile.in (clean): Remove tst_getsize when doing a make clean + +2005-02-03 Theodore Ts'o + + * bitops.c: Make the generic functions more efficient. + + * bitops.h: Drop SPARC assembly code. It's less efficient than GCC + 3.4 compiled code and also triggers nasty compiler + warnings on sparc64. Thanks to Matthias Andree for his + analysis and suggestion. + +2005-01-27 Theodore Ts'o + + * res_gdt.c (ext2fs_create_resize_inode): Create the resize inode + even if s_reserved_gdt_blocks is zero. + +2005-01-26 Theodore Ts'o + + * ext2fs.pc.in: Add pkg-config files. + +2005-01-25 Theodore Ts'o + + * ext2fs.h: Add definition of struct ext2_inode_large + + * ext2_fs.h: Add new function prototypes + + * ext_attr.c (ext2fs_read_ext_attr, ext2fs_write_ext_attr): The + ext2fs_swap_ext_attr() has been moved to swapfs.c, and + given a new argument, has_header. + + * swapfs.c (ext2fs_swap_ext_attr): Moved from ext_attr.c, and + takes an argument which controls whether or not there is + an EA header which needs to be byteswaped. + (ext2fs_swap_inode_full): New function which byte-swaps + the EA in inode. + + * inode.c (ext2fs_get_next_inode_full, ext2fs_read_inode_full, + ext2fs_write_inode_full): New functions, originally from + Alex Tomas, but which needed to be substantially fixed so + that the tests wouldn't cause major stack overwrite bugs + in byte-swapping is enabled. + +2005-01-18 Theodore Ts'o + + * Makefile.in: Fix the kernel compile-time echo commands to be + consistent and portable + +2005-01-07 Theodore Ts'o + + * unlink.c (ext2fs_unlink): If both the name and the inode number + are unspecified, then return an error, so that we don't do + something surprising such as unconditionally deleting the + first directory entry. + (unlink_proc): Delete directory entries by coalescing it + with the previous entry, to avoid directory fragmentation. + +2005-01-06 Theodore Ts'o + + * version.c (ext2fs_parse_version_string): Change parsing + algorithm so that version strings such as 1.36-rc1 returns + a non-surprising result (i.e., 136, and not 1361). + +2005-01-05 Theodore Ts'o + + * block.c (block_iterate_ind, block_iterate_dind, + block_iterate_tind): Move the code which byte swaps and + read/writes indirect blocks to ext2fs_{read,write}_ind_block. + This saves 400 bytes, and we need them for the + resize_inode handling. + + * ind_block.c (ext2fs_read_ind_block, ext2fs_write_ind_block): New + functions. + + * res_gdt.c (ext2fs_create_resize_inode): Use + ext2fs_{read,write}_ind_block so that byte swapping is + handled on big-endian systems. + + * dupfs.c (ext2fs_dup_handle): Make sure the new filesystem handle + has its own copy of the orig_super data structure. (This + is a better way of fixing a double-free problem in + resize2fs which Fedora attempted to fix in + e2fsprogs-1.35-double_free.patch. Addresses Red Hat + Bugzilla #132707.) + +2004-12-23 Theodore Ts'o + + * inode.c (ext2fs_flush_icache): When flushing the icache, clear + the last-read block information as well. + + * ext2fs.h (BMAP_SET), bmap.c (ext2fs_bmap): Add support for new + flag, BMAP_SET, which allows the caller to set a + particular logical->physical block mapping. + + * ext2_err.et.in (EXT2_ET_SET_BMAP_NO_IND): New error code + + * initialize.c (calc_reserved_gdt_blocks): #ifdef out all + debugging printf statements. + + * res_gdt.c (ext2fs_create_resize_inode): Return + EXT2_ET_RESIZE_INODE_CORRUPT if the resize inode is not + what we expect. #ifdef out all debugging printf + statements. + + * ext2_err.et.in (EXT2_ET_RESIZE_INODE_CORRUPT): Add new error code. + +2004-12-22 Theodore Ts'o + + * swapfs.c (ext2fs_swap_super): Byteswap the reserved_gdt_blocks + superblocks field. + +2004-12-15 Theodore Ts'o + + * sparse.c (ext2fs_list_backups, ext2fs_bg_has_super), + res_gdt.c (list_backups), closefs.c (ext2fs_bg_has_super), + ext2fs.h: Move ext2fs_list_backups() to res_gdt.c, and + ext2fs_bg_has_super() back to closefs.c. There's no + reason for the new file, since list_backups() isn't being + used by any other functions, and can be made static, and + all users of the ext2fs filesystem will have to call + ext2fs_close() anyway. + +2004-12-15 Theodore Ts'o + + * Applied resize inode patch from Andreas Dilger + + * res_gdt.c (ext2fs_create_resize_inode): New function that + creates the resize inode. + + * initialize.c (ext2fs_initialize): Reserve space for the resize + inode. + + * ext2fs.h (EXT2_LIB_FEATURE_COMPAT_SUPP): Add + EXT2_FEATURE_COMPAT_RESIZE_INODE to the list of supported + capabilities. + Add function prototypes for res_gdt.c and sparse.c. + + * closefs.c (ext2fs_super_and_bgd_loc): Take the reserved blocks + into account when calculating the number of overhead + blocks. + + * closefs.c (ext2fs_bg_has_super, test_root), sparse.c: Move these + functions to the new file sparse.c + + * alloc_sb.c (ext2fs_reserve_super_and_bgd): Reserve the blocks + saved in the resize inode as being in use. + + * ext2_err.et.in (EXT2_ET_RES_GDT_BLOCKS): Add new error code. + + * Makefile.in (srcdir): Add res_gdt.c and sparse.c to the ext2fs + library. + +2004-12-14 Theodore Ts'o + + * Makefile.in: Use Linux-kernel-style makefile output for "make + install" + + * Makefile.in (installdirs): Use $(MKINSTALLDIRS) macro + Update dependencies. + +2004-11-30 Theodore Ts'o + + * unix_io.c (unix_set_option): Add support for the offset option. + + * test_io.c (test_set_option): Add support for the set_option method. + + * ext2_io.h: Add new io_channel method, set_option(), and change + io_channel_write_byte() from a macro to a library function. + + * ext2fs.h, openfs.c(ext2fs_open2): New version of ext2fs_open + which adds a new parameter, io_options. + (ext2fs_open): If there is a question mark in the + filename, and no io_options are specified, assumed that + the text following the question mark are io_options. + + * io_manager.c, Makefile.in: New source file which contains + high-level functions for the io_channel layer. + + * freefs.c (ext2fs_free): Make sure we don't free the io_channel + if image_io is NULL. + + * Makefile.in: Use Linux-kernel-style makefile output to make it + easier to see errors/warnings. + +2004-11-29 Theodore Ts'o + + * ext2_fs.h (EXT2_EXTENTS_FL, EXT3_FEATURE_INCOMPAT_EXTENTS, + EXT2_MAX_BLOCK_LOG_SIZE): Add definition for extent + feature and inode flag. Change maximum allowable block + size to be 65536. + +2004-10-08 Theodore Ts'o + + * getsize.c (ext2fs_get_device_size): Add support for Windows + 9x/NT under Cygwin. Thanks to Sam Robb + (samrobb@users.sourceforge.net) for pointing this and the + suggested code patch. + +2004-09-17 Theodore Ts'o + + * getsize.c: Clean up header #include's. + + * llseek.c (ext2fs_llseek): On non-linux systems, use lseek64() if + it is present. (Addresses Debian bug #269044) + +2004-07-28 Theodore Ts'o + + * rw_bitmaps.c (read_bitmaps), block.c (block_iterate_ind, + block_iterate_dind, block_iterate_tind), inode.c + (ext2fs_read_inode): If EXT2_FLAG_IMAGE_FILE is set, so + read the metadata from fs->image_io instead of fs->io. + + * initialize.c (ext2fs_initialize), openfs.c (ext2fs_open): + Initialize fs->image_io to be the same as fs->io. + + * ext2_err.et.in (EXT2_ET_NOT_IMAGE_FILE): Add new error code. + + * openfs.c (ext2fs_get_data_io, ext2fs_set_data_io, + ext2fs_rewrite_to_io): New functions that allow + applications to manipulate fs->image_io and fs->io safely. + + * freefs.c (ext2fs_free): If fs->image_io is different fs->io, + then call io_channel_close on fs->image_io. + + * ext2fs.h: Add image_io element to the ext2_filsys data + structure. Add ext2fs_get_data_io() ext2fs_set_data_io(), + and ext2fs_rewrite_to_io() prototypes. + +2004-05-26 Theodore Ts'o + + * closefs.c (ext2fs_flush): Make sure the master superblock is + written last, and only after other I/O has been flushed to + disk. Thanks to Junfeng Yang from the Stanford + Metacompilation group for pointing a potential ordering + constraint problem if we don't write things out in the + right order. + + * test_io.c: Implement the ability to abort after n reads or + writes to a particular block. The block is specified by + TEST_IO_BLOCK environment variable, and the read/write + count by the TEST_IO_READ_ABORT and TEST_IO_WRITE_ABORT + environment variables. The block data is now only dumped + if the 0x10 bit is set in TEST_IO_FLAGS. + +2004-04-03 Theodore Ts'o + + * ext2_types.h.in: Remove check for _UUID_TYPES since uuid_types.h + is no longer used. + +2004-03-08 Theodore Ts'o + + * getsize.c (ext2fs_get_device_size): Only use the BLKGETSIZE64 + ioctl on Linux 2.6 since it is unreliable in Linux 2.4. + (Addresses Debian Bug #236528). Fix typo in the ioctl + used for Mac OS X. + +2004-03-02 Theodore Ts'o + + * getsize.c (ext2fs_get_device_size): Update getsize functions to + use Apple Darwin and Linux 64-bit ioctl's + +2004-02-29 Brian Bergstrand + + * Makefile.in: Use $(BSDLIB_PIC_FLAG) to determine whether to use + -fpic or -fPIC + +2004-02-28 Theodore Ts'o + + * Release of E2fsprogs 1.35 + +2004-02-21 Theodore Ts'o + + * ext2fs.h (ext2fs_resize_mem): Fix C++ problem. (Addresses Red + Hat Bugzilla #112448; thanks Thomas Woerner from Red Hat.) + +2004-02-14 Theodore Ts'o + + * namei.c (follow_link): Correctly deal with symlinks that have + extended attribute information. (Addresses Debian Bug + #232328) + +2004-01-30 Theodore Ts'o + + * ext2_fs.h: Reserve an extra 4 bytes for the journal backup, + which we're using due to a typo in the e2fsck code. (Oops) + + * swapfs.c (ext2fs_swap_inode): Fix byte swap bug which causes SE + Linux created symlinks with mandatory attributes to fail + to be properly handled on big endian systems. (Addresses + Debian Bug #228723). + (ext2fs_swap_super): Byte swap some new fields in the + superblock, including the journal backup fields. + +2003-12-02 Theodore Ts'o + + * alloc.c, bb_inode.c, bitops.c, block.c, check_desc.c, closefs.c, + dir_iterate.c, dirblock.c, expanddir.c, ext2fs.h, + get_pathname.c, icount.c, imager.c, initalize.c, inode.c, + lookup.c, openfs.c, read_bb.c, read_bb_file.c, + rw_bitmaps.c, unix_io.c, unlink.c, write_bb_file.c: Fix + gcc -Wall complaints. Mainly marking variables as being + unsued, and catching signed vs. unsigned comparisons. + +2003-09-03 Theodore Ts'o + + * closefs.c (ext2fs_super_and_bgd_loc): New function which + centralizes the calculation of the superblock and block + group descriptors. + (ext2fs_flush): Use ext2fs_super_and_bgd_lock to figure + out where to write the superblock and block group + descriptors. + + * alloc_sb.c (ext2fs_reserve_super_and_bgd): New function which + reserves space in the block bitmap using + ext2fs_super_and_bgd_loc. + + * initialize.c (ext2fs_initialize): Use + ext2fs_reserve_super_and_bgd to initialize the block bitmap. + +2003-08-20 Theodore Ts'o + + * inode_io.c (ext2fs_inode_io_intern2), ext2fs.h: Add new function + allows the caller to pass in the inode data structure. + + * fileio.c (ext2fs_file_open2), ext2fs.h: Add new function which + allows the caller to pass in the inode to be used in the + file I/O. + + * ext2_fs.h: Add a backup of the location of the journal inode + blocks to the superblock. + + * mkjournal.c (write_journal_inode): Save the location of the + journal inode to the backup location in the superblock. + +2003-08-01 Philipp Thomas + + * alloc.c, badblocks.c, bb_inode.c, bitmaps.c, block.c, bmap.c, + bmove.c, brel_ma.c, closefs.c, dblist.c, dblist_dir.c, + dir_iterate.c, dirblock.c, dupfs.c, expanddir.c, ext2fs.h, + ext_attr.c, fileio.c, freefs.c, get_pathname.c, icount.c, + initialize.c, inode.c, inode_io.c, irel_ma.c, mkdir.c, + mkjournal.c, namei.c, newdir.c, openfs.c, rs_bitmap.c, + rw_bitmaps.c, test_io.c, unix_io.c: ext2fs_getmem(), + ext2fs_free_mem(), and ext2fs_resize_mem() all now take a + 'void *' instead of a 'void **' in order to avoid pointer + aliasing problems with GCC 3.x. + +2003-07-25 Theodore Ts'o + + * Release of E2fsprogs 1.34 + +2003-07-06 Theodore Ts'o + + * kernel-jbd.h, flushb.c: Fix gcc -Wall nitpicks (indented cpp + directives) + + * ext2_types.h.in, initialize.c: Fix gcc -Wall nitpicks + (don't use #elsif) + + * ismounted.c: Fix gcc -Wall nitpicks (Don't use exit as a goto label) + + * llseek.c: Fix gcc -Wall nitpicks (don't use #elsif) + + * lookup.c, read_bb.c: Fix gcc -Wall nitpicks (indent + non-traditional #pragma) + + * test_io.c: Fix gcc -Wall nitpicks (const/unsigned type issues) + +2003-06-24 + + * badblocks.c, ext2fs.h (ext2fs_u32_list_find, + ext2fs_u32_list_test, ext2fs_u32_list_del, + ext2fs_badblocks_list_del): Add functions to delete a + block from the badblocks list. + * tst_badblocks.c: Add test cases for ext2fs_badblocks_list_del(). + +2003-05-21 Theodore Ts'o + + * getsectsize.c (ext2fs_get_device_sectsize): New function which + returns the hardware sector size (if it is available). + +2003-05-13 Theodore Ts'o + + * unix_io.c: Add #ifdef NO_IO_CACHE which disables all userspace + caching by the unix_io layer. Not enabled, only for + debugging. + +2003-05-05 Theodore Ts'o + + * test_io.c: Pay attention to the environment variables + TEST_IO_LOGFILE, TEST_IO_FLAGS, and TEST_IO_BLOCK to + determine whether or not we should log io activity, and to + where. + +2003-05-03 Theodore Ts'o + + * tst_badblocks.c (file_test): Use tmpfile() instead of mktemp(). + +2003-04-29 Theodore Ts'o + + * getsize.c (ext2fs_get_device_size): Allow windows code to get + the resize for filesystems that are in regular files. + +2003-04-21 Theodore Ts'o + + * Release of E2fsprogs 1.33 + +2003-04-21 Theodore Ts'o + + * Makefile.in: Use DYLD_LIBRAY_PATH so that "make check" works on + Darwin systems when building with shared libraries. + +2003-04-18 Theodore Ts'o + + * unix_io.c: Use __CYGWIN__ instead of CYGWIN. + +2003-04-17 Theodore Ts'o + + * getsize.c: Add Cygwin/Windows version of ext2fs_get_device_size() + +2003-04-12 Theodore Ts'o + + * unix_io.c (raw_read_blk): Add Cygwin support (the Windows block + device only accepts sector aligned read requests. + + * ismounted.c (check_mntent_file): Deal with OS's that don't + define MNTOPT_RO. + + * imager.c: If the OS doesn't define ssize_t, typedef it to int. + +2003-04-11 Theodore Ts'o + + * ext2_fs.h (EXT2_FEATURE_RO_COMPAT_BTREE_DIR): Comment out unused + feature flag + +2003-03-30 Theodore Ts'o + + * Makefile.in: Use the compile_et --build-tree option. + +2003-03-14 Theodore Ts'o + + * getsize.c: Add support for Apple Darwin's ioctl to get the hard + disk size. + + * badblocks.c (ext2fs_u32_list_count), ext2fs.h: Add new function + which returns the number of entries in the list. + +2003-03-10 Theodore Ts'o + + * fileio.c (ext2fs_file_lseek): Fix bug added when adding 64-bit + support; avoid null dereference when ret_pos is NULL. + +2003-03-06 Theodore Tso + + * ext2_types.h.in: Don't redefine types if other e2fsprogs + *_types.h files have been included already. + + * kernel-jbd.h: Use C99 variadic cpp macros if not using GCC. + (Older GCC's don't support the C99 variadic macros.) + + * flushb.c (ext2fs_sync_device), + ismounted.c (ext2fs_check_mount_point): Avoid GCC extension: + #warning not supported by Solaris suncc + + * ext2_ext_attr.h: Avoid GCC extension: 0 length arrays in + structure definition. Not needed for now in + ext2_ext_attr_entry. + +2003-01-25 Theodore Ts'o + + * dirhash.c: Fix gcc -Wall nits. + +2003-01-22 Theodore Ts'o + + * unix_io.c (unix_write_blk): Fix up GCC -Wall nits. + +2003-01-21 Theodore Ts'o + + * fileio.c (ext2fs_file_read, ext2_file_lseek, + ext2_file_get_size): Add 64-bit support. + + * ext2fs.h (EXT2_I_SIZE): Add macro which caluates a 64bit size + from i_size and i_size_high. + +2003-01-19 Theodore Ts'o + + * initialize.c (ext2fs_initialize): If the user specifies a really + large number of inodes, then reduce the number of blocks + per group until we find a workable set of filesystem + parameters. + + * ext2_err.et.in (EXT2_ET_TOO_MANY_INODES): Add new error code. + +2002-11-09 Theodore Ts'o + + * Release of E2fsprogs 1.32 + +2002-11-09 Theodore Ts'o + + * unix_io.c (find_cached_block, reuse_cache, unix_read_blk, + unix_write_blk): Optimize routines so that we don't end up + searching the cache twice when a block isn't in the + cache. If reads are larger than READ_DIRECT_SIZE, don't + let them go through the cache. + + * unix_io.c (find_cached_block): Fixed bug which caused some clean + blocks to be erroneously marked as dirty, so they would + get written back to the disk before they are evicted from + the cache. Harmless, but it slows down e2fsck + significantly. + +2002-11-08 Theodore Ts'o + + * Release of E2fsprogs 1.31 + +2002-11-08 + + * Makefile.in (check): Skip trying to compile test_byteswap + if --disable-byteswaap had been given to configure. + +2002-11-07 + + * closefs.c (write_bgdesc, ext2fs_flush): Fix bug in meta_bg + support when the MASTER_SB_ONLY flag is set. Some of + the descriptor blocks that should have been written out + were getting skipped. + +2002-10-31 Theodore Ts'o + + * Release of E2fsprogs 1.30 + +2002-10-31 Theodore Ts'o + + * ext2_fs.h: Add support for a new inode flag, which is to be used + for indicating the top of directory hierarchies for the + Orlov block allocator. + + * ismounted.c (check_mntent, check_mntent_file): Add better + support for loopback-mounted filesystems. Check /etc/mtab + if /proc/mounts doesn't turn up any mount flags, since + /etc/mtab has the loopback image filename, instead of + /dev/loop0. Also, check based on st_dev and st_ino, so + that if a relative pathname or a pathnames using symbolic + links are used, we can detect the the filesystem correctly + in those cases. (Addresses Sourceforge bug #619119) + + * flushb.c (ext2fs_sync_device): If the BLKFLSBUF ioctl succeeds, + don't try the FDFLUSH ioctl that was required for floppies + with older kernels. This avoids needless whining from the + MD device driver. (Addresses Sourceforge bug #545832). + + * openfs.c (ext2fs_open): Fix bug which caused us to pass the + wrong group_block to ext2fs_descriptor_block_loc if we're + using the backup superblock/block group descriptors. + (ext2fs_descriptor_block_loc): If we're using the backup + superblock descriptors, use the backup descriptor block in + the next block group. + +2002-10-30 Theodore Ts'o + + * alloc_tables.c (ext2fs_allocate_group_table): Allocate the inode + table so that it buts up against the bitmap blocks, to + avoid block fragmentation. + + * closefs.c (write_bgdesc), initalize.c (ext2fs_initialize): Fix + bug; only allocate group descriptor blocks up to + s_first_meta_bg. + +2002-10-25 Theodore Ts'o + + * ext2_fs.h: Add a new superblock field, s_mkfs_time, so that we + know when a filesystem was created. (Sometimes this can + be useful...) + + * initialize.c (ext2fs_initialize): Set the s_mkfs_time field. + +2002-10-20 Theodore Ts'o + + * ext2_fs.h (EXT3_DEFM_JMODE): Add new default mount options for + the journal data mode. + + * closefs.c (ext2fs_flush, write_bgdesc), ext2_fs.h, ext2fs.h, + openfs.c (ext2fs_descriptor_block_loc, ext2fs_open), initialize.c + (ext2fs_initialize), swapfs.c (ext2fs_swap_super): Add support for + the meta_blockgroup filesystem format. + +2002-10-15 + + * ext2_fs.h: Add new field in superblock for default mount options. + +2002-10-13 Theodore Ts'o + + * ext2fs.h: Add #include of header files necessary for ext2fs.h to + compile cleanly. + +2002-10-02 Theodore Y. Ts'o + + * rw_bitmaps.c (ext2fs_write_block_bitmap, + ext2fs_read_block_bitmap): Don't set the CHANGED bit just + because the bitmap is getting written to disk. Make + ext2fs_swap_bitmap be a static function, since it's not + intended to be exported. + + * swapfs.c (ext2fs_swap_super): Byte-swap the hash seed + +2001-09-24 Theodore Tso + + * Release of E2fsprogs 1.29 + +2001-08-31 Theodore Tso + + * Release of E2fsprogs 1.28 + +2002-08-31 Theodore Ts'o + + * dblist.c (ext2fs_dblist_sort): New function which allows the + caller to pass in a special sort comparison function. + +2002-08-20 Theodore Ts'o + + * valid_blk.c (ext2fs_inode_has_valid_blocks): Fix bug which + failed to accurately characterize non-standard slow + symlinks. (Which don't appear in practice on real-life + systems, fortunately.) + +2002-08-17 Theodore Ts'o + + * Makefile.in: Remove inode_io.o from the standard object files, + and only build it if debugfs is enabled (it requires + fileio.o, which is only built if --disable-debugfs isn't + specified to configure). + + * dirhash.c (ext2fs_dirhash): Change the MD4 hash in a backwards + incompatible way so that it is no longer + endian-dependent. Add the TEA hash. Allow the seed + parameter to be optional. + + * ext2_fs.h: Remove the HALF_MD4_SEED and HALF_MD4_64 hashes. + These features are all now in the HALF_MD4 hash. Add + definition for EXT2_HASH_TEA. + + * ext2fs.h (ext2fs_dirhash): Change function prototype so it takes + a pointer instead of an array. + +2002-08-16 Theodore Ts'o + + * ext2_err.et.in (EXT2_ET_BAD_EA_BLOCK_NUM): New error code + + * ext2fs.h (ext2fs_inode_data_blocks): New function which returns + the number of data blocks used by an inode exclusive of + the EA block. + + * ext_attr.c (ext2fs_adjust_ea_refcount): New function which + adjusts the reference count in an extended attribute block. + + * valid_blk.c (ext2fs_inode_has_valid_blocks): Add code to + correctly deal with extended attribute blocks in symbolic + links. + +2002-08-13 + + * Makefile.in: Move dupfs.o and test_io.o from the + needed-by-debugfs object list to the needed-by-resizer + object list. Fixes compile problem if the system is built + with only --disable-debugfs. + +2002-07-29 Theodore Ts'o + + * link.c (ext2fs_link): When adding a new link to a directory, + clear the HTREE bit. + +2002-07-23 Theodore Ts'o + + * dirhash.c (ext2fs_dirhash): Fix bug which caused MD4 + calculations for names > 32 characters to be completely + bogus. Changed MD4 calculation to match what is currently + being used in the CVS gkernel tree. + +2002-07-19 Theodore Ts'o + + * ext2_fs.h: Add s_hash_seed and s_def_hash_version to the + superblock definition. + + * badblocks.c, freefs.c, ext2fs.h: Use the badblocks functions to + create a set of u32_list functions. + + * dirhash.c (halfMD4Transform): Shift the hash by one bit, + since that's required by the directory indexing code. + +2002-07-14 Theodore Ts'o + + * ext2fs.h, read_bb_file.c: Change private to priv_data, to avoid + using a C++ reserved word. + + * unix_io.c (unix_open): Only attempt the setrlimit workaround if + the kernel version is 2.4.10 -- 2.4.17, since otherwise an + old version of glibc (built against 2.2 headers) will + interact badly with the workaround to actually cause more + problems. I hate it when the glibc folks think they're + being smarter than the kernel.... + +2002-06-28 Andreas Dilger + + * ext2_fs.h: Add superblock field for reserved group descriptors. + +2002-06-28 Theodore Ts'o + + * bitops.h: Add #define's for ext2fs_{l,b}e{32,16}_to_cpu and + ext2fs_cpu_to_{l,b}e{32,16} + +2002-06-27 Theodore Ts'o + + * ismounted.c (check_mntent): In AIX 4.3, MOUNTED isn't defined. + Add appropriate fallbacks in this case. + +2002-06-26 Theodore Ts'o + + * dirhash.c (ext2fs_dirhash): Change function signature to support + a hash seed, and to return the minor hash (for 64-bit hash + support). Add support for the half MD4, half MD4 with + seed, and half MD4 with seed and 64 bits. + +2002-06-15 Theodore Ts'o + + * ext2_fs.h (EXT2_DIRSYNC_FL): Add new file. + +2002-06-09 Andreas Dilger + + * ext2_fs.h: Add macros for maximum block/inode counts: + EXT2_INODES_PER_BLOCK, EXT2_MAX_BLOCKS_PER_GROUP, + and EXT2_MAX_INODES_PER_GROUP. + + * openfs.c (ext2fs_open): Check that the number of blocks in a group + is less than 2^16, otherwise we need an INCOMPAT flag (not + in existence yet, if ever) to open such a filesystem. + + * initialize.c (ext2fs_initialize): Limit the number of blocks and + inodes in a group to less than 2^16. + +2002-06-09 Andreas Dilger + + * ext2_fs.h: Further minor cleanups of the header. Consolidate + some checks for __KERNEL__ into one place. + +2002-05-22 Andreas Dilger + + * ext2_fs.h: Remove macros accessing u.ext2_sb field and use + the EXT2_SB() macro instead. Remove kernel function + prototypes also. This matches the 2.5 kernel, and + is also cleaner for other reasons. Whitespace cleanup. + +2002-05-21 Theodore Ts'o + + * ext2_ext_attr.h: Update to V2 version of the Bestbits format. + +2002-05-16 Andreas Dilger + + * ext2_fs.h: Change limits to support filesystems with 8k blocks. + + * initialize.c (ext2fs_initialize): Remove assumption that + blocksizes are always <= 4k. + +2002-05-11 Theodore Ts'o + + * bmap.c (ext2fs_bmap): Fix bug which caused ext2fs_bmap to fail + silently if inode pointer is NULL (and ext2fs_bmap is + expected to read the inode itself). + +2002-04-27 Theodore Ts'o + + * ismounted.c (check_mntent_file, is_swap_device): Verify that the + file we are checking is a block device file before looking + at st_rdev, since it's not valid for normal files. + (is_swap_device): Move so that it is outside the + HAVE_MNTENT_H, so that it is always built. + +2002-03-11 Theodore Tso + + * dirblock.c (ext2fs_read_dir_block2, ext2fs_write_dir_block): New + functions which take an extra flags argument. The flag + EXT2_DIRBLOCK_V2_STRUCT will reverse when the name_len + field is byte swampped on big-endian machines, since in + the V2 structure, name_len is a char field which is + doesn't need to be byte swapped --- except if an + old-style kernel had byte-swapped the name_len field + as part of the V1 structure. + + * ext2_err.et.in (EXT2_ET_DIRHASH_UNSUPP): New error code + + * dirhash.c (ext2fs_dirhash): New function which calculates the + hash for a filename in an indexed directory. + +2002-03-08 Theodore Tso + + * Release of E2fsprogs 1.27 + +2002-03-07 Theodore Tso + + * ext2fs.h (ext2fs_inode_io_intern): Add missing function prototype. + + * bmap.c, fileio.c, inode_io.c, tst_badblocks.c, + tst_byteswap.c: Fix gcc -Wall complaints + + * Makefile.in (check): Use LD_LIBRARY_PATH to run test programs. + (From Philipp Thomas ) + +2002-02-25 Theodore Tso + + * ext2_fs.h: Add structure definitions for the directory indexing + extension. + +2002-02-23 Theodore Tso + + * unix_io.c (unix_open): Fix 2.4 resource limit workaround so that + it doesn't break things on mis32, sparc32, and alpha + platforms. + +2002-02-21 Theodore Tso + + * ismounted.c (is_swap_device): Fix file descriptor/memory leak; + we were missing an fclose(). + +2002-02-20 Theodore Tso + + * Makefile.in, inode_io.c, ext2fs.h, ext2_err.et.in: Add new io + abstraction interface which exports an ext2 inode. + + * ext2fs.h, fileio.c (ext2fs_file_flush): Export ext2fs_file_flush + as a public interface. Change void * to const void * in + ext2fs_file_write's interface. + + * test_io.c (test_close), unix_io.c (unix_close): Remove unneeded + conditional; save a few bytes. + +2002-02-12 Theodore Tso + + * Makefile.in (tst_badblocks): Add some extra .o files when + linking the debugging program tst_badblocks which are + needed if we aren't compiling with inline functions enable. + + * kernel-list.h (__inline__): On non-gcc and non-Watcom compilers, + define away __inline__ since it may not be supported. + + * kernel-jbd.h (jbd_debug): For systems that don't do STDC, use a + stripped down jbd_debug that doesn't use variadic + arguments. This will cause warnings under AIX, but things + should still build. + +2002-02-03 Theodore Tso + + * Release of E2fsprogs 1.26 + +2002-02-03 Theodore Tso + + * mkdir.c (ext2fs_mkdir): Change to use ext2fs_inode_alloc_stats2 + so that the number of directories in use is adjusted + appropriately. + + * alloc_stats.c (ext2fs_inode_alloc_stats2): Add new function + which optionally will modify the number of directories + count. + +2002-01-03 Theodore Tso + + * dir_iterate.c (ext2fs_dir_iterate2, ext2fs_process_dir_block): + Add support for a new flag, DIRENT_FLAG_INCLUDE_REMOVED, + which will return deleted directory entries. + ext2fs_dir_iterate2 takes a new callback function which + is identical with the one used by + ext2fs_dblist_dir_iterate(). If the directory entry is + deleted, the callback function will be called with the + entry paraemter set to DIRENT_DELETED_FILE. + + * Makefile.in, alloc_stats.c (ext2fs_inode_alloc_stats, + ext2fs_block_alloc_stats): New functions which update + block/inode allocation statistics in the bitmaps, block + group descriptors, and superblock. + + * mkjournal.c (mkjournal_proc), mkdir.c (ext2fs_mkdir), + expanddir.c (expand_dir_proc), bb_inode.c + (clear_bad_block_proc, set_bad_block_proc, + ext2fs_update_bb_inode), alloc.c (ext2fs_alloc_block): + Update to use new block/inode allocation statistics. + +2001-12-24 Theodore Tso + + * ismounted.c (is_swap_device): New function used by + ext2fs_check_if_mounted and ext2fs_check_mount_point which + determines whether or not the specified device is a swap + device by using /proc/swaps. More bulletproofing for + idiotic/careless system administrators! + + * ext2fs.h, openfs.c (ext2fs_open), initialize.c + (ext2fs_initialize), mkdir.c (ext2fs_mkdir): Add a new + field to struct_ext2_filsys, umask. This field is + initialize to 022, and affects ext2fs_mkdir in the obvious + way. (In the future umask should also affect new file + creation routines, but the fileio functions don't + currently support this yes.) + + * ismounted.c (check_mntent_file): Stat all of the entries in + /etc/mtab and/or /proc/mounts in order to catch dim-witted + system administrators who might have created alias + devices. + +2001-12-23 Theodore Tso + + * Makefile.in, jfs_user.h: Move linux/jbd.h to + ext2fs/kernel-jbd.h, to avoid using the system header + file version of hbd.h when using diet glibc (since it + forcibly adds /usr/include to the beginning of the + include search path.) + + * kernel-jbd.h, kernel-list.h, jfs_compat.h: Move files from + include/linux directory. + +2001-12-16 Theodore Tso + + * bitops.h (ext2fs_mark_generic_bitmap, ext2fs_unmark_generic_bitmap), + ext_attr.c (ext2fs_read_ext_attr, ext2fs_write_ext_attr), + fileio.c (ext2fs_file_write): Fix gcc -Wall nits + + * Makefile.in, jfs_user.h: linux/jfs.h has been renamed to + linux/jbd.h + +2001-12-03 Theodore Tso + + * unix_io.c (unix_open): Make sure the ulimit workaround works + regardless of the version of glibc which is used to + compild e2fsprogs. + +2001-11-26 Theodore Tso + + * unix_io.c (unix_open): Work around a bug in 2.4.10+ kernels by + trying to unset the filesize limit if at all possible, + if a block device is getting opened. (The filesize limit + shouldn't be applied against writes to a block device, but + starting in 2.4.10, the kernel is doing this.) + +2001-11-05 Theodore Tso + + * mkjournal.c (ext2fs_add_journal_inode): When creating a .journal + file on adding a journal to an already-mounted filesystem, + try to clear the ext2 file attributes on an already + existing .journal file so that we don't fail if on a + partially added journal to the filesystem. + + * ext2_fs.h: Define a new ext2 file attribute, EXT2_NOTAIL_FL, + which signals that a particular inode should not have the + last bits of data (the "tail") be merged with another + file. This is necessary to keep LILO happy. + +2001-09-20 Theodore Tso + + * Release of E2fsprogs 1.25 + +2001-09-16 Theodore Tso + + * ext2_ext_attr.h: Remove unneeded #include of + which was breaking the build on the Hurd. (Addresses + Debian bug #112414). + +2001-09-13 Theodore Ts'o + + * ismounted.c (check_mntent_file): We now validate the entry in + /etc/mtab to make sure the filesystem is really mounted, + since some broken distributions (read: Slackware) have + buggy boot scripts that don't initialize /etc/mtab before + checking non-root filesystems. (Slackware also doesn't + check the root filesystem separately, and reboot if the + root filesystem had changes applied to it, which is + dangerous and broken.) + +2001-09-02 Theodore Tso + + * Release of E2fsprogs 1.24a + +2001-08-30 Theodore Tso + + * Release of E2fsprogs 1.24 + +2001-08-30 Theodore Tso + + * getsize.c (ext2fs_get_device_size): Back out BLKGETSIZE64 + changes, since the ioctl number has been reused by another + unofficial patch. + +2001-08-15 Theodore Tso + + * Release of E2fsprogs 1.23 + +2001-08-05 Theodore Tso + + * alloc.c (ext2fs_new_inode, ext2fs_new_block): Use the fast + version of the bitmap test routines to speed up these + routines. (At some point I may want to make these + routines use the find_first_bit functions, but that will + add a lot of complexity since it means that these + functions will have to break the bitmap abstraction + boundary. It's not clear it's worth it.) + + * mkjournal.c (mkjournal_proc): Remember the last block allocated + to speed up ext2fs_new_block(). + +2001-07-29 Theodore Tso + + * finddev.c (scan_dir): Fix memory leak; we weren't calling + closedir() when exiting the function in all cases. + +2001-07-27 Theodore Tso + + * mkjournal.c (ext2fs_create_journal_superblock): Set the first + block usable in the journal for external journals to be 2 + or 3, depending on the blocksize, so that the existing + kernel code does the right thing. + + * getsize.c (ext2fs_get_device_size): Add support for the + BLKGETSIZE64 ioctl. (Ioctl defined by unofficial patches + from Ben LaHaise, but it's likely this interface won't + change.) + + * mkjournal.c (ext2fs_add_journal_device): Use the correct block + when writing the journal superblock, too. (Oops! Needed + to make 1k filesystems with external journal to work.) + +2001-07-26 Theodore Tso + + * mkjournal.c (ext2fs_add_journal_device): Use the correct block + to find the journal superblock if the blocksize is 1024. + +2001-07-21 Theodore Tso + + * ext2_err.et.in (EXT2_ET_LOAD_EXT_JOURNAL): Add new error code + +2001-07-20 Theodore Tso + + * ext_attr.c (ext2fs_write_ext_attr): When writing the extended + attribute block, set the filesystem changed bit. + + * bitops.h (ext2fs_find_first_bit_set, ext2fs_find_next_bit_set): + Comment out these functions since we're not using them. + +2001-07-10 Theodore Tso + + * closefs.c (write_primary_superblock): After writing changes to + the primary superblock, update the original superblock + copy so we don't have to re-write those changes in the + future. + (ext2fs_flush): Clear the superblock dirty flag after + we've flushed out changes to disk. + +2001-07-07 Theodore Tso + + * bitops.h (ext2fs_find_first_bit_set): Use %esi instead of %ebx + to avoid register conflicts when compiling in PIC mode. + +2001-07-04 Theodore Tso + + * bitops.h (ext2fs_find_first_bit_set, ext2fs_find_next_bit_set): + Add new functions (C and in i386 assembler) which quickly + find bits set in a bitmask. + +2001-06-23 Theodore Tso + + * Makefile.in, ext_attr.c, ext2_attr.c, ext2fs.h: Add new files + ext2_ext_attr.h and ext_attr.c for extended attributes + support. + + * Release of E2fsprogs 1.22 + +2001-06-22 Theodore Tso + + * mkjournal.c (ext2fs_add_journal_inode): Move close of file + descriptor so that adding a journal to a mounted + filesystem doesn't die. (Fixes a bug accidentally + introduced in e2fsprogs 1.21.) + + * mkjournal.c (ext2fs_add_journal_inode): Only use fchflags if + HAVE_CHFLAGS and UF_NODUMP are defined, since the Hurd has + fchflags without defining UF_NODUMP. (Addresses Debian + bug #101361) + + * flushb.c: Use platform independent method of defining the + BLKFLSBUF and FDFLUSH ioctl's. Also include sys/mount.h + since on newer glibc's BLKFLSBUF is defined there. + + * bitops.h: The C language versions of ext2fs_swab16/32 need to be + included if EXT2FS_ENABLE_SWAPFS is defined, since we need + to support byte swapping even if we don't support the + conversion functions. (Fixes Debian bug #101686). + + * dirblock.c (ext2fs_read_dir_block): Remove use of dir_entry_2 + since the byte-swapping code all assumes the + ext2_dir_entry structure. (It's a question of whether or + not name_len should be byte-swapped or not, and whether + it's a 16 bit or 8 bit field.) + +2001-06-15 Theodore Tso + + * Release of E2fsprogs 1.21 + +2001-06-15 Theodore Tso + + * Makefile.in: Fix bug in installation of ext2_types.h. It is a + file which is generated and is therefore found in the + build directory, not source directory. + + * ismounted.c (check_mntent_file): Use a test file in / to check + to see if the root filesystem is mounted read-only. This + protects against the case where /etc might not be on /, as + well as the case where /etc/mtab doesn't exist. (Both are + should-never happen scenarios, but you never know...) + +2001-06-14 Theodore Tso + + * ismounted.c (ext2fs_check_if_mounted): Fix grammer in comment. + Remove unneeded #pragma argsused, since the arguments are + always used. + +2001-06-13 Theodore Tso + + * ext2_types.h.in: If linux/types.h has been defined, then don't + try to redefine the typedefs. + + * Makefile.in (HFILES): Add ext2_types.h to the list of files + which should be installed. + + * ismounted.c (check_mntent_file): Work around GNU hurd brain + damage. Addresses Debian bug #100304. + + * Makefile.in: Limit some .o files from being included into the + library if --disable-debugfs, --disable-swapfs, + --disable-imager, or --disable-resizer are used. + +2001-06-12 Theodore Tso + + * inode.c, tst_iscan.c: Stop using the compatibility badblocks + function, and use the ext2fs_badblocks_* functions + instead. + +2001-06-11 Theodore Tso + + * Makefile.in, gen_bitmap.c, bitops.h: Move inline functions + ext2fs_mark_generic_bitmap and + ext2fs_unmark_generic_bitmap to gen_bitmap.c as normal + functions. (This saves space and doesn't significantly + change the speed of e2fsck on a P-III.) + + * ext2fs.h, bitops.h, block.c, bmap.c, closefs.c, dirblock.c, + inode.c, native.c, openfs.c, rw_bitmaps.c, swapfs.c: Only + include the byte-swapping logic if ENABLE_SWAPFS is turned + on or if we're on a big-endian machine. + + * initialize.c (ext2fs_initialize):Use WORDS_BIGENDIAN directly to + set EXT2_FLAG_SWAP_BYTES, instead of using + ext2fs_native_flag. + + * native.c (ext2fs_native_flag): Use WORDS_BIGENDIAN provided by + autoconf to determine whether or not return + EXT2_FLAG_SWAP_BYTES. + +2001-06-10 Theodore Tso + + * Makefile.in: Remove the dependence on the libe2p library. + + * mkjournal.c (ext2fs_add_journal_inode): Replace use of fsetflags + with direct usage of the ioctl/fchflags so that we don't + have to depend on the libe2p library. + +2001-06-08 Theodore Tso + + * ext2_types.h.in: Use unsigned ints in favor of unsigned longs + when trying to find a 32-bit wide type. + + * icount.c (insert_icount_el): Fix the code used to estimate the + size of the new icount array to be more intelligent, to + avoid reallocating the array too many times. Thanks to + Enrique Perez-Terron for pointing this out. + +2001-06-02 Theodore Tso + + * valid_blk.c (ext2fs_inode_has_valid_blocks): Only check i_blocks + for a symlink to determine whether it is a fast symlink. + +2001-06-01 Theodore Tso + + * Makefile.in, dosio.c, ext2_fs.h, ext2_types.h.in, ext2fs.h: + Move include/asm/types.h.in to lib/ext2fs/ext2_types.h.in. + +2001-05-25 Theodore Tso + + * Release of E2fsprogs 1.20 + +2001-05-25 Theodore Tso + + * ismounted.c: More cleanups for ismounted.c, some from Andreas, + some to clean up Andreas's patches. Use strncpy instead + of strcpy to save the root's mountpoint. Clean up #ifdef + structure. Remove uneeded variable in testing/debug driver. + +2001-05-24 Andreas Dilger + + * ismounted.c: Add check for root device which doesn't depend on + /etc/fstab or /proc/mounts to be correct. Don't call + endmntent() before we are done with mnt struct. + +2001-05-23 Theodore Tso + + * ext2_err.et.in (EXT2_ET_JOURNAL_UNSUPP_VERSION): Added new error + code. + +2001-05-21 Theodore Tso + + * ext2_fs.h: Change assignment of EXT2_FEATURE_COMPAT_DIR_INDEX to + make room for pre-existing usage of + EXT2_FEATURE_COMPAT_EXT_ATTR. Add flag EXT2_INDEX_FL with + the same codepoint as EXT2_BTREE_FL. + +2001-05-20 Theodore Tso + + * ext2fs.h: #include <> instead of "" for ext2fs and et header + files, since they will be installed in /usr/include + +2001-05-14 Theodore Tso + + * alloc.c, alloc_tables.c, badblocks.c, bb_compat.c, bb_inode.c, + bitmaps.c, bitops.c, block.c, bmap.c, bmove.c, brel_ma.c, + check_desc.c, closefs.c, cmp_bitmaps.c, dblist.c, + dblist_dir.c, dir_iterate.c, dirblock.c, dupfs.c, + expanddir.c, ext2_fs.h, fileio.c, finddev.c, flushb.c, + freefs.c, get_pathname.c, getsize.c, icount.c, imager.c, + initialize.c, inline.c, inode.c, irel_ma.c, ismounted.c, + link.c, lookup.c, mkdir.c, mkjournal.c, namei.c, native.c, + newdir.c, nt_io.c, openfs.c, read_bb.c, read_bb_file.c, + rs_bitmap.c, rw_bitmaps.c, swapfs.c, test_io.c, + tst_badblocks.c, tst_byteswap.c, tst_getsize.c, + tst_iscan.c, unix_io.c, unlink.c, valid_blk.c, version.c, + write_bb_file.c, ext2_fs.h: Moved file from include/linux. + Adjust all files in this directroy to include this file. + + * mkjournal.c (ext2fs_create_journal_superblock): Remove redundant + code. + +2001-05-05 Theodore Tso + + * fileio.c (ext2fs_file_read): Factored out common code and + cleaned up function. Fixed a bug where if there was an + error reading from the disk, the number of bytes read + wasn't reliably set. (Fixes Debian bug #79163) + (ext2fs_file_write): Factored out common code and made + function more efficient; if writing a full block, don't + bother to do a read-modify-write cycle. + +2001-05-04 Theodore Tso + + * dirblock.c (ext2fs_read_dir_block): Check for an directory + record length which isn't a multiple four, and treat that + as an invalid. Scan the directory and return an error + (EXT2_ET_DIR_CORRUPTED) if the directory records are + corrupted. + (ext2fs_write_dir_block): If while byte-swapping the + directory block, if there's an error, abort and return + EXT2_ET_DIR_CORRUPTED. + +2001-05-02 Theodore Tso + + * ext2fs.h (EXT2_FLAG_IMAGE_FILE): Add new flag, and add + image_header field in the ext2_filsys structure + + * block.c (block_iterate_ind, block_iterate_dind, block_iterate_tind): + * inode.c (ext2fs_read_inode): + * rw_bitmaps.c (read_bitmaps): + * openfs.c (ext2fs_open): Add support for EXT2_FLAG_IMAGE_FILE + + * imager.c (ext2fs_image_bitmap_read): Fix bug in imager to make + sure the full bitmap is saved. + +2001-05-01 Theodore Tso + + * e2image.h (struct ext2_image_hdr): Add space for the device name + in the image header. + + * dir_iterate.c (ext2fs_process_dir_block): Add a double-check to + make sure the rec_len is a multiple of 4, to prevent + bus-errors on architectures which care about mis-aligned + pointer references. + +2001-04-25 Theodore Tso + + * getsize.c (ext2fs_get_device_size): Use an unsigned long to + query the device sizes using the BLKGETSIZE ioctl. + +2001-04-16 Theodore Tso + + * ismounted.c (check_mntent): Check /proc/mounts on Linux systems + before checking /etc/mtab. The EXT2_MF_READONLY flag is + now set from the /etc/mtab options field for all + filesystems, not just the root filesystem. Add debugging + code to make it easier to test ext2fs_check_if_mounted(). + + * mkjournal.c (ext2fs_create_journal_superblock): Add safety + check; return an error if there's an attempt to create a + journal less than 1024 filesystem blocks. + + * ext2_err.et.in, mkjournal.c: Change EXT2_JOURNAL_NOT_BLOCK and + EXT2_NO_JOURNAL_SB to be EXT2_ET_*. + +2001-02-20 Theodore Tso + + * bitops.h (ext2fs_swab16, ext2fs_swab32): Add i386 assembly + inline functions. + + * tst_byteswap.c: New function to test the byteswap functions. + Add to regression test suite. + +2001-02-08 Theodore Tso + + * e2image.h (struct ext2_image_hdr): Fix type for fs_hostname + +2001-02-07 Theodore Tso + + * mkjournal.c (ext2fs_create_journal_superblock): Fix the setting + of s_first for external devices to always be 1, since + jsb->s_first is always relative to the start of the + journal superblock. Use htonl(1) when setting s_nr_users. + +2001-01-17 Theodore Ts'o + + * mkjournal.c (ext2fs_add_journal_device): Fix bug where the + device number of the filesystem (instead of the journal) + was being dropped into s_journal_dev. + +2001-01-15 Theodore Ts'o + + * initialize.c (ext2fs_initialize): Add support for initializing + the ext2 superblock for external journal devices. This + basically means we don't bother to allocate any block + group descriptors. + + * openfs.c (ext2fs_open): Only open external journal devices if + the new flag EXT2_FLAG_JOURNAL_DEV_OK is passed to + ext2fs_open. When opening such devices, don't try to read + the block group descriptors, since they're not there. + + * ext2_err.et.in (EXT2_NO_JOURNAL_SB): Add new error code + + * mkjournal.c: Export a new function, + ext2fs_create_journal_superblock(), which allocates and + returns a buffer containing a journal superblock. This is + needed by mke2fs to create an external journal. Rewrote + ext2fs_add_journal_device() so that it no longer creates + the external journal, but rather adds a filesystem to an + existing external journal. It handles all of the UUID + manipulation. + + * ext2fs.h: List the EXT3_FEATURE_JOURNAL_DEV as a flag supported + by the library. Define the EXT2_FLAG_JOURNAL_DEV_OK. + Changed function prototype for ext2fs_add_journal_device(). + +2001-01-14 Theodore Ts'o + + * closefs.c (ext2fs_flush): Don't write out anything beyond the + primary superblock if EXT2_INCOMPAT_JOURNAL_DEV is + listed. + +2001-01-12 Theodore Ts'o + + * imager.c: Fix gcc -Wall complaints and a series of bugs where + retval wasn't set correctly. (Thanks to Andreas Dilger + for pointing this out.) + +2001-01-11 + + * flushb.c (ext2fs_sync_device): New function which centralizes + all of the places which might try to use the BLKFLSBUF + or FDFLUSH ioctls (and usually failing to define them + since the system header files don't usually do this for + us, and we're trying to avoid usage of kernel include + files now). + +2001-01-10 + + * alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, + bmove.c, brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, + dir_iterate.c, expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, + finddev.c, get_pathname.c, icount.c, inode.c, irel.h, + irel_ma.c, ismounted.c, link.c, lookup.c, mkdir.c, + mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c, + tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to + ext2_ino_t, to protect applications that attempt to + compile -D_FILE_OFFSET_BITS=64, since this inexplicably + changes ino_t(!?). So we use ext2_ino_t to avoid an + unexpected ABI change. + +2001-01-05 + + * dirblock.c (ext2fs_read_dir_block): Fix a potential case where + we may overrun allocated memory in case of a corrupted + filesystem (or an e2fsck test case :-) when byte-swapping + the directory block. + + * ext2fs.h: Indent the #warning to fix gcc -Wall complaint. + + * mkjournal.c (ext2fs_add_journal_device): Fix various gcc -Wall + complaints including a missing return 0 at the end of + ext2fs_add_journal_device. + +2001-01-03 + + * Makefile.in: Link in libe2p when creating libext2fs as a shared + library, since mkjournal.c now references fsetflags(). + + * mkjournal.c (ext2fs_add_journal_inode): Folded in Andreas + Dilger's changes (with fixups) to allow on-line creation + of a journal file. + + * ext2fs.h, closefs.c (ext2fs_flush): Add new flag, + EXT2_FLAG_SUPER_ONLY, which the close routines to only + update the superblock, and not the group descriptors. + +2000-12-30 Andreas Dilger + + * ismounted.c: add ext2fs_check_mount_point() function, which will + optionally return the mount point of a device if mounted + +2000-12-14 Andreas Dilger + + * mkjournal.c: rename ext2fs_add_journal_fs() to the more descriptive + ext2fs_add_journal_inode() + +2001-01-01 + + * ext2fs.h: Remove definition of ext2fs_sb. Note: this may break + source (but not binary) compatibility of some users of the + ext2 library. They should just simply do a global search + and replace of struct ext2fs_sb with struct + ext2_super_block, and use their own private copy of + ext2_fs.h if they aren't already. + + * closefs.c, initialize.c, link.c, newdir.c, openfs.c, swapfs.c: + Replace use of ext2fs_sb with ext2_super_block. + +2000-12-31 + + * ext2fs.h: Cleaned up header file by removing definitions of + feature flags that might not have been defined in older + ext2 header files. Now that we're using our own + include/linux/ext2fs.h header file, this can never happen. + + * jfs_dat.h: Removed old header file which is no longer needed. + +2000-12-13 Theodore Ts'o + + * closefs.c (ext2fs_update_dynamic_rev): New function suggested + by Andreas Dilger to update the filesystem revision to + EXT2_DYNAMIC_REV. + + * swapfs.c (ext2fs_swap_super): Add byte swapping for the journal + fields. + +2000-12-09 + + * ext2fs.h, mkjournal.c (ext2fs_add_journal_inode, + ext2fs_add_journal_device): Add a new argument to the APIs + of these function, which is a flags word. This is used to + allow the creation of a V1 superblock for those folks who + are using ext3 0.3b in production. Note, the user-land + interface for getting at this flag won't be documented, as + the V1 superblock is deprecated. + + * mkjournal.c (init_journal_superblock): Sync Stephen's changes + which creates a V2 superblock instead of a V1 superblock. + +2000-11-21 + + * test_io.c (test_write_blk, test_write_byte): Fix typos pointed + out by Andreas Dilger. + +2000-11-05 + + * imager.c (ext2fs_image_{inode,super,bitmap}_{read,write}, + ext2_fs.h, Makefile.in: New file that has routines that + save ext2fs metadata to a file. + + * ext2_err.et.in (EXT2_ET_MAGIC_E2IMAGE): New error code assigned. + + * e2image.h: New file which defines the file format for the ext2 + image file. (Saved copy of ext2 metadata to a file as a + saving throw against worst-case damage.) + +2000-11-01 + + * inode.c (ext2fs_flush_icache): Add new function + ext2fs_flush_icache() which flushes the internal inode + cache. Applications which modify the inode table blocks + directly must call this function. + +2000-10-26 + + * mkjournal.c: Add #include of netinet/in.h, since Solaris + requires it for ntohl(). + + * ext2_io.h (io_channel_write_byte): Add new interface to allow + callers to write specific byte ranges. This is an + optional interface, which not all IO channels may + implement. + + * unix_io.c (unix_write_byte): + * test_io.c (test_write_byte): Add implementation of the + write_byte function. + + * closefs.c (write_primary_superblock, ext2fs_flush): Add a new + function which writes the primary superblock. If the IO + channel supports writing raw bytes directly, only fields + which were modified are written to the disk. This makes + it safe(r) to use utilities like tune2fs on a mounted + filesystem. + + * freefs.c (ext2fs_free): Free the original superblock if it is + available. + + * openfs.c (ext2fs_open): Store a copy of the original superblock + when opening it. + + * ext2fs.h: Add a field to store the original superblock in the + ext2 context structure. + +2000-10-24 + + * llseek.c: Add #ifdef's for IA64 (it's a 64-bit platform, so we + don't need to use llseek). + +2000-10-24 + + * Makefile.in, ext2fs.h, jfs_dat.h, mkjournal.c: Add functions for + creating an ext3 journal on a filesystem. + +2000-08-21 + + * ext2_err.et.in (EXT2_JOURNAL_NOT_BLOCK): Add new error code. + +2000-08-22 + + * unix_io.c: Make massive changes to support a multiple block + writethrough cacheing. + + * ext2_io.h: Added flags field to the io_channel structure. + +2000-08-19 + + * finddev.c, ext2fs.h, Makefile.in: Add new file, finddev.c, which + provides the function ext2fs_find_block_device(). This + function returns the pathname to a block device, given its + device number. + +2000-07-13 + + * Release of E2fsprogs 1.19 + +2000-07-07 Theodore Ts'o + + * ext2fs.h (EXT2_LIB_FEATURE_INCOMPAT_SUPP): Add + EXT3_FEATURE_INCOMPAT_RECOVER (aka needs_recovery) to the + list of filesystem flags supported by the library. + +2000-07-04 Theodore Ts'o + + * ext2fs.h: Update to include latest journalling additions to the + superblock. + + * dll/jump.funcs: Add new jumptable entries for + ext2fs_write_bb_FILE, ext2fs_read_bb_FILE2, and + ext2fs_badblocks_equal. + + * tst_badblocks.c: Update test program to test + ext2fs_read_bb_FILE2 and ext2fs_write_FILE. + + * write_bb_file.c (ext2fs_write_bb_FILE): New function which + writes out bad blocks list to a file. + + * read_bb_file.c (ext2fs_read_bb_FILE2): Add new function which + changes the callback function to take two additional + arguments; a private blind pointer supplied by the caller, + and pointer to a char * containing a pointer to the + invalid string. + + * badblocks.c (ext2fs_badblocks_equal): Add new function which + returns true if two badblocks list are equal. + + * Makefile.in: Remove explicit link of -lc in the shared library. + (It shouldn't be necessary, and is harmful in some cases). + +2000-06-10 Theodore Ts'o + + * getsize.c (main): Add debugging code under #ifdef DEBUG + +2000-05-27 Theodore Ts'o + + * mkdir.c (ext2fs_mkdir): Read the parent directory's inode + earlier, so that if there's an error reading it, we can + more cleanly back out of the operation. + +2000-05-25 + + * getsize.c (ext2fs_get_device_size): Use open64() instead of + open() if it exists. Under linux, manually define the + ioctl for BLKGETSIZE if it isn't already defined and it's + safe to do so. + + * unix_io.c (unix_open): Use open64() instead of open() if it + exists. + + * llseek.c: Simplify header includes of unistd.h. If lseek64 is + available (and prototypes are defined) use it in + preference to llseek. + + * Makefile: Add hack dependency rule so that parallel makes work + correctly. + +2000-05-18 Theodore Ts'o + + * ext2fs.h: Add appropriate ifdef's to support C++ compilation. + +2000-04-03 Theodore Ts'o + + * block.c: Readibility tweak in conditionals involving + ctx->fs->flags. + + * ext2fs.h: Use AUTOCONF SIZEOF_* macros if available to determine + how to define __s64 and __u64. Turn off "compression is + experimental" warning if the cpp macro + I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL is defined. + +2000-02-11 + + * ext2fs.h: Define EXT2FS_COMPRESSED_BLKADDR and HOLE_BLKADDR. + Conditionally include Compression as a supported type if + ENABLE_COMPRESSION (via --enable-compression) is turned on. + + * swapfs.c (ext2fs_swap_super): Swap the compression usage bitmap. + +2000-02-08 + + * bitops.h (ext2fs_mark_generic_bitmap, ext2fs_unmark_generic_bitmap, + ext2fs_mark_block_bitmap, ext2fs_unmark_block_bitmap, + ext2fs_mark_inode_bitmap, ext2fs_unmark_inode_bitmap): + Change to return the previous state of the bit that is + being marked or unmarked. For speed optimization. + +2000-02-02 Theodore Ts'o + + * getsize.c, ismounted.c: Remove unneeded include of linux/fs.h + + * swapfs.c: Remove #ifdef HAVE_EXT2_INODE_VERSION since it's not + needed any more; we know it will always be i_generation. + Add support for swapping the high bits of the uid and gid. + +1999-11-19 + + * mkdir.c (ext2fs_mkdir): Only update the parent's inode link + counts if the link was successful. Patch suggested by + jeremy@goop.org. + + * Makefile.in (distclean): Remove TAGS and Makefile.in.old from + the source directory. + +1999-11-10 + + * Release of E2fsprogs 1.18 + +1999-11-08 + + * Makefile.in (tst_badblocks): Add freefs.o to the object list, + since ext2fs_badblocks_list_free was moved to freefs.c. + + * tst_badblocks.c: Use the newer badblocks API names. Add + duplicate blocks to the test inputs to test dealing with + adding blocks which are already in the badblocks list. + + * badblocks.c (ext2fs_badblocks_list_add): If appending to the end + of the list, use a shortcut O(1) operations instead of an + O(n) operation. (Idea suggested by David Beattie.) + + * freefs.c (ext2fs_free): Use ext2fs_badblocks_list_free() instead + of badblocks_list_free(), to save a procedure call. + +1999-10-26 + + * Release of E2fsprogs 1.17 + +1999-10-26 + + * ext2fs.h: Add kludge to deal with the fact that egcs cpp doesn't + seem to handle ~0UL the same way as they used to. + +1999-10-25 + + * nt_io.c (_OpenNtName): Open the device using + FILE_SYNCHRONOUS_IO_NONALERT instead of + FILE_SYNCHRONOUS_IO_ALERT + (nt_open): At the end of the device open routine, unlock + the drive but do not dismount it. + + * initialize.c (CREATOR_OS): Use __GNU__ instead of __gnu__ to + detect the Hurd OS. + +1999-10-22 + + * Release of E2fsprogs 1.16 + +1999-10-22 + + * mkdir.c (ext2fs_mkdir): Pass EXT2_FT_DIR flag to ext2fs_link(). + + * link.c (ext2fs_link): This call now uses the low three bits of + the flags parameter to pass the directory filetype + information; it will set the directory entry FILETYPE + information if the filesystem supports it. + + * newdir.c (ext2fs_new_dir_block): If the FILETYPE superblock + option is set, then create the '.' and '..' entries with + the filetype set to EXT2_FT_DIR. + +1999-09-24 + + * nt_io.c: New file which supports I/O under Windows NT. + +1999-09-07 + + * ext2fs.h: Add new fields for journalling and define new + feature bits used by newer filesystems: IMAGIC_INODES, + HAS_JOURNAL, RECOVER. + + * expanddir.c (ext2fs_expand_dir, expand_dir_proc): Change where + we update the inode block count and size files so that the + block count field is updated correctly when we create an + indirect block. + +1999-07-18 Theodore Ts'o + + * Release of E2fsprogs 1.15 + +1999-06-23 + + * swapfs.c (ext2fs_swap_inode): Add compatibility for Linux 2.3 + kernels that use i_generation instead of i_version. Patch + supplied by Jon Bright . + +1999-06-21 + + * dir_iterate.c (ext2fs_process_dir_block): Check for corrupted + directory entry before calling the callback function. + This should prevent some core dumps of insufficiently + paranoid callback functions. + +1999-05-29 + + * ext2fs.h: Add feature definition for AFS IMAGIC inodes. + + * fileio.c (ext2fs_file_open): Remove obsolete comment stating + that we don't handle writing yet (we do). Fixed bug where + we weren't allocating a big enough buffer for ext2_bmap. + +1999-05-03 + + * openfs.c (ext2fs_open): Check to make sure that the number of + blocks per group is not zero --- if so, it must be a bad + superblock! + +1999-01-09 Theodore Ts'o + + * Release of E2fsprogs 1.14 + +1999-01-07 Theodore Ts'o + + * inode.c (ext2fs_read_inode, ext2fs_write_inode): Check to see if + the inode number is zero; if it's zero, return + EXT2_ET_BAD_INODE_NUM. + +1998-12-30 Theodore Ts'o + + * initialize.c (ext2fs_initialize): Use EXT2_FIRST_INODE instead + of EXT2_FIRST_INO to ensure compatibility with Linux 1.2 + header files. + +Mon Jan 4 02:32:09 1999 Theodore Y. Ts'o + + * llseek.c (ext2fs_llseek): Change ext2fs_llseek() in the + non-Linux case to use EINVAL by default, unless it isn't + defined, in which case we use EXT2_ET_INVALID_ARGUMENT + instead. + +1998-12-15 Theodore Ts'o + + * Release of E2fsprogs 1.13 + +1998-12-03 Theodore Ts'o + + * Makefile.in: Updated dependencies. + +1998-09-22 Theodore Ts'o + + * initialize.c (ext2fs_initialize): Make sure that we allocate + enough inodes so that we can make a valid filesystem. + +1998-09-02 Theodore Ts'o + + * rw_bitmaps.c: Fixed signed/unsigned warnings. + + * fileio.c (ext2fs_file_set_size): Remove unneeded extern from the + function declaration. + + * dblist.c (make_dblist): Add safety check in case the dblist + pointer passed in is null (in which case, assign it to + fs->dblist). Fixed some signed/unsigned warnings. + + * bmap.c: Make addr_per_block be of type blk_t to avoid + signed/unsigned warnings. + + * namei.c (ext2fs_follow_link): Remove uneeded extern from the + function declaration. + + * get_pathname.c (get_pathname_proc): Use return value from + ext2fs_get_mem, instead of checking if &gp->name is + NULL. + + * dir_iterate.c (ext2fs_process_dir_block): + * dblist_dir.c (ext2fs_dblist_dir_iterate): Remove uneeded extern + from the function declaration. + + * block.c (ext2fs_block_iterate2): If the read_inode call fails, + return the error directly instead of jumping to the + cleanup routine, since we don't need to do any cleanup. + + * alloc_table.c (ext2fs_allocate_group_table): Make this + function take a dgrp_t for its group argument. + + * ext2fs.h: Make dgrp_t an __u32 type, and make + fs->desc_group_count be of type dgrp_t. + +1998-07-27 Theodore Ts'o + + * badblocks.c (ext2fs_badblocks_list_add): Use a bigger increment + than 10 blocks when we need to expand the size of the + badblocks list. + +1998-07-09 Theodore Ts'o + + * Release of E2fsprogs 1.12 + +1998-06-30 Theodore Ts'o + + * closefs.c (ext2fs_flush): Update the s_block_group_nr field as + appropriate for all of the block group copies, so that + it's clear where the beginning of the filesystem is on the + disk. (For when the partition table gets scrod.) + + * ext2fs.h: Change the name of the feature from + EXT2_FEATURE_INCOMPAT_DIRNAME_SIZE to + EXT2_FEATURE_INCOMPAT_FILESIZE (to match with the kernel). + +1998-06-18 Theodore Ts'o + + * inode.c (get_next_blockgroup): Fix bug where if + get_next_blockgroup() is called early because of a missing + inode table in a block group, the current_inode counter + wasn't incremented correctly. + +1998-06-16 Theodore Ts'o + + * read_bb.c (ext2fs_read_bb_inode): Make function more robust + against a completely trashed bad block inode. + +1998-06-10 Theodore Ts'o + + * alloc_tables.c (ext2fs_allocate_group_table): Fix bug so that if + the stride length hits a bad value, we retry the block + allocation starting at the beginning of the block group. + + * ext2fs.h, bb_inode.c, block.c, bmove.c, dir_iterate.c, + expanddir.c, ext2fsP.h, read_bb.c: Change blkcnt_t to be + e2_blkcnt_t to avoid collision with LFS API. + +1998-05-01 Theodore Ts'o + + * initialize.c (ext2fs_initialize): Initialize s_inodes_count in a + way that avoids overflows on disk sizes greater than 4GB. + +1998-04-28 Theodore Ts'o + + * ext2fs.h: Define EXT2_QSORT_TYPE appropriately for the + return type for comparison functions for qsort. + + * dblist.c (dir_block_cmp): Use EXT2_QSORT_TYPE in function + declaration. + +1998-04-26 Theodore Ts'o + + * ext2fs.h, bitops.h: Add support for the Watcom C compiler to do + inline functions. + + * ext2fs.h, dosio.c: Use asm/types.h instead of linux/types.h to + evade a potential problem with glibc's header files trying + to spike out linux/types.h. + + * ext2fs.h (ext2fs_resize_mem): Change the function prototype to + include the old size of the memory, which is needed for + some braindamaged memory allocation systems that don't + support realloc(). + + * badblocks.c (ext2fs_badblocks_list_add): + bb_inode.c (clear_bad_block_proc): + dblist.c (ext2fs_add_dir_block): + icount.c (insert_icount_el): + irel_ma.c (ima_put): + rs_bitmap.c (ext2fs_resize_generic_bitmap): Update functions to + pass the old size of the memory to be resized to + ext2fs_resize_mem(). + +1998-03-30 Theodore Ts'o + + * Makefile.in: Change to use new installation directory variables + convention. Fix uninstall rules to take $(DESTDIR) into + account. + +1998-03-29 Theodore Ts'o + + * ext2fs.h: If __STRICT_ANSI__ is defined and we're on a platform + with 32 bit longs, then we need to manually define __s64 + and __u64, since the current kernel header files don't + define these if __STRICT_ANSI__ is defined. This is a + problem if we are compiling with full GCC warnings, since + we do need 64 bit support. + + * Makefile.in (OBJS): Remove bmove.o from files to be built, + since we're not using ext2fs_move_blocks() and there + is some question as to its usefulness in its current + form. + + * bmap.c (block_bmap): Remove unused function. + + * bmove.c (process_block): Fix -Wall warning. + +1998-03-23 Theodore Ts'o + + * block.c (ext2fs_block_iterate3): Make the ref_offset field + contain the offset into the inode.i_blocks array when + ref_block is zero. Since we haven't done a formal + release of e2fsprogs since block_iterate2 was first + introduced, I removed block_iterate2, and renamed + block_iterate3 to be block_iterate2. + + * bb_inode.c, bmove.c, dblist_dir.c, dir_iterate.c, + expanddir.c, ext2fs.h, ext2fsP.h, read_bb.c: Change + use of block_iterate and block_iterate2 to + block_iterate2 with the new prototype for the + interator function. (using blkcnt_t forr blockcount) + +1998-03-21 Theodore Ts'o + + * ext2fs.h: Add new superblock fields (s_algorithm_usage_bitmap, + s_prealloc_blocks, s_prealloc_dir_blocks). Added + conditional defines of new features COMPAT_DIR_PREALLOC, + RO_COMPAT_LARGE_FILE RO_COMPAT_BTREE_DIR, + INCOMPAT_COMPRESSION, INCOMPAT_DIRNAME_SIZE. Changed + the library to declare that we support COMPAT_DIR_PREALLOC, + INCOMPAT_DIRNAME_SIZE, RO_COMPAT_LARGE_FILE. + + * fileio.c: Rename function ext2fs_file_llseek to be + ext2fs_file_lseek, which is more accurate. + + * block.c: Add new function ext2fs_block_iterate3 which calls + the iterator function with the blockcount argument of + type blkcnt_t. This version of the function is + allowed to handle large files; the other fucntions are + not. + + * ext2fs.h: Add new type blkcnt_t + + * ext2_err.et.in: Add error code EXT2_ET_FILE_TOO_BIG + + * block.c (ext2fs_block_iterate2): Fix bug where the block count + field wasn't getting correctly incremented for sparse + files when the indirect or doubly-indirect block + specified in the inode was zero. + +Sun Mar 8 22:42:47 1998 Theodore Ts'o + + * unlink.c (unlink_proc): + * lookup.c (lookup_proc): + * link.c (link_proc): + * get_pathname.c (get_pathname_proc): + * dir_iterate.c (ext2fs_process_dir_block): Mask off high 8 bits + from dirent->name_len, so it can be used for other + purposes. + + * ext2fs.h: Add definition of EXT2_FEATURE_INCOMPAT_DIRNAME_SIZE, + and indicate that we have support for this incompatible + option. + +Mon Feb 23 08:46:33 1998 Theodore Ts'o + + * ext2_err.et.in: Added new error code, EXT2_ET_CANCEL_REQUESTED. + +Fri Feb 20 23:58:01 1998 Theodore Ts'o + + * dblist.c (ext2fs_get_num_dirs): Improve the estimation of the + number of directories when the block group information is + unreliable. + +1998-02-20 Theodore Y. Ts'o + + * inode.c (ext2fs_get_next_inode): Always do the check to see if the + inode table is missing so that we catch the case where the + first block group is missing. + + * getsize.c, ismounted.c, unix_io.c: #include errno.h since it's + needed. + +Mon Feb 16 16:16:00 1998 Theodore Ts'o + + * ext2_io.h, ext2fs.h: Protect against being included multiple times. + + * bmove.c: #include ext2fsP.h instead of "ext2fs/ext2fs.h" + + * test_io.c (test_flush): Add a debugging printf when the flush + method is called. + + * rw_bitmaps.c (ext2fs_read_bitmaps): If the bitmaps are already + read in, return right away. + +Sun Feb 1 08:20:24 1998 Theodore Ts'o + + * bitops.h: Don't try to do i386 inline asm functions if the + compiler isn't GCC. + + * ext2fs.h: If EXT2_FLAT_INCLUDES is defined, #include e2_types.h, + instead of linux/types.h, and e2_bitops.h instead of + ext2fs/bitops.h. + + * icount.c, version.c: Don't #include , as it isn't + necessary. + +Sat Jan 17 13:13:31 1998 Theodore Ts'o + + * inode.c (ext2fs_open_inode_scan): Initialize the group variables + so that we don't need to call get_next_blockgroup() the + first time around. Saves a bit of time, and prevents us + from needing to assign -1 to current_group (which is an + unsigned value). + + * icount.c (insert_icount_el): Cast the estimated number of inodes + from a float to an ino_t. + + * alloc.c, alloc_tables.c, badlbocks.c, bb_compat.c, bb_inode.c, + bitmaps.c, bitops.c, block.c, bmap.c, bmove.c, brel_ma.c, + check_desc.c, closefs.c, cmp_bitmaps.c, dblist.c, + dblist_dir.c, dir_iterate.c, dirblock.c, dupfs.c, + expanddir.c, ext2fs.h, fileio.c, freefs.c, + get_pathname.c, getsize.c, icount.c, initialize.c, + inline.c, inode.c, irel_ma.c, ismounted.c, link.c, + lookup.c, mkdir.c, namei.c, native.c, newdir.c, + openfs.c, read_bb.c, read_bb_file.c, rs_bitmap.c, + rw_bitmaps.c, swapfs.c, test_io.c, tst_badblocks.c, + tst_getsize.c, tst_iscan.c, unix_io.c, unlink.c, + valid_blk.c, version.c: If EXT2_FLAT_INCLUDES is + defined, then assume all of the + ext2-specific header files are in a flat directory. + + * block.c, bmove.c, dirblock.c, fileio.c: Explicitly cast + all assignments from void * to be compatible with C++. + +Tue Jan 6 11:28:15 1998 Theodore Ts'o + + * closefs.c (ext2fs_flush): Add a call to io_channel_flush() to + make sure the contents of the disk are flushed to disk. + +Mon Dec 29 14:39:13 1997 Theodore Ts'o + + * dblist.c (ext2fs_add_dir_block): Change new to be new_entry to + avoid C++ namespace clash. + + * bitmaps.c (ext2fs_copy_bitmap): Change new to be new_map to + avoid C++ namespace clash. + + * ext2fs.h, bb_inode.c, block.c, bmove.c, brel.h, brel_ma.c, + irel.h, irel_ma.c, dblist.c, dblist_dir.c, dir_iterate.c, + ext2fsP.h, expanddir.c, get_pathname.c, inode.c, link.c, + unlink.c: Change private to be priv_data (to avoid C++ + namespace clash) + +Fri Nov 28 09:26:31 1997 Theodore Ts'o + + * dblist.c (ext2fs_get_num_dirs): Make ext2fs_get_num_dirs more + paranoid about validating the directory counts from the + block group information. + + * all files: Don't include stdlib.h anymore; include it in + ext2_fs.h, since that file requires stdlib.h + +Thu Nov 20 16:07:38 1997 Theodore Ts'o + + * expanddir.c (ext2fs_expand_dir): Check to make sure the block + bitmap is loaded, and return an error if it is not. + (expand_dir_proc): Only use ext2fs_write_dir_block when + writing a directory block, not when writing out a fresh + indirect block. + +Tue Nov 11 22:46:45 1997 Theodore Ts'o + + * Makefile.in, tst_getsize.c: Added new file which is used to test + the ext2fs_get_device_size function. + + * ext2_err.et.in (EXT2_ET_UNIMPLEMENTED): Added new error code. + +Sun Nov 2 20:36:13 1997 Theodore Ts'o + + * ext2fs.h: Make ext2fs_get_mem take an unsigned argument. + + * fileio.c (ext2fs_file_get_size, ext2fs_file_set_size, + ext2fs_file_get_fs): New functions added. + + +Fri Oct 31 12:16:52 1997 + + * bitops.c (ext2fs_warn_bitmap, ext2fs_warn_bitmap2): Don't call + com_err if OMIT_COM_ERR is defined. + +Thu Oct 30 11:33:57 1997 Theodore Ts'o + + * Rename new error codes to _ET_ in them for consistency. + +Sat Oct 25 00:06:58 1997 Theodore Ts'o + + * [all files, basically]: Added definition of ext2fs_get_mem, + ext2fs_free_mem, and ext2fs_resize_mem in ext2fs.h, and + changed all library routines to use these wrapper functions. + + * dblist.c, mkdir.c: use EXT2_DIR_EXISTS and EXT2_DB_NOT_FOUND + instead of the system error messages. + + * ext2_err.et.in: Added new error messages EXT2_DIR_EXISTS and + EXT2_DB_NOT_FOUND + + * ext2fs.h: Added function declarations and constants for bmap.c + and fileio.c. + + * ext2_err.et.in: Added new error messages EXT2_FILE_RO and + EXT2_ET_MAGIC_EXT2_FILE + + * Makefile.in: Added files bmap.c and fileio.c, and temporarily + commented out brel_ma.c and irel_ma.c + + * bmap.c: New file which maps a file's logical block number to its + physical block number. + + * fileio.c: New file which implements simple file reading and + writing primitives. + + * alloc.c (ext2fs_alloc_block): New function which allocates a + block, zeros it, and updates the filesystem accounting + records appropriately. + +Wed Oct 22 16:47:27 1997 Theodore Ts'o + + * ext2_err.et.in: Added new error codes: EXT2_NO_MEMORY, + EXT2_INVALID_ARGUMENT, EXT2_BLOCK_ALLOC_FAIL, + EXT2_INODE_ALLOC_FAIL, EXT2_NOT_DIRECTORY + + * Change various library files to use these functions instead of + EINVAL, ENOENT, etc. + +Mon Oct 20 19:32:40 1997 Theodore Ts'o + + * llseek.c: Check HAVE_LLSEEK_PROTOTYPE to see whether or not we + need to declare llseek(). + +Sun Oct 19 18:56:22 1997 Theodore Ts'o + + * Rename io.h to be ext2_io.h (avoid namespace collisions) + + * Add #ifdef's for HAVE_SYS_STAT_H and HAVE_SYS_TYPES_H + +Fri Oct 3 13:35:59 1997 Theodore Ts'o + + * llseek.c (ext2fs_llseek): Fix type error for ext2fs_llseek() + + * icount.c (ext2fs_icount_validate): + * bmove.c (process_block): Fix lint error in type for fprintf(). + +Mon Sep 15 11:45:09 1997 Theodore Ts'o + + * inode.c (ext2fs_check_directory): Add support for the callback + to return the error code EXT2_ET_CALLBACK_NOTHANDLED. + +Thu Sep 4 12:28:22 1997 Theodore Ts'o + + * bitmaps.c (ext2fs_set_bitmap_padding): New function which sets the + padding of the bitmap to be all one's. + +Wed Sep 3 14:27:30 1997 Theodore Y. Ts'o + + * llseek.c: Added missing semicolon to glibc fixup declaration of + llseek(). + + * bmove.c: Add #include of errno.h + +Sat Aug 23 22:47:46 1997 Theodore Ts'o + + * Makefile.in (ELF_SO_VERSION): Bump version to be 2.4 since we've + added a new field to the io_channel (app_data). + + * io.h: Add a new element to the io_channel structure, app_data. + + * initialize.c, openfs.c: Set io->app_data to point at the + filesystem handle. + +Thu Aug 14 08:14:17 1997 Theodore Ts'o + + * io.h: Change the prototype of ext2fs_llseek() to use int's + instead of unsigned int's. + + * llseek.c: Change to allow PIC and !HAVE_LLSEEK. Add a prototype + to make life easer for GNU Libc 2. + + * rw_bitmaps.c: On the PowerPC, the big-endian variant of the ext2 + filesystem has its bitmaps stored as 32-bit words with bit + 0 as the LSB of each word. Thus a bitmap with only bit 0 + set would be, as a string of bytes, 00 00 00 01 00 ... To + cope with this, we byte-reverse each word of a bitmap if + we have a big-endian filesystem, that is, if we are *not* + byte-swapping other word-sized numbers. + +Mon Aug 11 03:30:48 1997 Theodore Ts'o + + * dosio.c: New file to do DOS/BIOS disk accesses. + + * namei.c (open_namei): Make pathlen be of type size_t. + + * llseek.c: Always #include stdlib.h since it's need to define + size_t. + + * io.h: Use errcode_t for magic numbers. + + * icount.c (get_icount_el): Use size_t where appropriate + + * dupfs.c (ext2fs_dup_handle): + * dblist.c (dir_block_cmp): Use size_t where appropriate. + + * read_bb.c (ext2fs_read_bb_inode): + * cmp_bitmaps.c (ext2fs_compare_inode_bitmap): Use blk_t, ino_t + and size_t where appropriate. + + * closefs.c (ext2fs_flush): Use dgrp_t instead of int where + appropriate. + + * openfs.c (ext2fs_open): + * check_desc.c (ext2fs_check_desc): Use blk_t instead of int where + appropriate. + + * rw_bitmaps.c (read_bitmaps): + * irel_ma.c: + * inode.c (ext2fs_write_inode): + * initialize.c (ext2fs_initialize): + * brel_ma.c: Fix to make be 16-bit safe. + + * link.c (ext2fs_link): + * unlink.c (ext2fs_unlink): + * lookup.c (lookup_proc): + * ismounted.c (ext2fs_check_if_mounted): + * block.c (xlate_func): Add #pragma argsused for Turbo C. + +Sun Aug 10 10:05:22 1997 Theodore Ts'o + + * block.c (ext2fs_block_iterate2): Use retval which is a errcode_t + type. + + * bitmaps.c (make_bitmap): Use size_t instead of int where + appropriate. + + * bb_inode.c (set_bad_block_proc): Add #pragma argsused for Turbo C. + + * alloc.c (ext2fs_new_inode): Use ino_t instead of int for the + group number. + + * get_pathname.c: Use ino_t instead of int where appropriate. + + * ext2fs.h: Make the magic structure element be errcode_t instead + of int. + + * alloc.c alloc_tables.c badblocks.c bb_compat.c bb_inode.c + bitmaps.c block.c bmove.c brel_ma.c check_desc.c closefs.c + cmp_bitmaps.c dblist.c dblist_dir.c dir_iterate.c + dirblock.c dupfs.c expanddir.c freefs.c get_pathname.c + icount.c initialize.c inline.c inode.c irel_ma.c link.c + llseek.c lookup.c mkdir.c namei.c newdir.c read_bb.c + read_bb_file.c rs_bitmap.c rw_bitmaps.c swapfs.c + test_io.c tst_badblocks.c tst_iscan.c unix_io.c unlink.c + valid_blk.c version.c: Add an #ifdef for HAVE_UNISTD_H + +Tue Jun 17 01:33:20 1997 Theodore Ts'o + + * unix_io.c (unix_read_blk): If ext2fs_llseek() fails, but errno + is zero, then return EXT2_IO_LLSEEK_FAILED. + + * ext2_err.et.in: Add a new error code, EXT2_IO_LLSEEK_FAILED. + + * Release of E2fsprogs 1.11 + +Mon Jun 16 23:53:06 1997 Theodore Ts'o + + * dblist.c (ext2fs_dblist_count): Added new function which returns + the number of directory blocks in dblist. + +Sat Jun 14 01:39:13 1997 Theodore Ts'o + + * unix_io.c (unix_flush): Make the io_channel flush function do a + fsync to flush the kernel buffers to disk. + +Wed Jun 11 18:25:31 1997 Theodore Ts'o + + * inode.c (ext2fs_inode_scan_goto_blockgroup): Fix bug; the + current inode number wasn't being set by the + goto_blockgroup function. + +Mon Jun 9 10:45:48 1997 Theodore Ts'o + + * bmove.c (ext2fs_move_blocks): New function which takes a bitmap + of blocks which need to be moved, and moves those blocks + to another location in the filesystem. + + * rs_bitmap.c (ext2fs_resize_generic_bitmap): When expanding a + bitmap, make sure all of the new parts of the bitmap are + zero. + +Sun Jun 8 16:24:39 1997 Theodore Ts'o + + * bitmaps.c (ext2fs_copy_bitmap): Fix bug; the destination bitmap + wasn't being returned to the caller. + + * alloc_tables.c (ext2fs_allocate_group_table): Add new function + ext2fs_allocate_group_table() which sets the group tables + for a particular block group. The relevant code was + factored out of ext2fs_allocate_tables(). + + * dblist.c (make_dblist): Adjust the initial size of the directory + block list to be a bit more realistic (ten plus twice the + number of directories in the filesystem). + +Thu May 8 22:19:09 1997 Theodore Ts'o + + * badblocks.c (ext2fs_badblocks_list_test): Fix bug where + ext2fs_badblocks_list_test would test the list (and exceed + array boundaries) if there were no bad blocks on the bad + blocks list. (Showed up when user tried: mke2fs -c -b 4096). + +Thu Apr 24 12:16:42 1997 Theodre Ts'o + + * Release of E2fsprogs version 1.10 + +Thu Apr 24 10:13:42 1997 Theodre Ts'o + + * alloc_tables.c (ext2fs_allocate_tables): Correctly place the + inode and block bitmaps based on the RAID 0 stride + parameter (which is passed by mke2fs). + + * ext2fs.h: Add "stride" parameter to ext2_filsys, to be used by + mke2fs to communicate the stride length to + ext2fs_allocate_tables() + +Wed Apr 23 21:50:42 1997 Theodre Ts'o + + * initialize.c (ext2fs_initialize): Fix to compile under Linux 1.2 + systems. (We can't assume that the new filesystem types + are supported.) + +Wed Apr 23 18:40:53 1997 Theodore Ts'o + + * alloc_tables.c (ext2fs_allocate_tables): Make sure that we + allocate the inode and block bitmaps inside block group at + all times. + +Mon Apr 21 00:06:28 1997 Theodore Ts'o + + * alloc.c (ext2fs_new_block): Fix bug where if goal==0 and the + filesystem has no free blocks, ext2fs_new_block would loop + forever. + + * dupfs.c (ext2fs_dup_handle): Duplicate an ext2 filesystem handle + + * freefs.c (ext2fs_free_inode_cache): Decrement refcount and only + free if refcount goes to zero. + + * inode.c (create_icache): Initialize refcount to 1. + + * ext2fsP.h: Added refcount to ext2_inode_cache + + * dblist.c (ext2fs_copy_dblist): New function to copy a directory + block list. + + * badblocks.c (ext2fs_badblocks_copy): New function to copy a + badblocks structure. + +Sun Apr 20 23:19:51 1997 Theodore Ts'o + + * bitmaps.c (ext2fs_copy_bitmap): New function to copy a bitmap. + + * unix_io.c, test_io.c (unix_open, test_open): Initialize the + refcount to 1. + (unix_close, test_close): Decrement the refcount and only + close the io_channel if the refcount goes to 0. + + * io.h: Add refcount to the io_channel structure. Add new macro + interface io_channel_bumpcount() to bump the refcount. + +Thu Apr 17 20:25:03 1997 Theodore Ts'o + + * inode.c (ext2fs_read_inode, ext2fs_write_inode): Use the inode + cache in the filesystem handle, instead of the inode cache + in a static variable. + + * freefs.c: Added static function to free the inode cache (called by + ext2fs_free). + + * ext2fsP.h: Added definition of the ext2_inode_cache structures. + + * ext2fs.h: Added pointer to the inode_cache structure. + + * block.c (block_iterate_ind, block_iterate_dind, + block_iterate_tind): If there are holes in the indirect, + doubly indirect, or triply indirect blocks, increment the + block count field automatically. + +Thu Apr 17 12:23:38 1997 Theodore Ts'o + + * Release of E2fsprogs version 1.09 + +Mon Apr 14 20:38:56 1997 Theodore Ts'o + + * version.c (ext2fs_parse_version_string): Check the passed in + version string (instead of the hard-coded one). + + * alloc_tables.c (ext2fs_allocate_tables): If the last block is + greater filesystem size, clamp it to prevent allocating a + block or inode bitmap beyond the filesystem. + + * initialize.c (ext2fs_initialize): Fix bug where the metatdata + overhead calculation was accidentally removed. + +Fri Apr 11 18:56:26 1997 Theodore Ts'o + + * Release of E2fsprogs version 1.08 + +Thu Apr 10 13:15:15 1997 Theodore Ts'o + + * dblist.c (ext2fs_set_dir_block): New function which sets the + block of a dblist entry, given the directory inode and + blockcnt. + +Sat Apr 5 12:42:42 1997 Theodore Ts'o + + * alloc_tables.c (ext2fs_allocate_tables): Allocate the bitmap and + inode bitmaps at staggered locations across the block + groups, to avoid concentrating the bitmaps on a small + number of disks when using striped RAID arrays. + + * initialize.c (ext2fs_initialize): By default, choose the maximum + possible number of blocks per group (based on the size of + the bitmaps in the blocksize). + +Fri Apr 4 11:28:16 1997 Theodore Ts'o + + * initialize.c (ext2fs_initialize): Add support for + EXT2_COMPAT_SPARSE_SUPER feature. + + * closefs.c (ext2fs_bg_has_super): New function to determine + whether or a particular block group should have a + superblock and block group descriptor. Used for the + EXT2_COMPAT_SPARSE_SUPER feature is turned on. + (ext2fs_flush): Check ext2fs_bg_has_super to see whether + or not the superblock should be written out for the block + group. + + * ext2fs.h (EXT2_COMPAT_SPARSE_SUPER): Define compatibility flag + for sparse duplicate superblocks. + + * version.c (ext2fs_get_library_version): New function which + returns the library version. + + * version.c (ext2fs_parse_version_string): New function which + parses a version string and returns a version number, + so application programs can compare version numbers as + integers. + +Wed Mar 26 00:43:52 1997 Theodore Ts'o + + * icount.c (ext2fs_create_icount): Change function so that it also + takes a new argument which contains a "hint" icount + structure. This "hint" icount allows the create function + to set up the sorted list in advance. This reduces + significantly the amount of data moving needed to insert + these inodes into the list later. + + * icount.c (ext2fs_icount_validate): New function which validates + that the icount structure's rep invariant. + + * icount.c (get_icount_el): Completely revamped implementation + to subsume put_icount_el(). Put_icount_el() used to + use an O(N) implementation to insert in the middle + of the icount list. It now uses a O(ln N) to search + for where the icount should be inserted, and then uses + a memcpy to move the list down (instead of a for loop). + + * icount.c (ext2fs_icount_fetch, ext2fs_icount_store, + ext2fs_icount_increment, ext2fs_icount_decrement): Check + to see if the inode is within bounds; if it isn't, return + EINVAL. + + * bitops.h (ext2fs_test_generic_bitmap): Fix error message given + when a bad inode number is passed to test_generic_bitmap + to be EXT2FS_TEST_ERROR instead of the wrong + EXT2FS_UNMARK_ERROR. + +Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o + + * Release of E2fsprogs version 1.07 + +Sun Mar 2 16:46:18 1997 Theodore Ts'o + + * Makefile.in (ELF_VERSION): Change version to be 2.2 + +Tue Feb 11 14:54:02 1997 Theodore Ts'o + + * alloc.c (ext2fs_get_free_blocks): Change routine to use + ext2fs_fast_test_block_bitmap_range(). + + * bitops.h (ext2fs_fast_test_block_bitmap_range, + ext2fs_test_block_bitmap_range: New inline functions which + test to see whether a contiguous range of blocks is + available. + +Thu Feb 6 10:00:13 1997 Theodore Ts'o + + * badblocks.c (ext2fs_badblocks_list_create): Rename sybmols to use + use ext2fs_badblocks_* instead of badblocks_* + + * bb_compat.c: New file which translates between old badblocks_*() + names to ext2fs_badblocks_*() + + * unlink.c (ext2fs_unlink): New file, moved ext2fs_unlink() from + link.c (since e2fsck doesn't use ext2fs_unlink()). + + * rs_bitmap.c (ext2fs_resize_generic_bitmap): New file, contains + bitmap resizing routine moved from bitmaps.c, since e2fsck + doesn't need to use this function. + + * lookup.c (ext2fs_lookup): Moved ext2fs_lookup to its own file, + since e2fsck only needs ext2fs_lookup. + +Mon Feb 3 10:11:40 1997 Theodore Ts'o + + * inode.c (ext2fs_open_inode_scan): Set fs->badblocks if it is not + already set; this is needed so that programs like dump + which use the inode scan functions will deal with + filesystems that have bad blocks in the inode table. + +Sun Feb 2 00:17:36 1997 Theodore Ts'o + + * ext2fs.h (struct_badblocks_list, struct_badblocks_iterate): + Moved to ext2fsP.h, since it doesn't need to be part of + the public interface. + + * dir_iterate.c: Move ext2_dir_iterate out of namei.c. + +Sat Feb 1 10:14:55 1997 Theodore Ts'o + + * dblist.c (ext2fs_get_num_dirs): New file, which implements a + directory block list abstraction. (Code moved from + e2fsck). + + * ext2fs.h, inode.c: Moved definition of ext2_struct_inode_scan to + to inode.c (since no one else should be peeking inside it!) + + * valid_blk.c (ext2_inode_has_valid_blocks): New function. + + * openfs.c (ext2fs_open): Check the feature set in the ext2 + superblock, and refuse to open filesystems if they contain + incompatible features. (Can be overriden with the + EXT2_FLAG_FORCE + +Sun Jan 12 11:31:46 1997 Theodore Ts'o + + * block.c (ext2fs_block_iterate2): Added new function + ext2fs_block_iterate2 which changes the function + signature of the callback function to include the + referencing block and offset. + + * inode.c (ext2fs_inode_scan_goto_blockgroup): Added new function + ext2fs_inode_scan_goto_blockgroup which allows an + application to jump to a particular block group while + doing an inode scan. + +Wed Jan 1 23:50:12 1997 Theodore Ts'o + + * dirblock.c: Include string.h, since we use memcpy(). + +Tue Dec 3 12:27:29 1996 Theodore Ts'o + + * getsize.c (ext2fs_get_device_size): The ioctl BLKGETSIZE returns + a long not an int; this doesn't matter on i386 machines, + but it does on Alpha's. + +Fri Nov 29 20:57:37 1996 Theodore Ts'o + + * inode.c (ext2fs_write_inode, ext2fs_read_inode): If the inode + table pointer is NULL, then return an error indicating + that the inode table is missing. + (get_next_blockgroup, get_next_blocks, + ext2fs_get_next_inode): Don't treat a missing inode table + as permanent error. Return MISSING_INODE_TABLE, but as an + advisory error code, much like BAD_BLOCK_IN_INODE_TABLE. + + * rw_bitmaps.c (ext2fs_write_block_bitmap, + ext2fs_write_inode_bitmap): If the inode or block bitmap + block is zero, then don't write out the inode or block + bitmap. The idea here is to avoid stomping on the + superblock. + (read_bitmaps): If the inode or block bitmap block is + zero, then fill in that portion of the inode or block + bitmap with all zeros. + + * inode.c (ext2fs_get_next_inode): Fix bug in handling of bad + blocks in inode table when the inode table size is + non-standard (and can therefore span blocks). + +Tue Oct 29 20:13:14 1996 Theodore Ts'o + + * alloc.c (ext2fs_new_block): Fix fencepost error in + ext2fs_new_block; make sure we don't try to allocate the + first block beyond the end of the filesystem. + +Mon Oct 14 11:00:48 1996 Theodore Ts'o + + * inode.c (check_for_inode_bad_blocks): New function called by + get_next_blocks() to avoid reading in bad blocks marked in + fs->badblocks. Inodes located in bad blocks are returned + by ext2fs_get_next_inode() returns the error code + EXT2_ET_BAD_BLOCK_IN_INODE_TABLE. + + * alloc_tables.c (ext2fs_allocate_tables): New function which + performs the part of mke2fs's job of allocating the + filesystem tables. + + * test_io.c (test_close): IO manager which is used for testing + purposes. + +Sun Oct 13 04:31:57 1996 Theodore Ts'o + + * inode.c (ext2fs_get_next_inode): Separate out the function of + setting up for a new block group to get_next_blockgroup(). + Separate out the function of reading in blocks of the + inode table to get_next_blocks(). + + * ext2fs.h: Add the badblocks list to the ext2_filsys entry + + * badblocks.c (badblocks_list_add, badblocks_list_test): Add + blocks to the badblock list in sorted order. This allows + badblocks_list_test to be coded using a binary search for + speed. + +Tue Oct 8 02:02:03 1996 Theodore Ts'o + + * Release of E2fsprogs version 1.06 + +Mon Oct 7 00:44:17 1996 Theodore Ts'o + + * ext2fs.h, block.c, closefs.c, dirblock.c, inode.c, native.c, + open.c: Change EXT2_SWAP to EXT2_FLAG_SWAP for + consistency's sake. + + * closefs.c (ext2fs_flush): If the flag EXT2_MASTER_SB_ONLY is + set, then only write out the master superblock. + +Sun Oct 6 21:45:26 1996 Theodore Ts'o + + * block.c (ext2fs_block_iterate): Fixed bug which caused + block_iterate to fail to handle HURD created filesystems; + it tested the inode translator field before the inode was + loaded. + +Tue Sep 17 14:08:24 1996 Theodore Ts'o + + * initialize.c (ext2fs_initialize): Make sure the description for + the inode bitmap is set correctly. + + * bitmaps.c (ext2fs_allocate_generic_bitmap): Fix minor type typo. + +Thu Sep 12 15:23:07 1996 Theodore Ts'o + + * Release of E2fsprogs version 1.05 + +Sat Sep 7 07:36:03 1996 Theodore Ts'o + + * initialize.c: Override the kernel's idea of default + checkinterval from 0 (never) to 180 days. + +Wed Aug 28 03:20:03 1996 Theodore Ts'o + + * namei.c (ext2fs_namei_follow): New function which follows + symbolic link (if any) at the target. + +Tue Aug 27 01:48:43 1996 Theodore Ts'o + + * inode.c (ext2fs_read_inode, ext2fs_write_inode): Add support + for shortcut function fs->read_inode() and fs->write_inode(). + Added inode_cache to reduce CPU time spent in doing + byte swapping. + + * swapfs.c (ext2fs_swap_super): Swap the new fields in a V2 + superblock. + + * namei.c (ext2fs_follow_link): New function. + (ext2fs_namei): Extended to have support for chasing + symbolic links. ext2fs_namei() still returns an inode + which is a symbolic link. Symbolic links are only chased + while resolving the containing directory. To chase + symbolic links of the final result, use + ext2fs_follow_link(). + +Mon Aug 26 23:46:07 1996 Theodore Ts'o + + * ext2_err.et.in: Added new error code EXT2_ET_SYMLINK_LOOP. + + * bitops.h (ext2fs_set_bit, ext2fs_celar_bit): Use asm inlines + provided by Pete A. Zaitcev (zaitcev@lab.sun.mcst.ru). + +Thu Aug 22 00:40:18 1996 Theodore Ts'o + + * initialize.c (ext2fs_initialize): On systems where the byte + order is not i386 compatible, set the swap_byte flag. + + * inode.c (inocpy_with_swap): Check to see if inode contains a + fast symlink before swapping the inode block fields. This + required adding a new argument to inocpy_with_swap to + determine whether the mode field is in host order or not. + +Wed Aug 21 00:45:42 1996 Theodore Ts'o + + * bitops.h (ext2fs_set_bit, ext2fs_clear_bit, ext2fs_test_bit): On + the sparc, if EXT2_STD_BITOPS set, use the standard + i386-compatible bitmask operations, instead on the + non-standard native bitmask operators. + +Fri Aug 9 11:11:35 1996 Theodore Ts'o + + * block.c (ext2fs_block_iterate): Cause block iterator to return + the HURD translator block (along with everything else). + If the flag BLOCK_FLAG_DATA_ONLY is passed to the block + iterator, then don't return any meta data blocks + (including the HURD translator). + +Wed Jul 17 17:13:34 1996 Theodore Ts'o + + * gen_uuid.c: New file, which generates DCE-compatible UUIDs. + + * uuid.c: New file, containing UUID utility functions. + +Tue Jul 16 10:19:16 1996 Theodore Ts'o + + * ext2fs.h: Add a definition of the "real" ext2 superblock. + +Fri May 24 14:54:55 1996 Theodore Ts'o + + * ext2fs.h: Fix erroneous ino_t type used in block_bitmap type. + +Sun May 19 15:39:03 1996 Theodore Ts'o + + * openfs.c (ext2fs_open): If the blocksize in the superblock is + zero, return the error EXT2_ET_CORRUPT_SUPERBLOCK, since + that's a basic value that must be correct for the rest of + the library to work. + + * ext2_err.et.in (EXT2_ET_CORRUPT_SUPERBLOCK): Added new error + code. + +Thu May 16 11:12:30 1996 Theodore Ts'o + + * Release of E2fsprogs version 1.04 + +Wed Mar 27 00:33:40 1996 + + * Release of E2fsprogs version 1.03 + +Tue Mar 26 12:06:32 1996 + + * bitops.h (ext2fs_set_bit, ext2fs_clear_bit, ext2fs_test_bit): + Change the m68k bit numbering for bitmasks to match with + the bit numbering used by all other ext2 implementations. + +Thu Mar 7 03:37:00 1996 + + * inode.c (ext2fs_get_next_inode, ext2fs_close_inode_scan, + ext2fs_open_inode_scan): Support dynamically-sized inodes. + +Wed Mar 6 12:26:29 1996 + + * inode.c (ext2fs_read_inode, ext2fs_write_inode): Support + dynamically-sized inodes. + + * openfs.c (ext2fs_open): Allow dynamic revision filesystem to be + loaded. + +Tue Mar 5 03:49:37 1996 + + * initialize.c (ext2fs_initialize): Catch an error condition where + the passed in size is *really* too small. + + * alloc.c (ext2fs_new_inode): + * ext2fs.h (EXT2_FIRST_INODE): Add support for dynamic revision to + get first inode. + +Wed Feb 21 15:56:17 1996 + + * getsize.c (ext2fs_get_device_size): Open the device read-only + when trying to determine its size. + +Wed Jan 31 11:06:08 1996 + + * Release of E2fsprogs version 1.02 + +Sat Dec 9 09:57:50 1995 + + * rw_bitops.c (ext2fs_write_block_bitmap): + * bitops.c (ext2fs_test_bit, ext2fs_clear_bit, ext2fs_set_bit): + * bitops.h (ext2fs_test_bit, ext2fs_clear_bit, ext2fs_set_bit): + Rename {test,set,clear}_bit to ext2fs_{test,set,clear}_bit, + to avoid conflicts with with kernel include files. Also + rename ADDR and CONST_ADDR to EXT2FS_ADDR and + EXT2FS_CONST_ADDR. + +Thu Oct 26 12:09:16 1995 + + * ext2_err.et: Updated message in EXT2_ET_BASE to say version 0.5c + + * swapfs.c (ext2fs_swap_super): Put an #ifdef check around + s_def_resuid and s_def_resgid for backwards compatibility. + +Fri Oct 20 23:33:31 1995 + + * bitops.h: Added #ifdef's for Sparc. + +Wed Sep 6 22:14:46 1995 + + * getsize.c: #include under Linux to pick up ioctl() + declaration + + * closefs.c: #include to pick up memset() declaration + +Mon Sep 4 21:45:29 1995 Remy Card + + * Makefile.in: Added support for BSD shared libraries. + + * initialize.c (ext2fs_initialize): Correctly set the s_creator_os + flag. + +Mon Sep 4 09:55:30 1995 + + * unix_io.c (unix_open): Add a double check; if the passed in name + is NULL, return EXT2_ET_BAD_DEVICE_NAME. + + * ext2_err.et (EXT2_ET_BAD_DEVICE_NAME): Added new error code + +Wed Aug 16 15:44:10 1995 + + * inode.c (ext2fs_check_directory): Use LINUX_S_ISDIR instead of + S_ISDIR. + +Tue Aug 15 13:08:36 1995 + + * getsize.c (ext2fs_get_device_size): Add support for reading the + partition size from a BSD disk label. + +Thu Aug 10 09:33:26 1995 Theodore Y. Ts'o + + * getsize.c (ext2fs_get_device_size): New function that determins + the size of a device. Used by mke2fs and e2fsck. + +Sat Aug 12 03:09:54 1995 Remy Card + + * Makefile.in (install): Install static libraries in $(ulibdir) + (/usr/lib on Linux) instead of $(libdir) (/lib on Linux). + +Wed Aug 9 17:04:23 1995 Theodore Y. Ts'o + + * bitmaps.c (ext2fs_free_inode_bitmap, ext2fs_free_block_bitmap): + Move these functions to freefs.c. + + * closefs.c (ext2fs_flush): If swapping blocks, clear the group + descriptors shadow memory to keep purify quiet. (This + also has the nice benefit that the unused portion of the + shadow descriptors are zeroed out.) + + * dirblock.c (ext2fs_write_dir_block): We need to use + dirent->rec_len *before* it's byteswapped to find the + location of the next directory structure! + + * alloc.c (ext2fs_new_inode): Fix bug which could potentially + cause ext2fs_new_inode to loop infinitely if we're trying + to allocate an inode in group #0 and there are no free + inodes at all in the system. + + * closefs.c: #include if it exists. + +Sun Aug 6 13:27:50 1995 Theodore Y. Ts'o + + * ext2fs.h (BLOCK_FLAG_HOLE): Added new definition for + BLOCK_FLAG_APPEND. Added documentation for the block + interator flags. + +Sat Aug 5 11:44:05 1995 Theodore Y. Ts'o + + * Makefile.in (DLL_INSTALL_DIR, ELF_INSTALL_DIR): Set the + installation directories correctly. + +Tue Jul 18 09:27:38 1995 + + * namei.c (process_dir_block): + * mkdir.c (ext2fs_mkdir): + * expanddir.c (expand_dir_proc): Use ext2fs_{read,write}_dir_block + to read/write the directory block. + + * dirblock.c (ext2fs_read_dir_block), ext2fs_write_dir_block): New + file containing functions for reading and writing + directory blocks (byte swapping if necesssary) + + * block.c (block_iterate_ind, block_iterate_dind, + block_iterate_tind): Byte swap the block addresses if + EXT2_SWAP_BYTES is set (and swap them back before writing + them out.) + + * inode.c (inocpy_with_swap): New function. + (ext2fs_get_next_inode, ext2fs_read_inode, ext2fs_write_inode): + Call inocpy_with_swap if EXT2_SWAP_BYTES if set. + + * closefs.c (ext2fs_flush): If EXT2_SWAP_BYTES is set, then swap + the superblock and group descriptors before writing it out. + + * openfs.c (ext2fs_open): If the magic number is byte-swapped, + then set the EXT2_SWAP_BYTES and byte-swap the superblock + and group descriptors. + + * swapfs.c (ext2fs_swap_super, ext2fs_swap_group_desc): New functions + to desp ext2 filesystem structures. + + * bitops.c (set_bit, clear_bit, test_bit): Use modifications + supplied by Pete A. Zaitcev so that the C language + versions of these functions are more portable. They will + now work on both little and big endian systems, and the + assumption that 32-bit integers are used is gone. + + * bitops.h (ext2_swab16, ext2_swab32): Added new functions for + doing byte swapping. + + * ext2fs.h (EXT2_SWAP_BYTES): Add new flag which indicates that + byte swapping should take place. + +Sun Jul 16 06:21:43 1995 + + * Makefile.in, cmp_bitmaps.c (ext2fs_compare_block_bitmap_end, + ext2fs_compare_inode_bitmap_end): Added new file + containing routines to compare bitmaps. + + * ext2_err.et (EXT2_ET_NEQ_BLOCK_BITMAP, EXT2_ET_NEQ_INODE_BITMAP): + Added new error codes. + +Sat Jul 15 04:23:37 1995 + + * inode.c (ext2fs_get_next_inode): Don't check scan->inode_buffer; + if the magic number is correct, it will be allocated. + +Fri Jul 14 19:02:59 1995 + + * block.c (block_iterate_ind, block_iterate_dind, + block_iterate_tind): Don't recompute block_nr each loop; + just increment it! Factor check of BLOCK_FLAG_APPEND out + of the loop. Factor mask of BLOCK_CHANGED into changed + variable out of the loop. (block_iterate_ind, in + particular, gets called a lot, so every little + optimization helps.) + +Thu Jul 13 08:02:45 1995 + + * block.c (block_iterate_ind, block_iterate_dind, + block_iterate_tind): Precompute limit of loop to speed up + block_iterate_ind and company. + + * bitops.h (ext2fs_fast_mark_block_bitmap, + ext2fs_fast_unmark_block_bitmap, ext2fs_fast_test_block_bitmap, + ext2fs_fast_mark_inode_bitmap, ext2fs_fast_unmark_inode_bitmap, + ext2fs_fast_test_inode_bitmap): Add fast version of these + functions, which don't do range checking. + + * bitops.h (ext2fs_get_block_bitmap_start, + ext2fs_get_inode_bitmap_start, ext2fs_get_block_bitmap_end, + ext2fs_get_inode_bitmap_end): Add new accessor functions + which return the start and end points of the bitmaps. + +Tue Jul 11 18:59:41 1995 + + * llseek.c (ext2_llseek): If the offset is small enough, use lseek + instead of llseek. The errno if the offset is too large + and lseek is not supported should be EINVAL, not -EINVAL. + +Thu Jun 15 23:43:02 1995 Remy Card + + * Makefile.in: Added support for ELF shared libraries. + Fixed typos in the compilation rules. + (distclean): Added Makefile. + + * llseek.c (llseek): New function, if llseek() does not exist in the + C library. + (ext2_llseek): Changed to call llseek(). + +Mon Jun 12 08:29:07 1995 Theodore Y. Ts'o + + * ext2fs.h: Use __u32 to define blk_t, instead of unsigned long. + +Sun Jun 11 15:02:54 1995 Theodore Y. Ts'o + + * mkdir.c (ext2fs_mkdir): Use LINUX_S_IFDIR instead of S_IFDIR. + + * ext2fs.h (LINUX_S_IFDIR): Define a linux specific versions of + the S_*, which are normally defined in . This + allows us to compile e2fsprogs on a non-Linux system, + which may have a different value for S_IFDIR. + +Sat Jun 10 23:47:05 1995 Theodore Y. Ts'o + + * bitops.c (clear_bit, set_bit): Remove calls to cli() and sti(); + this is a user-mode application! + +Thu Jun 8 13:13:22 1995 Miles Bader + + * llseek.c: Put the include of inside the #ifdef + __linux__ so that non-linux systems won't see it. + + * alloc.c: Include if possible. + * badblocks.c: Ditto. + * bb_inode.c: Ditto. + * bitmaps.c: Ditto. + * block.c: Ditto. + * expanddir.c: Ditto. + * get_pathname.c: Ditto. + * initialize.c: Ditto. + * inode.c: Ditto. + * llseek.c: Ditto. + * mkdir.c: Ditto. + * namei.c: Ditto. + * newdir.c: Ditto. + * openfs.c: Ditto. + * rw_bitmaps.c: Ditto. + * unix_io.c: Ditto. + + * Makefile.in: Rewritten to conform to GNU coding standards and + support separate compilation directories. + +Thu May 11 04:13:12 1995 + + * initialize.c (ext2fs_initialize): Don't allow more than one + bitmaps's worth of inodes in a group. + +Sat Mar 11 14:07:11 1995 Theodore Y. Ts'o + + * llseek.c (ext2_llseek): Added error checking to the llseek() + compat code to protect against overflow. This only + applies to 1.0 and early 1.1 kernels, which don't support + the llseek() system call. + +Thu Nov 24 16:29:00 1994 Theodore Y. Ts'o (tytso@rt-11) + + * unix_io.c (unix_open): Initialize the read_error and write_error + io_channel pointers to be null. + + * bb_inode.c (clear_bad_block_proc): If an illegal block number is + found, clear it but don't try to update the filesystem + accounting information, since that's hopeless anyway. + + * block.c (bloblock_iterate_ind, bloblock_iterate_dind, + bloblock_iterate_tind): Check to see if the indirect blocks are + valid before trying to read them. + + * ext2_err.et (EXT2_ET_BAD_IND_BLOCK, EX2_ET_BAD_DIND_BLOCK, + EXT2_ET_BAD_TIND_BLOCK): Add new error codes. + + * bitops.h (ext2fs_mark_block_bitmap, ext2fs_unmark_block_bitmap, + ext2fs_test_block_bitmap, ext2fs_mark_inode_bitmap, + ext2fs_unmark_inode_bitmap, ext2fs_test_inode_bitmap): If an + illegal block or inode number is passed in, return instead + of trying to test, set, or clear the bit. + +Mon Nov 7 21:32:33 1994 Remy Card + + * Makefile: Added a dummy install target in case shared libraries + are not built. + +Mon Oct 24 14:11:44 1994 (tytso@rsx-11) + + * bitmaps.c (ext2fs_allocate_block_bitmap): Fix calculation of how + the real last block of the bitmap should be calculated. + +Wed Sep 7 10:05:36 1994 (tytso@rsx-11) + + * bitmaps.c (ext2fs_fudge_inode_bitmap_end, + ext2fs_fudge_block_bitmap_end, ext2fs_clear_inode_bitmap, + ext2fs_clear_block_bitmap, ext2fs_free_inode_bitmap, + ext2fs_free_block_bitmap): Add magic number checking for + the inode and block bitmaps. + + * bitmaps.c (ext2fs_allocate_block_bitmap): Fix to set the correct + magic number for a block bitmap instead of an inode bitmap. + + * inode.c (ext2fs_close_inode_scan, ext2fs_get_next_inode): Add + magic number checking for the inode_scan structure. + + * badblocks.c (badblocks_list_free, badblocks_list_add, + badblocks_list_test, badblocks_list_iterate_begin, + badblocks_list_iterate, badblocks_list_iterate_end): Add + magic number checking for the badblocks_list and + badblocks_iterate structures. + + * ext2_err.et (EXT2_ET_MAGIC_UNIX_IO_CHANNEL): + * unix_io.c (unix_open, unix_close, unix_set_blksize, unix_read_blk, + unix_write_blk, unix_flush): Add magic number checking + both for io_channel structure and unix_private_data + structure. + + * openfs.c (ext2fs_open): Add check for io_manager structure's + magic number. + + * rw_bitmaps.c (ext2fs_write_inode_bitmap, ext2fs_write_block_bitmap, + ext2fs_read_inode_bitmap, ext2fs_read_block_bitmap, + ext2fs_read_bitmaps, ext2fs_write_bitmaps): + * read_bb.c (ext2fs_read_bb_inode): + * read_bb_file.c (ext2fs_read_bb_FILE): + * newdir.c (ext2fs_new_dir_block): + * namei.c (ext2fs_dir_iterate, ext2fs_lookup, ext2fs_namei): + * link.c (ext2fs_link, ext2fs_unlink): + * inode.c (ext2fs_open_inode_scan, ext2fs_read_inode, + ext2fs_write_inode, ext2fs_get_blocks, + ext2fs_check_directory): + * get_pathname.c (ext2fs_get_pathname): + * expanddir.c (ext2fs_expand_dir): + * block.c (ext2fs_block_iterate): + * bitmaps.c (ext2fs_allocate_inode_bitmap, + ext2fs_allocate_block_bitmap): + * bb_inode.c (ext2fs_update_bb_inode): + * alloc.c (ext2fs_new_inode,ext2fs_new_block,ext2fs_get_free_blocks): + * check_desc.c (ext2fs_check_desc): + * closefs.c (ext2fs_close, ext2fs_flush): + * freefs.c (ext2fs_free): Add check for ext2_filsys magic number. + + * Makefile: + * ext2fs.h: + * openfs.c: + * check_desc.c (ext2fs_check_desc): Move ext2fs_check_desc from + openfs.c into its own file. + + * ext2fs.h (EXT2_CHECK_MAGIC): Added macro for checking for + structure magic numbers. + + * closefs.c (ext2fs_flush): Folded in Remy Card's changes to clear + the EXT2_VALID_FS flag in the backup superblock blocks, so that if + someone uses the -b option to specify the use of the backup + superblock --- this usually means that the main superblock is + toast. :-) + + * ext2fs.h: + * ext2_err.et (EXT2_ET_REV_TOO_HIGH): + * openfs.c (ext2fs_open): Folded in Remy Card's changes to add a + revision level to the superblock. + +Sun Aug 21 00:50:08 1994 Theodore Y. Ts'o (tytso@rt-11) + + * ext2fs.h: + * bitmaps.c: + * bitops.c + * bitops.h: + * openfs.c: + * initialize.c: Completely revamped the inode and block bitmap + structures, so that they can be better chance of being extensible + in a shared library. They are now their own type, instead of + being a char *. Also, the function signatures of + ext2fs_test_block_bitmap, ext2fs_mark_block_bitmap, + ext2fs_unmark_block_bitmap, ext2fs_test_inode_bitmap, + ext2fs_mark_inode_bitmap, and ext2fs_unmark_inode_bitmap were + changed to eliminate the ext2_filsys argument, since it is no + longer necessary. + +Wed Aug 17 21:46:44 1994 Remy Card (card@bbj) + + * unix_io.c (unix_read_blk and unix_write_blk): use the llseek + system call if available. + + * llseek.c: new file. This is the stub calling the llseek system + call which allows supports for 2GB+ file systems. + + * initialize.c (ext2fs_initialize): Ext2fs_initialize now stores + the creator operating system. + +Wed Aug 17 10:03:24 1994 Theodore Y. Ts'o (tytso@rt-11) + + * initialize.c (ext2fs_initialize): Ext2fs_initialize now sets up + the group descriptor statistics in addition to everything else. + This relieves mke2fs of the responsibility of doing it. + + * bitops.c, bitops.h: Add assembly inline functions for the 68000. + Added a new #define, _EXT2_HAVE_ASM_BITOPS_ to control whether or + not the generic C function equivalents should be included or not. + + * openfs.c (ext2fs_open): If a superblock is specified, then use + the backup group descriptors that go along with this superblock, + instead of using the primary group descriptors. This allows + e2fsck to recover filesystems where the primary group descriptors + have been trashed. + + diff -Naur silo-1.4.14.orig/libext2fs/Makefile silo-1.4.14/libext2fs/Makefile --- silo-1.4.14.orig/libext2fs/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/Makefile 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,21 @@ + +include ../Rules.make + +DEFS = -DLOCALEDIR=\"$(localedir)\" -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DENABLE_HTREE=1 -DENABLE_SWAPFS=1 -DPACKAGE=\"e2fsprogs\" -DVERSION=\"0.14.1\" -DHAVE_LONG_LONG=1 -DHAVE_LONG_DOUBLE=1 -DHAVE_WCHAR_T=1 -DHAVE_WINT_T=1 -DHAVE_INTTYPES_H_WITH_UINTMAX=1 -DHAVE_STDINT_H_WITH_UINTMAX=1 -DHAVE_INTMAX_T=1 -DHAVE_POSIX_PRINTF=1 -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_GETPAGESIZE=1 -DHAVE_MMAP=1 -DINTDIV0_RAISES_SIGFPE=1 -DHAVE_UNSIGNED_LONG_LONG=1 -DHAVE_UINTMAX_T=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_STDINT_H=1 -DHAVE_ARGZ_H=1 -DHAVE_LIMITS_H=1 -DHAVE_LOCALE_H=1 -DHAVE_NL_TYPES_H=1 -DHAVE_MALLOC_H=1 -DHAVE_STDDEF_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_ASPRINTF=1 -DHAVE_FWPRINTF=1 -DHAVE_GETCWD=1 -DHAVE_GETEGID=1 -DHAVE_GETEUID=1 -DHAVE_GETGID=1 -DHAVE_GETUID=1 -DHAVE_MEMPCPY=1 -DHAVE_MUNMAP=1 -DHAVE_PUTENV=1 -DHAVE_SETENV=1 -DHAVE_SETLOCALE=1 -DHAVE_SNPRINTF=1 -DHAVE_STPCPY=1 -DHAVE_STRCASECMP=1 -DHAVE_STRDUP=1 -DHAVE_STRTOUL=1 -DHAVE_TSEARCH=1 -DHAVE_WCSLEN=1 -DHAVE___ARGZ_COUNT=1 -DHAVE___ARGZ_STRINGIFY=1 -DHAVE___ARGZ_NEXT=1 -DHAVE___FSETLOCKING=1 -DHAVE_DECL__SNPRINTF=0 -DHAVE_DECL__SNWPRINTF=0 -DHAVE_DECL_FEOF_UNLOCKED=1 -DHAVE_DECL_FGETS_UNLOCKED=0 -DHAVE_DECL_GETC_UNLOCKED=1 -DHAVE_ICONV=1 -DICONV_CONST= -DHAVE_LANGINFO_CODESET=1 -DHAVE_LC_MESSAGES=1 -DENABLE_NLS=1 -DHAVE_GETTEXT=1 -DHAVE_DCGETTEXT=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STDARG_H=1 -DHAVE_STDINT_H=1 -DHAVE_ERRNO_H=1 -DHAVE_MALLOC_H=1 -DHAVE_MNTENT_H=1 -DHAVE_PATHS_H=1 -DHAVE_DIRENT_H=1 -DHAVE_GETOPT_H=1 -DHAVE_SETJMP_H=1 -DHAVE_SIGNAL_H=1 -DHAVE_TERMIOS_H=1 -DHAVE_LINUX_FD_H=1 -DHAVE_LINUX_MAJOR_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_SYS_PRCTL_H=1 -DHAVE_SYS_QUEUE_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_SYS_SYSMACROS_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_WAIT_H=1 -DHAVE_SYS_RESOURCE_H=1 -DHAVE_NETINET_IN_H=1 -DHAVE_SYS_MOUNT_H=1 -DHAVE_NET_IF_H=1 -DHAVE_VPRINTF=1 -DHAVE_RECLEN_DIRENT=1 -DHAVE_TYPE_SSIZE_T=1 -DHAVE_LSEEK64_PROTOTYPE=1 -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_LONG_LONG=8 -DHAVE_INTTYPES_H=1 -DHAVE_INTPTR_T=1 -DHAVE_GETRUSAGE=1 -DHAVE_LLSEEK=1 -DHAVE_LSEEK64=1 -DHAVE_OPEN64=1 -DHAVE_STRTOULL=1 -DHAVE_STRCASECMP=1 -DHAVE_SRANDOM=1 -DHAVE_FCHOWN=1 -DHAVE_MALLINFO=1 -DHAVE_FDATASYNC=1 -DHAVE_STRNLEN=1 -DHAVE_STRPTIME=1 -DHAVE_SYSCONF=1 -DHAVE_PATHCONF=1 -DHAVE_POSIX_MEMALIGN=1 -DHAVE_MEMALIGN=1 -DHAVE_VALLOC=1 -DHAVE___SECURE_GETENV=1 -DHAVE_PRCTL=1 -DHAVE_DLOPEN=1 -DHAVE_EXT2_IOCTLS=1 + +DEBUGFS_LIB_OBJS = inode_io.o namei.o write_bb_file.o +RESIZE_LIB_OBJS = rs_bitmap.o dupfs.o test_io.o +E2IMAGE_LIB_OBJS = imager.o +OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) ext2_err.o alloc.o alloc_sb.o alloc_stats.o alloc_tables.o badblocks.o bb_inode.o bitmaps.o bitops.o block.o bmap.o check_desc.o closefs.o dblist.o dblist_dir.o dirblock.o dirhash.o dir_iterate.o expanddir.o ext_attr.o finddev.o flushb.o freefs.o gen_bitmap.o get_pathname.o getsize.o getsectsize.o icount.o ind_block.o initialize.o inline.o inode.o io_manager.o ismounted.o link.o llseek.o lookup.o mkdir.o mkjournal.o native.o newdir.o openfs.o read_bb.o read_bb_file.o res_gdt.o rw_bitmaps.o swapfs.o unix_io.o unlink.o valid_blk.o version.o + +all: libext2fs.a + +libext2fs.a: $(OBJS) + $(RM) libext2fs.a + $(AR) rc libext2fs.a $(OBJS) + +clean: + $(RM) -f libext2fs.a $(OBJS) + +.c.o: + $(CC-SILO) $(CFLAGS) $(DEFS) -c $< -o $@ diff -Naur silo-1.4.14.orig/libext2fs/alloc.c silo-1.4.14/libext2fs/alloc.c --- silo-1.4.14.orig/libext2fs/alloc.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/alloc.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,173 @@ +/* + * alloc.c --- allocate new inodes, blocks for ext2fs + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "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, ext2_ino_t dir, + int mode EXT2FS_ATTR((unused)), + ext2fs_inode_bitmap map, ext2_ino_t *ret) +{ + ext2_ino_t dir_group = 0; + ext2_ino_t i; + ext2_ino_t start_inode; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + 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; + if (start_inode < EXT2_FIRST_INODE(fs->super)) + start_inode = EXT2_FIRST_INODE(fs->super); + i = start_inode; + + do { + if (!ext2fs_fast_test_inode_bitmap(map, i)) + break; + i++; + if (i > fs->super->s_inodes_count) + i = EXT2_FIRST_INODE(fs->super); + } while (i != start_inode); + + if (ext2fs_test_inode_bitmap(map, i)) + return EXT2_ET_INODE_ALLOC_FAIL; + *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, + ext2fs_block_bitmap map, blk_t *ret) +{ + blk_t i; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!map) + map = fs->block_map; + if (!map) + return EXT2_ET_NO_BLOCK_BITMAP; + if (!goal || (goal >= fs->super->s_blocks_count)) + goal = fs->super->s_first_data_block; + i = goal; + do { + if (!ext2fs_fast_test_block_bitmap(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 EXT2_ET_BLOCK_ALLOC_FAIL; +} + +/* + * This function zeros out the allocated block, and updates all of the + * appropriate filesystem records. + */ +errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal, + char *block_buf, blk_t *ret) +{ + errcode_t retval; + blk_t block; + char *buf = 0; + + if (!block_buf) { + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + block_buf = buf; + } + memset(block_buf, 0, fs->blocksize); + + if (!fs->block_map) { + retval = ext2fs_read_block_bitmap(fs); + if (retval) + goto fail; + } + + retval = ext2fs_new_block(fs, goal, 0, &block); + if (retval) + goto fail; + + retval = io_channel_write_blk(fs->io, block, 1, block_buf); + if (retval) + goto fail; + + ext2fs_block_alloc_stats(fs, block, +1); + *ret = block; + return 0; + +fail: + if (buf) + ext2fs_free_mem(&buf); + return retval; +} + +errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish, + int num, ext2fs_block_bitmap map, blk_t *ret) +{ + blk_t b = start; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + 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 (b+num-1 > fs->super->s_blocks_count) + b = fs->super->s_first_data_block; + if (ext2fs_fast_test_block_bitmap_range(map, b, num)) { + *ret = b; + return 0; + } + b++; + } while (b != finish); + return EXT2_ET_BLOCK_ALLOC_FAIL; +} + diff -Naur silo-1.4.14.orig/libext2fs/alloc_sb.c silo-1.4.14/libext2fs/alloc_sb.c --- silo-1.4.14.orig/libext2fs/alloc_sb.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/alloc_sb.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,57 @@ +/* + * alloc_sb.c --- Allocate the superblock and block group descriptors for a + * newly initialized filesystem. Used by mke2fs when initializing a filesystem + * + * Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +int ext2fs_reserve_super_and_bgd(ext2_filsys fs, + dgrp_t group, + ext2fs_block_bitmap bmap) +{ + blk_t super_blk, old_desc_blk, new_desc_blk; + int j, old_desc_blocks, num_blocks; + + num_blocks = ext2fs_super_and_bgd_loc(fs, group, &super_blk, + &old_desc_blk, &new_desc_blk, 0); + + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = + fs->desc_blocks + fs->super->s_reserved_gdt_blocks; + + if (super_blk || (group == 0)) + ext2fs_mark_block_bitmap(bmap, super_blk); + + if (old_desc_blk) { + for (j=0; j < old_desc_blocks; j++) + ext2fs_mark_block_bitmap(bmap, old_desc_blk + j); + } + if (new_desc_blk) + ext2fs_mark_block_bitmap(bmap, new_desc_blk); + + return num_blocks; +} diff -Naur silo-1.4.14.orig/libext2fs/alloc_stats.c silo-1.4.14/libext2fs/alloc_stats.c --- silo-1.4.14.orig/libext2fs/alloc_stats.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/alloc_stats.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,52 @@ +/* + * alloc_stats.c --- Update allocation statistics for ext2fs + * + * Copyright (C) 2001 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + */ + +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino, + int inuse, int isdir) +{ + int group = ext2fs_group_of_ino(fs, ino); + + if (inuse > 0) + ext2fs_mark_inode_bitmap(fs->inode_map, ino); + else + ext2fs_unmark_inode_bitmap(fs->inode_map, ino); + fs->group_desc[group].bg_free_inodes_count -= inuse; + if (isdir) + fs->group_desc[group].bg_used_dirs_count += inuse; + fs->super->s_free_inodes_count -= inuse; + ext2fs_mark_super_dirty(fs); + ext2fs_mark_ib_dirty(fs); +} + +void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse) +{ + ext2fs_inode_alloc_stats2(fs, ino, inuse, 0); +} + +void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse) +{ + int group = ext2fs_group_of_blk(fs, blk); + + if (inuse > 0) + ext2fs_mark_block_bitmap(fs->block_map, blk); + else + ext2fs_unmark_block_bitmap(fs->block_map, blk); + fs->group_desc[group].bg_free_blocks_count -= inuse; + fs->super->s_free_blocks_count -= inuse; + ext2fs_mark_super_dirty(fs); + ext2fs_mark_bb_dirty(fs); +} diff -Naur silo-1.4.14.orig/libext2fs/alloc_tables.c silo-1.4.14/libext2fs/alloc_tables.c --- silo-1.4.14.orig/libext2fs/alloc_tables.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/alloc_tables.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,117 @@ +/* + * alloc_tables.c --- Allocate tables for a newly initialized + * filesystem. Used by mke2fs when initializing a filesystem + * + * Copyright (C) 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, + ext2fs_block_bitmap bmap) +{ + errcode_t retval; + blk_t group_blk, start_blk, last_blk, new_blk, blk; + int j; + + group_blk = fs->super->s_first_data_block + + (group * fs->super->s_blocks_per_group); + + last_blk = group_blk + fs->super->s_blocks_per_group; + if (last_blk >= fs->super->s_blocks_count) + last_blk = fs->super->s_blocks_count - 1; + + if (!bmap) + bmap = fs->block_map; + + /* + * Allocate the block and inode bitmaps, if necessary + */ + if (fs->stride) { + start_blk = group_blk + fs->inode_blocks_per_group; + start_blk += ((fs->stride * group) % + (last_blk - start_blk)); + if (start_blk > last_blk) + start_blk = group_blk; + } else + start_blk = group_blk; + + if (!fs->group_desc[group].bg_block_bitmap) { + retval = ext2fs_get_free_blocks(fs, start_blk, last_blk, + 1, bmap, &new_blk); + if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) + retval = ext2fs_get_free_blocks(fs, group_blk, + last_blk, 1, bmap, &new_blk); + if (retval) + return retval; + ext2fs_mark_block_bitmap(bmap, new_blk); + fs->group_desc[group].bg_block_bitmap = new_blk; + } + + if (!fs->group_desc[group].bg_inode_bitmap) { + retval = ext2fs_get_free_blocks(fs, start_blk, last_blk, + 1, bmap, &new_blk); + if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) + retval = ext2fs_get_free_blocks(fs, group_blk, + last_blk, 1, bmap, &new_blk); + if (retval) + return retval; + ext2fs_mark_block_bitmap(bmap, new_blk); + fs->group_desc[group].bg_inode_bitmap = new_blk; + } + + /* + * Allocate the inode table + */ + if (!fs->group_desc[group].bg_inode_table) { + retval = ext2fs_get_free_blocks(fs, group_blk, last_blk, + fs->inode_blocks_per_group, + bmap, &new_blk); + if (retval) + return retval; + for (j=0, blk = new_blk; + j < fs->inode_blocks_per_group; + j++, blk++) + ext2fs_mark_block_bitmap(bmap, blk); + fs->group_desc[group].bg_inode_table = new_blk; + } + + + return 0; +} + + + +errcode_t ext2fs_allocate_tables(ext2_filsys fs) +{ + errcode_t retval; + dgrp_t i; + + for (i = 0; i < fs->group_desc_count; i++) { + retval = ext2fs_allocate_group_table(fs, i, fs->block_map); + if (retval) + return retval; + } + return 0; +} + diff -Naur silo-1.4.14.orig/libext2fs/badblocks.c silo-1.4.14/libext2fs/badblocks.c --- silo-1.4.14.orig/libext2fs/badblocks.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/badblocks.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,327 @@ +/* + * badblocks.c --- routines to manipulate the bad block structure + * + * Copyright (C) 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +/* + * Helper function for making a badblocks list + */ +static errcode_t make_u32_list(int size, int num, __u32 *list, + ext2_u32_list *ret) +{ + ext2_u32_list bb; + errcode_t retval; + + retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb); + if (retval) + return retval; + memset(bb, 0, sizeof(struct ext2_struct_u32_list)); + bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST; + bb->size = size ? size : 10; + bb->num = num; + retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list); + if (!bb->list) { + ext2fs_free_mem(&bb); + return retval; + } + if (list) + memcpy(bb->list, list, bb->size * sizeof(blk_t)); + else + memset(bb->list, 0, bb->size * sizeof(blk_t)); + *ret = bb; + return 0; +} + + +/* + * This procedure creates an empty u32 list. + */ +errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size) +{ + return make_u32_list(size, 0, 0, ret); +} + +/* + * This procedure creates an empty badblocks list. + */ +errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size) +{ + return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret); +} + + +/* + * This procedure copies a badblocks list + */ +errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest) +{ + errcode_t retval; + + retval = make_u32_list(src->size, src->num, src->list, dest); + if (retval) + return retval; + (*dest)->badblocks_flags = src->badblocks_flags; + return 0; +} + +errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, + ext2_badblocks_list *dest) +{ + return ext2fs_u32_copy((ext2_u32_list) src, + (ext2_u32_list *) dest); +} + +/* + * This procedure frees a badblocks list. + * + * (note: moved to closefs.c) + */ + + +/* + * This procedure adds a block to a badblocks list. + */ +errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk) +{ + errcode_t retval; + int i, j; + unsigned long old_size; + + EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); + + if (bb->num >= bb->size) { + old_size = bb->size * sizeof(__u32); + bb->size += 100; + retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32), + &bb->list); + if (retval) { + bb->size -= 100; + return retval; + } + } + + /* + * Add special case code for appending to the end of the list + */ + i = bb->num-1; + if ((bb->num != 0) && (bb->list[i] == blk)) + return 0; + if ((bb->num == 0) || (bb->list[i] < blk)) { + bb->list[bb->num++] = blk; + return 0; + } + + j = bb->num; + for (i=0; i < bb->num; i++) { + if (bb->list[i] == blk) + return 0; + if (bb->list[i] > blk) { + j = i; + break; + } + } + for (i=bb->num; i > j; i--) + bb->list[i] = bb->list[i-1]; + bb->list[j] = blk; + bb->num++; + return 0; +} + +errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk) +{ + return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk); +} + +/* + * This procedure finds a particular block is on a badblocks + * list. + */ +int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk) +{ + int low, high, mid; + + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) + return -1; + + if (bb->num == 0) + return -1; + + low = 0; + high = bb->num-1; + if (blk == bb->list[low]) + return low; + if (blk == bb->list[high]) + return high; + + while (low < high) { + mid = (low+high)/2; + if (mid == low || mid == high) + break; + if (blk == bb->list[mid]) + return mid; + if (blk < bb->list[mid]) + high = mid; + else + low = mid; + } + return -1; +} + +/* + * This procedure tests to see if a particular block is on a badblocks + * list. + */ +int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk) +{ + if (ext2fs_u32_list_find(bb, blk) < 0) + return 0; + else + return 1; +} + +int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk) +{ + return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk); +} + + +/* + * Remove a block from the badblock list + */ +int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk) +{ + int remloc, i; + + if (bb->num == 0) + return -1; + + remloc = ext2fs_u32_list_find(bb, blk); + if (remloc < 0) + return -1; + + for (i = remloc ; i < bb->num-1; i++) + bb->list[i] = bb->list[i+1]; + bb->num--; + return 0; +} + +void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk) +{ + ext2fs_u32_list_del(bb, blk); +} + +errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb, + ext2_u32_iterate *ret) +{ + ext2_u32_iterate iter; + errcode_t retval; + + EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); + + retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter); + if (retval) + return retval; + + iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE; + iter->bb = bb; + iter->ptr = 0; + *ret = iter; + return 0; +} + +errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, + ext2_badblocks_iterate *ret) +{ + return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb, + (ext2_u32_iterate *) ret); +} + + +int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk) +{ + ext2_u32_list bb; + + if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE) + return 0; + + bb = iter->bb; + + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) + return 0; + + if (iter->ptr < bb->num) { + *blk = bb->list[iter->ptr++]; + return 1; + } + *blk = 0; + return 0; +} + +int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk) +{ + return ext2fs_u32_list_iterate((ext2_u32_iterate) iter, + (__u32 *) blk); +} + + +void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter) +{ + if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)) + return; + + iter->bb = 0; + ext2fs_free_mem(&iter); +} + +void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter) +{ + ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter); +} + + +int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2) +{ + EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST); + EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST); + + if (bb1->num != bb2->num) + return 0; + + if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0) + return 0; + return 1; +} + +int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2) +{ + return ext2fs_u32_list_equal((ext2_u32_list) bb1, + (ext2_u32_list) bb2); +} + +int ext2fs_u32_list_count(ext2_u32_list bb) +{ + return bb->num; +} diff -Naur silo-1.4.14.orig/libext2fs/bb_compat.c silo-1.4.14/libext2fs/bb_compat.c --- silo-1.4.14.orig/libext2fs/bb_compat.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/bb_compat.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,63 @@ +/* + * bb_compat.c --- compatibility badblocks routines + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +errcode_t badblocks_list_create(badblocks_list *ret, int size) +{ + return ext2fs_badblocks_list_create(ret, size); +} + +void badblocks_list_free(badblocks_list bb) +{ + ext2fs_badblocks_list_free(bb); +} + +errcode_t badblocks_list_add(badblocks_list bb, blk_t blk) +{ + return ext2fs_badblocks_list_add(bb, blk); +} + +int badblocks_list_test(badblocks_list bb, blk_t blk) +{ + return ext2fs_badblocks_list_test(bb, blk); +} + +errcode_t badblocks_list_iterate_begin(badblocks_list bb, + badblocks_iterate *ret) +{ + return ext2fs_badblocks_list_iterate_begin(bb, ret); +} + +int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk) +{ + return ext2fs_badblocks_list_iterate(iter, blk); +} + +void badblocks_list_iterate_end(badblocks_iterate iter) +{ + ext2fs_badblocks_list_iterate_end(iter); +} diff -Naur silo-1.4.14.orig/libext2fs/bb_inode.c silo-1.4.14/libext2fs/bb_inode.c --- silo-1.4.14.orig/libext2fs/bb_inode.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/bb_inode.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,267 @@ +/* + * 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, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct set_badblock_record { + ext2_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, + e2_blkcnt_t blockcnt, + blk_t ref_block, int ref_offset, + void *priv_data); +static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, + e2_blkcnt_t blockcnt, + blk_t ref_block, int ref_offset, + void *priv_data); + +/* + * Given a bad blocks bitmap, update the bad blocks inode to reflect + * the map. + */ +errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list) +{ + errcode_t retval; + struct set_badblock_record rec; + struct ext2_inode inode; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + 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; + retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t), + &rec.ind_blocks); + if (retval) + return retval; + memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t)); + retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf); + if (retval) + 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_iterate2(fs, EXT2_BAD_INO, + BLOCK_FLAG_DEPTH_TRAVERSE, 0, + clear_bad_block_proc, &rec); + if (retval) + goto cleanup; + if (rec.err) { + retval = rec.err; + goto cleanup; + } + + /* + * Now set the bad blocks! + * + * First, mark the bad blocks as used. This prevents a bad + * block from being used as an indirecto block for the bad + * block inode (!). + */ + if (bb_list) { + retval = ext2fs_badblocks_list_iterate_begin(bb_list, + &rec.bb_iter); + if (retval) + goto cleanup; + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, + BLOCK_FLAG_APPEND, 0, + set_bad_block_proc, &rec); + ext2fs_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: + ext2fs_free_mem(&rec.ind_blocks); + ext2fs_free_mem(&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. + */ +#ifdef __TURBOC__ + #pragma argsused +#endif +static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, + e2_blkcnt_t blockcnt, + blk_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct set_badblock_record *rec = (struct set_badblock_record *) + priv_data; + errcode_t retval; + unsigned long old_size; + + if (!*block_nr) + return 0; + + /* + * If the block number is outrageous, clear it and ignore it. + */ + if (*block_nr >= fs->super->s_blocks_count || + *block_nr < fs->super->s_first_data_block) { + *block_nr = 0; + return BLOCK_CHANGED; + } + + if (blockcnt < 0) { + if (rec->ind_blocks_size >= rec->max_ind_blocks) { + old_size = rec->max_ind_blocks * sizeof(blk_t); + rec->max_ind_blocks += 10; + retval = ext2fs_resize_mem(old_size, + rec->max_ind_blocks * sizeof(blk_t), + &rec->ind_blocks); + if (retval) { + rec->max_ind_blocks -= 10; + rec->err = retval; + return BLOCK_ABORT; + } + } + rec->ind_blocks[rec->ind_blocks_size++] = *block_nr; + } + + /* + * Mark the block as unused, and update accounting information + */ + ext2fs_block_alloc_stats(fs, *block_nr, -1); + + *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. + */ +#ifdef __TURBOC__ + #pragma argsused +#endif +static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, + e2_blkcnt_t blockcnt, + blk_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct set_badblock_record *rec = (struct set_badblock_record *) + priv_data; + errcode_t retval; + blk_t blk; + + if (blockcnt >= 0) { + /* + * Get the next bad block. + */ + if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk)) + return BLOCK_ABORT; + rec->bad_block_count++; + } else { + /* + * An indirect block; fetch a block from the + * previously used indirect block list. The block + * most be not marked as used; if so, get another one. + * If we run out of reserved indirect blocks, allocate + * a new one. + */ + retry: + if (rec->ind_blocks_ptr < rec->ind_blocks_size) { + blk = rec->ind_blocks[rec->ind_blocks_ptr++]; + if (ext2fs_test_block_bitmap(fs->block_map, blk)) + goto retry; + } else { + 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; + } + } + + /* + * Update block counts + */ + ext2fs_block_alloc_stats(fs, blk, +1); + + *block_nr = blk; + return BLOCK_CHANGED; +} + + + + + + diff -Naur silo-1.4.14.orig/libext2fs/bitmaps.c silo-1.4.14/libext2fs/bitmaps.c --- silo-1.4.14.orig/libext2fs/bitmaps.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/bitmaps.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,212 @@ +/* + * bitmaps.c --- routines to read, write, and manipulate the inode and + * block bitmaps. + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end, + const char *descr, char *init_map, + ext2fs_generic_bitmap *ret) +{ + ext2fs_generic_bitmap bitmap; + errcode_t retval; + size_t size; + + retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap), + &bitmap); + if (retval) + return retval; + + bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; + bitmap->fs = NULL; + bitmap->start = start; + bitmap->end = end; + bitmap->real_end = real_end; + bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK; + if (descr) { + retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description); + if (retval) { + ext2fs_free_mem(&bitmap); + return retval; + } + strcpy(bitmap->description, descr); + } else + bitmap->description = 0; + + size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1); + retval = ext2fs_get_mem(size, &bitmap->bitmap); + if (retval) { + ext2fs_free_mem(&bitmap->description); + ext2fs_free_mem(&bitmap); + return retval; + } + + if (init_map) + memcpy(bitmap->bitmap, init_map, size); + else + memset(bitmap->bitmap, 0, size); + *ret = bitmap; + return 0; +} + +errcode_t ext2fs_allocate_generic_bitmap(__u32 start, + __u32 end, + __u32 real_end, + const char *descr, + ext2fs_generic_bitmap *ret) +{ + return make_bitmap(start, end, real_end, descr, 0, ret); +} + +errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, + ext2fs_generic_bitmap *dest) +{ + errcode_t retval; + ext2fs_generic_bitmap new_map; + + retval = make_bitmap(src->start, src->end, src->real_end, + src->description, src->bitmap, &new_map); + if (retval) + return retval; + new_map->magic = src->magic; + new_map->fs = src->fs; + new_map->base_error_code = src->base_error_code; + *dest = new_map; + return 0; +} + +void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map) +{ + __u32 i, j; + + for (i=map->end+1, j = i - map->start; i <= map->real_end; i++, j++) + ext2fs_set_bit(j, map->bitmap); + + return; +} + +errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, + const char *descr, + ext2fs_inode_bitmap *ret) +{ + ext2fs_inode_bitmap bitmap; + errcode_t retval; + __u32 start, end, real_end; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + fs->write_bitmaps = ext2fs_write_bitmaps; + + start = 1; + end = fs->super->s_inodes_count; + real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count); + + retval = ext2fs_allocate_generic_bitmap(start, end, real_end, + descr, &bitmap); + if (retval) + return retval; + + bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP; + bitmap->fs = fs; + bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK; + + *ret = bitmap; + return 0; +} + +errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, + const char *descr, + ext2fs_block_bitmap *ret) +{ + ext2fs_block_bitmap bitmap; + errcode_t retval; + __u32 start, end, real_end; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + fs->write_bitmaps = ext2fs_write_bitmaps; + + start = fs->super->s_first_data_block; + end = fs->super->s_blocks_count-1; + real_end = (EXT2_BLOCKS_PER_GROUP(fs->super) + * fs->group_desc_count)-1 + start; + + retval = ext2fs_allocate_generic_bitmap(start, end, real_end, + descr, &bitmap); + if (retval) + return retval; + + bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP; + bitmap->fs = fs; + bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK; + + *ret = bitmap; + return 0; +} + +errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap, + ext2_ino_t end, ext2_ino_t *oend) +{ + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP); + + if (end > bitmap->real_end) + return EXT2_ET_FUDGE_INODE_BITMAP_END; + if (oend) + *oend = bitmap->end; + bitmap->end = end; + return 0; +} + +errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap, + blk_t end, blk_t *oend) +{ + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP); + + if (end > bitmap->real_end) + return EXT2_ET_FUDGE_BLOCK_BITMAP_END; + if (oend) + *oend = bitmap->end; + bitmap->end = end; + return 0; +} + +void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap) +{ + if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP)) + return; + + memset(bitmap->bitmap, 0, + (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1)); +} + +void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap) +{ + if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP)) + return; + + memset(bitmap->bitmap, 0, + (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1)); +} diff -Naur silo-1.4.14.orig/libext2fs/bitops.c silo-1.4.14/libext2fs/bitops.c --- silo-1.4.14.orig/libext2fs/bitops.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/bitops.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,91 @@ +/* + * bitops.c --- Bitmap frobbing code. See bitops.h for the inlined + * routines. + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#ifndef _EXT2_HAVE_ASM_BITOPS_ + +/* + * 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. + * + * C language equivalents written by Theodore Ts'o, 9/26/92. + * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian + * systems, as well as non-32 bit systems. + */ + +int ext2fs_set_bit(unsigned int nr,void * addr) +{ + int mask, retval; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + retval = mask & *ADDR; + *ADDR |= mask; + return retval; +} + +int ext2fs_clear_bit(unsigned int nr, void * addr) +{ + int mask, retval; + unsigned char *ADDR = (unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + retval = mask & *ADDR; + *ADDR &= ~mask; + return retval; +} + +int ext2fs_test_bit(unsigned int nr, const void * addr) +{ + int mask; + const unsigned char *ADDR = (const unsigned char *) addr; + + ADDR += nr >> 3; + mask = 1 << (nr & 0x07); + return (mask & *ADDR); +} + +#endif /* !_EXT2_HAVE_ASM_BITOPS_ */ + +void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, + const char *description) +{ +#ifndef OMIT_COM_ERR + if (description) + com_err(0, errcode, "#%lu for %s", arg, description); + else + com_err(0, errcode, "#%lu", arg); +#endif +} + +void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap, + int code, unsigned long arg) +{ +#ifndef OMIT_COM_ERR + if (bitmap->description) + com_err(0, bitmap->base_error_code+code, + "#%lu for %s", arg, bitmap->description); + else + com_err(0, bitmap->base_error_code + code, "#%lu", arg); +#endif +} + diff -Naur silo-1.4.14.orig/libext2fs/bitops.h silo-1.4.14/libext2fs/bitops.h --- silo-1.4.14.orig/libext2fs/bitops.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/bitops.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,617 @@ +/* + * bitops.h --- Bitmap frobbing code. The byte swapping routines are + * also included here. + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * i386 bitops operations taken from , Copyright 1992, + * Linus Torvalds. + */ + + +extern int ext2fs_set_bit(unsigned int nr,void * addr); +extern int ext2fs_clear_bit(unsigned int nr, void * addr); +extern int ext2fs_test_bit(unsigned int nr, const void * addr); +extern __u16 ext2fs_swab16(__u16 val); +extern __u32 ext2fs_swab32(__u32 val); + +#ifdef WORDS_BIGENDIAN +#define ext2fs_cpu_to_le32(x) ext2fs_swab32((x)) +#define ext2fs_le32_to_cpu(x) ext2fs_swab32((x)) +#define ext2fs_cpu_to_le16(x) ext2fs_swab16((x)) +#define ext2fs_le16_to_cpu(x) ext2fs_swab16((x)) +#define ext2fs_cpu_to_be32(x) ((__u32)(x)) +#define ext2fs_be32_to_cpu(x) ((__u32)(x)) +#define ext2fs_cpu_to_be16(x) ((__u16)(x)) +#define ext2fs_be16_to_cpu(x) ((__u16)(x)) +#else +#define ext2fs_cpu_to_le32(x) ((__u32)(x)) +#define ext2fs_le32_to_cpu(x) ((__u32)(x)) +#define ext2fs_cpu_to_le16(x) ((__u16)(x)) +#define ext2fs_le16_to_cpu(x) ((__u16)(x)) +#define ext2fs_cpu_to_be32(x) ext2fs_swab32((x)) +#define ext2fs_be32_to_cpu(x) ext2fs_swab32((x)) +#define ext2fs_cpu_to_be16(x) ext2fs_swab16((x)) +#define ext2fs_be16_to_cpu(x) ext2fs_swab16((x)) +#endif + +/* + * 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(errcode_t errcode, unsigned long arg, + const char *description); +extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap, + int code, unsigned long arg); + +extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block); +extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block); +extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block); + +extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode); +extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode); + +extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block); +extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block); +extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block); + +extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode); +extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap); +extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap); +extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap); +extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap); + +extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num); +extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map); + +/* These two routines moved to gen_bitmap.c */ +extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, + __u32 bitno); +extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, + blk_t bitno); +/* + * The inline routines themselves... + * + * If NO_INLINE_FUNCS is defined, then we won't try to do inline + * functions at all; they will be included as normal functions in + * inline.c + */ +#ifdef NO_INLINE_FUNCS +#if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__mc68000__) || \ + defined(__sparc__))) + /* This prevents bitops.c from trying to include the C */ + /* function version of these functions */ +#define _EXT2_HAVE_ASM_BITOPS_ +#endif +#endif /* NO_INLINE_FUNCS */ + +#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) +#ifdef INCLUDE_INLINE_FUNCS +#define _INLINE_ extern +#else +#ifdef __GNUC__ +#define _INLINE_ extern __inline__ +#else /* For Watcom C */ +#define _INLINE_ extern inline +#endif +#endif + +#if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \ + (defined(__i386__) || defined(__i486__) || defined(__i586__))) + +#define _EXT2_HAVE_ASM_BITOPS_ +#define _EXT2_HAVE_ASM_SWAB_ +#define _EXT2_HAVE_ASM_FINDBIT_ + +/* + * 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 EXT2FS_ADDR (*(struct __dummy_h *) addr) +#define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr) + +_INLINE_ int ext2fs_set_bit(unsigned int nr, void * addr) +{ + int oldbit; + + __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (EXT2FS_ADDR) + :"r" (nr)); + return oldbit; +} + +_INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr) +{ + int oldbit; + + __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (EXT2FS_ADDR) + :"r" (nr)); + return oldbit; +} + +_INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr) +{ + int oldbit; + + __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit) + :"m" (EXT2FS_CONST_ADDR),"r" (nr)); + return oldbit; +} + +#if 0 +_INLINE_ int ext2fs_find_first_bit_set(void * addr, unsigned size) +{ + int d0, d1, d2; + int res; + + if (!size) + return 0; + /* This looks at memory. Mark it volatile to tell gcc not to move it around */ + __asm__ __volatile__( + "cld\n\t" + "xorl %%eax,%%eax\n\t" + "xorl %%edx,%%edx\n\t" + "repe; scasl\n\t" + "je 1f\n\t" + "movl -4(%%edi),%%eax\n\t" + "subl $4,%%edi\n\t" + "bsfl %%eax,%%edx\n" + "1:\tsubl %%esi,%%edi\n\t" + "shll $3,%%edi\n\t" + "addl %%edi,%%edx" + :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) + :"1" ((size + 31) >> 5), "2" (addr), "S" (addr)); + return res; +} + +_INLINE_ int ext2fs_find_next_bit_set (void * addr, int size, int offset) +{ + unsigned long * p = ((unsigned long *) addr) + (offset >> 5); + int set = 0, bit = offset & 31, res; + + if (bit) { + /* + * Look for zero in first byte + */ + __asm__("bsfl %1,%0\n\t" + "jne 1f\n\t" + "movl $32, %0\n" + "1:" + : "=r" (set) + : "r" (*p >> bit)); + if (set < (32 - bit)) + return set + offset; + set = 32 - bit; + p++; + } + /* + * No bit found yet, search remaining full bytes for a bit + */ + res = ext2fs_find_first_bit_set(p, size - 32 * (p - (unsigned long *) addr)); + return (offset + set + res); +} +#endif + +#ifdef EXT2FS_ENABLE_SWAPFS +_INLINE_ __u32 ext2fs_swab32(__u32 val) +{ +#ifdef EXT2FS_REQUIRE_486 + __asm__("bswap %0" : "=r" (val) : "0" (val)); +#else + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ + "rorl $16,%0\n\t" /* swap words */ + "xchgb %b0,%h0" /* swap higher bytes */ + :"=q" (val) + : "0" (val)); +#endif + return val; +} + +_INLINE_ __u16 ext2fs_swab16(__u16 val) +{ + __asm__("xchgb %b0,%h0" /* swap bytes */ \ + : "=q" (val) \ + : "0" (val)); \ + return val; +} +#endif + +#undef EXT2FS_ADDR + +#endif /* i386 */ + +#ifdef __mc68000__ + +#define _EXT2_HAVE_ASM_BITOPS_ + +_INLINE_ int ext2fs_set_bit(unsigned int nr,void * addr) +{ + char retval; + + __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0" + : "=d" (retval) : "d" (nr^7), "a" (addr)); + + return retval; +} + +_INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr) +{ + char retval; + + __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0" + : "=d" (retval) : "d" (nr^7), "a" (addr)); + + return retval; +} + +_INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr) +{ + char retval; + + __asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0" + : "=d" (retval) : "d" (nr^7), "a" (addr)); + + return retval; +} + +#endif /* __mc68000__ */ + + +#if !defined(_EXT2_HAVE_ASM_SWAB_) && defined(EXT2FS_ENABLE_SWAPFS) + +_INLINE_ __u16 ext2fs_swab16(__u16 val) +{ + return (val >> 8) | (val << 8); +} + +_INLINE_ __u32 ext2fs_swab32(__u32 val) +{ + return ((val>>24) | ((val>>8)&0xFF00) | + ((val<<8)&0xFF0000) | (val<<24)); +} + +#endif /* !_EXT2_HAVE_ASM_SWAB */ + +#if !defined(_EXT2_HAVE_ASM_FINDBIT_) +_INLINE_ int ext2fs_find_first_bit_set(void * addr, unsigned size) +{ + char *cp = (unsigned char *) addr; + int res = 0, d0; + + if (!size) + return 0; + + while ((size > res) && (*cp == 0)) { + cp++; + res += 8; + } + d0 = ffs(*cp); + if (d0 == 0) + return size; + + return res + d0 - 1; +} + +_INLINE_ int ext2fs_find_next_bit_set (void * addr, int size, int offset) +{ + unsigned char * p; + int set = 0, bit = offset & 7, res = 0, d0; + + res = offset >> 3; + p = ((unsigned char *) addr) + res; + + if (bit) { + set = ffs(*p & ~((1 << bit) - 1)); + if (set) + return (offset & ~7) + set - 1; + p++; + res += 8; + } + while ((size > res) && (*p == 0)) { + p++; + res += 8; + } + d0 = ffs(*p); + if (d0 == 0) + return size; + + return (res + d0 - 1); +} +#endif + +_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, + blk_t bitno); + +_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, + blk_t bitno) +{ + if ((bitno < bitmap->start) || (bitno > bitmap->end)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno); + return 0; + } + return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap); +} + +_INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ + return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) + bitmap, + block); +} + +_INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ + return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, + block); +} + +_INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, + block); +} + +_INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ + return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, + inode); +} + +_INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ +#ifdef EXT2FS_DEBUG_FAST_OPS + if ((block < bitmap->start) || (block > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, + bitmap->description); + return; + } +#endif + ext2fs_set_bit(block - bitmap->start, bitmap->bitmap); +} + +_INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ +#ifdef EXT2FS_DEBUG_FAST_OPS + if ((block < bitmap->start) || (block > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, + block, bitmap->description); + return; + } +#endif + ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap); +} + +_INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap, + blk_t block) +{ +#ifdef EXT2FS_DEBUG_FAST_OPS + if ((block < bitmap->start) || (block > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, + block, bitmap->description); + return 0; + } +#endif + return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap); +} + +_INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ +#ifdef EXT2FS_DEBUG_FAST_OPS + if ((inode < bitmap->start) || (inode > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK, + inode, bitmap->description); + return; + } +#endif + ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap); +} + +_INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ +#ifdef EXT2FS_DEBUG_FAST_OPS + if ((inode < bitmap->start) || (inode > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK, + inode, bitmap->description); + return; + } +#endif + ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap); +} + +_INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap, + ext2_ino_t inode) +{ +#ifdef EXT2FS_DEBUG_FAST_OPS + if ((inode < bitmap->start) || (inode > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST, + inode, bitmap->description); + return 0; + } +#endif + return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap); +} + +_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap) +{ + return bitmap->start; +} + +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap) +{ + return bitmap->start; +} + +_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap) +{ + return bitmap->end; +} + +_INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap) +{ + return bitmap->end; +} + +_INLINE_ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + int i; + + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, + block, bitmap->description); + return 0; + } + for (i=0; i < num; i++) { + if (ext2fs_fast_test_block_bitmap(bitmap, block+i)) + return 0; + } + return 1; +} + +_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + int i; + +#ifdef EXT2FS_DEBUG_FAST_OPS + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, + block, bitmap->description); + return 0; + } +#endif + for (i=0; i < num; i++) { + if (ext2fs_fast_test_block_bitmap(bitmap, block+i)) + return 0; + } + return 1; +} + +_INLINE_ void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + int i; + + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, + bitmap->description); + return; + } + for (i=0; i < num; i++) + ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap); +} + +_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + int i; + +#ifdef EXT2FS_DEBUG_FAST_OPS + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, + bitmap->description); + return; + } +#endif + for (i=0; i < num; i++) + ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap); +} + +_INLINE_ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + int i; + + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, + bitmap->description); + return; + } + for (i=0; i < num; i++) + ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap); +} + +_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, + blk_t block, int num) +{ + int i; + +#ifdef EXT2FS_DEBUG_FAST_OPS + if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, + bitmap->description); + return; + } +#endif + for (i=0; i < num; i++) + ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap); +} +#undef _INLINE_ +#endif + diff -Naur silo-1.4.14.orig/libext2fs/block.c silo-1.4.14/libext2fs/block.c --- silo-1.4.14.orig/libext2fs/block.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/block.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,437 @@ +/* + * block.c --- iterate over all blocks in an inode + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct block_context { + ext2_filsys fs; + int (*func)(ext2_filsys fs, + blk_t *blocknr, + e2_blkcnt_t bcount, + blk_t ref_blk, + int ref_offset, + void *priv_data); + e2_blkcnt_t bcount; + int bsize; + int flags; + errcode_t errcode; + char *ind_buf; + char *dind_buf; + char *tind_buf; + void *priv_data; +}; + +static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, + int ref_offset, struct block_context *ctx) +{ + int ret = 0, changed = 0; + int i, flags, limit, offset; + blk_t *block_nr; + + limit = ctx->fs->blocksize >> 2; + if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && + !(ctx->flags & BLOCK_FLAG_DATA_ONLY)) + ret = (*ctx->func)(ctx->fs, ind_block, + BLOCK_COUNT_IND, ref_block, + ref_offset, ctx->priv_data); + if (!*ind_block || (ret & BLOCK_ABORT)) { + ctx->bcount += limit; + return ret; + } + if (*ind_block >= ctx->fs->super->s_blocks_count || + *ind_block < ctx->fs->super->s_first_data_block) { + ctx->errcode = EXT2_ET_BAD_IND_BLOCK; + ret |= BLOCK_ERROR; + return ret; + } + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block, + ctx->ind_buf); + if (ctx->errcode) { + ret |= BLOCK_ERROR; + return ret; + } + + block_nr = (blk_t *) ctx->ind_buf; + offset = 0; + if (ctx->flags & BLOCK_FLAG_APPEND) { + for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { + flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount, + *ind_block, offset, + ctx->priv_data); + changed |= flags; + if (flags & BLOCK_ABORT) { + ret |= BLOCK_ABORT; + break; + } + offset += sizeof(blk_t); + } + } else { + for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { + if (*block_nr == 0) + continue; + flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount, + *ind_block, offset, + ctx->priv_data); + changed |= flags; + if (flags & BLOCK_ABORT) { + ret |= BLOCK_ABORT; + break; + } + offset += sizeof(blk_t); + } + } + if (changed & BLOCK_CHANGED) { + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block, + ctx->ind_buf); + if (ctx->errcode) + ret |= BLOCK_ERROR | BLOCK_ABORT; + } + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && + !(ret & BLOCK_ABORT)) + ret |= (*ctx->func)(ctx->fs, ind_block, + BLOCK_COUNT_IND, ref_block, + ref_offset, ctx->priv_data); + return ret; +} + +static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, + int ref_offset, struct block_context *ctx) +{ + int ret = 0, changed = 0; + int i, flags, limit, offset; + blk_t *block_nr; + + limit = ctx->fs->blocksize >> 2; + if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | + BLOCK_FLAG_DATA_ONLY))) + ret = (*ctx->func)(ctx->fs, dind_block, + BLOCK_COUNT_DIND, ref_block, + ref_offset, ctx->priv_data); + if (!*dind_block || (ret & BLOCK_ABORT)) { + ctx->bcount += limit*limit; + return ret; + } + if (*dind_block >= ctx->fs->super->s_blocks_count || + *dind_block < ctx->fs->super->s_first_data_block) { + ctx->errcode = EXT2_ET_BAD_DIND_BLOCK; + ret |= BLOCK_ERROR; + return ret; + } + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block, + ctx->dind_buf); + if (ctx->errcode) { + ret |= BLOCK_ERROR; + return ret; + } + + block_nr = (blk_t *) ctx->dind_buf; + offset = 0; + if (ctx->flags & BLOCK_FLAG_APPEND) { + for (i = 0; i < limit; i++, block_nr++) { + flags = block_iterate_ind(block_nr, + *dind_block, offset, + ctx); + changed |= flags; + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); + break; + } + offset += sizeof(blk_t); + } + } else { + for (i = 0; i < limit; i++, block_nr++) { + if (*block_nr == 0) { + ctx->bcount += limit; + continue; + } + flags = block_iterate_ind(block_nr, + *dind_block, offset, + ctx); + changed |= flags; + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); + break; + } + offset += sizeof(blk_t); + } + } + if (changed & BLOCK_CHANGED) { + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block, + ctx->dind_buf); + if (ctx->errcode) + ret |= BLOCK_ERROR | BLOCK_ABORT; + } + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && + !(ret & BLOCK_ABORT)) + ret |= (*ctx->func)(ctx->fs, dind_block, + BLOCK_COUNT_DIND, ref_block, + ref_offset, ctx->priv_data); + return ret; +} + +static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, + int ref_offset, struct block_context *ctx) +{ + int ret = 0, changed = 0; + int i, flags, limit, offset; + blk_t *block_nr; + + limit = ctx->fs->blocksize >> 2; + if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | + BLOCK_FLAG_DATA_ONLY))) + ret = (*ctx->func)(ctx->fs, tind_block, + BLOCK_COUNT_TIND, ref_block, + ref_offset, ctx->priv_data); + if (!*tind_block || (ret & BLOCK_ABORT)) { + ctx->bcount += limit*limit*limit; + return ret; + } + if (*tind_block >= ctx->fs->super->s_blocks_count || + *tind_block < ctx->fs->super->s_first_data_block) { + ctx->errcode = EXT2_ET_BAD_TIND_BLOCK; + ret |= BLOCK_ERROR; + return ret; + } + ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block, + ctx->tind_buf); + if (ctx->errcode) { + ret |= BLOCK_ERROR; + return ret; + } + + block_nr = (blk_t *) ctx->tind_buf; + offset = 0; + if (ctx->flags & BLOCK_FLAG_APPEND) { + for (i = 0; i < limit; i++, block_nr++) { + flags = block_iterate_dind(block_nr, + *tind_block, + offset, ctx); + changed |= flags; + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); + break; + } + offset += sizeof(blk_t); + } + } else { + for (i = 0; i < limit; i++, block_nr++) { + if (*block_nr == 0) { + ctx->bcount += limit*limit; + continue; + } + flags = block_iterate_dind(block_nr, + *tind_block, + offset, ctx); + changed |= flags; + if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { + ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); + break; + } + offset += sizeof(blk_t); + } + } + if (changed & BLOCK_CHANGED) { + ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block, + ctx->tind_buf); + if (ctx->errcode) + ret |= BLOCK_ERROR | BLOCK_ABORT; + } + if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && + !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && + !(ret & BLOCK_ABORT)) + ret |= (*ctx->func)(ctx->fs, tind_block, + BLOCK_COUNT_TIND, ref_block, + ref_offset, ctx->priv_data); + + return ret; +} + +errcode_t ext2fs_block_iterate2(ext2_filsys fs, + ext2_ino_t ino, + int flags, + char *block_buf, + int (*func)(ext2_filsys fs, + blk_t *blocknr, + e2_blkcnt_t blockcnt, + blk_t ref_blk, + int ref_offset, + void *priv_data), + void *priv_data) +{ + int i; + int got_inode = 0; + int ret = 0; + blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */ + struct ext2_inode inode; + errcode_t retval; + struct block_context ctx; + int limit; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + /* + * Check to see if we need to limit large files + */ + if (flags & BLOCK_FLAG_NO_LARGE) { + ctx.errcode = ext2fs_read_inode(fs, ino, &inode); + if (ctx.errcode) + return ctx.errcode; + got_inode = 1; + if (!LINUX_S_ISDIR(inode.i_mode) && + (inode.i_size_high != 0)) + return EXT2_ET_FILE_TOO_BIG; + } + + retval = ext2fs_get_blocks(fs, ino, blocks); + if (retval) + return retval; + + limit = fs->blocksize >> 2; + + ctx.fs = fs; + ctx.func = func; + ctx.priv_data = priv_data; + ctx.flags = flags; + ctx.bcount = 0; + if (block_buf) { + ctx.ind_buf = block_buf; + } else { + retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf); + if (retval) + return retval; + } + ctx.dind_buf = ctx.ind_buf + fs->blocksize; + ctx.tind_buf = ctx.dind_buf + fs->blocksize; + + /* + * Iterate over the HURD translator block (if present) + */ + if ((fs->super->s_creator_os == EXT2_OS_HURD) && + !(flags & BLOCK_FLAG_DATA_ONLY)) { + ctx.errcode = ext2fs_read_inode(fs, ino, &inode); + if (ctx.errcode) + goto abort_exit; + got_inode = 1; + if (inode.osd1.hurd1.h_i_translator) { + ret |= (*ctx.func)(fs, + &inode.osd1.hurd1.h_i_translator, + BLOCK_COUNT_TRANSLATOR, + 0, 0, priv_data); + if (ret & BLOCK_ABORT) + goto abort_exit; + } + } + + /* + * Iterate over normal data blocks + */ + for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) { + if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) { + ret |= (*ctx.func)(fs, &blocks[i], + ctx.bcount, 0, i, priv_data); + if (ret & BLOCK_ABORT) + goto abort_exit; + } + } + if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { + ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK, + 0, EXT2_IND_BLOCK, &ctx); + if (ret & BLOCK_ABORT) + goto abort_exit; + } else + ctx.bcount += limit; + if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { + ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK, + 0, EXT2_DIND_BLOCK, &ctx); + if (ret & BLOCK_ABORT) + goto abort_exit; + } else + ctx.bcount += limit * limit; + if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { + ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK, + 0, EXT2_TIND_BLOCK, &ctx); + if (ret & BLOCK_ABORT) + goto abort_exit; + } + +abort_exit: + if (ret & BLOCK_CHANGED) { + if (!got_inode) { + 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) + ext2fs_free_mem(&ctx.ind_buf); + + return (ret & BLOCK_ERROR) ? ctx.errcode : 0; +} + +/* + * Emulate the old ext2fs_block_iterate function! + */ + +struct xlate { + int (*func)(ext2_filsys fs, + blk_t *blocknr, + int bcount, + void *priv_data); + void *real_private; +}; + +#ifdef __TURBOC__ + #pragma argsused +#endif +static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt, + blk_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct xlate *xl = (struct xlate *) priv_data; + + return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private); +} + +errcode_t ext2fs_block_iterate(ext2_filsys fs, + ext2_ino_t ino, + int flags, + char *block_buf, + int (*func)(ext2_filsys fs, + blk_t *blocknr, + int blockcnt, + void *priv_data), + void *priv_data) +{ + struct xlate xl; + + xl.real_private = priv_data; + xl.func = func; + + return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags, + block_buf, xlate_func, &xl); +} + diff -Naur silo-1.4.14.orig/libext2fs/bmap.c silo-1.4.14/libext2fs/bmap.c --- silo-1.4.14.orig/libext2fs/bmap.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/bmap.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,270 @@ +/* + * bmap.c --- logical to physical block mapping + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#if defined(__GNUC__) && !defined(NO_INLINE_FUNCS) +#define _BMAP_INLINE_ __inline__ +#else +#define _BMAP_INLINE_ +#endif + +extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + char *block_buf, int bmap_flags, + blk_t block, blk_t *phys_blk); + +#define inode_bmap(inode, nr) ((inode)->i_block[(nr)]) + +static _BMAP_INLINE_ errcode_t block_ind_bmap(ext2_filsys fs, int flags, + blk_t ind, char *block_buf, + int *blocks_alloc, + blk_t nr, blk_t *ret_blk) +{ + errcode_t retval; + blk_t b; + + if (!ind) { + if (flags & BMAP_SET) + return EXT2_ET_SET_BMAP_NO_IND; + *ret_blk = 0; + return 0; + } + retval = io_channel_read_blk(fs->io, ind, 1, block_buf); + if (retval) + return retval; + + if (flags & BMAP_SET) { + b = *ret_blk; +#ifdef EXT2FS_ENABLE_SWAPFS + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) + b = ext2fs_swab32(b); +#endif + ((blk_t *) block_buf)[nr] = b; + return io_channel_write_blk(fs->io, ind, 1, block_buf); + } + + b = ((blk_t *) block_buf)[nr]; + +#ifdef EXT2FS_ENABLE_SWAPFS + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) + b = ext2fs_swab32(b); +#endif + + if (!b && (flags & BMAP_ALLOC)) { + b = nr ? ((blk_t *) block_buf)[nr-1] : 0; + retval = ext2fs_alloc_block(fs, b, + block_buf + fs->blocksize, &b); + if (retval) + return retval; + +#ifdef EXT2FS_ENABLE_SWAPFS + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) + ((blk_t *) block_buf)[nr] = ext2fs_swab32(b); + else +#endif + ((blk_t *) block_buf)[nr] = b; + + retval = io_channel_write_blk(fs->io, ind, 1, block_buf); + if (retval) + return retval; + + (*blocks_alloc)++; + } + + *ret_blk = b; + return 0; +} + +static _BMAP_INLINE_ errcode_t block_dind_bmap(ext2_filsys fs, int flags, + blk_t dind, char *block_buf, + int *blocks_alloc, + blk_t nr, blk_t *ret_blk) +{ + blk_t b; + errcode_t retval; + blk_t addr_per_block; + + addr_per_block = (blk_t) fs->blocksize >> 2; + + retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf, + blocks_alloc, nr / addr_per_block, &b); + if (retval) + return retval; + retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, + nr % addr_per_block, ret_blk); + return retval; +} + +static _BMAP_INLINE_ errcode_t block_tind_bmap(ext2_filsys fs, int flags, + blk_t tind, char *block_buf, + int *blocks_alloc, + blk_t nr, blk_t *ret_blk) +{ + blk_t b; + errcode_t retval; + blk_t addr_per_block; + + addr_per_block = (blk_t) fs->blocksize >> 2; + + retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf, + blocks_alloc, nr / addr_per_block, &b); + if (retval) + return retval; + retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, + nr % addr_per_block, ret_blk); + return retval; +} + +errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, + char *block_buf, int bmap_flags, blk_t block, + blk_t *phys_blk) +{ + struct ext2_inode inode_buf; + blk_t addr_per_block; + blk_t b; + char *buf = 0; + errcode_t retval = 0; + int blocks_alloc = 0, inode_dirty = 0; + + if (!(bmap_flags & BMAP_SET)) + *phys_blk = 0; + + /* Read inode structure if necessary */ + if (!inode) { + retval = ext2fs_read_inode(fs, ino, &inode_buf); + if (retval) + return retval; + inode = &inode_buf; + } + addr_per_block = (blk_t) fs->blocksize >> 2; + + if (!block_buf) { + retval = ext2fs_get_mem(fs->blocksize * 2, &buf); + if (retval) + return retval; + block_buf = buf; + } + + if (block < EXT2_NDIR_BLOCKS) { + if (bmap_flags & BMAP_SET) { + b = *phys_blk; +#ifdef EXT2FS_ENABLE_SWAPFS + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) + b = ext2fs_swab32(b); +#endif + inode_bmap(inode, block) = b; + inode_dirty++; + goto done; + } + + *phys_blk = inode_bmap(inode, block); + b = block ? inode_bmap(inode, block-1) : 0; + + if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) { + retval = ext2fs_alloc_block(fs, b, block_buf, &b); + if (retval) + goto done; + inode_bmap(inode, block) = b; + blocks_alloc++; + *phys_blk = b; + } + goto done; + } + + /* Indirect block */ + block -= EXT2_NDIR_BLOCKS; + if (block < addr_per_block) { + b = inode_bmap(inode, EXT2_IND_BLOCK); + if (!b) { + if (!(bmap_flags & BMAP_ALLOC)) { + if (bmap_flags & BMAP_SET) + retval = EXT2_ET_SET_BMAP_NO_IND; + goto done; + } + + b = inode_bmap(inode, EXT2_IND_BLOCK-1); + retval = ext2fs_alloc_block(fs, b, block_buf, &b); + if (retval) + goto done; + inode_bmap(inode, EXT2_IND_BLOCK) = b; + blocks_alloc++; + } + retval = block_ind_bmap(fs, bmap_flags, b, block_buf, + &blocks_alloc, block, phys_blk); + goto done; + } + + /* Doubly indirect block */ + block -= addr_per_block; + if (block < addr_per_block * addr_per_block) { + b = inode_bmap(inode, EXT2_DIND_BLOCK); + if (!b) { + if (!(bmap_flags & BMAP_ALLOC)) { + if (bmap_flags & BMAP_SET) + retval = EXT2_ET_SET_BMAP_NO_IND; + goto done; + } + + b = inode_bmap(inode, EXT2_IND_BLOCK); + retval = ext2fs_alloc_block(fs, b, block_buf, &b); + if (retval) + goto done; + inode_bmap(inode, EXT2_DIND_BLOCK) = b; + blocks_alloc++; + } + retval = block_dind_bmap(fs, bmap_flags, b, block_buf, + &blocks_alloc, block, phys_blk); + goto done; + } + + /* Triply indirect block */ + block -= addr_per_block * addr_per_block; + b = inode_bmap(inode, EXT2_TIND_BLOCK); + if (!b) { + if (!(bmap_flags & BMAP_ALLOC)) { + if (bmap_flags & BMAP_SET) + retval = EXT2_ET_SET_BMAP_NO_IND; + goto done; + } + + b = inode_bmap(inode, EXT2_DIND_BLOCK); + retval = ext2fs_alloc_block(fs, b, block_buf, &b); + if (retval) + goto done; + inode_bmap(inode, EXT2_TIND_BLOCK) = b; + blocks_alloc++; + } + retval = block_tind_bmap(fs, bmap_flags, b, block_buf, + &blocks_alloc, block, phys_blk); +done: + if (buf) + ext2fs_free_mem(&buf); + if ((retval == 0) && (blocks_alloc || inode_dirty)) { + inode->i_blocks += (blocks_alloc * fs->blocksize) / 512; + retval = ext2fs_write_inode(fs, ino, inode); + } + return retval; +} + + + diff -Naur silo-1.4.14.orig/libext2fs/bmove.c silo-1.4.14/libext2fs/bmove.c --- silo-1.4.14.orig/libext2fs/bmove.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/bmove.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,160 @@ +/* + * bmove.c --- Move blocks around to make way for a particular + * filesystem structure. + * + * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_TIME_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +struct process_block_struct { + ext2_ino_t ino; + struct ext2_inode * inode; + ext2fs_block_bitmap reserve; + ext2fs_block_bitmap alloc_map; + errcode_t error; + char *buf; + int add_dir; + int flags; +}; + +static int process_block(ext2_filsys fs, blk_t *block_nr, + e2_blkcnt_t blockcnt, blk_t ref_block, + int ref_offset, void *priv_data) +{ + struct process_block_struct *pb; + errcode_t retval; + int ret; + blk_t block, orig; + + pb = (struct process_block_struct *) priv_data; + block = orig = *block_nr; + ret = 0; + + /* + * Let's see if this is one which we need to relocate + */ + if (ext2fs_test_block_bitmap(pb->reserve, block)) { + do { + if (++block >= fs->super->s_blocks_count) + block = fs->super->s_first_data_block; + if (block == orig) { + pb->error = EXT2_ET_BLOCK_ALLOC_FAIL; + return BLOCK_ABORT; + } + } while (ext2fs_test_block_bitmap(pb->reserve, block) || + ext2fs_test_block_bitmap(pb->alloc_map, block)); + + retval = io_channel_read_blk(fs->io, orig, 1, pb->buf); + if (retval) { + pb->error = retval; + return BLOCK_ABORT; + } + retval = io_channel_write_blk(fs->io, block, 1, pb->buf); + if (retval) { + pb->error = retval; + return BLOCK_ABORT; + } + *block_nr = block; + ext2fs_mark_block_bitmap(pb->alloc_map, block); + ret = BLOCK_CHANGED; + if (pb->flags & EXT2_BMOVE_DEBUG) + printf("ino=%ld, blockcnt=%lld, %d->%d\n", pb->ino, + blockcnt, orig, block); + } + if (pb->add_dir) { + retval = ext2fs_add_dir_block(fs->dblist, pb->ino, + block, (int) blockcnt); + if (retval) { + pb->error = retval; + ret |= BLOCK_ABORT; + } + } + return ret; +} + +errcode_t ext2fs_move_blocks(ext2_filsys fs, + ext2fs_block_bitmap reserve, + ext2fs_block_bitmap alloc_map, + int flags) +{ + ext2_ino_t ino; + struct ext2_inode inode; + errcode_t retval; + struct process_block_struct pb; + ext2_inode_scan scan; + char *block_buf; + + retval = ext2fs_open_inode_scan(fs, 0, &scan); + if (retval) + return retval; + + pb.reserve = reserve; + pb.error = 0; + pb.alloc_map = alloc_map ? alloc_map : fs->block_map; + pb.flags = flags; + + retval = ext2fs_get_mem(fs->blocksize * 4, &block_buf); + if (retval) + return retval; + pb.buf = block_buf + fs->blocksize * 3; + + /* + * If GET_DBLIST is set in the flags field, then we should + * gather directory block information while we're doing the + * block move. + */ + if (flags & EXT2_BMOVE_GET_DBLIST) { + if (fs->dblist) { + ext2fs_free_dblist(fs->dblist); + fs->dblist = NULL; + } + retval = ext2fs_init_dblist(fs, 0); + if (retval) + return retval; + } + + retval = ext2fs_get_next_inode(scan, &ino, &inode); + if (retval) + return retval; + + while (ino) { + if ((inode.i_links_count == 0) || + !ext2fs_inode_has_valid_blocks(&inode)) + goto next; + + pb.ino = ino; + pb.inode = &inode; + + pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) && + flags & EXT2_BMOVE_GET_DBLIST); + + retval = ext2fs_block_iterate2(fs, ino, 0, block_buf, + process_block, &pb); + if (retval) + return retval; + if (pb.error) + return pb.error; + + next: + retval = ext2fs_get_next_inode(scan, &ino, &inode); + if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) + goto next; + } + return 0; +} + diff -Naur silo-1.4.14.orig/libext2fs/brel.h silo-1.4.14/libext2fs/brel.h --- silo-1.4.14.orig/libext2fs/brel.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/brel.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,86 @@ +/* + * brel.h + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +struct ext2_block_relocate_entry { + blk_t new; + __s16 offset; + __u16 flags; + union { + blk_t block_ref; + ext2_ino_t inode_ref; + } owner; +}; + +#define RELOCATE_TYPE_REF 0x0007 +#define RELOCATE_BLOCK_REF 0x0001 +#define RELOCATE_INODE_REF 0x0002 + +typedef struct ext2_block_relocation_table *ext2_brel; + +struct ext2_block_relocation_table { + __u32 magic; + char *name; + blk_t current; + void *priv_data; + + /* + * Add a block relocation entry. + */ + errcode_t (*put)(ext2_brel brel, blk_t old, + struct ext2_block_relocate_entry *ent); + + /* + * Get a block relocation entry. + */ + errcode_t (*get)(ext2_brel brel, blk_t old, + struct ext2_block_relocate_entry *ent); + + /* + * Initialize for iterating over the block relocation entries. + */ + errcode_t (*start_iter)(ext2_brel brel); + + /* + * The iterator function for the inode relocation entries. + * Returns an inode number of 0 when out of entries. + */ + errcode_t (*next)(ext2_brel brel, blk_t *old, + struct ext2_block_relocate_entry *ent); + + /* + * Move the inode relocation table from one block number to + * another. + */ + errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new); + + /* + * Remove a block relocation entry. + */ + errcode_t (*delete)(ext2_brel brel, blk_t old); + + + /* + * Free the block relocation table. + */ + errcode_t (*free)(ext2_brel brel); +}; + +errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block, + ext2_brel *brel); + +#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent)) +#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent)) +#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel))) +#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent)) +#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new)) +#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old)) +#define ext2fs_brel_free(brel) ((brel)->free((brel))) + diff -Naur silo-1.4.14.orig/libext2fs/brel_ma.c silo-1.4.14/libext2fs/brel_ma.c --- silo-1.4.14.orig/libext2fs/brel_ma.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/brel_ma.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,197 @@ +/* + * brel_ma.c + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * TODO: rewrite to not use a direct array!!! (Fortunately this + * module isn't really used yet.) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "brel.h" + +static errcode_t bma_put(ext2_brel brel, blk_t old, + struct ext2_block_relocate_entry *ent); +static errcode_t bma_get(ext2_brel brel, blk_t old, + struct ext2_block_relocate_entry *ent); +static errcode_t bma_start_iter(ext2_brel brel); +static errcode_t bma_next(ext2_brel brel, blk_t *old, + struct ext2_block_relocate_entry *ent); +static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new); +static errcode_t bma_delete(ext2_brel brel, blk_t old); +static errcode_t bma_free(ext2_brel brel); + +struct brel_ma { + __u32 magic; + blk_t max_block; + struct ext2_block_relocate_entry *entries; +}; + +errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block, + ext2_brel *new_brel) +{ + ext2_brel brel = 0; + errcode_t retval; + struct brel_ma *ma = 0; + size_t size; + + *new_brel = 0; + + /* + * Allocate memory structures + */ + retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table), + &brel); + if (retval) + goto errout; + memset(brel, 0, sizeof(struct ext2_block_relocation_table)); + + retval = ext2fs_get_mem(strlen(name)+1, &brel->name); + if (retval) + goto errout; + strcpy(brel->name, name); + + retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma); + if (retval) + goto errout; + memset(ma, 0, sizeof(struct brel_ma)); + brel->priv_data = ma; + + size = (size_t) (sizeof(struct ext2_block_relocate_entry) * + (max_block+1)); + retval = ext2fs_get_mem(size, &ma->entries); + if (retval) + goto errout; + memset(ma->entries, 0, size); + ma->max_block = max_block; + + /* + * Fill in the brel data structure + */ + brel->put = bma_put; + brel->get = bma_get; + brel->start_iter = bma_start_iter; + brel->next = bma_next; + brel->move = bma_move; + brel->delete = bma_delete; + brel->free = bma_free; + + *new_brel = brel; + return 0; + +errout: + bma_free(brel); + return retval; +} + +static errcode_t bma_put(ext2_brel brel, blk_t old, + struct ext2_block_relocate_entry *ent) +{ + struct brel_ma *ma; + + ma = brel->priv_data; + if (old > ma->max_block) + return EXT2_ET_INVALID_ARGUMENT; + ma->entries[(unsigned)old] = *ent; + return 0; +} + +static errcode_t bma_get(ext2_brel brel, blk_t old, + struct ext2_block_relocate_entry *ent) +{ + struct brel_ma *ma; + + ma = brel->priv_data; + if (old > ma->max_block) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned)old].new == 0) + return ENOENT; + *ent = ma->entries[old]; + return 0; +} + +static errcode_t bma_start_iter(ext2_brel brel) +{ + brel->current = 0; + return 0; +} + +static errcode_t bma_next(ext2_brel brel, blk_t *old, + struct ext2_block_relocate_entry *ent) +{ + struct brel_ma *ma; + + ma = brel->priv_data; + while (++brel->current < ma->max_block) { + if (ma->entries[(unsigned)brel->current].new == 0) + continue; + *old = brel->current; + *ent = ma->entries[(unsigned)brel->current]; + return 0; + } + *old = 0; + return 0; +} + +static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new) +{ + struct brel_ma *ma; + + ma = brel->priv_data; + if ((old > ma->max_block) || (new > ma->max_block)) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned)old].new == 0) + return ENOENT; + ma->entries[(unsigned)new] = ma->entries[old]; + ma->entries[(unsigned)old].new = 0; + return 0; +} + +static errcode_t bma_delete(ext2_brel brel, blk_t old) +{ + struct brel_ma *ma; + + ma = brel->priv_data; + if (old > ma->max_block) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned)old].new == 0) + return ENOENT; + ma->entries[(unsigned)old].new = 0; + return 0; +} + +static errcode_t bma_free(ext2_brel brel) +{ + struct brel_ma *ma; + + if (!brel) + return 0; + + ma = brel->priv_data; + + if (ma) { + if (ma->entries) + ext2fs_free_mem(&ma->entries); + ext2fs_free_mem(&ma); + } + if (brel->name) + ext2fs_free_mem(&brel->name); + ext2fs_free_mem(&brel); + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/check_desc.c silo-1.4.14/libext2fs/check_desc.c --- silo-1.4.14.orig/libext2fs/check_desc.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/check_desc.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,68 @@ +/* + * check_desc.c --- Check the group descriptors of an ext2 filesystem + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * This routine sanity checks the group descriptors + */ +errcode_t ext2fs_check_desc(ext2_filsys fs) +{ + dgrp_t i; + blk_t block = fs->super->s_first_data_block; + blk_t next; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + for (i = 0; i < fs->group_desc_count; i++) { + next = block + fs->super->s_blocks_per_group; + /* + * Check to make sure block bitmap for group is + * located within the group. + */ + if (fs->group_desc[i].bg_block_bitmap < block || + fs->group_desc[i].bg_block_bitmap >= next) + return EXT2_ET_GDESC_BAD_BLOCK_MAP; + /* + * Check to make sure inode bitmap for group is + * located within the group + */ + if (fs->group_desc[i].bg_inode_bitmap < block || + fs->group_desc[i].bg_inode_bitmap >= next) + return EXT2_ET_GDESC_BAD_INODE_MAP; + /* + * Check to make sure inode table for group is located + * within the group + */ + if (fs->group_desc[i].bg_inode_table < block || + ((fs->group_desc[i].bg_inode_table + + fs->inode_blocks_per_group) >= next)) + return EXT2_ET_GDESC_BAD_INODE_TABLE; + + block = next; + } + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/closefs.c silo-1.4.14/libext2fs/closefs.c --- silo-1.4.14.orig/libext2fs/closefs.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/closefs.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,381 @@ +/* + * closefs.c --- close an ext2 filesystem + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +static int test_root(int a, int b) +{ + if (a == 0) + return 1; + while (1) { + if (a == 1) + return 1; + if (a % b) + return 0; + a = a / b; + } +} + +int ext2fs_bg_has_super(ext2_filsys fs, int group_block) +{ + if (!(fs->super->s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) + return 1; + + if (test_root(group_block, 3) || (test_root(group_block, 5)) || + test_root(group_block, 7)) + return 1; + + return 0; +} + +int ext2fs_super_and_bgd_loc(ext2_filsys fs, + dgrp_t group, + blk_t *ret_super_blk, + blk_t *ret_old_desc_blk, + blk_t *ret_new_desc_blk, + int *ret_meta_bg) +{ + blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0; + unsigned int meta_bg, meta_bg_size; + int numblocks, has_super; + int old_desc_blocks; + + group_block = fs->super->s_first_data_block + + (group * fs->super->s_blocks_per_group); + + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = + fs->desc_blocks + fs->super->s_reserved_gdt_blocks; + + if (group == fs->group_desc_count-1) { + numblocks = (fs->super->s_blocks_count - + fs->super->s_first_data_block) % + fs->super->s_blocks_per_group; + if (!numblocks) + numblocks = fs->super->s_blocks_per_group; + } else + numblocks = fs->super->s_blocks_per_group; + + has_super = ext2fs_bg_has_super(fs, group); + + if (has_super) { + super_blk = group_block; + numblocks--; + } + meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); + meta_bg = group / meta_bg_size; + + if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || + (meta_bg < fs->super->s_first_meta_bg)) { + if (has_super) { + old_desc_blk = group_block + 1; + numblocks -= old_desc_blocks; + } + } else { + if (((group % meta_bg_size) == 0) || + ((group % meta_bg_size) == 1) || + ((group % meta_bg_size) == (meta_bg_size-1))) { + if (has_super) + has_super = 1; + new_desc_blk = group_block + has_super; + numblocks--; + } + } + + numblocks -= 2 + fs->inode_blocks_per_group; + + if (ret_super_blk) + *ret_super_blk = super_blk; + if (ret_old_desc_blk) + *ret_old_desc_blk = old_desc_blk; + if (ret_new_desc_blk) + *ret_new_desc_blk = new_desc_blk; + if (ret_meta_bg) + *ret_meta_bg = meta_bg; + return (numblocks); +} + + +/* + * This function forces out the primary superblock. We need to only + * write out those fields which we have changed, since if the + * filesystem is mounted, it may have changed some of the other + * fields. + * + * It takes as input a superblock which has already been byte swapped + * (if necessary). + * + */ +static errcode_t write_primary_superblock(ext2_filsys fs, + struct ext2_super_block *super) +{ + __u16 *old_super, *new_super; + int check_idx, write_idx, size; + errcode_t retval; + + if (!fs->io->manager->write_byte || !fs->orig_super) { + io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); + retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE, + super); + io_channel_set_blksize(fs->io, fs->blocksize); + return retval; + } + + old_super = (__u16 *) fs->orig_super; + new_super = (__u16 *) super; + + for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) { + if (old_super[check_idx] == new_super[check_idx]) + continue; + write_idx = check_idx; + for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++) + if (old_super[check_idx] == new_super[check_idx]) + break; + size = 2 * (check_idx - write_idx); +#if 0 + printf("Writing %d bytes starting at %d\n", + size, write_idx*2); +#endif + retval = io_channel_write_byte(fs->io, + SUPERBLOCK_OFFSET + (2 * write_idx), size, + new_super + write_idx); + if (retval) + return retval; + } + memcpy(fs->orig_super, super, SUPERBLOCK_SIZE); + return 0; +} + + +/* + * Updates the revision to EXT2_DYNAMIC_REV + */ +void ext2fs_update_dynamic_rev(ext2_filsys fs) +{ + struct ext2_super_block *sb = fs->super; + + if (sb->s_rev_level > EXT2_GOOD_OLD_REV) + return; + + sb->s_rev_level = EXT2_DYNAMIC_REV; + sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; + sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; + /* s_uuid is handled by e2fsck already */ + /* other fields should be left alone */ +} + +static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group, + blk_t group_block, + struct ext2_super_block *super_shadow) +{ + dgrp_t sgrp = group; + + if (sgrp > ((1 << 16) - 1)) + sgrp = (1 << 16) - 1; +#ifdef EXT2FS_ENABLE_SWAPFS + if (fs->flags & EXT2_FLAG_SWAP_BYTES) + super_shadow->s_block_group_nr = ext2fs_swab16(sgrp); + else +#endif + fs->super->s_block_group_nr = sgrp; + + return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE, + super_shadow); +} + + +errcode_t ext2fs_flush(ext2_filsys fs) +{ + dgrp_t i,j; + blk_t group_block; + errcode_t retval; + unsigned long fs_state; + struct ext2_super_block *super_shadow = 0; + struct ext2_group_desc *group_shadow = 0; + struct ext2_group_desc *s, *t; + char *group_ptr; + int old_desc_blocks; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + fs_state = fs->super->s_state; + + fs->super->s_wtime = time(NULL); + fs->super->s_block_group_nr = 0; +#ifdef EXT2FS_ENABLE_SWAPFS + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { + retval = EXT2_ET_NO_MEMORY; + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow); + if (retval) + goto errout; + retval = ext2fs_get_mem((size_t)(fs->blocksize * + fs->desc_blocks), + &group_shadow); + if (retval) + goto errout; + memset(group_shadow, 0, (size_t) fs->blocksize * + fs->desc_blocks); + + /* swap the group descriptors */ + for (j=0, s=fs->group_desc, t=group_shadow; + j < fs->group_desc_count; j++, t++, s++) { + *t = *s; + ext2fs_swap_group_desc(t); + } + } else { + super_shadow = fs->super; + group_shadow = fs->group_desc; + } +#else + super_shadow = fs->super; + group_shadow = fs->group_desc; +#endif + + /* + * If this is an external journal device, don't write out the + * block group descriptors or any of the backup superblocks + */ + if (fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) + goto write_primary_superblock_only; + + /* + * Set the state of the FS to be non-valid. (The state has + * already been backed up earlier, and will be restored after + * we write out the backup superblocks.) + */ + fs->super->s_state &= ~EXT2_VALID_FS; +#ifdef EXT2FS_ENABLE_SWAPFS + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { + *super_shadow = *fs->super; + ext2fs_swap_super(super_shadow); + } +#endif + + /* + * Write out the master group descriptors, and the backup + * superblocks and group descriptors. + */ + group_block = fs->super->s_first_data_block; + group_ptr = (char *) group_shadow; + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = fs->desc_blocks; + + for (i = 0; i < fs->group_desc_count; i++) { + blk_t super_blk, old_desc_blk, new_desc_blk; + int meta_bg; + + ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk, + &new_desc_blk, &meta_bg); + + if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) { + retval = write_backup_super(fs, i, super_blk, + super_shadow); + if (retval) + goto errout; + } + if (fs->flags & EXT2_FLAG_SUPER_ONLY) + continue; + if ((old_desc_blk) && + (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) { + retval = io_channel_write_blk(fs->io, + old_desc_blk, old_desc_blocks, group_ptr); + if (retval) + goto errout; + } + if (new_desc_blk) { + retval = io_channel_write_blk(fs->io, new_desc_blk, + 1, group_ptr + (meta_bg*fs->blocksize)); + if (retval) + goto errout; + } + } + fs->super->s_block_group_nr = 0; + fs->super->s_state = fs_state; +#ifdef EXT2FS_ENABLE_SWAPFS + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { + *super_shadow = *fs->super; + ext2fs_swap_super(super_shadow); + } +#endif + + /* + * 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) + goto errout; + } + +write_primary_superblock_only: + /* + * Write out master superblock. This has to be done + * separately, since it is located at a fixed location + * (SUPERBLOCK_OFFSET). We flush all other pending changes + * out to disk first, just to avoid a race condition with an + * insy-tinsy window.... + */ + retval = io_channel_flush(fs->io); + retval = write_primary_superblock(fs, super_shadow); + if (retval) + goto errout; + + fs->flags &= ~EXT2_FLAG_DIRTY; + + retval = io_channel_flush(fs->io); +errout: + fs->super->s_state = fs_state; + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { + if (super_shadow) + ext2fs_free_mem(&super_shadow); + if (group_shadow) + ext2fs_free_mem(&group_shadow); + } + return retval; +} + +errcode_t ext2fs_close(ext2_filsys fs) +{ + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (fs->flags & EXT2_FLAG_DIRTY) { + retval = ext2fs_flush(fs); + if (retval) + return retval; + } + if (fs->write_bitmaps) { + retval = fs->write_bitmaps(fs); + if (retval) + return retval; + } + ext2fs_free(fs); + return 0; +} + diff -Naur silo-1.4.14.orig/libext2fs/cmp_bitmaps.c silo-1.4.14/libext2fs/cmp_bitmaps.c --- silo-1.4.14.orig/libext2fs/cmp_bitmaps.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/cmp_bitmaps.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,72 @@ +/* + * cmp_bitmaps.c --- routines to compare inode and block bitmaps. + * + * Copyright (C) 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1, + ext2fs_block_bitmap bm2) +{ + blk_t i; + + EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP); + EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP); + + if ((bm1->start != bm2->start) || + (bm1->end != bm2->end) || + (memcmp(bm1->bitmap, bm2->bitmap, + (size_t) (bm1->end - bm1->start)/8))) + return EXT2_ET_NEQ_BLOCK_BITMAP; + + for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++) + if (ext2fs_fast_test_block_bitmap(bm1, i) != + ext2fs_fast_test_block_bitmap(bm2, i)) + return EXT2_ET_NEQ_BLOCK_BITMAP; + + return 0; +} + +errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1, + ext2fs_inode_bitmap bm2) +{ + ext2_ino_t i; + + EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_INODE_BITMAP); + EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_INODE_BITMAP); + + if ((bm1->start != bm2->start) || + (bm1->end != bm2->end) || + (memcmp(bm1->bitmap, bm2->bitmap, + (size_t) (bm1->end - bm1->start)/8))) + return EXT2_ET_NEQ_INODE_BITMAP; + + for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++) + if (ext2fs_fast_test_inode_bitmap(bm1, i) != + ext2fs_fast_test_inode_bitmap(bm2, i)) + return EXT2_ET_NEQ_INODE_BITMAP; + + return 0; +} + diff -Naur silo-1.4.14.orig/libext2fs/dblist.c silo-1.4.14/libext2fs/dblist.c --- silo-1.4.14.orig/libext2fs/dblist.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/dblist.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,260 @@ +/* + * dblist.c -- directory block list functions + * + * Copyright 1997 by Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b); + +/* + * Returns the number of directories in the filesystem as reported by + * the group descriptors. Of course, the group descriptors could be + * wrong! + */ +errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs) +{ + dgrp_t i; + ext2_ino_t num_dirs, max_dirs; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + num_dirs = 0; + max_dirs = fs->super->s_inodes_per_group; + for (i = 0; i < fs->group_desc_count; i++) { + if (fs->group_desc[i].bg_used_dirs_count > max_dirs) + num_dirs += max_dirs / 8; + else + num_dirs += fs->group_desc[i].bg_used_dirs_count; + } + if (num_dirs > fs->super->s_inodes_count) + num_dirs = fs->super->s_inodes_count; + + *ret_num_dirs = num_dirs; + + return 0; +} + +/* + * helper function for making a new directory block list (for + * initialize and copy). + */ +static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, ext2_ino_t count, + struct ext2_db_entry *list, + ext2_dblist *ret_dblist) +{ + ext2_dblist dblist; + errcode_t retval; + size_t len; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if ((ret_dblist == 0) && fs->dblist && + (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST)) + return 0; + + retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist); + if (retval) + return retval; + memset(dblist, 0, sizeof(struct ext2_struct_dblist)); + + dblist->magic = EXT2_ET_MAGIC_DBLIST; + dblist->fs = fs; + if (size) + dblist->size = size; + else { + retval = ext2fs_get_num_dirs(fs, &dblist->size); + if (retval) + goto cleanup; + dblist->size = (dblist->size * 2) + 12; + } + len = (size_t) sizeof(struct ext2_db_entry) * dblist->size; + dblist->count = count; + retval = ext2fs_get_mem(len, &dblist->list); + if (retval) + goto cleanup; + + if (list) + memcpy(dblist->list, list, len); + else + memset(dblist->list, 0, len); + if (ret_dblist) + *ret_dblist = dblist; + else + fs->dblist = dblist; + return 0; +cleanup: + if (dblist) + ext2fs_free_mem(&dblist); + return retval; +} + +/* + * Initialize a directory block list + */ +errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist) +{ + ext2_dblist dblist; + errcode_t retval; + + retval = make_dblist(fs, 0, 0, 0, &dblist); + if (retval) + return retval; + + dblist->sorted = 1; + if (ret_dblist) + *ret_dblist = dblist; + else + fs->dblist = dblist; + + return 0; +} + +/* + * Copy a directory block list + */ +errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest) +{ + ext2_dblist dblist; + errcode_t retval; + + retval = make_dblist(src->fs, src->size, src->count, src->list, + &dblist); + if (retval) + return retval; + dblist->sorted = src->sorted; + *dest = dblist; + return 0; +} + +/* + * Close a directory block list + * + * (moved to closefs.c) + */ + + +/* + * Add a directory block to the directory block list + */ +errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk, + int blockcnt) +{ + struct ext2_db_entry *new_entry; + errcode_t retval; + unsigned long old_size; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + if (dblist->count >= dblist->size) { + old_size = dblist->size * sizeof(struct ext2_db_entry); + dblist->size += 100; + retval = ext2fs_resize_mem(old_size, (size_t) dblist->size * + sizeof(struct ext2_db_entry), + &dblist->list); + if (retval) { + dblist->size -= 100; + return retval; + } + } + new_entry = dblist->list + ( (int) dblist->count++); + new_entry->blk = blk; + new_entry->ino = ino; + new_entry->blockcnt = blockcnt; + + dblist->sorted = 0; + + return 0; +} + +/* + * Change the directory block to the directory block list + */ +errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk, + int blockcnt) +{ + dgrp_t i; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + for (i=0; i < dblist->count; i++) { + if ((dblist->list[i].ino != ino) || + (dblist->list[i].blockcnt != blockcnt)) + continue; + dblist->list[i].blk = blk; + dblist->sorted = 0; + return 0; + } + return EXT2_ET_DB_NOT_FOUND; +} + +void ext2fs_dblist_sort(ext2_dblist dblist, + EXT2_QSORT_TYPE (*sortfunc)(const void *, + const void *)) +{ + if (!sortfunc) + sortfunc = dir_block_cmp; + qsort(dblist->list, (size_t) dblist->count, + sizeof(struct ext2_db_entry), sortfunc); + dblist->sorted = 1; +} + +/* + * This function iterates over the directory block list + */ +errcode_t ext2fs_dblist_iterate(ext2_dblist dblist, + int (*func)(ext2_filsys fs, + struct ext2_db_entry *db_info, + void *priv_data), + void *priv_data) +{ + ext2_ino_t i; + int ret; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + if (!dblist->sorted) + ext2fs_dblist_sort(dblist, 0); + for (i=0; i < dblist->count; i++) { + ret = (*func)(dblist->fs, &dblist->list[(int)i], priv_data); + if (ret & DBLIST_ABORT) + return 0; + } + return 0; +} + +static EXT2_QSORT_TYPE dir_block_cmp(const void *a, const void *b) +{ + const struct ext2_db_entry *db_a = + (const struct ext2_db_entry *) a; + const struct ext2_db_entry *db_b = + (const struct ext2_db_entry *) b; + + if (db_a->blk != db_b->blk) + return (int) (db_a->blk - db_b->blk); + + if (db_a->ino != db_b->ino) + return (int) (db_a->ino - db_b->ino); + + return (int) (db_a->blockcnt - db_b->blockcnt); +} + +int ext2fs_dblist_count(ext2_dblist dblist) +{ + return (int) dblist->count; +} diff -Naur silo-1.4.14.orig/libext2fs/dblist_dir.c silo-1.4.14/libext2fs/dblist_dir.c --- silo-1.4.14.orig/libext2fs/dblist_dir.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/dblist_dir.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,75 @@ +/* + * dblist_dir.c --- iterate by directory entry + * + * Copyright 1997 by Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info, + void *priv_data); + +errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist, + int flags, + char *block_buf, + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data) +{ + errcode_t retval; + struct dir_context ctx; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + ctx.dir = 0; + ctx.flags = flags; + if (block_buf) + ctx.buf = block_buf; + else { + retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf); + if (retval) + return retval; + } + ctx.func = func; + ctx.priv_data = priv_data; + ctx.errcode = 0; + + retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx); + + if (!block_buf) + ext2fs_free_mem(&ctx.buf); + if (retval) + return retval; + return ctx.errcode; +} + +static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info, + void *priv_data) +{ + struct dir_context *ctx; + + ctx = (struct dir_context *) priv_data; + ctx->dir = db_info->ino; + + return ext2fs_process_dir_block(fs, &db_info->blk, + db_info->blockcnt, 0, 0, priv_data); +} diff -Naur silo-1.4.14.orig/libext2fs/dir_iterate.c silo-1.4.14/libext2fs/dir_iterate.c --- silo-1.4.14.orig/libext2fs/dir_iterate.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/dir_iterate.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,219 @@ +/* + * dir_iterate.c --- ext2fs directory iteration operations + * + * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +/* + * This function checks to see whether or not a potential deleted + * directory entry looks valid. What we do is check the deleted entry + * and each successive entry to make sure that they all look valid and + * that the last deleted entry ends at the beginning of the next + * undeleted entry. Returns 1 if the deleted entry looks valid, zero + * if not valid. + */ +static int ext2fs_validate_entry(char *buf, int offset, int final_offset) +{ + struct ext2_dir_entry *dirent; + + while (offset < final_offset) { + dirent = (struct ext2_dir_entry *)(buf + offset); + offset += dirent->rec_len; + if ((dirent->rec_len < 8) || + ((dirent->rec_len % 4) != 0) || + (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) + return 0; + } + return (offset == final_offset); +} + +errcode_t ext2fs_dir_iterate2(ext2_filsys fs, + ext2_ino_t dir, + int flags, + char *block_buf, + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data) +{ + struct dir_context ctx; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_check_directory(fs, dir); + if (retval) + return retval; + + ctx.dir = dir; + ctx.flags = flags; + if (block_buf) + ctx.buf = block_buf; + else { + retval = ext2fs_get_mem(fs->blocksize, &ctx.buf); + if (retval) + return retval; + } + ctx.func = func; + ctx.priv_data = priv_data; + ctx.errcode = 0; + retval = ext2fs_block_iterate2(fs, dir, 0, 0, + ext2fs_process_dir_block, &ctx); + if (!block_buf) + ext2fs_free_mem(&ctx.buf); + if (retval) + return retval; + return ctx.errcode; +} + +struct xlate { + int (*func)(struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data); + void *real_private; +}; + +static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)), + int entry EXT2FS_ATTR((unused)), + struct ext2_dir_entry *dirent, int offset, + int blocksize, char *buf, void *priv_data) +{ + struct xlate *xl = (struct xlate *) priv_data; + + return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private); +} + +extern errcode_t ext2fs_dir_iterate(ext2_filsys fs, + ext2_ino_t dir, + int flags, + char *block_buf, + int (*func)(struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data) +{ + struct xlate xl; + + xl.real_private = priv_data; + xl.func = func; + + return ext2fs_dir_iterate2(fs, dir, flags, block_buf, + xlate_func, &xl); +} + + +/* + * Helper function which is private to this module. Used by + * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate() + */ +int ext2fs_process_dir_block(ext2_filsys fs, + blk_t *blocknr, + e2_blkcnt_t blockcnt, + blk_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct dir_context *ctx = (struct dir_context *) priv_data; + unsigned int offset = 0; + unsigned int next_real_entry = 0; + int ret = 0; + int changed = 0; + int do_abort = 0; + int entry, size; + struct ext2_dir_entry *dirent; + + if (blockcnt < 0) + return 0; + + entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE; + + ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf); + if (ctx->errcode) + return BLOCK_ABORT; + + while (offset < fs->blocksize) { + dirent = (struct ext2_dir_entry *) (ctx->buf + offset); + if (((offset + dirent->rec_len) > fs->blocksize) || + (dirent->rec_len < 8) || + ((dirent->rec_len % 4) != 0) || + (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { + ctx->errcode = EXT2_ET_DIR_CORRUPTED; + return BLOCK_ABORT; + } + if (!dirent->inode && + !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY)) + goto next; + + ret = (ctx->func)(ctx->dir, + (next_real_entry > offset) ? + DIRENT_DELETED_FILE : entry, + dirent, offset, + fs->blocksize, ctx->buf, + ctx->priv_data); + if (entry < DIRENT_OTHER_FILE) + entry++; + + if (ret & DIRENT_CHANGED) + changed++; + if (ret & DIRENT_ABORT) { + do_abort++; + break; + } +next: + if (next_real_entry == offset) + next_real_entry += dirent->rec_len; + + if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) { + size = ((dirent->name_len & 0xFF) + 11) & ~3; + + if (dirent->rec_len != size) { + unsigned int final_offset; + + final_offset = offset + dirent->rec_len; + offset += size; + while (offset < final_offset && + !ext2fs_validate_entry(ctx->buf, + offset, + final_offset)) + offset += 4; + continue; + } + } + offset += dirent->rec_len; + } + + if (changed) { + ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf); + if (ctx->errcode) + return BLOCK_ABORT; + } + if (do_abort) + return BLOCK_ABORT; + return 0; +} + diff -Naur silo-1.4.14.orig/libext2fs/dirblock.c silo-1.4.14/libext2fs/dirblock.c --- silo-1.4.14.orig/libext2fs/dirblock.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/dirblock.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,130 @@ +/* + * dirblock.c --- directory block routines. + * + * Copyright (C) 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block, + void *buf, int flags EXT2FS_ATTR((unused))) +{ + errcode_t retval; + char *p, *end; + struct ext2_dir_entry *dirent; + unsigned int name_len, rec_len, do_swap; + + + retval = io_channel_read_blk(fs->io, block, 1, buf); + if (retval) + return retval; +#ifdef EXT2FS_ENABLE_SWAPFS + do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES| + EXT2_FLAG_SWAP_BYTES_READ)) != 0; +#endif + p = (char *) buf; + end = (char *) buf + fs->blocksize; + while (p < end-8) { + dirent = (struct ext2_dir_entry *) p; +#ifdef EXT2FS_ENABLE_SWAPFS + if (do_swap) { + dirent->inode = ext2fs_swab32(dirent->inode); + dirent->rec_len = ext2fs_swab16(dirent->rec_len); + dirent->name_len = ext2fs_swab16(dirent->name_len); + } +#endif + name_len = dirent->name_len; +#ifdef WORDS_BIGENDIAN + if (flags & EXT2_DIRBLOCK_V2_STRUCT) + dirent->name_len = ext2fs_swab16(dirent->name_len); +#endif + rec_len = dirent->rec_len; + if ((rec_len < 8) || (rec_len % 4)) { + rec_len = 8; + retval = EXT2_ET_DIR_CORRUPTED; + } + if (((name_len & 0xFF) + 8) > dirent->rec_len) + retval = EXT2_ET_DIR_CORRUPTED; + p += rec_len; + } + return retval; +} + +errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block, + void *buf) +{ + return ext2fs_read_dir_block2(fs, block, buf, 0); +} + + +errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block, + void *inbuf, int flags EXT2FS_ATTR((unused))) +{ +#ifdef EXT2FS_ENABLE_SWAPFS + int do_swap = 0; + errcode_t retval; + char *p, *end; + char *buf = 0; + struct ext2_dir_entry *dirent; + + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) + do_swap = 1; + +#ifndef WORDS_BIGENDIAN + if (!do_swap) + return io_channel_write_blk(fs->io, block, 1, (char *) inbuf); +#endif + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + memcpy(buf, inbuf, fs->blocksize); + p = buf; + end = buf + fs->blocksize; + while (p < end) { + dirent = (struct ext2_dir_entry *) p; + if ((dirent->rec_len < 8) || + (dirent->rec_len % 4)) { + ext2fs_free_mem(&buf); + return (EXT2_ET_DIR_CORRUPTED); + } + p += dirent->rec_len; + if (do_swap) { + dirent->inode = ext2fs_swab32(dirent->inode); + dirent->rec_len = ext2fs_swab16(dirent->rec_len); + dirent->name_len = ext2fs_swab16(dirent->name_len); + } +#ifdef WORDS_BIGENDIAN + if (flags & EXT2_DIRBLOCK_V2_STRUCT) + dirent->name_len = ext2fs_swab16(dirent->name_len); +#endif + } + retval = io_channel_write_blk(fs->io, block, 1, buf); + ext2fs_free_mem(&buf); + return retval; +#else + return io_channel_write_blk(fs->io, block, 1, (char *) inbuf); +#endif +} + + +errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block, + void *inbuf) +{ + return ext2fs_write_dir_block2(fs, block, inbuf, 0); +} + diff -Naur silo-1.4.14.orig/libext2fs/dirhash.c silo-1.4.14/libext2fs/dirhash.c --- silo-1.4.14.orig/libext2fs/dirhash.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/dirhash.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,233 @@ +/* + * dirhash.c -- Calculate the hash of a directory entry + * + * Copyright (c) 2001 Daniel Phillips + * + * Copyright (c) 2002 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * Keyed 32-bit hash function using TEA in a Davis-Meyer function + * H0 = Key + * Hi = E Mi(Hi-1) + Hi-1 + * + * (see Applied Cryptography, 2nd edition, p448). + * + * Jeremy Fitzhardinge 1998 + * + * This code is made available under the terms of the GPL + */ +#define DELTA 0x9E3779B9 + +static void TEA_transform(__u32 buf[4], __u32 const in[]) +{ + __u32 sum = 0; + __u32 b0 = buf[0], b1 = buf[1]; + __u32 a = in[0], b = in[1], c = in[2], d = in[3]; + int n = 16; + + do { + sum += DELTA; + b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); + b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); + } while(--n); + + buf[0] += b0; + buf[1] += b1; +} + +/* F, G and H are basic MD4 functions: selection, majority, parity */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* + * The generic round function. The application is so specific that + * we don't bother protecting all the arguments with parens, as is generally + * good macro practice, in favor of extra legibility. + * Rotation is separate from addition to prevent recomputation + */ +#define ROUND(f, a, b, c, d, x, s) \ + (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) +#define K1 0 +#define K2 013240474631UL +#define K3 015666365641UL + +/* + * Basic cut-down MD4 transform. Returns only 32 bits of result. + */ +static void halfMD4Transform (__u32 buf[4], __u32 const in[]) +{ + __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ + ROUND(F, a, b, c, d, in[0] + K1, 3); + ROUND(F, d, a, b, c, in[1] + K1, 7); + ROUND(F, c, d, a, b, in[2] + K1, 11); + ROUND(F, b, c, d, a, in[3] + K1, 19); + ROUND(F, a, b, c, d, in[4] + K1, 3); + ROUND(F, d, a, b, c, in[5] + K1, 7); + ROUND(F, c, d, a, b, in[6] + K1, 11); + ROUND(F, b, c, d, a, in[7] + K1, 19); + + /* Round 2 */ + ROUND(G, a, b, c, d, in[1] + K2, 3); + ROUND(G, d, a, b, c, in[3] + K2, 5); + ROUND(G, c, d, a, b, in[5] + K2, 9); + ROUND(G, b, c, d, a, in[7] + K2, 13); + ROUND(G, a, b, c, d, in[0] + K2, 3); + ROUND(G, d, a, b, c, in[2] + K2, 5); + ROUND(G, c, d, a, b, in[4] + K2, 9); + ROUND(G, b, c, d, a, in[6] + K2, 13); + + /* Round 3 */ + ROUND(H, a, b, c, d, in[3] + K3, 3); + ROUND(H, d, a, b, c, in[7] + K3, 9); + ROUND(H, c, d, a, b, in[2] + K3, 11); + ROUND(H, b, c, d, a, in[6] + K3, 15); + ROUND(H, a, b, c, d, in[1] + K3, 3); + ROUND(H, d, a, b, c, in[5] + K3, 9); + ROUND(H, c, d, a, b, in[0] + K3, 11); + ROUND(H, b, c, d, a, in[4] + K3, 15); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#undef ROUND +#undef F +#undef G +#undef H +#undef K1 +#undef K2 +#undef K3 + +/* The old legacy hash */ +static ext2_dirhash_t dx_hack_hash (const char *name, int len) +{ + __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; + while (len--) { + __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373)); + + if (hash & 0x80000000) hash -= 0x7fffffff; + hash1 = hash0; + hash0 = hash; + } + return (hash0 << 1); +} + +static void str2hashbuf(const char *msg, int len, __u32 *buf, int num) +{ + __u32 pad, val; + int i; + + pad = (__u32)len | ((__u32)len << 8); + pad |= pad << 16; + + val = pad; + if (len > num*4) + len = num * 4; + for (i=0; i < len; i++) { + if ((i % 4) == 0) + val = pad; + val = msg[i] + (val << 8); + if ((i % 4) == 3) { + *buf++ = val; + val = pad; + num--; + } + } + if (--num >= 0) + *buf++ = val; + while (--num >= 0) + *buf++ = pad; +} + +/* + * Returns the hash of a filename. If len is 0 and name is NULL, then + * this function can be used to test whether or not a hash version is + * supported. + * + * The seed is an 4 longword (32 bits) "secret" which can be used to + * uniquify a hash. If the seed is all zero's, then some default seed + * may be used. + * + * A particular hash version specifies whether or not the seed is + * represented, and whether or not the returned hash is 32 bits or 64 + * bits. 32 bit hashes will return 0 for the minor hash. + */ +errcode_t ext2fs_dirhash(int version, const char *name, int len, + const __u32 *seed, + ext2_dirhash_t *ret_hash, + ext2_dirhash_t *ret_minor_hash) +{ + __u32 hash; + __u32 minor_hash = 0; + const char *p; + int i; + __u32 in[8], buf[4]; + + /* Initialize the default seed for the hash checksum functions */ + buf[0] = 0x67452301; + buf[1] = 0xefcdab89; + buf[2] = 0x98badcfe; + buf[3] = 0x10325476; + + /* Check to see if the seed is all zero's */ + if (seed) { + for (i=0; i < 4; i++) { + if (seed[i]) + break; + } + if (i < 4) + memcpy(buf, seed, sizeof(buf)); + } + + switch (version) { + case EXT2_HASH_LEGACY: + hash = dx_hack_hash(name, len); + break; + case EXT2_HASH_HALF_MD4: + p = name; + while (len > 0) { + str2hashbuf(p, len, in, 8); + halfMD4Transform(buf, in); + len -= 32; + p += 32; + } + minor_hash = buf[2]; + hash = buf[1]; + break; + case EXT2_HASH_TEA: + p = name; + while (len > 0) { + str2hashbuf(p, len, in, 4); + TEA_transform(buf, in); + len -= 16; + p += 16; + } + hash = buf[0]; + minor_hash = buf[1]; + break; + default: + *ret_hash = 0; + return EXT2_ET_DIRHASH_UNSUPP; + } + *ret_hash = hash & ~1; + if (ret_minor_hash) + *ret_minor_hash = minor_hash; + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/dosio.c silo-1.4.14/libext2fs/dosio.c --- silo-1.4.14.orig/libext2fs/dosio.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/dosio.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,456 @@ +/* + * dosio.c -- Disk I/O module for the ext2fs/DOS library. + * + * Copyright (c) 1997 by Theodore Ts'o. + * + * Copyright (c) 1997 Mark Habersack + * This file may be distributed under the terms of the GNU Public License. + * + */ + +#include +#include +#include +#include +#include +#ifdef HAVE_ERRNO_H +#include +#endif + +#include +#include "utils.h" +#include "dosio.h" +#include "et/com_err.h" +#include "ext2_err.h" +#include "ext2fs/io.h" + +/* + * Some helper macros + */ +#define LINUX_EXT2FS 0x83 +#define LINUX_SWAP 0x82 +#define WRITE_ERR(_msg_) write(2, _msg_, strlen(_msg_)) +#define WRITE_ERR_S(_msg_) write(2, _msg_, sizeof(_msg_)) + +/* + * Exported variables + */ +unsigned long _dio_error; +unsigned long _dio_hw_error; + +/* + * Array of all opened partitions + */ +static PARTITION **partitions = NULL; +static unsigned short npart = 0; /* Number of mapped partitions */ +static PARTITION *active = NULL; + +/* + * I/O Manager routine prototypes + */ +static errcode_t dos_open(const char *dev, int flags, io_channel *channel); +static errcode_t dos_close(io_channel channel); +static errcode_t dos_set_blksize(io_channel channel, int blksize); +static errcode_t dos_read_blk(io_channel channel, unsigned long block, + int count, void *buf); +static errcode_t dos_write_blk(io_channel channel, unsigned long block, + int count, const void *buf); +static errcode_t dos_flush(io_channel channel); + +static struct struct_io_manager struct_dos_manager = { + EXT2_ET_MAGIC_IO_MANAGER, + "DOS I/O Manager", + dos_open, + dos_close, + dos_set_blksize, + dos_read_blk, + dos_write_blk, + dos_flush +}; +io_manager dos_io_manager = &struct_dos_manager; + +/* + * Macro taken from unix_io.c + */ +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +/* + * Calculates a CHS address of a sector from its LBA + * offset for the given partition. + */ +static void lba2chs(unsigned long lba_addr, CHS *chs, PARTITION *part) +{ + unsigned long abss; + + chs->offset = lba_addr & 0x000001FF; + abss = (lba_addr >> 9) + part->start; + chs->cyl = abss / (part->sects * part->heads); + chs->head = (abss / part->sects) % part->heads; + chs->sector = (abss % part->sects) + 1; +} + +#ifdef __TURBOC__ +#pragma argsused +#endif +/* + * Scans the passed partition table looking for *pno partition + * that has LINUX_EXT2FS type. + * + * TODO: + * For partition numbers >5 Linux uses DOS extended partitions - + * dive into them an return an appropriate entry. Also dive into + * extended partitions when scanning for a first Linux/ext2fs. + */ +static PTABLE_ENTRY *scan_partition_table(PTABLE_ENTRY *pentry, + unsigned short phys, + unsigned char *pno) +{ + unsigned i; + + if(*pno != 0xFF && *pno >= 5) + return NULL; /* We don't support extended partitions for now */ + + if(*pno != 0xFF) + { + if(pentry[*pno].type == LINUX_EXT2FS) + return &pentry[*pno]; + else + { + if(!pentry[*pno].type) + *pno = 0xFE; + else if(pentry[*pno].type == LINUX_SWAP) + *pno = 0xFD; + return NULL; + } + } + + for(i = 0; i < 4; i++) + if(pentry[i].type == LINUX_EXT2FS) + { + *pno = i; + return &pentry[i]; + } + + return NULL; +} + +/* + * Allocate libext2fs structures associated with I/O manager + */ +static io_channel alloc_io_channel(PARTITION *part) +{ + io_channel ioch; + + ioch = (io_channel)malloc(sizeof(struct struct_io_channel)); + if (!ioch) + return NULL; + memset(ioch, 0, sizeof(struct struct_io_channel)); + ioch->magic = EXT2_ET_MAGIC_IO_CHANNEL; + ioch->manager = dos_io_manager; + ioch->name = (char *)malloc(strlen(part->dev)+1); + if (!ioch->name) { + free(ioch); + return NULL; + } + strcpy(ioch->name, part->dev); + ioch->private_data = part; + ioch->block_size = 1024; /* The smallest ext2fs block size */ + ioch->read_error = 0; + ioch->write_error = 0; + + return ioch; +} + +#ifdef __TURBOC__ +#pragma argsused +#endif +/* + * Open the 'name' partition, initialize all information structures + * we need to keep and create libext2fs I/O manager. + */ +static errcode_t dos_open(const char *dev, int flags, io_channel *channel) +{ + unsigned char *tmp, sec[512]; + PARTITION *part; + PTABLE_ENTRY *pent; + PARTITION **newparts; + + if(!dev) + { + _dio_error = ERR_BADDEV; + return EXT2_ET_BAD_DEVICE_NAME; + } + + /* + * First check whether the dev name is OK + */ + tmp = (unsigned char*)strrchr(dev, '/'); + if(!tmp) + { + _dio_error = ERR_BADDEV; + return EXT2_ET_BAD_DEVICE_NAME; + } + *tmp = 0; + if(strcmp(dev, "/dev")) + { + _dio_error = ERR_BADDEV; + return EXT2_ET_BAD_DEVICE_NAME; + } + *tmp++ = '/'; + + /* + * Check whether the partition data is already in cache + */ + + part = (PARTITION*)malloc(sizeof(PARTITION)); + if (!part) + return ENOMEM; + { + int i = 0; + + for(;i < npart; i++) + if(!strcmp(partitions[i]->dev, dev)) + { + /* Found it! Make it the active one */ + active = partitions[i]; + *channel = alloc_io_channel(active); + if (!*channel) + return ENOMEM; + return 0; + } + } + + /* + * Drive number & optionally partn number + */ + switch(tmp[0]) + { + case 'h': + case 's': + part->phys = 0x80; + part->phys += toupper(tmp[2]) - 'A'; + /* + * Do we have the partition number? + */ + if(tmp[3]) + part->pno = isdigit((int)tmp[3]) ? tmp[3] - '0' - 1: 0; + else + part->pno = 0xFF; + break; + + case 'f': + if(tmp[2]) + part->phys = isdigit((int)tmp[2]) ? tmp[2] - '0' : 0; + else + part->phys = 0x00; /* We'll assume /dev/fd0 */ + break; + + default: + _dio_error = ERR_BADDEV; + return ENODEV; + } + + if(part->phys < 0x80) + { + /* We don't support floppies for now */ + _dio_error = ERR_NOTSUPP; + return EINVAL; + } + + part->dev = strdup(dev); + + /* + * Get drive's geometry + */ + _dio_hw_error = biosdisk(DISK_GET_GEOMETRY, + part->phys, + 0, /* head */ + 0, /* cylinder */ + 1, /* sector */ + 1, /* just one sector */ + sec); + + if(!HW_OK()) + { + _dio_error = ERR_HARDWARE; + if (part) + free(part); + return EFAULT; + } + + /* + * Calculate the geometry + */ + part->cyls = (unsigned short)(((sec[0] >> 6) << 8) + sec[1] + 1); + part->heads = sec[3] + 1; + part->sects = sec[0] & 0x3F; + + /* + * Now that we know all we need, let's look for the partition + */ + _dio_hw_error = biosdisk(DISK_READ, part->phys, 0, 0, 1, 1, sec); + + if(!HW_OK()) + { + _dio_error = ERR_HARDWARE; + if (part) + free(part); + return EFAULT; + } + + pent = (PTABLE_ENTRY*)&sec[0x1BE]; + pent = scan_partition_table(pent, part->phys, &part->pno); + + if(!pent) + { + _dio_error = part->pno == 0xFE ? ERR_EMPTYPART : + part->pno == 0xFD ? ERR_LINUXSWAP : ERR_NOTEXT2FS; + if (part) + free(part); + return ENODEV; + } + + /* + * Calculate the remaining figures + */ + { + unsigned long fsec, fhead, fcyl; + + fsec = (unsigned long)(pent->start_sec & 0x3F); + fhead = (unsigned long)pent->start_head; + fcyl = ((pent->start_sec >> 6) << 8) + pent->start_cyl; + part->start = fsec + fhead * part->sects + fcyl * + (part->heads * part->sects) - 1; + part->len = pent->size; + } + + /* + * Add the partition to the table + */ + newparts = (PARTITION**)realloc(partitions, sizeof(PARTITION) * npart); + if (!newparts) { + free(part); + return ENOMEM; + } + partitions = newparts; + partitions[npart++] = active = part; + + /* + * Now alloc all libe2fs structures + */ + *channel = alloc_io_channel(active); + if (!*channel) + return ENOMEM; + + return 0; +} + +static errcode_t dos_close(io_channel channel) +{ + if (channel->name) + free(channel->name); + if (channel) + free(channel); + + return 0; +} + +static errcode_t dos_set_blksize(io_channel channel, int blksize) +{ + channel->block_size = blksize; + + return 0; +} + +static errcode_t dos_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + PARTITION *part; + size_t size; + ext2_loff_t loc; + CHS chs; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + part = (PARTITION*)channel->private_data; + + size = (size_t)((count < 0) ? -count : count * channel->block_size); + loc = (ext2_loff_t) block * channel->block_size; + + lba2chs(loc, &chs, part); + /* + * Potential bug here: + * If DJGPP is used then reads of >18 sectors will fail! + * Have to rewrite biosdisk. + */ + _dio_hw_error = biosdisk(DISK_READ, + part->phys, + chs.head, + chs.cyl, + chs.sector, + size < 512 ? 1 : size/512, + buf); + + if(!HW_OK()) + { + _dio_error = ERR_HARDWARE; + return EFAULT; + } + + return 0; +} + +static errcode_t dos_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + PARTITION *part; + size_t size; + ext2_loff_t loc; + CHS chs; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + part = (PARTITION*)channel->private_data; + + if(count == 1) + size = (size_t)channel->block_size; + else + { + if (count < 0) + size = (size_t)-count; + else + size = (size_t)(count * channel->block_size); + } + + loc = (ext2_loff_t)block * channel->block_size; + lba2chs(loc, &chs, part); + _dio_hw_error = biosdisk(DISK_WRITE, + part->phys, + chs.head, + chs.cyl, + chs.sector, + size < 512 ? 1 : size/512, + (void*)buf); + + if(!HW_OK()) + { + _dio_error = ERR_HARDWARE; + return EFAULT; + } + + return 0; +} + +#ifdef __TURBOC__ +#pragma argsused +#endif +static errcode_t dos_flush(io_channel channel) +{ + /* + * No buffers, no flush... + */ + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/dosio.h silo-1.4.14/libext2fs/dosio.h --- silo-1.4.14.orig/libext2fs/dosio.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/dosio.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,153 @@ +/* + * v1.0 + * + * Disk I/O include file for the ext2fs/DOS library. + * + * Copyright (c) 1997 Mark Habersack + * This file may be distributed under the terms of the GNU Public License. + * + */ +#ifndef __diskio_h +#define __diskio_h +#ifdef __TURBOC__ +#ifndef __LARGE__ +# error "ext2fs/DOS library requires LARGE model!" +#endif +#endif + +#ifdef __TURBOC__ +#include "msdos.h" +#endif + +/* + * A helper structure used in LBA => CHS conversion + */ +typedef struct +{ + unsigned short cyl; /* Cylinder (or track) */ + unsigned short head; + unsigned short sector; + unsigned short offset; /* Offset of byte within the sector */ +} CHS; + +/* + * All partition data we need is here + */ +typedef struct +{ + char *dev; /* _Linux_ device name (like "/dev/hda1") */ + unsigned char phys; /* Physical DOS drive number */ + unsigned long start; /* LBA address of partition start */ + unsigned long len; /* length of partition in sectors */ + unsigned char pno; /* Partition number (read from *dev) */ + + /* This partition's drive geometry */ + unsigned short cyls; + unsigned short heads; + unsigned short sects; +} PARTITION; + +/* + * PC partition table entry format + */ +#ifdef __DJGPP__ +#pragma pack(1) +#endif +typedef struct +{ + unsigned char active; + unsigned char start_head; + unsigned char start_sec; + unsigned char start_cyl; + unsigned char type; + unsigned char end_head; + unsigned char end_sec; + unsigned char end_cyl; + unsigned long first_sec_rel; + unsigned long size; +} PTABLE_ENTRY; +#ifdef __DJGPP__ +#pragma pack() +#endif + +/* + * INT 0x13 operation codes + */ +#define DISK_READ 0x02 +#define DISK_WRITE 0x03 +#define DISK_GET_GEOMETRY 0x08 +#define DISK_READY 0x10 + +/* + * Errors to put in _dio_error + */ +#define ERR_BADDEV 0x00000001L +#define ERR_HARDWARE 0x00000002L +#define ERR_NOTSUPP 0x00000003L +#define ERR_NOTEXT2FS 0x00000004L +#define ERR_EMPTYPART 0x00000005L +#define ERR_LINUXSWAP 0x00000006L + +/* + * Functions in diskio.c + */ + +/* + * Variable contains last module's error + */ +extern unsigned long _dio_error; + +/* + * This one contains last hardware error (if _dio_error == ERR_HARDWARE) + */ +extern unsigned long _dio_hw_error; + +/* + * Macros to check for disk hardware errors + */ +#define HW_OK() ((unsigned char)_dio_hw_error == 0x00) +#define HW_BAD_CMD() ((unsigned char)_dio_hw_error == 0x01) +#define HW_NO_ADDR_MARK() ((unsigned char)_dio_hw_error == 0x02) +#define HW_WRITE_PROT() ((unsigned char)_dio_hw_error == 0x03) +#define HW_NO_SECTOR() ((unsigned char)_dio_hw_error == 0x04) +#define HW_RESET_FAIL() ((unsigned char)_dio_hw_error == 0x05) +#define HW_DISK_CHANGED() ((unsigned char)_dio_hw_error == 0x06) +#define HW_DRIVE_FAIL() ((unsigned char)_dio_hw_error == 0x07) +#define HW_DMA_OVERRUN() ((unsigned char)_dio_hw_error == 0x08) +#define HW_DMA_BOUNDARY() ((unsigned char)_dio_hw_error == 0x09) +#define HW_BAD_SECTOR() ((unsigned char)_dio_hw_error == 0x0A) +#define HW_BAD_TRACK() ((unsigned char)_dio_hw_error == 0x0B) +#define HW_UNSUPP_TRACK() ((unsigned char)_dio_hw_error == 0x0C) +#define HW_BAD_CRC_ECC() ((unsigned char)_dio_hw_error == 0x10) +#define HW_CRC_ECC_CORR() ((unsigned char)_dio_hw_error == 0x11) +#define HW_CONTR_FAIL() ((unsigned char)_dio_hw_error == 0x20) +#define HW_SEEK_FAIL() ((unsigned char)_dio_hw_error == 0x40) +#define HW_ATTACH_FAIL() ((unsigned char)_dio_hw_error == 0x80) +#define HW_DRIVE_NREADY() ((unsigned char)_dio_hw_error == 0xAA) +#define HW_UNDEF_ERROR() ((unsigned char)_dio_hw_error == 0xBB) +#define HW_WRITE_FAULT() ((unsigned char)_dio_hw_error == 0xCC) +#define HW_STATUS_ERROR() ((unsigned char)_dio_hw_error == 0xE0) +#define HW_SENSE_FAIL() ((unsigned char)_dio_hw_error == 0xFF) + + +/* + * Open the specified partition. + * String 'dev' must have a format: + * + * /dev/{sd|hd|fd}[X] + * + * where, + * + * only one of the option in curly braces can be used and X is an optional + * partition number for the given device. If X is not specified, function + * scans the drive's partition table in search for the first Linux ext2fs + * partition (signature 0x83). Along the way it dives into every extended + * partition encountered. + * Scan ends if either (a) there are no more used partition entries, or + * (b) there is no Xth partition. + * + * Routine returns 0 on success and !=0 otherwise. + */ +int open_partition(char *dev); + +#endif /* __diskio_h */ diff -Naur silo-1.4.14.orig/libext2fs/dupfs.c silo-1.4.14/libext2fs/dupfs.c --- silo-1.4.14.orig/libext2fs/dupfs.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/dupfs.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,96 @@ +/* + * dupfs.c --- duplicate a ext2 filesystem handle + * + * Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest) +{ + ext2_filsys fs; + errcode_t retval; + + EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); + if (retval) + return retval; + + *fs = *src; + fs->device_name = 0; + fs->super = 0; + fs->orig_super = 0; + fs->group_desc = 0; + fs->inode_map = 0; + fs->block_map = 0; + fs->badblocks = 0; + fs->dblist = 0; + + io_channel_bumpcount(fs->io); + if (fs->icache) + fs->icache->refcount++; + + retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name); + if (retval) + goto errout; + strcpy(fs->device_name, src->device_name); + + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super); + if (retval) + goto errout; + memcpy(fs->super, src->super, SUPERBLOCK_SIZE); + + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super); + if (retval) + goto errout; + memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE); + + retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize, + &fs->group_desc); + if (retval) + goto errout; + memcpy(fs->group_desc, src->group_desc, + (size_t) fs->desc_blocks * fs->blocksize); + + if (src->inode_map) { + retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map); + if (retval) + goto errout; + } + if (src->block_map) { + retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map); + if (retval) + goto errout; + } + if (src->badblocks) { + retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks); + if (retval) + goto errout; + } + if (src->dblist) { + retval = ext2fs_copy_dblist(src->dblist, &fs->dblist); + if (retval) + goto errout; + } + *dest = fs; + return 0; +errout: + ext2fs_free(fs); + return retval; + +} + diff -Naur silo-1.4.14.orig/libext2fs/e2image.h silo-1.4.14/libext2fs/e2image.h --- silo-1.4.14.orig/libext2fs/e2image.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/e2image.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,51 @@ +/* + * e2image.h --- header file describing the ext2 image format + * + * Copyright (C) 2000 Theodore Ts'o. + * + * Note: this uses the POSIX IO interfaces, unlike most of the other + * functions in this library. So sue me. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + + +struct ext2_image_hdr { + __u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */ + char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */ + char fs_hostname[64];/* Hostname of machine of image */ + char fs_netaddr[32]; /* Network address */ + __u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */ + __u32 fs_device; /* Device number of image */ + char fs_device_name[64]; /* Device name */ + char fs_uuid[16]; /* UUID of filesystem */ + __u32 fs_blocksize; /* Block size of the filesystem */ + __u32 fs_reserved[8]; + + __u32 image_device; /* Device number of image file */ + __u32 image_inode; /* Inode number of image file */ + __u32 image_time; /* Time of image creation */ + __u32 image_reserved[8]; + + __u32 offset_super; /* Byte offset of the sb and descriptors */ + __u32 offset_inode; /* Byte offset of the inode table */ + __u32 offset_inodemap; /* Byte offset of the inode bitmaps */ + __u32 offset_blockmap; /* Byte offset of the inode bitmaps */ + __u32 offset_reserved[8]; +}; + + + + + + + + + + + + + diff -Naur silo-1.4.14.orig/libext2fs/expanddir.c silo-1.4.14/libext2fs/expanddir.c --- silo-1.4.14.orig/libext2fs/expanddir.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/expanddir.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,126 @@ +/* + * expand.c --- expand an ext2fs directory + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct expand_dir_struct { + int done; + int newblocks; + errcode_t err; +}; + +static int expand_dir_proc(ext2_filsys fs, + blk_t *blocknr, + e2_blkcnt_t blockcnt, + blk_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; + 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, 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; + retval = ext2fs_write_dir_block(fs, new_blk, block); + } else { + retval = ext2fs_get_mem(fs->blocksize, &block); + if (retval) { + es->err = retval; + 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; + } + ext2fs_free_mem(&block); + *blocknr = new_blk; + ext2fs_block_alloc_stats(fs, new_blk, +1); + es->newblocks++; + + if (es->done) + return (BLOCK_CHANGED | BLOCK_ABORT); + else + return BLOCK_CHANGED; +} + +errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir) +{ + errcode_t retval; + struct expand_dir_struct es; + struct ext2_inode inode; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + if (!fs->block_map) + return EXT2_ET_NO_BLOCK_BITMAP; + + retval = ext2fs_check_directory(fs, dir); + if (retval) + return retval; + + es.done = 0; + es.err = 0; + es.newblocks = 0; + + retval = ext2fs_block_iterate2(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) * es.newblocks; + + retval = ext2fs_write_inode(fs, dir, &inode); + if (retval) + return retval; + + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/ext2_err.c silo-1.4.14/libext2fs/ext2_err.c --- silo-1.4.14.orig/libext2fs/ext2_err.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/ext2_err.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,148 @@ +/* + * ext2_err.c: + * This file is automatically generated; please do not edit it. + */ + +#include + +static const char * const text[] = { + "EXT2FS Library version 1.38", + "Wrong magic number for ext2_filsys structure", + "Wrong magic number for badblocks_list structure", + "Wrong magic number for badblocks_iterate structure", + "Wrong magic number for inode_scan structure", + "Wrong magic number for io_channel structure", + "Wrong magic number for unix io_channel structure", + "Wrong magic number for io_manager structure", + "Wrong magic number for block_bitmap structure", + "Wrong magic number for inode_bitmap structure", + "Wrong magic number for generic_bitmap structure", + "Wrong magic number for test io_channel structure", + "Wrong magic number for directory block list structure", + "Wrong magic number for icount structure", + "Wrong magic number for Powerquest io_channel structure", + "Wrong magic number for ext2 file structure", + "Wrong magic number for Ext2 Image Header", + "Wrong magic number for inode io_channel structure", + "Wrong magic number --- RESERVED_9", + "Bad magic number in super-block", + "Filesystem revision too high", + "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", + "Illegal block number passed to ext2fs_mark_block_bitmap", + "Illegal block number passed to ext2fs_unmark_block_bitmap", + "Illegal block number passed to ext2fs_test_block_bitmap", + "Illegal inode number passed to ext2fs_mark_inode_bitmap", + "Illegal inode number passed to ext2fs_unmark_inode_bitmap", + "Illegal inode number passed to ext2fs_test_inode_bitmap", + "Attempt to fudge end of block bitmap past the real end", + "Attempt to fudge end of inode bitmap past the real end", + "Illegal indirect block found" , + "Illegal doubly indirect block found" , + "Illegal triply indirect block found" , + "Block bitmaps are not the same", + "Inode bitmaps are not the same", + "Illegal or malformed device name", + "A block group is missing an inode table", + "The ext2 superblock is corrupt", + "Illegal generic bit number passed to ext2fs_mark_generic_bitmap", + "Illegal generic bit number passed to ext2fs_unmark_generic_bitmap", + "Illegal generic bit number passed to ext2fs_test_generic_bitmap", + "Too many symbolic links encountered.", + "The callback function will not handle this case", + "The inode is from a bad block in the inode table", + "Filesystem has unsupported feature(s)", + "Filesystem has unsupported read-only feature(s)", + "IO Channel failed to seek on read or write", + "Memory allocation failed", + "Invalid argument passed to ext2 library", + "Could not allocate block in ext2 filesystem", + "Could not allocate inode in ext2 filesystem", + "Ext2 inode is not a directory", + "Too many references in table", + "File not found by ext2_lookup", + "File open read-only", + "Ext2 directory block not found", + "Ext2 directory already exists", + "Unimplemented ext2 library function", + "User cancel requested", + "Ext2 file too big", + "Supplied journal device not a block device", + "Journal superblock not found", + "Journal must be at least 1024 blocks", + "Unsupported journal version", + "Error loading external journal", + "Journal not found", + "Directory hash unsupported", + "Illegal extended attribute block number", + "Cannot create filesystem with requested number of inodes", + "E2image snapshot not in use", + "Too many reserved group descriptor blocks", + "Resize inode is corrupt", + "Missing indirect block not present", + 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; + +const struct error_table et_ext2_error_table = { text, 2133571328L, 96 }; + +static struct et_list link = { 0, 0 }; + +void initialize_ext2_error_table_r(struct et_list **list); +void initialize_ext2_error_table(void); + +void initialize_ext2_error_table(void) { + initialize_ext2_error_table_r(&_et_list); +} + +/* For Heimdal compatibility */ +void initialize_ext2_error_table_r(struct et_list **list) +{ + struct et_list *et, **end; + + for (end = list, et = *list; et; end = &et->next, et = et->next) + if (et->table->msgs == text) + return; + et = malloc(sizeof(struct et_list)); + if (et == 0) { + if (!link.table) + et = &link; + else + return; + } + et->table = &et_ext2_error_table; + et->next = 0; + *end = et; +} diff -Naur silo-1.4.14.orig/libext2fs/ext2_ext_attr.h silo-1.4.14/libext2fs/ext2_ext_attr.h --- silo-1.4.14.orig/libext2fs/ext2_ext_attr.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/ext2_ext_attr.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,69 @@ +/* + File: linux/ext2_ext_attr.h + + On-disk format of extended attributes for the ext2 filesystem. + + (C) 2000 Andreas Gruenbacher, +*/ + +/* Magic value in attribute blocks */ +#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000 +#define EXT2_EXT_ATTR_MAGIC 0xEA020000 + +/* Maximum number of references to one attribute block */ +#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024 + +struct ext2_ext_attr_header { + __u32 h_magic; /* magic number for identification */ + __u32 h_refcount; /* reference count */ + __u32 h_blocks; /* number of disk blocks used */ + __u32 h_hash; /* hash value of all attributes */ + __u32 h_reserved[4]; /* zero right now */ +}; + +struct ext2_ext_attr_entry { + __u8 e_name_len; /* length of name */ + __u8 e_name_index; /* attribute name index */ + __u16 e_value_offs; /* offset in disk block of value */ + __u32 e_value_block; /* disk block attribute is stored on (n/i) */ + __u32 e_value_size; /* size of attribute value */ + __u32 e_hash; /* hash value of name and value */ +#if 0 + char e_name[0]; /* attribute name */ +#endif +}; + +#define EXT2_EXT_ATTR_PAD_BITS 2 +#define EXT2_EXT_ATTR_PAD (1<e_name_len)) ) +#define EXT2_EXT_ATTR_SIZE(size) \ + (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND) +#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL) +#define EXT2_EXT_ATTR_NAME(entry) \ + (((char *) (entry)) + sizeof(struct ext2_ext_attr_entry)) +#define EXT2_XATTR_LEN(name_len) \ + (((name_len) + EXT2_EXT_ATTR_ROUND + \ + sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND) +#define EXT2_XATTR_SIZE(size) \ + (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND) + +#ifdef __KERNEL__ +# ifdef CONFIG_EXT2_FS_EXT_ATTR +extern int ext2_get_ext_attr(struct inode *, const char *, char *, size_t, int); +extern int ext2_set_ext_attr(struct inode *, const char *, char *, size_t, int); +extern void ext2_ext_attr_free_inode(struct inode *inode); +extern void ext2_ext_attr_put_super(struct super_block *sb); +extern int ext2_ext_attr_init(void); +extern void ext2_ext_attr_done(void); +# else +# define ext2_get_ext_attr NULL +# define ext2_set_ext_attr NULL +# endif +#endif /* __KERNEL__ */ + diff -Naur silo-1.4.14.orig/libext2fs/ext2_fs.h silo-1.4.14/libext2fs/ext2_fs.h --- silo-1.4.14.orig/libext2fs/ext2_fs.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/ext2_fs.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,644 @@ +/* + * linux/include/linux/ext2_fs.h + * + * Copyright (C) 1992, 1993, 1994, 1995 + * Remy Card (card@masi.ibp.fr) + * Laboratoire MASI - Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * from + * + * linux/include/linux/minix_fs.h + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#ifndef _LINUX_EXT2_FS_H +#define _LINUX_EXT2_FS_H + +#include /* Changed from linux/types.h */ + +/* + * The second extended filesystem constants/structures + */ + +/* + * Define EXT2FS_DEBUG to produce debug messages + */ +#undef EXT2FS_DEBUG + +/* + * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files + */ +#define EXT2_PREALLOCATE +#define EXT2_DEFAULT_PREALLOC_BLOCKS 8 + +/* + * The second extended file system version + */ +#define EXT2FS_DATE "95/08/09" +#define EXT2FS_VERSION "0.5b" + +/* + * Special inode numbers + */ +#define EXT2_BAD_INO 1 /* Bad blocks inode */ +#define EXT2_ROOT_INO 2 /* Root inode */ +#define EXT2_ACL_IDX_INO 3 /* ACL inode */ +#define EXT2_ACL_DATA_INO 4 /* ACL inode */ +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ +#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ +#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */ +#define EXT2_JOURNAL_INO 8 /* Journal inode */ + +/* First non-reserved inode for old ext2 filesystems */ +#define EXT2_GOOD_OLD_FIRST_INO 11 + +/* + * The second extended file system magic number + */ +#define EXT2_SUPER_MAGIC 0xEF53 + +#ifdef __KERNEL__ +#define EXT2_SB(sb) (&((sb)->u.ext2_sb)) +#else +/* Assume that user mode programs are passing in an ext2fs superblock, not + * a kernel struct super_block. This will allow us to call the feature-test + * macros from user land. */ +#define EXT2_SB(sb) (sb) +#endif + +/* + * Maximal count of links to a file + */ +#define EXT2_LINK_MAX 32000 + +/* + * Macro-instructions used to manage several block sizes + */ +#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */ +#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */ +#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE) +#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE) +#ifdef __KERNEL__ +#define EXT2_BLOCK_SIZE(s) ((s)->s_blocksize) +#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits) +#define EXT2_ADDR_PER_BLOCK_BITS(s) (EXT2_SB(s)->addr_per_block_bits) +#define EXT2_INODE_SIZE(s) (EXT2_SB(s)->s_inode_size) +#define EXT2_FIRST_INO(s) (EXT2_SB(s)->s_first_ino) +#else +#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) +#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) +#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ + EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size) +#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ + EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino) +#endif +#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32)) + +/* + * Macro-instructions used to manage fragments + */ +#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE +#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE +#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE +#ifdef __KERNEL__ +# define EXT2_FRAG_SIZE(s) (EXT2_SB(s)->s_frag_size) +# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_SB(s)->s_frags_per_block) +#else +# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size) +# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s)) +#endif + +/* + * ACL structures + */ +struct ext2_acl_header /* Header of Access Control Lists */ +{ + __u32 aclh_size; + __u32 aclh_file_count; + __u32 aclh_acle_count; + __u32 aclh_first_acle; +}; + +struct ext2_acl_entry /* Access Control List Entry */ +{ + __u32 acle_size; + __u16 acle_perms; /* Access permissions */ + __u16 acle_type; /* Type of entry */ + __u16 acle_tag; /* User or group identity */ + __u16 acle_pad1; + __u32 acle_next; /* Pointer on next entry for the */ + /* same inode or on next free entry */ +}; + +/* + * Structure of a blocks group descriptor + */ +struct ext2_group_desc +{ + __u32 bg_block_bitmap; /* Blocks bitmap block */ + __u32 bg_inode_bitmap; /* Inodes bitmap block */ + __u32 bg_inode_table; /* Inodes table block */ + __u16 bg_free_blocks_count; /* Free blocks count */ + __u16 bg_free_inodes_count; /* Free inodes count */ + __u16 bg_used_dirs_count; /* Directories count */ + __u16 bg_pad; + __u32 bg_reserved[3]; +}; + +/* + * Data structures used by the directory indexing feature + * + * Note: all of the multibyte integer fields are little endian. + */ + +/* + * Note: dx_root_info is laid out so that if it should somehow get + * overlaid by a dirent the two low bits of the hash version will be + * zero. Therefore, the hash version mod 4 should never be 0. + * Sincerely, the paranoia department. + */ +struct ext2_dx_root_info { + __u32 reserved_zero; + __u8 hash_version; /* 0 now, 1 at release */ + __u8 info_length; /* 8 */ + __u8 indirect_levels; + __u8 unused_flags; +}; + +#define EXT2_HASH_LEGACY 0 +#define EXT2_HASH_HALF_MD4 1 +#define EXT2_HASH_TEA 2 + +#define EXT2_HASH_FLAG_INCOMPAT 0x1 + +struct ext2_dx_entry { + __u32 hash; + __u32 block; +}; + +struct ext2_dx_countlimit { + __u16 limit; + __u16 count; +}; + + +/* + * Macro-instructions used to manage group descriptors + */ +#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) +#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) +#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s)) +/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */ +#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8) +#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s)) +#ifdef __KERNEL__ +#define EXT2_DESC_PER_BLOCK(s) (EXT2_SB(s)->s_desc_per_block) +#define EXT2_DESC_PER_BLOCK_BITS(s) (EXT2_SB(s)->s_desc_per_block_bits) +#else +#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) +#endif + +/* + * Constants relative to the data blocks + */ +#define EXT2_NDIR_BLOCKS 12 +#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS +#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) +#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) +#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) + +/* + * Inode flags + */ +#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */ +#define EXT2_UNRM_FL 0x00000002 /* Undelete */ +#define EXT2_COMPR_FL 0x00000004 /* Compress file */ +#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ +#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ +#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ +#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ +#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ +/* Reserved for compression usage... */ +#define EXT2_DIRTY_FL 0x00000100 +#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ +#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */ +#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */ +/* End compression flags --- maybe not all used */ +#define EXT2_BTREE_FL 0x00001000 /* btree format dir */ +#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */ +#define EXT2_IMAGIC_FL 0x00002000 +#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ +#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */ +#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */ +#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ +#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ +#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ + +#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ +#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ + +/* + * ioctl commands + */ +#define EXT2_IOC_GETFLAGS _IOR('f', 1, long) +#define EXT2_IOC_SETFLAGS _IOW('f', 2, long) +#define EXT2_IOC_GETVERSION _IOR('v', 1, long) +#define EXT2_IOC_SETVERSION _IOW('v', 2, long) + +/* + * Structure of an inode on the disk + */ +struct ext2_inode { + __u16 i_mode; /* File mode */ + __u16 i_uid; /* Low 16 bits of Owner Uid */ + __u32 i_size; /* Size in bytes */ + __u32 i_atime; /* Access time */ + __u32 i_ctime; /* Creation time */ + __u32 i_mtime; /* Modification time */ + __u32 i_dtime; /* Deletion Time */ + __u16 i_gid; /* Low 16 bits of Group Id */ + __u16 i_links_count; /* Links count */ + __u32 i_blocks; /* Blocks count */ + __u32 i_flags; /* File flags */ + union { + struct { + __u32 l_i_reserved1; + } linux1; + struct { + __u32 h_i_translator; + } hurd1; + struct { + __u32 m_i_reserved1; + } masix1; + } osd1; /* OS dependent 1 */ + __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ + __u32 i_generation; /* File version (for NFS) */ + __u32 i_file_acl; /* File ACL */ + __u32 i_dir_acl; /* Directory ACL */ + __u32 i_faddr; /* Fragment address */ + union { + struct { + __u8 l_i_frag; /* Fragment number */ + __u8 l_i_fsize; /* Fragment size */ + __u16 i_pad1; + __u16 l_i_uid_high; /* these 2 fields */ + __u16 l_i_gid_high; /* were reserved2[0] */ + __u32 l_i_reserved2; + } linux2; + struct { + __u8 h_i_frag; /* Fragment number */ + __u8 h_i_fsize; /* Fragment size */ + __u16 h_i_mode_high; + __u16 h_i_uid_high; + __u16 h_i_gid_high; + __u32 h_i_author; + } hurd2; + struct { + __u8 m_i_frag; /* Fragment number */ + __u8 m_i_fsize; /* Fragment size */ + __u16 m_pad1; + __u32 m_i_reserved2[2]; + } masix2; + } osd2; /* OS dependent 2 */ +}; + +/* + * Permanent part of an large inode on the disk + */ +struct ext2_inode_large { + __u16 i_mode; /* File mode */ + __u16 i_uid; /* Low 16 bits of Owner Uid */ + __u32 i_size; /* Size in bytes */ + __u32 i_atime; /* Access time */ + __u32 i_ctime; /* Creation time */ + __u32 i_mtime; /* Modification time */ + __u32 i_dtime; /* Deletion Time */ + __u16 i_gid; /* Low 16 bits of Group Id */ + __u16 i_links_count; /* Links count */ + __u32 i_blocks; /* Blocks count */ + __u32 i_flags; /* File flags */ + union { + struct { + __u32 l_i_reserved1; + } linux1; + struct { + __u32 h_i_translator; + } hurd1; + struct { + __u32 m_i_reserved1; + } masix1; + } osd1; /* OS dependent 1 */ + __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ + __u32 i_generation; /* File version (for NFS) */ + __u32 i_file_acl; /* File ACL */ + __u32 i_dir_acl; /* Directory ACL */ + __u32 i_faddr; /* Fragment address */ + union { + struct { + __u8 l_i_frag; /* Fragment number */ + __u8 l_i_fsize; /* Fragment size */ + __u16 i_pad1; + __u16 l_i_uid_high; /* these 2 fields */ + __u16 l_i_gid_high; /* were reserved2[0] */ + __u32 l_i_reserved2; + } linux2; + struct { + __u8 h_i_frag; /* Fragment number */ + __u8 h_i_fsize; /* Fragment size */ + __u16 h_i_mode_high; + __u16 h_i_uid_high; + __u16 h_i_gid_high; + __u32 h_i_author; + } hurd2; + struct { + __u8 m_i_frag; /* Fragment number */ + __u8 m_i_fsize; /* Fragment size */ + __u16 m_pad1; + __u32 m_i_reserved2[2]; + } masix2; + } osd2; /* OS dependent 2 */ + __u16 i_extra_isize; + __u16 i_pad1; +}; + +#define i_size_high i_dir_acl + +#if defined(__KERNEL__) || defined(__linux__) +#define i_reserved1 osd1.linux1.l_i_reserved1 +#define i_frag osd2.linux2.l_i_frag +#define i_fsize osd2.linux2.l_i_fsize +#define i_uid_low i_uid +#define i_gid_low i_gid +#define i_uid_high osd2.linux2.l_i_uid_high +#define i_gid_high osd2.linux2.l_i_gid_high +#define i_reserved2 osd2.linux2.l_i_reserved2 + +#else +#if defined(__GNU__) + +#define i_translator osd1.hurd1.h_i_translator +#define i_frag osd2.hurd2.h_i_frag; +#define i_fsize osd2.hurd2.h_i_fsize; +#define i_uid_high osd2.hurd2.h_i_uid_high +#define i_gid_high osd2.hurd2.h_i_gid_high +#define i_author osd2.hurd2.h_i_author + +#else +#if defined(__masix__) + +#define i_reserved1 osd1.masix1.m_i_reserved1 +#define i_frag osd2.masix2.m_i_frag +#define i_fsize osd2.masix2.m_i_fsize +#define i_reserved2 osd2.masix2.m_i_reserved2 + +#endif /* __masix__ */ +#endif /* __GNU__ */ +#endif /* defined(__KERNEL__) || defined(__linux__) */ + +/* + * File system states + */ +#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */ +#define EXT2_ERROR_FS 0x0002 /* Errors detected */ + +/* + * Mount flags + */ +#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */ +#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */ +#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */ +#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ +#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ +#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ +#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ +#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ + +#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt +#define set_opt(o, opt) o |= EXT2_MOUNT_##opt +#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \ + EXT2_MOUNT_##opt) +/* + * Maximal mount counts between two filesystem checks + */ +#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */ +#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */ + +/* + * Behaviour when detecting errors + */ +#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */ +#define EXT2_ERRORS_RO 2 /* Remount fs read-only */ +#define EXT2_ERRORS_PANIC 3 /* Panic */ +#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE + +/* + * Structure of the super block + */ +struct ext2_super_block { + __u32 s_inodes_count; /* Inodes count */ + __u32 s_blocks_count; /* Blocks count */ + __u32 s_r_blocks_count; /* Reserved blocks count */ + __u32 s_free_blocks_count; /* Free blocks count */ + __u32 s_free_inodes_count; /* Free inodes count */ + __u32 s_first_data_block; /* First Data Block */ + __u32 s_log_block_size; /* Block size */ + __s32 s_log_frag_size; /* Fragment size */ + __u32 s_blocks_per_group; /* # Blocks per group */ + __u32 s_frags_per_group; /* # Fragments per group */ + __u32 s_inodes_per_group; /* # Inodes per group */ + __u32 s_mtime; /* Mount time */ + __u32 s_wtime; /* Write time */ + __u16 s_mnt_count; /* Mount count */ + __s16 s_max_mnt_count; /* Maximal mount count */ + __u16 s_magic; /* Magic signature */ + __u16 s_state; /* File system state */ + __u16 s_errors; /* Behaviour when detecting errors */ + __u16 s_minor_rev_level; /* minor revision level */ + __u32 s_lastcheck; /* time of last check */ + __u32 s_checkinterval; /* max. time between checks */ + __u32 s_creator_os; /* OS */ + __u32 s_rev_level; /* Revision level */ + __u16 s_def_resuid; /* Default uid for reserved blocks */ + __u16 s_def_resgid; /* Default gid for reserved blocks */ + /* + * These fields are for EXT2_DYNAMIC_REV superblocks only. + * + * Note: the difference between the compatible feature set and + * the incompatible feature set is that if there is a bit set + * in the incompatible feature set that the kernel doesn't + * know about, it should refuse to mount the filesystem. + * + * e2fsck's requirements are more strict; if it doesn't know + * about a feature in either the compatible or incompatible + * feature set, it must abort and not try to meddle with + * things it doesn't understand... + */ + __u32 s_first_ino; /* First non-reserved inode */ + __u16 s_inode_size; /* size of inode structure */ + __u16 s_block_group_nr; /* block group # of this superblock */ + __u32 s_feature_compat; /* compatible feature set */ + __u32 s_feature_incompat; /* incompatible feature set */ + __u32 s_feature_ro_compat; /* readonly-compatible feature set */ + __u8 s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + __u32 s_algorithm_usage_bitmap; /* For compression */ + /* + * Performance hints. Directory preallocation should only + * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on. + */ + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + __u16 s_reserved_gdt_blocks; /* Per group table for online growth */ + /* + * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. + */ + __u8 s_journal_uuid[16]; /* uuid of journal superblock */ + __u32 s_journal_inum; /* inode number of journal file */ + __u32 s_journal_dev; /* device number of journal file */ + __u32 s_last_orphan; /* start of list of inodes to delete */ + __u32 s_hash_seed[4]; /* HTREE hash seed */ + __u8 s_def_hash_version; /* Default hash version to use */ + __u8 s_jnl_backup_type; /* Default type of journal backup */ + __u16 s_reserved_word_pad; + __u32 s_default_mount_opts; + __u32 s_first_meta_bg; /* First metablock group */ + __u32 s_mkfs_time; /* When the filesystem was created */ + __u32 s_jnl_blocks[17]; /* Backup of the journal inode */ + __u32 s_reserved[172]; /* Padding to the end of the block */ +}; + +/* + * Codes for operating systems + */ +#define EXT2_OS_LINUX 0 +#define EXT2_OS_HURD 1 +#define EXT2_OS_MASIX 2 +#define EXT2_OS_FREEBSD 3 +#define EXT2_OS_LITES 4 + +/* + * Revision levels + */ +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ + +#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV +#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV + +#define EXT2_GOOD_OLD_INODE_SIZE 128 + +/* + * Journal inode backup types + */ +#define EXT3_JNL_BACKUP_BLOCKS 1 + +/* + * Feature set definitions + */ + +#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_feature_compat & (mask) ) +#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_feature_ro_compat & (mask) ) +#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_feature_incompat & (mask) ) + +#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 +#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 +#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008 +#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010 +#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 + +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 +/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */ + +#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 + + +#define EXT2_FEATURE_COMPAT_SUPP 0 +#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE) +#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) + +/* + * Default values for user and/or group using reserved blocks + */ +#define EXT2_DEF_RESUID 0 +#define EXT2_DEF_RESGID 0 + +/* + * Default mount options + */ +#define EXT2_DEFM_DEBUG 0x0001 +#define EXT2_DEFM_BSDGROUPS 0x0002 +#define EXT2_DEFM_XATTR_USER 0x0004 +#define EXT2_DEFM_ACL 0x0008 +#define EXT2_DEFM_UID16 0x0010 +#define EXT3_DEFM_JMODE 0x0060 +#define EXT3_DEFM_JMODE_DATA 0x0020 +#define EXT3_DEFM_JMODE_ORDERED 0x0040 +#define EXT3_DEFM_JMODE_WBACK 0x0060 + +/* + * Structure of a directory entry + */ +#define EXT2_NAME_LEN 255 + +struct ext2_dir_entry { + __u32 inode; /* Inode number */ + __u16 rec_len; /* Directory entry length */ + __u16 name_len; /* Name length */ + char name[EXT2_NAME_LEN]; /* File name */ +}; + +/* + * The new version of the directory entry. Since EXT2 structures are + * stored in intel byte order, and the name_len field could never be + * bigger than 255 chars, it's safe to reclaim the extra byte for the + * file_type field. + */ +struct ext2_dir_entry_2 { + __u32 inode; /* Inode number */ + __u16 rec_len; /* Directory entry length */ + __u8 name_len; /* Name length */ + __u8 file_type; + char name[EXT2_NAME_LEN]; /* File name */ +}; + +/* + * Ext2 directory file types. Only the low 3 bits are used. The + * other bits are reserved for now. + */ +#define EXT2_FT_UNKNOWN 0 +#define EXT2_FT_REG_FILE 1 +#define EXT2_FT_DIR 2 +#define EXT2_FT_CHRDEV 3 +#define EXT2_FT_BLKDEV 4 +#define EXT2_FT_FIFO 5 +#define EXT2_FT_SOCK 6 +#define EXT2_FT_SYMLINK 7 + +#define EXT2_FT_MAX 8 + +/* + * EXT2_DIR_PAD defines the directory entries boundaries + * + * NOTE: It must be a multiple of 4 + */ +#define EXT2_DIR_PAD 4 +#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) +#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ + ~EXT2_DIR_ROUND) + +#endif /* _LINUX_EXT2_FS_H */ diff -Naur silo-1.4.14.orig/libext2fs/ext2_io.h silo-1.4.14/libext2fs/ext2_io.h --- silo-1.4.14.orig/libext2fs/ext2_io.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/ext2_io.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,108 @@ +/* + * io.h --- the I/O manager abstraction + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#ifndef _EXT2FS_EXT2_IO_H +#define _EXT2FS_EXT2_IO_H + +/* + * ext2_loff_t is defined here since unix_io.c needs it. + */ +#if defined(__GNUC__) || defined(HAS_LONG_LONG) +typedef long long ext2_loff_t; +#else +typedef long ext2_loff_t; +#endif + +/* llseek.c */ +ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int); + +typedef struct struct_io_manager *io_manager; +typedef struct struct_io_channel *io_channel; + +#define CHANNEL_FLAGS_WRITETHROUGH 0x01 + +struct struct_io_channel { + errcode_t magic; + io_manager manager; + char *name; + int block_size; + errcode_t (*read_error)(io_channel channel, + unsigned long block, + int count, + void *data, + size_t size, + int actual_bytes_read, + errcode_t error); + errcode_t (*write_error)(io_channel channel, + unsigned long block, + int count, + const void *data, + size_t size, + int actual_bytes_written, + errcode_t error); + int refcount; + int flags; + int reserved[14]; + void *private_data; + void *app_data; +}; + +struct struct_io_manager { + errcode_t magic; + const char *name; + errcode_t (*open)(const char *name, int flags, io_channel *channel); + errcode_t (*close)(io_channel channel); + errcode_t (*set_blksize)(io_channel channel, int blksize); + errcode_t (*read_blk)(io_channel channel, unsigned long block, + int count, void *data); + errcode_t (*write_blk)(io_channel channel, unsigned long block, + int count, const void *data); + errcode_t (*flush)(io_channel channel); + errcode_t (*write_byte)(io_channel channel, unsigned long offset, + int count, const void *data); + errcode_t (*set_option)(io_channel channel, const char *option, + const char *arg); + int reserved[14]; +}; + +#define IO_FLAG_RW 1 + +/* + * Convenience functions.... + */ +#define io_channel_close(c) ((c)->manager->close((c))) +#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s)) +#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d)) +#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d)) +#define io_channel_flush(c) ((c)->manager->flush((c))) +#define io_channel_bumpcount(c) ((c)->refcount++) + +/* io_manager.c */ +extern errcode_t io_channel_set_options(io_channel channel, + const char *options); +extern errcode_t io_channel_write_byte(io_channel channel, + unsigned long offset, + int count, const void *data); + +/* unix_io.c */ +extern io_manager unix_io_manager; + +/* test_io.c */ +extern io_manager test_io_manager, test_io_backing_manager; +extern void (*test_io_cb_read_blk) + (unsigned long block, int count, errcode_t err); +extern void (*test_io_cb_write_blk) + (unsigned long block, int count, errcode_t err); +extern void (*test_io_cb_set_blksize) + (int blksize, errcode_t err); + +#endif /* _EXT2FS_EXT2_IO_H */ + diff -Naur silo-1.4.14.orig/libext2fs/ext2fs.h silo-1.4.14/libext2fs/ext2fs.h --- silo-1.4.14.orig/libext2fs/ext2fs.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/ext2fs.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,1140 @@ +/* + * ext2fs.h --- ext2fs + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#ifndef _EXT2FS_EXT2FS_H +#define _EXT2FS_EXT2FS_H + +#ifdef __GNUC__ +#define EXT2FS_ATTR(x) __attribute__(x) +#else +#define EXT2FS_ATTR(x) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Non-GNU C compilers won't necessarily understand inline + */ +#if (!defined(__GNUC__) && !defined(__WATCOMC__)) +#define NO_INLINE_FUNCS +#endif + +/* + * Build in support for byte-swapping filesystems if we the feature + * has been configured or if we're being built on a CPU architecture + * with a non-native byte order. + */ +#if defined(ENABLE_SWAPFS) || defined(WORDS_BIGENDIAN) +#define EXT2FS_ENABLE_SWAPFS +#endif + +/* + * Where the master copy of the superblock is located, and how big + * superblocks are supposed to be. We define SUPERBLOCK_SIZE because + * the size of the superblock structure is not necessarily trustworthy + * (some versions have the padding set up so that the superblock is + * 1032 bytes long). + */ +#define SUPERBLOCK_OFFSET 1024 +#define SUPERBLOCK_SIZE 1024 + +/* + * The last ext2fs revision level that this version of the library is + * able to support. + */ +#define EXT2_LIB_CURRENT_REV EXT2_DYNAMIC_REV + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#include +#include + +#if EXT2_FLAT_INCLUDES +#include "e2_types.h" +#include "ext2_fs.h" +#else +#include +#include +#endif /* EXT2_FLAT_INCLUDES */ + +typedef __u32 ext2_ino_t; +typedef __u32 blk_t; +typedef __u32 dgrp_t; +typedef __u32 ext2_off_t; +typedef __s64 e2_blkcnt_t; +typedef __u32 ext2_dirhash_t; + +#if EXT2_FLAT_INCLUDES +#include "com_err.h" +#include "ext2_io.h" +#include "ext2_err.h" +#else +#include +#include +#include +#endif + +/* + * Portability help for Microsoft Visual C++ + */ +#ifdef _MSC_VER +#define EXT2_QSORT_TYPE int __cdecl +#else +#define EXT2_QSORT_TYPE int +#endif + +typedef struct struct_ext2_filsys *ext2_filsys; + +struct ext2fs_struct_generic_bitmap { + errcode_t magic; + ext2_filsys fs; + __u32 start, end; + __u32 real_end; + char * description; + char * bitmap; + errcode_t base_error_code; + __u32 reserved[7]; +}; + +#define EXT2FS_MARK_ERROR 0 +#define EXT2FS_UNMARK_ERROR 1 +#define EXT2FS_TEST_ERROR 2 + +typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap; +typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap; +typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap; + +#ifdef EXT2_DYNAMIC_REV +#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s) +#else +#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO +#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode) +#endif + +/* + * badblocks list definitions + */ + +typedef struct ext2_struct_u32_list *ext2_badblocks_list; +typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate; + +typedef struct ext2_struct_u32_list *ext2_u32_list; +typedef struct ext2_struct_u32_iterate *ext2_u32_iterate; + +/* old */ +typedef struct ext2_struct_u32_list *badblocks_list; +typedef struct ext2_struct_u32_iterate *badblocks_iterate; + +#define BADBLOCKS_FLAG_DIRTY 1 + +/* + * ext2_dblist structure and abstractions (see dblist.c) + */ +struct ext2_db_entry { + ext2_ino_t ino; + blk_t blk; + int blockcnt; +}; + +typedef struct ext2_struct_dblist *ext2_dblist; + +#define DBLIST_ABORT 1 + +/* + * ext2_fileio definitions + */ + +#define EXT2_FILE_WRITE 0x0001 +#define EXT2_FILE_CREATE 0x0002 + +#define EXT2_FILE_MASK 0x00FF + +#define EXT2_FILE_BUF_DIRTY 0x4000 +#define EXT2_FILE_BUF_VALID 0x2000 + +typedef struct ext2_file *ext2_file_t; + +#define EXT2_SEEK_SET 0 +#define EXT2_SEEK_CUR 1 +#define EXT2_SEEK_END 2 + +/* + * Flags for the ext2_filsys structure and for ext2fs_open() + */ +#define EXT2_FLAG_RW 0x01 +#define EXT2_FLAG_CHANGED 0x02 +#define EXT2_FLAG_DIRTY 0x04 +#define EXT2_FLAG_VALID 0x08 +#define EXT2_FLAG_IB_DIRTY 0x10 +#define EXT2_FLAG_BB_DIRTY 0x20 +#define EXT2_FLAG_SWAP_BYTES 0x40 +#define EXT2_FLAG_SWAP_BYTES_READ 0x80 +#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100 +#define EXT2_FLAG_MASTER_SB_ONLY 0x200 +#define EXT2_FLAG_FORCE 0x400 +#define EXT2_FLAG_SUPER_ONLY 0x800 +#define EXT2_FLAG_JOURNAL_DEV_OK 0x1000 +#define EXT2_FLAG_IMAGE_FILE 0x2000 + +/* + * Special flag in the ext2 inode i_flag field that means that this is + * a new inode. (So that ext2_write_inode() can clear extra fields.) + */ +#define EXT2_NEW_INODE_FL 0x80000000 + +/* + * Flags for mkjournal + * + * EXT2_MKJOURNAL_V1_SUPER Make a (deprecated) V1 journal superblock + */ +#define EXT2_MKJOURNAL_V1_SUPER 0x0000001 + +struct struct_ext2_filsys { + errcode_t magic; + io_channel io; + int flags; + char * device_name; + struct ext2_super_block * super; + unsigned int blocksize; + int fragsize; + dgrp_t group_desc_count; + unsigned long desc_blocks; + struct ext2_group_desc * group_desc; + int inode_blocks_per_group; + ext2fs_inode_bitmap inode_map; + ext2fs_block_bitmap block_map; + errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks); + errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino); + errcode_t (*write_bitmaps)(ext2_filsys fs); + errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode); + errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode); + ext2_badblocks_list badblocks; + ext2_dblist dblist; + __u32 stride; /* for mke2fs */ + struct ext2_super_block * orig_super; + struct ext2_image_hdr * image_header; + __u32 umask; + /* + * Reserved for future expansion + */ + __u32 reserved[8]; + + /* + * Reserved for the use of the calling application. + */ + void * priv_data; + + /* + * Inode cache + */ + struct ext2_inode_cache *icache; + io_channel image_io; +}; + +#if EXT2_FLAT_INCLUDES +#include "e2_bitops.h" +#else +#include +#endif + +/* + * Return flags for the block iterator functions + */ +#define BLOCK_CHANGED 1 +#define BLOCK_ABORT 2 +#define BLOCK_ERROR 4 + +/* + * Block interate flags + * + * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator + * function should be called on blocks where the block number is zero. + * This is used by ext2fs_expand_dir() to be able to add a new block + * to an inode. It can also be used for programs that want to be able + * to deal with files that contain "holes". + * + * BLOCK_FLAG_TRAVERSE indicates that the iterator function for the + * indirect, doubly indirect, etc. blocks should be called after all + * of the blocks containined in the indirect blocks are processed. + * This is useful if you are going to be deallocating blocks from an + * inode. + * + * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be + * called for data blocks only. + * + * BLOCK_FLAG_NO_LARGE is for internal use only. It informs + * ext2fs_block_iterate2 that large files won't be accepted. + */ +#define BLOCK_FLAG_APPEND 1 +#define BLOCK_FLAG_HOLE 1 +#define BLOCK_FLAG_DEPTH_TRAVERSE 2 +#define BLOCK_FLAG_DATA_ONLY 4 + +#define BLOCK_FLAG_NO_LARGE 0x1000 + +/* + * Magic "block count" return values for the block iterator function. + */ +#define BLOCK_COUNT_IND (-1) +#define BLOCK_COUNT_DIND (-2) +#define BLOCK_COUNT_TIND (-3) +#define BLOCK_COUNT_TRANSLATOR (-4) + +#if 0 +/* + * Flags for ext2fs_move_blocks + */ +#define EXT2_BMOVE_GET_DBLIST 0x0001 +#define EXT2_BMOVE_DEBUG 0x0002 +#endif + +/* + * Flags for directory block reading and writing functions + */ +#define EXT2_DIRBLOCK_V2_STRUCT 0x0001 + +/* + * Return flags for the directory iterator functions + */ +#define DIRENT_CHANGED 1 +#define DIRENT_ABORT 2 +#define DIRENT_ERROR 3 + +/* + * Directory iterator flags + */ + +#define DIRENT_FLAG_INCLUDE_EMPTY 1 +#define DIRENT_FLAG_INCLUDE_REMOVED 2 + +#define DIRENT_DOT_FILE 1 +#define DIRENT_DOT_DOT_FILE 2 +#define DIRENT_OTHER_FILE 3 +#define DIRENT_DELETED_FILE 4 + +/* + * Inode scan definitions + */ +typedef struct ext2_struct_inode_scan *ext2_inode_scan; + +/* + * ext2fs_scan flags + */ +#define EXT2_SF_CHK_BADBLOCKS 0x0001 +#define EXT2_SF_BAD_INODE_BLK 0x0002 +#define EXT2_SF_BAD_EXTRA_BYTES 0x0004 +#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008 + +/* + * ext2fs_check_if_mounted flags + */ +#define EXT2_MF_MOUNTED 1 +#define EXT2_MF_ISROOT 2 +#define EXT2_MF_READONLY 4 +#define EXT2_MF_SWAP 8 +#define EXT2_MF_BUSY 16 + +/* + * Ext2/linux mode flags. We define them here so that we don't need + * to depend on the OS's sys/stat.h, since we may be compiling on a + * non-Linux system. + */ +#define LINUX_S_IFMT 00170000 +#define LINUX_S_IFSOCK 0140000 +#define LINUX_S_IFLNK 0120000 +#define LINUX_S_IFREG 0100000 +#define LINUX_S_IFBLK 0060000 +#define LINUX_S_IFDIR 0040000 +#define LINUX_S_IFCHR 0020000 +#define LINUX_S_IFIFO 0010000 +#define LINUX_S_ISUID 0004000 +#define LINUX_S_ISGID 0002000 +#define LINUX_S_ISVTX 0001000 + +#define LINUX_S_IRWXU 00700 +#define LINUX_S_IRUSR 00400 +#define LINUX_S_IWUSR 00200 +#define LINUX_S_IXUSR 00100 + +#define LINUX_S_IRWXG 00070 +#define LINUX_S_IRGRP 00040 +#define LINUX_S_IWGRP 00020 +#define LINUX_S_IXGRP 00010 + +#define LINUX_S_IRWXO 00007 +#define LINUX_S_IROTH 00004 +#define LINUX_S_IWOTH 00002 +#define LINUX_S_IXOTH 00001 + +#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK) +#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG) +#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR) +#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR) +#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK) +#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO) +#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK) + +/* + * ext2 size of an inode + */ +#define EXT2_I_SIZE(i) ((i)->i_size | ((__u64) (i)->i_size_high << 32)) + +/* + * ext2_icount_t abstraction + */ +#define EXT2_ICOUNT_OPT_INCREMENT 0x01 + +typedef struct ext2_icount *ext2_icount_t; + +/* + * Flags for ext2fs_bmap + */ +#define BMAP_ALLOC 0x0001 +#define BMAP_SET 0x0002 + +/* + * Flags for imager.c functions + */ +#define IMAGER_FLAG_INODEMAP 1 +#define IMAGER_FLAG_SPARSEWRITE 2 + +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + + +/* + * For ext2 compression support + */ +#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff) +#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR) + +/* + * Features supported by this version of the library + */ +#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\ + EXT2_FEATURE_COMPAT_IMAGIC_INODES|\ + EXT3_FEATURE_COMPAT_HAS_JOURNAL|\ + EXT2_FEATURE_COMPAT_RESIZE_INODE|\ + EXT2_FEATURE_COMPAT_DIR_INDEX|\ + EXT2_FEATURE_COMPAT_EXT_ATTR) + +/* This #ifdef is temporary until compression is fully supported */ +#ifdef ENABLE_COMPRESSION +#ifndef I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL +/* If the below warning bugs you, then have + `CPPFLAGS=-DI_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL' in your + environment at configure time. */ + #warning "Compression support is experimental" +#endif +#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ + EXT2_FEATURE_INCOMPAT_COMPRESSION|\ + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\ + EXT2_FEATURE_INCOMPAT_META_BG|\ + EXT3_FEATURE_INCOMPAT_RECOVER) +#else +#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\ + EXT2_FEATURE_INCOMPAT_META_BG|\ + EXT3_FEATURE_INCOMPAT_RECOVER) +#endif +#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE) +/* + * function prototypes + */ + +/* alloc.c */ +extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode, + ext2fs_inode_bitmap map, ext2_ino_t *ret); +extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal, + ext2fs_block_bitmap map, blk_t *ret); +extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, + blk_t finish, int num, + ext2fs_block_bitmap map, + blk_t *ret); +extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal, + char *block_buf, blk_t *ret); + +/* alloc_sb.c */ +extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs, + dgrp_t group, + ext2fs_block_bitmap bmap); + +/* alloc_stats.c */ +void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse); +void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino, + int inuse, int isdir); +void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse); + +/* alloc_tables.c */ +extern errcode_t ext2fs_allocate_tables(ext2_filsys fs); +extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, + ext2fs_block_bitmap bmap); + +/* badblocks.c */ +extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size); +extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk); +extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk); +extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk); +extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb, + ext2_u32_iterate *ret); +extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk); +extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter); +extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest); +extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2); + +extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, + int size); +extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, + blk_t blk); +extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb, + blk_t blk); +extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk); +extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk); +extern errcode_t + ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, + ext2_badblocks_iterate *ret); +extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, + blk_t *blk); +extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter); +extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, + ext2_badblocks_list *dest); +extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1, + ext2_badblocks_list bb2); +extern int ext2fs_u32_list_count(ext2_u32_list bb); + +/* bb_compat */ +extern errcode_t badblocks_list_create(badblocks_list *ret, int size); +extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk); +extern int badblocks_list_test(badblocks_list bb, blk_t blk); +extern errcode_t badblocks_list_iterate_begin(badblocks_list bb, + badblocks_iterate *ret); +extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk); +extern void badblocks_list_iterate_end(badblocks_iterate iter); +extern void badblocks_list_free(badblocks_list bb); + +/* bb_inode.c */ +extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs, + ext2_badblocks_list bb_list); + +/* bitmaps.c */ +extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs); +extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs); +extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs); +extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs); +extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start, + __u32 end, + __u32 real_end, + const char *descr, + ext2fs_generic_bitmap *ret); +extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, + const char *descr, + ext2fs_block_bitmap *ret); +extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, + const char *descr, + ext2fs_inode_bitmap *ret); +extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap, + ext2_ino_t end, ext2_ino_t *oend); +extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap, + blk_t end, blk_t *oend); +extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap); +extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap); +extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs); +extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs); + +/* block.c */ +extern errcode_t ext2fs_block_iterate(ext2_filsys fs, + ext2_ino_t ino, + int flags, + char *block_buf, + int (*func)(ext2_filsys fs, + blk_t *blocknr, + int blockcnt, + void *priv_data), + void *priv_data); +errcode_t ext2fs_block_iterate2(ext2_filsys fs, + ext2_ino_t ino, + int flags, + char *block_buf, + int (*func)(ext2_filsys fs, + blk_t *blocknr, + e2_blkcnt_t blockcnt, + blk_t ref_blk, + int ref_offset, + void *priv_data), + void *priv_data); + +/* bmap.c */ +extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + char *block_buf, int bmap_flags, + blk_t block, blk_t *phys_blk); + + +#if 0 +/* bmove.c */ +extern errcode_t ext2fs_move_blocks(ext2_filsys fs, + ext2fs_block_bitmap reserve, + ext2fs_block_bitmap alloc_map, + int flags); +#endif + +/* check_desc.c */ +extern errcode_t ext2fs_check_desc(ext2_filsys fs); + +/* closefs.c */ +extern errcode_t ext2fs_close(ext2_filsys fs); +extern errcode_t ext2fs_flush(ext2_filsys fs); +extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block); +extern int ext2fs_super_and_bgd_loc(ext2_filsys fs, + dgrp_t group, + blk_t *ret_super_blk, + blk_t *ret_old_desc_blk, + blk_t *ret_new_desc_blk, + int *ret_meta_bg); +extern void ext2fs_update_dynamic_rev(ext2_filsys fs); + +/* cmp_bitmaps.c */ +extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1, + ext2fs_block_bitmap bm2); +extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1, + ext2fs_inode_bitmap bm2); + +/* dblist.c */ + +extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs); +extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist); +extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, + blk_t blk, int blockcnt); +extern void ext2fs_dblist_sort(ext2_dblist dblist, + EXT2_QSORT_TYPE (*sortfunc)(const void *, + const void *)); +extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist, + int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info, + void *priv_data), + void *priv_data); +extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, + blk_t blk, int blockcnt); +extern errcode_t ext2fs_copy_dblist(ext2_dblist src, + ext2_dblist *dest); +extern int ext2fs_dblist_count(ext2_dblist dblist); + +/* dblist_dir.c */ +extern errcode_t + ext2fs_dblist_dir_iterate(ext2_dblist dblist, + int flags, + char *block_buf, + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data); + +/* dirblock.c */ +extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block, + void *buf); +extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block, + void *buf, int flags); +extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block, + void *buf); +extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block, + void *buf, int flags); + +/* dirhash.c */ +extern errcode_t ext2fs_dirhash(int version, const char *name, int len, + const __u32 *seed, + ext2_dirhash_t *ret_hash, + ext2_dirhash_t *ret_minor_hash); + + +/* dir_iterate.c */ +extern errcode_t ext2fs_dir_iterate(ext2_filsys fs, + ext2_ino_t dir, + int flags, + char *block_buf, + int (*func)(struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data); +extern errcode_t ext2fs_dir_iterate2(ext2_filsys fs, + ext2_ino_t dir, + int flags, + char *block_buf, + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data), + void *priv_data); + +/* dupfs.c */ +extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest); + +/* expanddir.c */ +extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir); + +/* ext_attr.c */ +extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf); +extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, + void *buf); +extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, + char *block_buf, + int adjust, __u32 *newcount); + +/* fileio.c */ +extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + int flags, ext2_file_t *ret); +extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, + int flags, ext2_file_t *ret); +extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file); +extern errcode_t ext2fs_file_close(ext2_file_t file); +extern errcode_t ext2fs_file_flush(ext2_file_t file); +extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf, + unsigned int wanted, unsigned int *got); +extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, + unsigned int nbytes, unsigned int *written); +extern errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset, + int whence, __u64 *ret_pos); +extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset, + int whence, ext2_off_t *ret_pos); +errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size); +extern ext2_off_t ext2fs_file_get_size(ext2_file_t file); +extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size); + +/* finddev.c */ +extern char *ext2fs_find_block_device(dev_t device); + +/* flushb.c */ +extern errcode_t ext2fs_sync_device(int fd, int flushb); + +/* freefs.c */ +extern void ext2fs_free(ext2_filsys fs); +extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap); +extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap); +extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap); +extern void ext2fs_free_dblist(ext2_dblist dblist); +extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb); +extern void ext2fs_u32_list_free(ext2_u32_list bb); + +/* getsize.c */ +extern errcode_t ext2fs_get_device_size(const char *file, int blocksize, + blk_t *retblocks); + +/* getsectsize.c */ +errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize); + +/* imager.c */ +extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags); +extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags); +extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags); +extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags); +extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags); +extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags); + +/* ind_block.c */ +errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf); +errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf); + +/* initialize.c */ +extern errcode_t ext2fs_initialize(const char *name, int flags, + struct ext2_super_block *param, + io_manager manager, ext2_filsys *ret_fs); + +/* icount.c */ +extern void ext2fs_free_icount(ext2_icount_t icount); +extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, + unsigned int size, + ext2_icount_t hint, ext2_icount_t *ret); +extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, + unsigned int size, + ext2_icount_t *ret); +extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret); +extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret); +extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret); +extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, + __u16 count); +extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount); +errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *); + +/* inode.c */ +extern errcode_t ext2fs_flush_icache(ext2_filsys fs); +extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, + ext2_ino_t *ino, + struct ext2_inode *inode, + int bufsize); +extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, + ext2_inode_scan *ret_scan); +extern void ext2fs_close_inode_scan(ext2_inode_scan scan); +extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, + struct ext2_inode *inode); +extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, + int group); +extern void ext2fs_set_inode_callback + (ext2_inode_scan scan, + errcode_t (*done_group)(ext2_filsys fs, + ext2_inode_scan scan, + dgrp_t group, + void * priv_data), + void *done_group_data); +extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, + int clear_flags); +extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, + int bufsize); +extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode); +extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, + int bufsize); +extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode); +extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode); +extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks); +extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino); + +/* inode_io.c */ +extern io_manager inode_io_manager; +extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino, + char **name); +extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + char **name); + +/* ismounted.c */ +extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags); +extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, + char *mtpt, int mtlen); + +/* namei.c */ +extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name, + int namelen, char *buf, ext2_ino_t *inode); +extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + const char *name, ext2_ino_t *inode); +errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + const char *name, ext2_ino_t *inode); +extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + ext2_ino_t inode, ext2_ino_t *res_inode); + +/* native.c */ +int ext2fs_native_flag(void); + +/* newdir.c */ +extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino, + ext2_ino_t parent_ino, char **block); + +/* mkdir.c */ +extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, + const char *name); + +/* mkjournal.c */ +extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, + __u32 size, int flags, + char **ret_jsb); +extern errcode_t ext2fs_add_journal_device(ext2_filsys fs, + ext2_filsys journal_dev); +extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, + int flags); + +/* openfs.c */ +extern errcode_t ext2fs_open(const char *name, int flags, int superblock, + unsigned int block_size, io_manager manager, + ext2_filsys *ret_fs); +extern errcode_t ext2fs_open2(const char *name, const char *io_options, + int flags, int superblock, + unsigned int block_size, io_manager manager, + ext2_filsys *ret_fs); +extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, + dgrp_t i); +errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io); +errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io); +errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io); + +/* get_pathname.c */ +extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino, + char **name); + +/* link.c */ +errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, + ext2_ino_t ino, int flags); +errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name, + ext2_ino_t ino, int flags); + +/* read_bb.c */ +extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs, + ext2_badblocks_list *bb_list); + +/* read_bb_file.c */ +extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f, + ext2_badblocks_list *bb_list, + void *priv_data, + void (*invalid)(ext2_filsys fs, + blk_t blk, + char *badstr, + void *priv_data)); +extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f, + ext2_badblocks_list *bb_list, + void (*invalid)(ext2_filsys fs, + blk_t blk)); + +/* res_gdt.c */ +extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs); + +/* rs_bitmap.c */ +extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, + __u32 new_real_end, + ext2fs_generic_bitmap bmap); +extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end, + ext2fs_inode_bitmap bmap); +extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end, + ext2fs_block_bitmap bmap); +extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, + ext2fs_generic_bitmap *dest); + +/* swapfs.c */ +extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, + int has_header); +extern void ext2fs_swap_super(struct ext2_super_block * super); +extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp); +extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, + struct ext2_inode_large *f, int hostorder, + int bufsize); +extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t, + struct ext2_inode *f, int hostorder); + +/* valid_blk.c */ +extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode); + +/* version.c */ +extern int ext2fs_parse_version_string(const char *ver_string); +extern int ext2fs_get_library_version(const char **ver_string, + const char **date_string); + +/* write_bb_file.c */ +extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list, + unsigned int flags, + FILE *f); + + +/* inline functions */ +extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr); +extern errcode_t ext2fs_free_mem(void *ptr); +extern errcode_t ext2fs_resize_mem(unsigned long old_size, + unsigned long size, void *ptr); +extern void ext2fs_mark_super_dirty(ext2_filsys fs); +extern void ext2fs_mark_changed(ext2_filsys fs); +extern int ext2fs_test_changed(ext2_filsys fs); +extern void ext2fs_mark_valid(ext2_filsys fs); +extern void ext2fs_unmark_valid(ext2_filsys fs); +extern int ext2fs_test_valid(ext2_filsys fs); +extern void ext2fs_mark_ib_dirty(ext2_filsys fs); +extern void ext2fs_mark_bb_dirty(ext2_filsys fs); +extern int ext2fs_test_ib_dirty(ext2_filsys fs); +extern int ext2fs_test_bb_dirty(ext2_filsys fs); +extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk); +extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino); +extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs, + struct ext2_inode *inode); + +/* + * The actual inlined functions definitions 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 +#ifdef __GNUC__ +#define _INLINE_ extern __inline__ +#else /* For Watcom C */ +#define _INLINE_ extern inline +#endif +#endif + +#ifndef EXT2_CUSTOM_MEMORY_ROUTINES +/* + * Allocate memory + */ +_INLINE_ errcode_t ext2fs_get_mem(unsigned long size, void *ptr) +{ + void **pp = (void **)ptr; + + *pp = malloc(size); + if (!*pp) + return EXT2_ET_NO_MEMORY; + return 0; +} + +/* + * Free memory + */ +_INLINE_ errcode_t ext2fs_free_mem(void *ptr) +{ + void **pp = (void **)ptr; + + free(*pp); + *pp = 0; + return 0; +} + +/* + * Resize memory + */ +_INLINE_ errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size, + unsigned long size, void *ptr) +{ + void *p; + + /* Use "memcpy" for pointer assignments here to avoid problems + * with C99 strict type aliasing rules. */ + memcpy(&p, ptr, sizeof (p)); + p = realloc(p, size); + if (!p) + return EXT2_ET_NO_MEMORY; + memcpy(ptr, &p, sizeof (p)); + return 0; +} +#endif /* Custom memory routines */ + +/* + * Mark a filesystem superblock as dirty + */ +_INLINE_ void ext2fs_mark_super_dirty(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED; +} + +/* + * Mark a filesystem as changed + */ +_INLINE_ void ext2fs_mark_changed(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_CHANGED; +} + +/* + * Check to see if a filesystem has changed + */ +_INLINE_ int ext2fs_test_changed(ext2_filsys fs) +{ + return (fs->flags & EXT2_FLAG_CHANGED); +} + +/* + * Mark a filesystem as valid + */ +_INLINE_ void ext2fs_mark_valid(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_VALID; +} + +/* + * Mark a filesystem as NOT valid + */ +_INLINE_ void ext2fs_unmark_valid(ext2_filsys fs) +{ + fs->flags &= ~EXT2_FLAG_VALID; +} + +/* + * Check to see if a filesystem is valid + */ +_INLINE_ int ext2fs_test_valid(ext2_filsys fs) +{ + return (fs->flags & EXT2_FLAG_VALID); +} + +/* + * Mark the inode bitmap as dirty + */ +_INLINE_ void ext2fs_mark_ib_dirty(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED; +} + +/* + * Mark the block bitmap as dirty + */ +_INLINE_ void ext2fs_mark_bb_dirty(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED; +} + +/* + * Check to see if a filesystem's inode bitmap is dirty + */ +_INLINE_ int ext2fs_test_ib_dirty(ext2_filsys fs) +{ + return (fs->flags & EXT2_FLAG_IB_DIRTY); +} + +/* + * Check to see if a filesystem's block bitmap is dirty + */ +_INLINE_ int ext2fs_test_bb_dirty(ext2_filsys fs) +{ + return (fs->flags & EXT2_FLAG_BB_DIRTY); +} + +/* + * Return the group # of a block + */ +_INLINE_ int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk) +{ + return (blk - fs->super->s_first_data_block) / + fs->super->s_blocks_per_group; +} + +/* + * Return the group # of an inode number + */ +_INLINE_ int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino) +{ + return (ino - 1) / fs->super->s_inodes_per_group; +} + +_INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs, + struct ext2_inode *inode) +{ + return inode->i_blocks - + (inode->i_file_acl ? fs->blocksize >> 9 : 0); +} +#undef _INLINE_ +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _EXT2FS_EXT2FS_H */ diff -Naur silo-1.4.14.orig/libext2fs/ext2fsP.h silo-1.4.14/libext2fs/ext2fsP.h --- silo-1.4.14.orig/libext2fs/ext2fsP.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/ext2fsP.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,88 @@ +/* + * ext2fsP.h --- private header file for ext2 library + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include "ext2fs.h" + +/* + * Badblocks list + */ +struct ext2_struct_u32_list { + int magic; + int num; + int size; + __u32 *list; + int badblocks_flags; +}; + +struct ext2_struct_u32_iterate { + int magic; + ext2_u32_list bb; + int ptr; +}; + + +/* + * Directory block iterator definition + */ +struct ext2_struct_dblist { + int magic; + ext2_filsys fs; + ext2_ino_t size; + ext2_ino_t count; + int sorted; + struct ext2_db_entry * list; +}; + +/* + * For directory iterators + */ +struct dir_context { + ext2_ino_t dir; + int flags; + char *buf; + int (*func)(ext2_ino_t dir, + int entry, + struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data); + void *priv_data; + errcode_t errcode; +}; + +/* + * Inode cache structure + */ +struct ext2_inode_cache { + void * buffer; + blk_t buffer_blk; + int cache_last; + int cache_size; + int refcount; + struct ext2_inode_cache_ent *cache; +}; + +struct ext2_inode_cache_ent { + ext2_ino_t ino; + struct ext2_inode inode; +}; + +/* Function prototypes */ + +extern int ext2fs_process_dir_block(ext2_filsys fs, + blk_t *blocknr, + e2_blkcnt_t blockcnt, + blk_t ref_block, + int ref_offset, + void *priv_data); + + diff -Naur silo-1.4.14.orig/libext2fs/ext_attr.c silo-1.4.14/libext2fs/ext_attr.c --- silo-1.4.14.orig/libext2fs/ext_attr.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/ext_attr.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,105 @@ +/* + * ext_attr.c --- extended attribute blocks + * + * Copyright (C) 2001 Andreas Gruenbacher, + * + * Copyright (C) 2002 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2_ext_attr.h" + +#include "ext2fs.h" + +errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf) +{ + errcode_t retval; + + retval = io_channel_read_blk(fs->io, block, 1, buf); + if (retval) + return retval; +#ifdef EXT2FS_ENABLE_SWAPFS + if ((fs->flags & (EXT2_FLAG_SWAP_BYTES| + EXT2_FLAG_SWAP_BYTES_READ)) != 0) + ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1); +#endif + return 0; +} + +errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf) +{ + errcode_t retval; + char *write_buf; + char *buf = NULL; + +#ifdef EXT2FS_ENABLE_SWAPFS + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) { + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + write_buf = buf; + ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1); + } else +#endif + write_buf = (char *) inbuf; + retval = io_channel_write_blk(fs->io, block, 1, write_buf); + if (buf) + ext2fs_free_mem(&buf); + if (!retval) + ext2fs_mark_changed(fs); + return retval; +} + +/* + * This function adjusts the reference count of the EA block. + */ +errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, + char *block_buf, int adjust, + __u32 *newcount) +{ + errcode_t retval; + struct ext2_ext_attr_header *header; + char *buf = 0; + + if ((blk >= fs->super->s_blocks_count) || + (blk < fs->super->s_first_data_block)) + return EXT2_ET_BAD_EA_BLOCK_NUM; + + if (!block_buf) { + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + block_buf = buf; + } + + retval = ext2fs_read_ext_attr(fs, blk, block_buf); + if (retval) + goto errout; + + header = (struct ext2_ext_attr_header *) block_buf; + header->h_refcount += adjust; + if (newcount) + *newcount = header->h_refcount; + + retval = ext2fs_write_ext_attr(fs, blk, block_buf); + if (retval) + goto errout; + +errout: + if (buf) + ext2fs_free_mem(&buf); + return retval; +} diff -Naur silo-1.4.14.orig/libext2fs/fileio.c silo-1.4.14/libext2fs/fileio.c --- silo-1.4.14.orig/libext2fs/fileio.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/fileio.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,378 @@ +/* + * fileio.c --- Simple file I/O routines + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct ext2_file { + errcode_t magic; + ext2_filsys fs; + ext2_ino_t ino; + struct ext2_inode inode; + int flags; + __u64 pos; + blk_t blockno; + blk_t physblock; + char *buf; +}; + +#define BMAP_BUFFER (file->buf + fs->blocksize) + +errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + int flags, ext2_file_t *ret) +{ + ext2_file_t file; + errcode_t retval; + + /* + * Don't let caller create or open a file for writing if the + * filesystem is read-only. + */ + if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) && + !(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + retval = ext2fs_get_mem(sizeof(struct ext2_file), &file); + if (retval) + return retval; + + memset(file, 0, sizeof(struct ext2_file)); + file->magic = EXT2_ET_MAGIC_EXT2_FILE; + file->fs = fs; + file->ino = ino; + file->flags = flags & EXT2_FILE_MASK; + + if (inode) { + memcpy(&file->inode, inode, sizeof(struct ext2_inode)); + } else { + retval = ext2fs_read_inode(fs, ino, &file->inode); + if (retval) + goto fail; + } + + retval = ext2fs_get_mem(fs->blocksize * 3, &file->buf); + if (retval) + goto fail; + + *ret = file; + return 0; + +fail: + if (file->buf) + ext2fs_free_mem(&file->buf); + ext2fs_free_mem(&file); + return retval; +} + +errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, + int flags, ext2_file_t *ret) +{ + return ext2fs_file_open2(fs, ino, NULL, flags, ret); +} + +/* + * This function returns the filesystem handle of a file from the structure + */ +ext2_filsys ext2fs_file_get_fs(ext2_file_t file) +{ + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) + return 0; + return file->fs; +} + +/* + * This function flushes the dirty block buffer out to disk if + * necessary. + */ +errcode_t ext2fs_file_flush(ext2_file_t file) +{ + errcode_t retval; + ext2_filsys fs; + + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + fs = file->fs; + + if (!(file->flags & EXT2_FILE_BUF_VALID) || + !(file->flags & EXT2_FILE_BUF_DIRTY)) + return 0; + + /* + * OK, the physical block hasn't been allocated yet. + * Allocate it. + */ + if (!file->physblock) { + retval = ext2fs_bmap(fs, file->ino, &file->inode, + BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0, + file->blockno, &file->physblock); + if (retval) + return retval; + } + + retval = io_channel_write_blk(fs->io, file->physblock, + 1, file->buf); + if (retval) + return retval; + + file->flags &= ~EXT2_FILE_BUF_DIRTY; + + return retval; +} + +/* + * This function synchronizes the file's block buffer and the current + * file position, possibly invalidating block buffer if necessary + */ +static errcode_t sync_buffer_position(ext2_file_t file) +{ + blk_t b; + errcode_t retval; + + b = file->pos / file->fs->blocksize; + if (b != file->blockno) { + retval = ext2fs_file_flush(file); + if (retval) + return retval; + file->flags &= ~EXT2_FILE_BUF_VALID; + } + file->blockno = b; + return 0; +} + +/* + * This function loads the file's block buffer with valid data from + * the disk as necessary. + * + * If dontfill is true, then skip initializing the buffer since we're + * going to be replacing its entire contents anyway. If set, then the + * function basically only sets file->physblock and EXT2_FILE_BUF_VALID + */ +#define DONTFILL 1 +static errcode_t load_buffer(ext2_file_t file, int dontfill) +{ + ext2_filsys fs = file->fs; + errcode_t retval; + + if (!(file->flags & EXT2_FILE_BUF_VALID)) { + retval = ext2fs_bmap(fs, file->ino, &file->inode, + BMAP_BUFFER, 0, file->blockno, + &file->physblock); + if (retval) + return retval; + if (!dontfill) { + if (file->physblock) { + retval = io_channel_read_blk(fs->io, + file->physblock, + 1, file->buf); + if (retval) + return retval; + } else + memset(file->buf, 0, fs->blocksize); + } + file->flags |= EXT2_FILE_BUF_VALID; + } + return 0; +} + + +errcode_t ext2fs_file_close(ext2_file_t file) +{ + errcode_t retval; + + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + + retval = ext2fs_file_flush(file); + + if (file->buf) + ext2fs_free_mem(&file->buf); + ext2fs_free_mem(&file); + + return retval; +} + + +errcode_t ext2fs_file_read(ext2_file_t file, void *buf, + unsigned int wanted, unsigned int *got) +{ + ext2_filsys fs; + errcode_t retval = 0; + unsigned int start, c, count = 0; + __u64 left; + char *ptr = (char *) buf; + + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + fs = file->fs; + + while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) { + retval = sync_buffer_position(file); + if (retval) + goto fail; + retval = load_buffer(file, 0); + if (retval) + goto fail; + + start = file->pos % fs->blocksize; + c = fs->blocksize - start; + if (c > wanted) + c = wanted; + left = EXT2_I_SIZE(&file->inode) - file->pos ; + if (c > left) + c = left; + + memcpy(ptr, file->buf+start, c); + file->pos += c; + ptr += c; + count += c; + wanted -= c; + } + +fail: + if (got) + *got = count; + return retval; +} + + +errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, + unsigned int nbytes, unsigned int *written) +{ + ext2_filsys fs; + errcode_t retval = 0; + unsigned int start, c, count = 0; + const char *ptr = (const char *) buf; + + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + fs = file->fs; + + if (!(file->flags & EXT2_FILE_WRITE)) + return EXT2_ET_FILE_RO; + + while (nbytes > 0) { + retval = sync_buffer_position(file); + if (retval) + goto fail; + + start = file->pos % fs->blocksize; + c = fs->blocksize - start; + if (c > nbytes) + c = nbytes; + + /* + * We only need to do a read-modify-update cycle if + * we're doing a partial write. + */ + retval = load_buffer(file, (c == fs->blocksize)); + if (retval) + goto fail; + + file->flags |= EXT2_FILE_BUF_DIRTY; + memcpy(file->buf+start, ptr, c); + file->pos += c; + ptr += c; + count += c; + nbytes -= c; + } + +fail: + if (written) + *written = count; + return retval; +} + +errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset, + int whence, __u64 *ret_pos) +{ + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + + if (whence == EXT2_SEEK_SET) + file->pos = offset; + else if (whence == EXT2_SEEK_CUR) + file->pos += offset; + else if (whence == EXT2_SEEK_END) + file->pos = EXT2_I_SIZE(&file->inode) + offset; + else + return EXT2_ET_INVALID_ARGUMENT; + + if (ret_pos) + *ret_pos = file->pos; + + return 0; +} + +errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset, + int whence, ext2_off_t *ret_pos) +{ + __u64 loffset, ret_loffset; + errcode_t retval; + + loffset = offset; + retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset); + if (ret_pos) + *ret_pos = (ext2_off_t) ret_loffset; + return retval; +} + + +/* + * This function returns the size of the file, according to the inode + */ +errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size) +{ + if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) + return EXT2_ET_MAGIC_EXT2_FILE; + *ret_size = EXT2_I_SIZE(&file->inode); + return 0; +} + +/* + * This function returns the size of the file, according to the inode + */ +ext2_off_t ext2fs_file_get_size(ext2_file_t file) +{ + __u64 size; + + if (ext2fs_file_get_lsize(file, &size)) + return 0; + if ((size >> 32) != 0) + return 0; + return size; +} + +/* + * This function sets the size of the file, truncating it if necessary + * + * XXX still need to call truncate + */ +errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size) +{ + errcode_t retval; + EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); + + file->inode.i_size = size; + file->inode.i_size_high = 0; + if (file->ino) { + retval = ext2fs_write_inode(file->fs, file->ino, &file->inode); + if (retval) + return retval; + } + + /* + * XXX truncate inode if necessary + */ + + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/finddev.c silo-1.4.14/libext2fs/finddev.c --- silo-1.4.14.orig/libext2fs/finddev.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/finddev.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,208 @@ +/* + * finddev.c -- this routine attempts to find a particular device in + * /dev + * + * Copyright (C) 2000 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#include +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_SYS_MKDEV_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct dir_list { + char *name; + struct dir_list *next; +}; + +/* + * This function adds an entry to the directory list + */ +static void add_to_dirlist(const char *name, struct dir_list **list) +{ + struct dir_list *dp; + + dp = malloc(sizeof(struct dir_list)); + if (!dp) + return; + dp->name = malloc(strlen(name)+1); + if (!dp->name) { + free(dp); + return; + } + strcpy(dp->name, name); + dp->next = *list; + *list = dp; +} + +/* + * This function frees a directory list + */ +static void free_dirlist(struct dir_list **list) +{ + struct dir_list *dp, *next; + + for (dp = *list; dp; dp = next) { + next = dp->next; + free(dp->name); + free(dp); + } + *list = 0; +} + +static int scan_dir(char *dirname, dev_t device, struct dir_list **list, + char **ret_path) +{ + DIR *dir; + struct dirent *dp; + char path[1024], *cp; + int dirlen; + struct stat st; + + dirlen = strlen(dirname); + if ((dir = opendir(dirname)) == NULL) + return errno; + dp = readdir(dir); + while (dp) { + if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path)) + goto skip_to_next; + if (dp->d_name[0] == '.' && + ((dp->d_name[1] == 0) || + ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) + goto skip_to_next; + sprintf(path, "%s/%s", dirname, dp->d_name); + if (stat(path, &st) < 0) + goto skip_to_next; + if (S_ISDIR(st.st_mode)) + add_to_dirlist(path, list); + if (S_ISBLK(st.st_mode) && st.st_rdev == device) { + cp = malloc(strlen(path)+1); + if (!cp) { + closedir(dir); + return ENOMEM; + } + strcpy(cp, path); + *ret_path = cp; + goto success; + } + skip_to_next: + dp = readdir(dir); + } +success: + closedir(dir); + return 0; +} + +/* + * This function finds the pathname to a block device with a given + * device number. It returns a pointer to allocated memory to the + * pathname on success, and NULL on failure. + */ +char *ext2fs_find_block_device(dev_t device) +{ + struct dir_list *list = 0, *new_list = 0; + struct dir_list *current; + char *ret_path = 0; + + /* + * Add the starting directories to search... + */ + add_to_dirlist("/devices", &list); + add_to_dirlist("/devfs", &list); + add_to_dirlist("/dev", &list); + + while (list) { + current = list; + list = list->next; +#ifdef DEBUG + printf("Scanning directory %s\n", current->name); +#endif + scan_dir(current->name, device, &new_list, &ret_path); + free(current->name); + free(current); + if (ret_path) + break; + /* + * If we're done checking at this level, descend to + * the next level of subdirectories. (breadth-first) + */ + if (list == 0) { + list = new_list; + new_list = 0; + } + } + free_dirlist(&list); + free_dirlist(&new_list); + return ret_path; +} + + +#ifdef DEBUG +int main(int argc, char** argv) +{ + char *devname, *tmp; + int major, minor; + dev_t device; + const char *errmsg = "Couldn't parse %s: %s\n"; + + if ((argc != 2) && (argc != 3)) { + fprintf(stderr, "Usage: %s device_number\n", argv[0]); + fprintf(stderr, "\t: %s major minor\n", argv[0]); + exit(1); + } + if (argc == 2) { + device = strtoul(argv[1], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "device number", argv[1]); + exit(1); + } + } else { + major = strtoul(argv[1], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "major number", argv[1]); + exit(1); + } + minor = strtoul(argv[2], &tmp, 0); + if (*tmp) { + fprintf(stderr, errmsg, "minor number", argv[2]); + exit(1); + } + device = makedev(major, minor); + printf("Looking for device 0x%04x (%d:%d)\n", device, + major, minor); + } + devname = ext2fs_find_block_device(device); + if (devname) { + printf("Found device! %s\n", devname); + free(devname); + } else { + printf("Couldn't find device.\n"); + } + return 0; +} + +#endif diff -Naur silo-1.4.14.orig/libext2fs/flushb.c silo-1.4.14/libext2fs/flushb.c --- silo-1.4.14.orig/libext2fs/flushb.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/flushb.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,82 @@ +/* + * flushb.c --- Hides system-dependent information for both syncing a + * device to disk and to flush any buffers from disk cache. + * + * Copyright (C) 2000 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_SYS_IOCTL_H +#include +#endif +#if HAVE_SYS_MOUNT_H +#include +#include /* This may define BLKFLSBUF */ +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * For Linux, define BLKFLSBUF and FDFLUSH if necessary, since + * not all portable header file does so for us. This really should be + * fixed in the glibc header files. (Recent glibcs appear to define + * BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be + * defined anywhere portable.) Until then.... + */ +#ifdef __linux__ +#ifndef BLKFLSBUF +#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ +#endif +#ifndef FDFLUSH +#define FDFLUSH _IO(2,0x4b) /* flush floppy disk */ +#endif +#endif + +/* + * This function will sync a device/file, and optionally attempt to + * flush the buffer cache. The latter is basically only useful for + * system benchmarks and for torturing systems in burn-in tests. :) + */ +errcode_t ext2fs_sync_device(int fd, int flushb) +{ + /* + * We always sync the device in case we're running on old + * kernels for which we can lose data if we don't. (There + * still is a race condition for those kernels, but this + * reduces it greatly.) + */ + if (fsync (fd) == -1) + return errno; + + if (flushb) { + +#ifdef BLKFLSBUF + if (ioctl (fd, BLKFLSBUF, 0) == 0) + return 0; +#else +#ifdef __GNUC__ + #warning BLKFLSBUF not defined +#endif /* __GNUC__ */ +#endif +#ifdef FDFLUSH + ioctl (fd, FDFLUSH, 0); /* In case this is a floppy */ +#else +#ifdef __GNUC__ + #warning FDFLUSH not defined +#endif /* __GNUC__ */ +#endif + } + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/freefs.c silo-1.4.14/libext2fs/freefs.c --- silo-1.4.14.orig/libext2fs/freefs.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/freefs.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,147 @@ +/* + * freefs.c --- free an ext2 filesystem + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" + +static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache); + +void ext2fs_free(ext2_filsys fs) +{ + if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)) + return; + if (fs->image_io != fs->io) { + if (fs->image_io) + io_channel_close(fs->image_io); + } + if (fs->io) { + io_channel_close(fs->io); + } + if (fs->device_name) + ext2fs_free_mem(&fs->device_name); + if (fs->super) + ext2fs_free_mem(&fs->super); + if (fs->orig_super) + ext2fs_free_mem(&fs->orig_super); + if (fs->group_desc) + ext2fs_free_mem(&fs->group_desc); + if (fs->block_map) + ext2fs_free_block_bitmap(fs->block_map); + if (fs->inode_map) + ext2fs_free_inode_bitmap(fs->inode_map); + + if (fs->badblocks) + ext2fs_badblocks_list_free(fs->badblocks); + fs->badblocks = 0; + + if (fs->dblist) + ext2fs_free_dblist(fs->dblist); + + if (fs->icache) + ext2fs_free_inode_cache(fs->icache); + + fs->magic = 0; + + ext2fs_free_mem(&fs); +} + +void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap) +{ + if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_GENERIC_BITMAP)) + return; + + bitmap->magic = 0; + if (bitmap->description) { + ext2fs_free_mem(&bitmap->description); + bitmap->description = 0; + } + if (bitmap->bitmap) { + ext2fs_free_mem(&bitmap->bitmap); + bitmap->bitmap = 0; + } + ext2fs_free_mem(&bitmap); +} + +void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap) +{ + if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP)) + return; + + bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; + ext2fs_free_generic_bitmap(bitmap); +} + +void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap) +{ + if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP)) + return; + + bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; + ext2fs_free_generic_bitmap(bitmap); +} + +/* + * Free the inode cache structure + */ +static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache) +{ + if (--icache->refcount) + return; + if (icache->buffer) + ext2fs_free_mem(&icache->buffer); + if (icache->cache) + ext2fs_free_mem(&icache->cache); + icache->buffer_blk = 0; + ext2fs_free_mem(&icache); +} + +/* + * This procedure frees a badblocks list. + */ +void ext2fs_u32_list_free(ext2_u32_list bb) +{ + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) + return; + + if (bb->list) + ext2fs_free_mem(&bb->list); + bb->list = 0; + ext2fs_free_mem(&bb); +} + +void ext2fs_badblocks_list_free(ext2_badblocks_list bb) +{ + ext2fs_u32_list_free((ext2_u32_list) bb); +} + + +/* + * Free a directory block list + */ +void ext2fs_free_dblist(ext2_dblist dblist) +{ + if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST)) + return; + + if (dblist->list) + ext2fs_free_mem(&dblist->list); + dblist->list = 0; + if (dblist->fs && dblist->fs->dblist == dblist) + dblist->fs->dblist = 0; + dblist->magic = 0; + ext2fs_free_mem(&dblist); +} + diff -Naur silo-1.4.14.orig/libext2fs/gen_bitmap.c silo-1.4.14/libext2fs/gen_bitmap.c --- silo-1.4.14.orig/libext2fs/gen_bitmap.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/gen_bitmap.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,48 @@ +/* + * gen_bitmap.c --- Generic bitmap routines that used to be inlined. + * + * Copyright (C) 2001 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, + __u32 bitno) +{ + if ((bitno < bitmap->start) || (bitno > bitmap->end)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno); + return 0; + } + return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap); +} + +int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, + blk_t bitno) +{ + if ((bitno < bitmap->start) || (bitno > bitmap->end)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno); + return 0; + } + return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap); +} diff -Naur silo-1.4.14.orig/libext2fs/get_pathname.c silo-1.4.14/libext2fs/get_pathname.c --- silo-1.4.14.orig/libext2fs/get_pathname.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/get_pathname.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,157 @@ +/* + * get_pathname.c --- do directry/inode -> name translation + * + * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * ext2fs_get_pathname(fs, dir, ino, name) + * + * This function translates takes two inode numbers into a + * string, placing the result in . is the containing + * directory inode, and is the inode number itself. If + * is zero, then ext2fs_get_pathname will return pathname + * of the the directory . + * + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct get_pathname_struct { + ext2_ino_t search_ino; + ext2_ino_t parent; + char *name; + errcode_t errcode; +}; + +#ifdef __TURBOC__ + #pragma argsused +#endif +static int get_pathname_proc(struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct get_pathname_struct *gp; + errcode_t retval; + + gp = (struct get_pathname_struct *) priv_data; + + if (((dirent->name_len & 0xFF) == 2) && + !strncmp(dirent->name, "..", 2)) + gp->parent = dirent->inode; + if (dirent->inode == gp->search_ino) { + retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1, + &gp->name); + if (retval) { + gp->errcode = retval; + return DIRENT_ABORT; + } + strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF)); + gp->name[dirent->name_len & 0xFF] = '\0'; + return DIRENT_ABORT; + } + return 0; +} + +static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir, + ext2_ino_t ino, int maxdepth, + char *buf, char **name) +{ + struct get_pathname_struct gp; + char *parent_name, *ret; + errcode_t retval; + + if (dir == ino) { + retval = ext2fs_get_mem(2, name); + if (retval) + return retval; + strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : "."); + return 0; + } + + if (!dir || (maxdepth < 0)) { + retval = ext2fs_get_mem(4, name); + if (retval) + return retval; + strcpy(*name, "..."); + return 0; + } + + gp.search_ino = ino; + gp.parent = 0; + gp.name = 0; + gp.errcode = 0; + + retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp); + if (retval) + goto cleanup; + if (gp.errcode) { + retval = gp.errcode; + goto cleanup; + } + + retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1, + buf, &parent_name); + if (retval) + goto cleanup; + if (!ino) { + *name = parent_name; + return 0; + } + + if (gp.name) + retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2, + &ret); + else + retval = ext2fs_get_mem(strlen(parent_name)+5, &ret); + if (retval) + goto cleanup; + + ret[0] = 0; + if (parent_name[1]) + strcat(ret, parent_name); + strcat(ret, "/"); + if (gp.name) + strcat(ret, gp.name); + else + strcat(ret, "???"); + *name = ret; + ext2fs_free_mem(&parent_name); + retval = 0; + +cleanup: + if (gp.name) + ext2fs_free_mem(&gp.name); + return retval; +} + +errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino, + char **name) +{ + char *buf; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + if (dir == ino) + ino = 0; + retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name); + ext2fs_free_mem(&buf); + return retval; + +} diff -Naur silo-1.4.14.orig/libext2fs/getsectsize.c silo-1.4.14/libext2fs/getsectsize.c --- silo-1.4.14.orig/libext2fs/getsectsize.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/getsectsize.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,60 @@ +/* + * getsectsize.c --- get the sector size of a device. + * + * Copyright (C) 1995, 1995 Theodore Ts'o. + * Copyright (C) 2003 VMware, Inc. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_LINUX_FD_H +#include +#include +#endif + +#if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET) +#define BLKSSZGET _IO(0x12,104)/* get block device sector size */ +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * Returns the number of blocks in a partition + */ +errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize) +{ + int fd; + +#ifdef HAVE_OPEN64 + fd = open64(file, O_RDONLY); +#else + fd = open(file, O_RDONLY); +#endif + if (fd < 0) + return errno; + +#ifdef BLKSSZGET + if (ioctl(fd, BLKSSZGET, sectsize) >= 0) { + close(fd); + return 0; + } +#endif + *sectsize = 0; + close(fd); + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/getsize.c silo-1.4.14/libext2fs/getsize.c --- silo-1.4.14.orig/libext2fs/getsize.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/getsize.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,293 @@ +/* + * getsize.c --- get the size of a partition. + * + * Copyright (C) 1995, 1995 Theodore Ts'o. + * Copyright (C) 2003 VMware, Inc. + * + * Windows version of ext2fs_get_device_size by Chris Li, VMware. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_LINUX_FD_H +#include +#endif +#ifdef HAVE_SYS_DISKLABEL_H +#include +#endif +#ifdef HAVE_SYS_DISK_H +#ifdef HAVE_SYS_QUEUE_H +#include /* for LIST_HEAD */ +#endif +#include +#endif +#ifdef __linux__ +#include +#endif + +#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) +#define BLKGETSIZE _IO(0x12,96) /* return device size */ +#endif + +#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ +#endif + +#ifdef APPLE_DARWIN +#define BLKGETSIZE DKIOCGETBLOCKCOUNT32 +#endif /* APPLE_DARWIN */ + +#include "ext2_fs.h" +#include "ext2fs.h" + +#if defined(__CYGWIN__) || defined (WIN32) +#include "windows.h" +#include "winioctl.h" + +#if (_WIN32_WINNT >= 0x0500) +#define HAVE_GET_FILE_SIZE_EX 1 +#endif + +errcode_t ext2fs_get_device_size(const char *file, int blocksize, + blk_t *retblocks) +{ + HANDLE dev; + PARTITION_INFORMATION pi; + DISK_GEOMETRY gi; + DWORD retbytes; +#ifdef HAVE_GET_FILE_SIZE_EX + LARGE_INTEGER filesize; +#else + DWORD filesize; +#endif /* HAVE_GET_FILE_SIZE_EX */ + + dev = CreateFile(file, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE , + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (dev == INVALID_HANDLE_VALUE) + return EBADF; + if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO, + &pi, sizeof(PARTITION_INFORMATION), + &pi, sizeof(PARTITION_INFORMATION), + &retbytes, NULL)) { + + *retblocks = pi.PartitionLength.QuadPart / blocksize; + + } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, + &gi, sizeof(DISK_GEOMETRY), + &gi, sizeof(DISK_GEOMETRY), + &retbytes, NULL)) { + + *retblocks = gi.BytesPerSector * + gi.SectorsPerTrack * + gi.TracksPerCylinder * + gi.Cylinders.QuadPart / blocksize; + +#ifdef HAVE_GET_FILE_SIZE_EX + } else if (GetFileSizeEx(dev, &filesize)) { + *retblocks = filesize.QuadPart / blocksize; + } +#else + } else { + filesize = GetFileSize(dev, NULL); + if (INVALID_FILE_SIZE != filesize) { + *retblocks = filesize / blocksize; + } + } +#endif /* HAVE_GET_FILE_SIZE_EX */ + + CloseHandle(dev); + return 0; +} + +#else + +static int valid_offset (int fd, ext2_loff_t offset) +{ + char ch; + + if (ext2fs_llseek (fd, offset, 0) < 0) + return 0; + if (read (fd, &ch, 1) < 1) + return 0; + return 1; +} + +/* + * Returns the number of blocks in a partition + */ +errcode_t ext2fs_get_device_size(const char *file, int blocksize, + blk_t *retblocks) +{ + int fd; + int valid_blkgetsize64 = 1; +#ifdef __linux__ + struct utsname ut; +#endif + unsigned long long size64; + unsigned long size; + ext2_loff_t high, low; +#ifdef FDGETPRM + struct floppy_struct this_floppy; +#endif +#ifdef HAVE_SYS_DISKLABEL_H + int part; + struct disklabel lab; + struct partition *pp; + char ch; +#endif /* HAVE_SYS_DISKLABEL_H */ + +#ifdef HAVE_OPEN64 + fd = open64(file, O_RDONLY); +#else + fd = open(file, O_RDONLY); +#endif + if (fd < 0) + return errno; + +#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */ + if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) { + if ((sizeof(*retblocks) < sizeof(unsigned long long)) + && ((size64 / (blocksize / 512)) > 0xFFFFFFFF)) + return EFBIG; + close(fd); + *retblocks = size64 / (blocksize / 512); + return 0; + } +#endif + +#ifdef BLKGETSIZE64 +#ifdef __linux__ + if ((uname(&ut) == 0) && + ((ut.release[0] == '2') && (ut.release[1] == '.') && + (ut.release[2] < '6') && (ut.release[3] == '.'))) + valid_blkgetsize64 = 0; +#endif + if (valid_blkgetsize64 && + ioctl(fd, BLKGETSIZE64, &size64) >= 0) { + if ((sizeof(*retblocks) < sizeof(unsigned long long)) + && ((size64 / blocksize) > 0xFFFFFFFF)) + return EFBIG; + close(fd); + *retblocks = size64 / blocksize; + return 0; + } +#endif + +#ifdef BLKGETSIZE + if (ioctl(fd, BLKGETSIZE, &size) >= 0) { + close(fd); + *retblocks = size / (blocksize / 512); + return 0; + } +#endif + +#ifdef FDGETPRM + if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) { + close(fd); + *retblocks = this_floppy.size / (blocksize / 512); + return 0; + } +#endif + +#ifdef HAVE_SYS_DISKLABEL_H +#if defined(DIOCGMEDIASIZE) + { + off_t ms; + u_int bs; + if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) { + *retblocks = ms / blocksize; + return 0; + } + } +#elif defined(DIOCGDINFO) + /* old disklabel interface */ + part = strlen(file) - 1; + if (part >= 0) { + ch = file[part]; + if (isdigit(ch)) + part = 0; + else if (ch >= 'a' && ch <= 'h') + part = ch - 'a'; + else + part = -1; + } + if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { + pp = &lab.d_partitions[part]; + if (pp->p_size) { + close(fd); + *retblocks = pp->p_size / (blocksize / 512); + return 0; + } + } +#endif /* defined(DIOCG*) */ +#endif /* HAVE_SYS_DISKLABEL_H */ + + /* + * OK, we couldn't figure it out by using a specialized ioctl, + * which is generally the best way. So do binary search to + * find the size of the partition. + */ + low = 0; + for (high = 1024; valid_offset (fd, high); high *= 2) + low = high; + while (low < high - 1) + { + const ext2_loff_t mid = (low + high) / 2; + + if (valid_offset (fd, mid)) + low = mid; + else + high = mid; + } + valid_offset (fd, 0); + close(fd); + size64 = low + 1; + if ((sizeof(*retblocks) < sizeof(unsigned long long)) + && ((size64 / blocksize) > 0xFFFFFFFF)) + return EFBIG; + *retblocks = size64 / blocksize; + return 0; +} + +#endif /* WIN32 */ + +#ifdef DEBUG +int main(int argc, char **argv) +{ + blk_t blocks; + int retval; + + if (argc < 2) { + fprintf(stderr, "Usage: %s device\n", argv[0]); + exit(1); + } + + retval = ext2fs_get_device_size(argv[1], 1024, &blocks); + if (retval) { + com_err(argv[0], retval, + "while calling ext2fs_get_device_size"); + exit(1); + } + printf("Device %s has %d 1k blocks.\n", argv[1], blocks); + exit(0); +} +#endif diff -Naur silo-1.4.14.orig/libext2fs/icount.c silo-1.4.14/libext2fs/icount.c --- silo-1.4.14.orig/libext2fs/icount.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/icount.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,483 @@ +/* + * icount.c --- an efficient inode count abstraction + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * The data storage strategy used by icount relies on the observation + * that most inode counts are either zero (for non-allocated inodes), + * one (for most files), and only a few that are two or more + * (directories and files that are linked to more than one directory). + * + * Also, e2fsck tends to load the icount data sequentially. + * + * So, we use an inode bitmap to indicate which inodes have a count of + * one, and then use a sorted list to store the counts for inodes + * which are greater than one. + * + * We also use an optional bitmap to indicate which inodes are already + * in the sorted list, to speed up the use of this abstraction by + * e2fsck's pass 2. Pass 2 increments inode counts as it finds them, + * so this extra bitmap avoids searching the sorted list to see if a + * particular inode is on the sorted list already. + */ + +struct ext2_icount_el { + ext2_ino_t ino; + __u16 count; +}; + +struct ext2_icount { + errcode_t magic; + ext2fs_inode_bitmap single; + ext2fs_inode_bitmap multiple; + ext2_ino_t count; + ext2_ino_t size; + ext2_ino_t num_inodes; + ext2_ino_t cursor; + struct ext2_icount_el *list; +}; + +void ext2fs_free_icount(ext2_icount_t icount) +{ + if (!icount) + return; + + icount->magic = 0; + if (icount->list) + ext2fs_free_mem(&icount->list); + if (icount->single) + ext2fs_free_inode_bitmap(icount->single); + if (icount->multiple) + ext2fs_free_inode_bitmap(icount->multiple); + ext2fs_free_mem(&icount); +} + +errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size, + ext2_icount_t hint, ext2_icount_t *ret) +{ + ext2_icount_t icount; + errcode_t retval; + size_t bytes; + ext2_ino_t i; + + if (hint) { + EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT); + if (hint->size > size) + size = (size_t) hint->size; + } + + retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount); + if (retval) + return retval; + memset(icount, 0, sizeof(struct ext2_icount)); + + retval = ext2fs_allocate_inode_bitmap(fs, 0, + &icount->single); + if (retval) + goto errout; + + if (flags & EXT2_ICOUNT_OPT_INCREMENT) { + retval = ext2fs_allocate_inode_bitmap(fs, 0, + &icount->multiple); + if (retval) + goto errout; + } else + icount->multiple = 0; + + if (size) { + icount->size = size; + } else { + /* + * Figure out how many special case inode counts we will + * have. We know we will need one for each directory; + * we also need to reserve some extra room for file links + */ + retval = ext2fs_get_num_dirs(fs, &icount->size); + if (retval) + goto errout; + icount->size += fs->super->s_inodes_count / 50; + } + + bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el)); +#if 0 + printf("Icount allocated %d entries, %d bytes.\n", + icount->size, bytes); +#endif + retval = ext2fs_get_mem(bytes, &icount->list); + if (retval) + goto errout; + memset(icount->list, 0, bytes); + + icount->magic = EXT2_ET_MAGIC_ICOUNT; + icount->count = 0; + icount->cursor = 0; + icount->num_inodes = fs->super->s_inodes_count; + + /* + * Populate the sorted list with those entries which were + * found in the hint icount (since those are ones which will + * likely need to be in the sorted list this time around). + */ + if (hint) { + for (i=0; i < hint->count; i++) + icount->list[i].ino = hint->list[i].ino; + icount->count = hint->count; + } + + *ret = icount; + return 0; + +errout: + ext2fs_free_icount(icount); + return(retval); +} + +errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, + unsigned int size, + ext2_icount_t *ret) +{ + return ext2fs_create_icount2(fs, flags, size, 0, ret); +} + +/* + * insert_icount_el() --- Insert a new entry into the sorted list at a + * specified position. + */ +static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount, + ext2_ino_t ino, int pos) +{ + struct ext2_icount_el *el; + errcode_t retval; + ext2_ino_t new_size = 0; + int num; + + if (icount->count >= icount->size) { + if (icount->count) { + new_size = icount->list[(unsigned)icount->count-1].ino; + new_size = (ext2_ino_t) (icount->count * + ((float) icount->num_inodes / new_size)); + } + if (new_size < (icount->size + 100)) + new_size = icount->size + 100; +#if 0 + printf("Reallocating icount %d entries...\n", new_size); +#endif + retval = ext2fs_resize_mem((size_t) icount->size * + sizeof(struct ext2_icount_el), + (size_t) new_size * + sizeof(struct ext2_icount_el), + &icount->list); + if (retval) + return 0; + icount->size = new_size; + } + num = (int) icount->count - pos; + if (num < 0) + return 0; /* should never happen */ + if (num) { + memmove(&icount->list[pos+1], &icount->list[pos], + sizeof(struct ext2_icount_el) * num); + } + icount->count++; + el = &icount->list[pos]; + el->count = 0; + el->ino = ino; + return el; +} + +/* + * get_icount_el() --- given an inode number, try to find icount + * information in the sorted list. If the create flag is set, + * and we can't find an entry, create one in the sorted list. + */ +static struct ext2_icount_el *get_icount_el(ext2_icount_t icount, + ext2_ino_t ino, int create) +{ + float range; + int low, high, mid; + ext2_ino_t lowval, highval; + + if (!icount || !icount->list) + return 0; + + if (create && ((icount->count == 0) || + (ino > icount->list[(unsigned)icount->count-1].ino))) { + return insert_icount_el(icount, ino, (unsigned) icount->count); + } + if (icount->count == 0) + return 0; + + if (icount->cursor >= icount->count) + icount->cursor = 0; + if (ino == icount->list[icount->cursor].ino) + return &icount->list[icount->cursor++]; +#if 0 + printf("Non-cursor get_icount_el: %u\n", ino); +#endif + low = 0; + high = (int) icount->count-1; + while (low <= high) { +#if 0 + mid = (low+high)/2; +#else + if (low == high) + mid = low; + else { + /* Interpolate for efficiency */ + lowval = icount->list[low].ino; + highval = icount->list[high].ino; + + if (ino < lowval) + range = 0; + else if (ino > highval) + range = 1; + else + range = ((float) (ino - lowval)) / + (highval - lowval); + mid = low + ((int) (range * (high-low))); + } +#endif + if (ino == icount->list[mid].ino) { + icount->cursor = mid+1; + return &icount->list[mid]; + } + if (ino < icount->list[mid].ino) + high = mid-1; + else + low = mid+1; + } + /* + * If we need to create a new entry, it should be right at + * low (where high will be left at low-1). + */ + if (create) + return insert_icount_el(icount, ino, low); + return 0; +} + +errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out) +{ + errcode_t ret = 0; + unsigned int i; + const char *bad = "bad icount"; + + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (icount->count > icount->size) { + fprintf(out, "%s: count > size\n", bad); + return EXT2_ET_INVALID_ARGUMENT; + } + for (i=1; i < icount->count; i++) { + if (icount->list[i-1].ino >= icount->list[i].ino) { + fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n", + bad, i-1, icount->list[i-1].ino, + i, icount->list[i].ino); + ret = EXT2_ET_INVALID_ARGUMENT; + } + } + return ret; +} + +errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret) +{ + struct ext2_icount_el *el; + + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (!ino || (ino > icount->num_inodes)) + return EXT2_ET_INVALID_ARGUMENT; + + if (ext2fs_test_inode_bitmap(icount->single, ino)) { + *ret = 1; + return 0; + } + if (icount->multiple && + !ext2fs_test_inode_bitmap(icount->multiple, ino)) { + *ret = 0; + return 0; + } + el = get_icount_el(icount, ino, 0); + if (!el) { + *ret = 0; + return 0; + } + *ret = el->count; + return 0; +} + +errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret) +{ + struct ext2_icount_el *el; + + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (!ino || (ino > icount->num_inodes)) + return EXT2_ET_INVALID_ARGUMENT; + + if (ext2fs_test_inode_bitmap(icount->single, ino)) { + /* + * If the existing count is 1, then we know there is + * no entry in the list. + */ + el = get_icount_el(icount, ino, 1); + if (!el) + return EXT2_ET_NO_MEMORY; + ext2fs_unmark_inode_bitmap(icount->single, ino); + el->count = 2; + } else if (icount->multiple) { + /* + * The count is either zero or greater than 1; if the + * inode is set in icount->multiple, then there should + * be an entry in the list, so find it using + * get_icount_el(). + */ + if (ext2fs_test_inode_bitmap(icount->multiple, ino)) { + el = get_icount_el(icount, ino, 1); + if (!el) + return EXT2_ET_NO_MEMORY; + el->count++; + } else { + /* + * The count was zero; mark the single bitmap + * and return. + */ + zero_count: + ext2fs_mark_inode_bitmap(icount->single, ino); + if (ret) + *ret = 1; + return 0; + } + } else { + /* + * The count is either zero or greater than 1; try to + * find an entry in the list to determine which. + */ + el = get_icount_el(icount, ino, 0); + if (!el) { + /* No entry means the count was zero */ + goto zero_count; + } + el = get_icount_el(icount, ino, 1); + if (!el) + return EXT2_ET_NO_MEMORY; + el->count++; + } + if (icount->multiple) + ext2fs_mark_inode_bitmap(icount->multiple, ino); + if (ret) + *ret = el->count; + return 0; +} + +errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, + __u16 *ret) +{ + struct ext2_icount_el *el; + + if (!ino || (ino > icount->num_inodes)) + return EXT2_ET_INVALID_ARGUMENT; + + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (ext2fs_test_inode_bitmap(icount->single, ino)) { + ext2fs_unmark_inode_bitmap(icount->single, ino); + if (icount->multiple) + ext2fs_unmark_inode_bitmap(icount->multiple, ino); + else { + el = get_icount_el(icount, ino, 0); + if (el) + el->count = 0; + } + if (ret) + *ret = 0; + return 0; + } + + if (icount->multiple && + !ext2fs_test_inode_bitmap(icount->multiple, ino)) + return EXT2_ET_INVALID_ARGUMENT; + + el = get_icount_el(icount, ino, 0); + if (!el || el->count == 0) + return EXT2_ET_INVALID_ARGUMENT; + + el->count--; + if (el->count == 1) + ext2fs_mark_inode_bitmap(icount->single, ino); + if ((el->count == 0) && icount->multiple) + ext2fs_unmark_inode_bitmap(icount->multiple, ino); + + if (ret) + *ret = el->count; + return 0; +} + +errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, + __u16 count) +{ + struct ext2_icount_el *el; + + if (!ino || (ino > icount->num_inodes)) + return EXT2_ET_INVALID_ARGUMENT; + + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (count == 1) { + ext2fs_mark_inode_bitmap(icount->single, ino); + if (icount->multiple) + ext2fs_unmark_inode_bitmap(icount->multiple, ino); + return 0; + } + if (count == 0) { + ext2fs_unmark_inode_bitmap(icount->single, ino); + if (icount->multiple) { + /* + * If the icount->multiple bitmap is enabled, + * we can just clear both bitmaps and we're done + */ + ext2fs_unmark_inode_bitmap(icount->multiple, ino); + } else { + el = get_icount_el(icount, ino, 0); + if (el) + el->count = 0; + } + return 0; + } + + /* + * Get the icount element + */ + el = get_icount_el(icount, ino, 1); + if (!el) + return EXT2_ET_NO_MEMORY; + el->count = count; + ext2fs_unmark_inode_bitmap(icount->single, ino); + if (icount->multiple) + ext2fs_mark_inode_bitmap(icount->multiple, ino); + return 0; +} + +ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount) +{ + if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT) + return 0; + + return icount->size; +} diff -Naur silo-1.4.14.orig/libext2fs/imager.c silo-1.4.14/libext2fs/imager.c --- silo-1.4.14.orig/libext2fs/imager.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/imager.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,387 @@ +/* + * image.c --- writes out the critical parts of the filesystem as a + * flat file. + * + * Copyright (C) 2000 Theodore Ts'o. + * + * Note: this uses the POSIX IO interfaces, unlike most of the other + * functions in this library. So sue me. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#ifndef HAVE_TYPE_SSIZE_T +typedef int ssize_t; +#endif + +/* + * This function returns 1 if the specified block is all zeros + */ +static int check_zero_block(char *buf, int blocksize) +{ + char *cp = buf; + int left = blocksize; + + while (left > 0) { + if (*cp++) + return 0; + left--; + } + return 1; +} + +/* + * Write the inode table out as a single block. + */ +#define BUF_BLOCKS 32 + +errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags) +{ + unsigned int group, left, c, d; + char *buf, *cp; + blk_t blk; + ssize_t actual; + errcode_t retval; + + buf = malloc(fs->blocksize * BUF_BLOCKS); + if (!buf) + return ENOMEM; + + for (group = 0; group < fs->group_desc_count; group++) { + blk = fs->group_desc[(unsigned)group].bg_inode_table; + if (!blk) + return EXT2_ET_MISSING_INODE_TABLE; + left = fs->inode_blocks_per_group; + while (left) { + c = BUF_BLOCKS; + if (c > left) + c = left; + retval = io_channel_read_blk(fs->io, blk, c, buf); + if (retval) + goto errout; + cp = buf; + while (c) { + if (!(flags & IMAGER_FLAG_SPARSEWRITE)) { + d = c; + goto skip_sparse; + } + /* Skip zero blocks */ + if (check_zero_block(cp, fs->blocksize)) { + c--; + blk++; + left--; + cp += fs->blocksize; + lseek(fd, fs->blocksize, SEEK_CUR); + continue; + } + /* Find non-zero blocks */ + for (d=1; d < c; d++) { + if (check_zero_block(cp + d*fs->blocksize, fs->blocksize)) + break; + } + skip_sparse: + actual = write(fd, cp, fs->blocksize * d); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != (ssize_t) (fs->blocksize * d)) { + retval = EXT2_ET_SHORT_WRITE; + goto errout; + } + blk += d; + left -= d; + cp += fs->blocksize * d; + c -= d; + } + } + } + retval = 0; + +errout: + free(buf); + return retval; +} + +/* + * Read in the inode table and stuff it into place + */ +errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, + int flags EXT2FS_ATTR((unused))) +{ + unsigned int group, c, left; + char *buf; + blk_t blk; + ssize_t actual; + errcode_t retval; + + buf = malloc(fs->blocksize * BUF_BLOCKS); + if (!buf) + return ENOMEM; + + for (group = 0; group < fs->group_desc_count; group++) { + blk = fs->group_desc[(unsigned)group].bg_inode_table; + if (!blk) { + retval = EXT2_ET_MISSING_INODE_TABLE; + goto errout; + } + left = fs->inode_blocks_per_group; + while (left) { + c = BUF_BLOCKS; + if (c > left) + c = left; + actual = read(fd, buf, fs->blocksize * c); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != (ssize_t) (fs->blocksize * c)) { + retval = EXT2_ET_SHORT_READ; + goto errout; + } + retval = io_channel_write_blk(fs->io, blk, c, buf); + if (retval) + goto errout; + + blk += c; + left -= c; + } + } + retval = ext2fs_flush_icache(fs); + +errout: + free(buf); + return retval; +} + +/* + * Write out superblock and group descriptors + */ +errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, + int flags EXT2FS_ATTR((unused))) +{ + char *buf, *cp; + ssize_t actual; + errcode_t retval; + + buf = malloc(fs->blocksize); + if (!buf) + return ENOMEM; + + /* + * Write out the superblock + */ + memset(buf, 0, fs->blocksize); + memcpy(buf, fs->super, SUPERBLOCK_SIZE); + actual = write(fd, buf, fs->blocksize); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != (ssize_t) fs->blocksize) { + retval = EXT2_ET_SHORT_WRITE; + goto errout; + } + + /* + * Now write out the block group descriptors + */ + cp = (char *) fs->group_desc; + actual = write(fd, cp, fs->blocksize * fs->desc_blocks); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) { + retval = EXT2_ET_SHORT_WRITE; + goto errout; + } + + retval = 0; + +errout: + free(buf); + return retval; +} + +/* + * Read the superblock and group descriptors and overwrite them. + */ +errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, + int flags EXT2FS_ATTR((unused))) +{ + char *buf; + ssize_t actual, size; + errcode_t retval; + + size = fs->blocksize * (fs->group_desc_count + 1); + buf = malloc(size); + if (!buf) + return ENOMEM; + + /* + * Read it all in. + */ + actual = read(fd, buf, size); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != size) { + retval = EXT2_ET_SHORT_READ; + goto errout; + } + + /* + * Now copy in the superblock and group descriptors + */ + memcpy(fs->super, buf, SUPERBLOCK_SIZE); + + memcpy(fs->group_desc, buf + fs->blocksize, + fs->blocksize * fs->group_desc_count); + + retval = 0; + +errout: + free(buf); + return retval; +} + +/* + * Write the block/inode bitmaps. + */ +errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags) +{ + char *ptr; + int c, size; + char zero_buf[1024]; + ssize_t actual; + errcode_t retval; + + if (flags & IMAGER_FLAG_INODEMAP) { + if (!fs->inode_map) { + retval = ext2fs_read_inode_bitmap(fs); + if (retval) + return retval; + } + ptr = fs->inode_map->bitmap; + size = (EXT2_INODES_PER_GROUP(fs->super) / 8); + } else { + if (!fs->block_map) { + retval = ext2fs_read_block_bitmap(fs); + if (retval) + return retval; + } + ptr = fs->block_map->bitmap; + size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; + } + size = size * fs->group_desc_count; + + actual = write(fd, ptr, size); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != size) { + retval = EXT2_ET_SHORT_WRITE; + goto errout; + } + size = size % fs->blocksize; + memset(zero_buf, 0, sizeof(zero_buf)); + if (size) { + size = fs->blocksize - size; + while (size) { + c = size; + if (c > (int) sizeof(zero_buf)) + c = sizeof(zero_buf); + actual = write(fd, zero_buf, c); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != c) { + retval = EXT2_ET_SHORT_WRITE; + goto errout; + } + size -= c; + } + } + retval = 0; +errout: + return (retval); +} + + +/* + * Read the block/inode bitmaps. + */ +errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags) +{ + char *ptr, *buf = 0; + int size; + ssize_t actual; + errcode_t retval; + + if (flags & IMAGER_FLAG_INODEMAP) { + if (!fs->inode_map) { + retval = ext2fs_read_inode_bitmap(fs); + if (retval) + return retval; + } + ptr = fs->inode_map->bitmap; + size = (EXT2_INODES_PER_GROUP(fs->super) / 8); + } else { + if (!fs->block_map) { + retval = ext2fs_read_block_bitmap(fs); + if (retval) + return retval; + } + ptr = fs->block_map->bitmap; + size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; + } + size = size * fs->group_desc_count; + + buf = malloc(size); + if (!buf) + return ENOMEM; + + actual = read(fd, buf, size); + if (actual == -1) { + retval = errno; + goto errout; + } + if (actual != size) { + retval = EXT2_ET_SHORT_WRITE; + goto errout; + } + memcpy(ptr, buf, size); + + retval = 0; +errout: + if (buf) + free(buf); + return (retval); +} diff -Naur silo-1.4.14.orig/libext2fs/ind_block.c silo-1.4.14/libext2fs/ind_block.c --- silo-1.4.14.orig/libext2fs/ind_block.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/ind_block.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,66 @@ +/* + * ind_block.c --- indirect block I/O routines + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf) +{ + errcode_t retval; + blk_t *block_nr; + int i; + int limit = fs->blocksize >> 2; + + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) && + (fs->io != fs->image_io)) + memset(buf, 0, fs->blocksize); + else { + retval = io_channel_read_blk(fs->io, blk, 1, buf); + if (retval) + return retval; + } +#ifdef EXT2FS_ENABLE_SWAPFS + if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) { + block_nr = (blk_t *) buf; + for (i = 0; i < limit; i++, block_nr++) + *block_nr = ext2fs_swab32(*block_nr); + } +#endif + return 0; +} + +errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf) +{ + blk_t *block_nr; + int i; + int limit = fs->blocksize >> 2; + + if (fs->flags & EXT2_FLAG_IMAGE_FILE) + return 0; + +#ifdef EXT2FS_ENABLE_SWAPFS + if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) { + block_nr = (blk_t *) buf; + for (i = 0; i < limit; i++, block_nr++) + *block_nr = ext2fs_swab32(*block_nr); + } +#endif + return io_channel_write_blk(fs->io, blk, 1, buf); +} + + diff -Naur silo-1.4.14.orig/libext2fs/initialize.c silo-1.4.14/libext2fs/initialize.c --- silo-1.4.14.orig/libext2fs/initialize.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/initialize.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,387 @@ +/* + * initialize.c --- initialize a filesystem handle given superblock + * parameters. Used by mke2fs when initializing a filesystem. + * + * Copyright (C) 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#if defined(__linux__) && defined(EXT2_OS_LINUX) +#define CREATOR_OS EXT2_OS_LINUX +#else +#if defined(__GNU__) && defined(EXT2_OS_HURD) +#define CREATOR_OS EXT2_OS_HURD +#else +#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) +#define CREATOR_OS EXT2_OS_FREEBSD +#else +#if defined(LITES) && defined(EXT2_OS_LITES) +#define CREATOR_OS EXT2_OS_LITES +#else +#define CREATOR_OS EXT2_OS_LINUX /* by default */ +#endif /* defined(LITES) && defined(EXT2_OS_LITES) */ +#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */ +#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */ +#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */ + +/* + * Note we override the kernel include file's idea of what the default + * check interval (never) should be. It's a good idea to check at + * least *occasionally*, specially since servers will never rarely get + * to reboot, since Linux is so robust these days. :-) + * + * 180 days (six months) seems like a good value. + */ +#ifdef EXT2_DFL_CHECKINTERVAL +#undef EXT2_DFL_CHECKINTERVAL +#endif +#define EXT2_DFL_CHECKINTERVAL (86400L * 180L) + +/* + * Calculate the number of GDT blocks to reserve for online filesystem growth. + * The absolute maximum number of GDT blocks we can reserve is determined by + * the number of block pointers that can fit into a single block. + */ +static int calc_reserved_gdt_blocks(ext2_filsys fs) +{ + struct ext2_super_block *sb = fs->super; + unsigned long bpg = sb->s_blocks_per_group; + unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc); + unsigned long max_blocks = 0xffffffff; + unsigned long rsv_groups; + int rsv_gdb; + + /* We set it at 1024x the current filesystem size, or + * the upper block count limit (2^32), whichever is lower. + */ + if (sb->s_blocks_count < max_blocks / 1024) + max_blocks = sb->s_blocks_count * 1024; + rsv_groups = (max_blocks - sb->s_first_data_block + bpg - 1) / bpg; + rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - fs->desc_blocks; + if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb)) + rsv_gdb = EXT2_ADDR_PER_BLOCK(sb); +#ifdef RES_GDT_DEBUG + printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %lu\n", + max_blocks, rsv_groups, rsv_gdb); +#endif + + return rsv_gdb; +} + +errcode_t ext2fs_initialize(const char *name, int flags, + struct ext2_super_block *param, + io_manager manager, ext2_filsys *ret_fs) +{ + ext2_filsys fs; + errcode_t retval; + struct ext2_super_block *super; + int frags_per_block; + unsigned int rem; + unsigned int overhead = 0; + blk_t group_block; + unsigned int ipg; + dgrp_t i; + blk_t numblocks; + int rsv_gdt; + char *buf; + + if (!param || !param->s_blocks_count) + return EXT2_ET_INVALID_ARGUMENT; + + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); + if (retval) + return retval; + + memset(fs, 0, sizeof(struct struct_ext2_filsys)); + fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; + fs->flags = flags | EXT2_FLAG_RW; + fs->umask = 022; +#ifdef WORDS_BIGENDIAN + fs->flags |= EXT2_FLAG_SWAP_BYTES; +#endif + retval = manager->open(name, IO_FLAG_RW, &fs->io); + if (retval) + goto cleanup; + fs->image_io = fs->io; + fs->io->app_data = fs; + retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name); + if (retval) + goto cleanup; + + strcpy(fs->device_name, name); + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super); + if (retval) + goto cleanup; + fs->super = super; + + memset(super, 0, SUPERBLOCK_SIZE); + +#define set_field(field, default) (super->field = param->field ? \ + param->field : (default)) + + super->s_magic = EXT2_SUPER_MAGIC; + super->s_state = EXT2_VALID_FS; + + set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */ + set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */ + set_field(s_first_data_block, super->s_log_block_size ? 0 : 1); + set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT); + set_field(s_errors, EXT2_ERRORS_DEFAULT); + set_field(s_feature_compat, 0); + set_field(s_feature_incompat, 0); + set_field(s_feature_ro_compat, 0); + set_field(s_first_meta_bg, 0); + if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { + retval = EXT2_ET_UNSUPP_FEATURE; + goto cleanup; + } + if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) { + retval = EXT2_ET_RO_UNSUPP_FEATURE; + goto cleanup; + } + + set_field(s_rev_level, EXT2_GOOD_OLD_REV); + if (super->s_rev_level >= EXT2_DYNAMIC_REV) { + set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO); + set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE); + } + + set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL); + super->s_mkfs_time = super->s_lastcheck = time(NULL); + + super->s_creator_os = CREATOR_OS; + + fs->blocksize = EXT2_BLOCK_SIZE(super); + fs->fragsize = EXT2_FRAG_SIZE(super); + frags_per_block = fs->blocksize / fs->fragsize; + + /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */ + set_field(s_blocks_per_group, fs->blocksize * 8); + if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super)) + super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super); + super->s_frags_per_group = super->s_blocks_per_group * frags_per_block; + + super->s_blocks_count = param->s_blocks_count; + super->s_r_blocks_count = param->s_r_blocks_count; + if (super->s_r_blocks_count >= param->s_blocks_count) { + retval = EXT2_ET_INVALID_ARGUMENT; + goto cleanup; + } + + /* + * If we're creating an external journal device, we don't need + * to bother with the rest. + */ + if (super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { + fs->group_desc_count = 0; + ext2fs_mark_super_dirty(fs); + *ret_fs = fs; + return 0; + } + +retry: + fs->group_desc_count = (super->s_blocks_count - + super->s_first_data_block + + EXT2_BLOCKS_PER_GROUP(super) - 1) + / EXT2_BLOCKS_PER_GROUP(super); + if (fs->group_desc_count == 0) { + retval = EXT2_ET_TOOSMALL; + goto cleanup; + } + fs->desc_blocks = (fs->group_desc_count + + EXT2_DESC_PER_BLOCK(super) - 1) + / EXT2_DESC_PER_BLOCK(super); + + i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize; + set_field(s_inodes_count, super->s_blocks_count / i); + + /* + * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so + * that we have enough inodes for the filesystem(!) + */ + if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1) + super->s_inodes_count = EXT2_FIRST_INODE(super)+1; + + /* + * There should be at least as many inodes as the user + * requested. Figure out how many inodes per group that + * should be. But make sure that we don't allocate more than + * one bitmap's worth of inodes each group. + */ + ipg = (super->s_inodes_count + fs->group_desc_count - 1) / + fs->group_desc_count; + if (ipg > fs->blocksize * 8) { + if (super->s_blocks_per_group >= 256) { + /* Try again with slightly different parameters */ + super->s_blocks_per_group -= 8; + super->s_blocks_count = param->s_blocks_count; + super->s_frags_per_group = super->s_blocks_per_group * + frags_per_block; + goto retry; + } else + return EXT2_ET_TOO_MANY_INODES; + } + + if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super)) + ipg = EXT2_MAX_INODES_PER_GROUP(super); + + super->s_inodes_per_group = ipg; + if (super->s_inodes_count > ipg * fs->group_desc_count) + super->s_inodes_count = ipg * fs->group_desc_count; + + /* + * Make sure the number of inodes per group completely fills + * the inode table blocks in the descriptor. If not, add some + * additional inodes/group. Waste not, want not... + */ + fs->inode_blocks_per_group = (((super->s_inodes_per_group * + EXT2_INODE_SIZE(super)) + + EXT2_BLOCK_SIZE(super) - 1) / + EXT2_BLOCK_SIZE(super)); + super->s_inodes_per_group = ((fs->inode_blocks_per_group * + EXT2_BLOCK_SIZE(super)) / + EXT2_INODE_SIZE(super)); + /* + * Finally, make sure the number of inodes per group is a + * multiple of 8. This is needed to simplify the bitmap + * splicing code. + */ + super->s_inodes_per_group &= ~7; + fs->inode_blocks_per_group = (((super->s_inodes_per_group * + EXT2_INODE_SIZE(super)) + + EXT2_BLOCK_SIZE(super) - 1) / + EXT2_BLOCK_SIZE(super)); + + /* + * adjust inode count to reflect the adjusted inodes_per_group + */ + super->s_inodes_count = super->s_inodes_per_group * + fs->group_desc_count; + super->s_free_inodes_count = super->s_inodes_count; + + /* + * check the number of reserved group descriptor table blocks + */ + if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) + rsv_gdt = calc_reserved_gdt_blocks(fs); + else + rsv_gdt = 0; + set_field(s_reserved_gdt_blocks, rsv_gdt); + if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) { + retval = EXT2_ET_RES_GDT_BLOCKS; + goto cleanup; + } + + /* + * Overhead is the number of bookkeeping blocks per group. It + * includes the superblock backup, the group descriptor + * backups, the inode bitmap, the block bitmap, and the inode + * table. + */ + + overhead = (int) (2 + fs->inode_blocks_per_group); + + if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1)) + overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks; + + /* This can only happen if the user requested too many inodes */ + if (overhead > super->s_blocks_per_group) + return EXT2_ET_TOO_MANY_INODES; + + /* + * See if the last group is big enough to support the + * necessary data structures. If not, we need to get rid of + * it. + */ + rem = ((super->s_blocks_count - super->s_first_data_block) % + super->s_blocks_per_group); + if ((fs->group_desc_count == 1) && rem && (rem < overhead)) + return EXT2_ET_TOOSMALL; + if (rem && (rem < overhead+50)) { + super->s_blocks_count -= rem; + goto retry; + } + + /* + * At this point we know how big the filesystem will be. So + * we can do any and all allocations that depend on the block + * count. + */ + + retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); + if (retval) + goto cleanup; + + sprintf(buf, "block bitmap for %s", fs->device_name); + retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); + if (retval) + goto cleanup; + + sprintf(buf, "inode bitmap for %s", fs->device_name); + retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); + if (retval) + goto cleanup; + + ext2fs_free_mem(&buf); + + retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize, + &fs->group_desc); + if (retval) + goto cleanup; + + memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize); + + /* + * Reserve the superblock and group descriptors for each + * group, and fill in the correct group statistics for group. + * Note that although the block bitmap, inode bitmap, and + * inode table have not been allocated (and in fact won't be + * by this routine), they are accounted for nevertheless. + */ + group_block = super->s_first_data_block; + super->s_free_blocks_count = 0; + for (i = 0; i < fs->group_desc_count; i++) { + numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map); + + super->s_free_blocks_count += numblocks; + fs->group_desc[i].bg_free_blocks_count = numblocks; + fs->group_desc[i].bg_free_inodes_count = + fs->super->s_inodes_per_group; + fs->group_desc[i].bg_used_dirs_count = 0; + + group_block += super->s_blocks_per_group; + } + + ext2fs_mark_super_dirty(fs); + ext2fs_mark_bb_dirty(fs); + ext2fs_mark_ib_dirty(fs); + + io_channel_set_blksize(fs->io, fs->blocksize); + + *ret_fs = fs; + return 0; +cleanup: + ext2fs_free(fs); + return retval; +} diff -Naur silo-1.4.14.orig/libext2fs/inline.c silo-1.4.14/libext2fs/inline.c --- silo-1.4.14.orig/libext2fs/inline.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/inline.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,32 @@ +/* + * inline.c --- Includes the inlined functions defined in the header + * files as standalone functions, in case the application program + * is compiled with inlining turned off. + * + * Copyright (C) 1993, 1994 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#define INCLUDE_INLINE_FUNCS +#include "ext2fs.h" + diff -Naur silo-1.4.14.orig/libext2fs/inode.c silo-1.4.14/libext2fs/inode.c --- silo-1.4.14.orig/libext2fs/inode.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/inode.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,794 @@ +/* + * inode.c --- utility routines to read and write inodes + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fsP.h" +#include "e2image.h" + +struct ext2_struct_inode_scan { + errcode_t magic; + ext2_filsys fs; + ext2_ino_t current_inode; + blk_t current_block; + dgrp_t current_group; + ext2_ino_t inodes_left; + blk_t blocks_left; + dgrp_t groups_left; + blk_t inode_buffer_blocks; + char * inode_buffer; + int inode_size; + char * ptr; + int bytes_left; + char *temp_buffer; + errcode_t (*done_group)(ext2_filsys fs, + ext2_inode_scan scan, + dgrp_t group, + void * priv_data); + void * done_group_data; + int bad_block_ptr; + int scan_flags; + int reserved[6]; +}; + +/* + * This routine flushes the icache, if it exists. + */ +errcode_t ext2fs_flush_icache(ext2_filsys fs) +{ + int i; + + if (!fs->icache) + return 0; + + for (i=0; i < fs->icache->cache_size; i++) + fs->icache->cache[i].ino = 0; + + fs->icache->buffer_blk = 0; + return 0; +} + +static errcode_t create_icache(ext2_filsys fs) +{ + errcode_t retval; + + if (fs->icache) + return 0; + retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache); + if (retval) + return retval; + + memset(fs->icache, 0, sizeof(struct ext2_inode_cache)); + retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer); + if (retval) { + ext2fs_free_mem(&fs->icache); + return retval; + } + fs->icache->buffer_blk = 0; + fs->icache->cache_last = -1; + fs->icache->cache_size = 4; + fs->icache->refcount = 1; + retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent) + * fs->icache->cache_size, + &fs->icache->cache); + if (retval) { + ext2fs_free_mem(&fs->icache->buffer); + ext2fs_free_mem(&fs->icache); + return retval; + } + ext2fs_flush_icache(fs); + return 0; +} + +errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, + ext2_inode_scan *ret_scan) +{ + ext2_inode_scan scan; + errcode_t retval; + errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks); + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + /* + * If fs->badblocks isn't set, then set it --- since the inode + * scanning functions require it. + */ + if (fs->badblocks == 0) { + /* + * Temporarly save fs->get_blocks and set it to zero, + * for compatibility with old e2fsck's. + */ + save_get_blocks = fs->get_blocks; + fs->get_blocks = 0; + retval = ext2fs_read_bb_inode(fs, &fs->badblocks); + if (retval && fs->badblocks) { + ext2fs_badblocks_list_free(fs->badblocks); + fs->badblocks = 0; + } + fs->get_blocks = save_get_blocks; + } + + retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan); + if (retval) + return retval; + memset(scan, 0, sizeof(struct ext2_struct_inode_scan)); + + scan->magic = EXT2_ET_MAGIC_INODE_SCAN; + scan->fs = fs; + scan->inode_size = EXT2_INODE_SIZE(fs->super); + scan->bytes_left = 0; + scan->current_group = 0; + scan->groups_left = fs->group_desc_count - 1; + scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8; + scan->current_block = scan->fs-> + group_desc[scan->current_group].bg_inode_table; + scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); + scan->blocks_left = scan->fs->inode_blocks_per_group; + retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks * + fs->blocksize), + &scan->inode_buffer); + scan->done_group = 0; + scan->done_group_data = 0; + scan->bad_block_ptr = 0; + if (retval) { + ext2fs_free_mem(&scan); + return retval; + } + retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer); + if (retval) { + ext2fs_free_mem(&scan->inode_buffer); + ext2fs_free_mem(&scan); + return retval; + } + if (scan->fs->badblocks && scan->fs->badblocks->num) + scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS; + *ret_scan = scan; + return 0; +} + +void ext2fs_close_inode_scan(ext2_inode_scan scan) +{ + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) + return; + + ext2fs_free_mem(&scan->inode_buffer); + scan->inode_buffer = NULL; + ext2fs_free_mem(&scan->temp_buffer); + scan->temp_buffer = NULL; + ext2fs_free_mem(&scan); + return; +} + +void ext2fs_set_inode_callback(ext2_inode_scan scan, + errcode_t (*done_group)(ext2_filsys fs, + ext2_inode_scan scan, + dgrp_t group, + void * priv_data), + void *done_group_data) +{ + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) + return; + + scan->done_group = done_group; + scan->done_group_data = done_group_data; +} + +int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, + int clear_flags) +{ + int old_flags; + + if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) + return 0; + + old_flags = scan->scan_flags; + scan->scan_flags &= ~clear_flags; + scan->scan_flags |= set_flags; + return old_flags; +} + +/* + * This function is called by ext2fs_get_next_inode when it needs to + * get ready to read in a new blockgroup. + */ +static errcode_t get_next_blockgroup(ext2_inode_scan scan) +{ + scan->current_group++; + scan->groups_left--; + + scan->current_block = scan->fs-> + group_desc[scan->current_group].bg_inode_table; + + scan->current_inode = scan->current_group * + EXT2_INODES_PER_GROUP(scan->fs->super); + + scan->bytes_left = 0; + scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); + scan->blocks_left = scan->fs->inode_blocks_per_group; + return 0; +} + +errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, + int group) +{ + scan->current_group = group - 1; + scan->groups_left = scan->fs->group_desc_count - group; + return get_next_blockgroup(scan); +} + +/* + * This function is called by get_next_blocks() to check for bad + * blocks in the inode table. + * + * This function assumes that badblocks_list->list is sorted in + * increasing order. + */ +static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan, + blk_t *num_blocks) +{ + blk_t blk = scan->current_block; + badblocks_list bb = scan->fs->badblocks; + + /* + * If the inode table is missing, then obviously there are no + * bad blocks. :-) + */ + if (blk == 0) + return 0; + + /* + * If the current block is greater than the bad block listed + * in the bad block list, then advance the pointer until this + * is no longer the case. If we run out of bad blocks, then + * we don't need to do any more checking! + */ + while (blk > bb->list[scan->bad_block_ptr]) { + if (++scan->bad_block_ptr >= bb->num) { + scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; + return 0; + } + } + + /* + * If the current block is equal to the bad block listed in + * the bad block list, then handle that one block specially. + * (We could try to handle runs of bad blocks, but that + * only increases CPU efficiency by a small amount, at the + * expense of a huge expense of code complexity, and for an + * uncommon case at that.) + */ + if (blk == bb->list[scan->bad_block_ptr]) { + scan->scan_flags |= EXT2_SF_BAD_INODE_BLK; + *num_blocks = 1; + if (++scan->bad_block_ptr >= bb->num) + scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; + return 0; + } + + /* + * If there is a bad block in the range that we're about to + * read in, adjust the number of blocks to read so that we we + * don't read in the bad block. (Then the next block to read + * will be the bad block, which is handled in the above case.) + */ + if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr]) + *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk); + + return 0; +} + +/* + * This function is called by ext2fs_get_next_inode when it needs to + * read in more blocks from the current blockgroup's inode table. + */ +static errcode_t get_next_blocks(ext2_inode_scan scan) +{ + blk_t num_blocks; + errcode_t retval; + + /* + * Figure out how many blocks to read; we read at most + * inode_buffer_blocks, and perhaps less if there aren't that + * many blocks left to read. + */ + num_blocks = scan->inode_buffer_blocks; + if (num_blocks > scan->blocks_left) + num_blocks = scan->blocks_left; + + /* + * If the past block "read" was a bad block, then mark the + * left-over extra bytes as also being bad. + */ + if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) { + if (scan->bytes_left) + scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES; + scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK; + } + + /* + * Do inode bad block processing, if necessary. + */ + if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) { + retval = check_for_inode_bad_blocks(scan, &num_blocks); + if (retval) + return retval; + } + + if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) || + (scan->current_block == 0)) { + memset(scan->inode_buffer, 0, + (size_t) num_blocks * scan->fs->blocksize); + } else { + retval = io_channel_read_blk(scan->fs->io, + scan->current_block, + (int) num_blocks, + scan->inode_buffer); + if (retval) + return EXT2_ET_NEXT_INODE_READ; + } + scan->ptr = scan->inode_buffer; + scan->bytes_left = num_blocks * scan->fs->blocksize; + + scan->blocks_left -= num_blocks; + if (scan->current_block) + scan->current_block += num_blocks; + return 0; +} + +#if 0 +/* + * Returns 1 if the entire inode_buffer has a non-zero size and + * contains all zeros. (Not just deleted inodes, since that means + * that part of the inode table was used at one point; we want all + * zeros, which means that the inode table is pristine.) + */ +static inline int is_empty_scan(ext2_inode_scan scan) +{ + int i; + + if (scan->bytes_left == 0) + return 0; + + for (i=0; i < scan->bytes_left; i++) + if (scan->ptr[i]) + return 0; + return 1; +} +#endif + +errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino, + struct ext2_inode *inode, int bufsize) +{ + errcode_t retval; + int extra_bytes = 0; + + EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN); + + /* + * Do we need to start reading a new block group? + */ + if (scan->inodes_left <= 0) { + force_new_group: + if (scan->done_group) { + retval = (scan->done_group) + (scan->fs, scan, scan->current_group, + scan->done_group_data); + if (retval) + return retval; + } + if (scan->groups_left <= 0) { + *ino = 0; + return 0; + } + retval = get_next_blockgroup(scan); + if (retval) + return retval; + } + /* + * This is done outside the above if statement so that the + * check can be done for block group #0. + */ + if (scan->current_block == 0) { + if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) { + goto force_new_group; + } else + return EXT2_ET_MISSING_INODE_TABLE; + } + + + /* + * Have we run out of space in the inode buffer? If so, we + * need to read in more blocks. + */ + if (scan->bytes_left < scan->inode_size) { + memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left); + extra_bytes = scan->bytes_left; + + retval = get_next_blocks(scan); + if (retval) + return retval; +#if 0 + /* + * XXX test Need check for used inode somehow. + * (Note: this is hard.) + */ + if (is_empty_scan(scan)) + goto force_new_group; +#endif + } + + retval = 0; + if (extra_bytes) { + memcpy(scan->temp_buffer+extra_bytes, scan->ptr, + scan->inode_size - extra_bytes); + scan->ptr += scan->inode_size - extra_bytes; + scan->bytes_left -= scan->inode_size - extra_bytes; + +#ifdef EXT2FS_ENABLE_SWAPFS + if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || + (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) + ext2fs_swap_inode_full(scan->fs, + (struct ext2_inode_large *) inode, + (struct ext2_inode_large *) scan->temp_buffer, + 0, bufsize); + else +#endif + *inode = *((struct ext2_inode *) scan->temp_buffer); + if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES) + retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; + scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES; + } else { +#ifdef EXT2FS_ENABLE_SWAPFS + if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || + (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) + ext2fs_swap_inode_full(scan->fs, + (struct ext2_inode_large *) inode, + (struct ext2_inode_large *) scan->ptr, + 0, bufsize); + else +#endif + memcpy(inode, scan->ptr, bufsize); + scan->ptr += scan->inode_size; + scan->bytes_left -= scan->inode_size; + if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) + retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; + } + + scan->inodes_left--; + scan->current_inode++; + *ino = scan->current_inode; + return retval; +} + +errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, + struct ext2_inode *inode) +{ + return ext2fs_get_next_inode_full(scan, ino, inode, + sizeof(struct ext2_inode)); +} + +/* + * Functions to read and write a single inode. + */ +errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, int bufsize) +{ + unsigned long group, block, block_nr, offset; + char *ptr; + errcode_t retval; + int clen, i, inodes_per_block, length; + io_channel io; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + /* Check to see if user has an override function */ + if (fs->read_inode) { + retval = (fs->read_inode)(fs, ino, inode); + if (retval != EXT2_ET_CALLBACK_NOTHANDLED) + return retval; + } + /* Create inode cache if not present */ + if (!fs->icache) { + retval = create_icache(fs); + if (retval) + return retval; + } + /* Check to see if it's in the inode cache */ + if (bufsize == sizeof(struct ext2_inode)) { + /* only old good inode can be retrieve from the cache */ + for (i=0; i < fs->icache->cache_size; i++) { + if (fs->icache->cache[i].ino == ino) { + *inode = fs->icache->cache[i].inode; + return 0; + } + } + } + if ((ino == 0) || (ino > fs->super->s_inodes_count)) + return EXT2_ET_BAD_INODE_NUM; + if (fs->flags & EXT2_FLAG_IMAGE_FILE) { + inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super); + block_nr = fs->image_header->offset_inode / fs->blocksize; + block_nr += (ino - 1) / inodes_per_block; + offset = ((ino - 1) % inodes_per_block) * + EXT2_INODE_SIZE(fs->super); + io = fs->image_io; + } else { + group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); + offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * + EXT2_INODE_SIZE(fs->super); + block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); + if (!fs->group_desc[(unsigned)group].bg_inode_table) + return EXT2_ET_MISSING_INODE_TABLE; + block_nr = fs->group_desc[(unsigned)group].bg_inode_table + + block; + io = fs->io; + } + offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); + + length = EXT2_INODE_SIZE(fs->super); + if (bufsize < length) + length = bufsize; + + ptr = (char *) inode; + while (length) { + clen = length; + if ((offset + length) > fs->blocksize) + clen = fs->blocksize - offset; + + if (block_nr != fs->icache->buffer_blk) { + retval = io_channel_read_blk(io, block_nr, 1, + fs->icache->buffer); + if (retval) + return retval; + fs->icache->buffer_blk = block_nr; + } + + memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset, + clen); + + offset = 0; + length -= clen; + ptr += clen; + block_nr++; + } + +#ifdef EXT2FS_ENABLE_SWAPFS + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) + ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode, + (struct ext2_inode_large *) inode, + 0, length); +#endif + + /* Update the inode cache */ + fs->icache->cache_last = (fs->icache->cache_last + 1) % + fs->icache->cache_size; + fs->icache->cache[fs->icache->cache_last].ino = ino; + fs->icache->cache[fs->icache->cache_last].inode = *inode; + + return 0; +} + +errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode) +{ + return ext2fs_read_inode_full(fs, ino, inode, + sizeof(struct ext2_inode)); +} + +errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode * inode, int bufsize) +{ + unsigned long group, block, block_nr, offset; + errcode_t retval = 0; + struct ext2_inode_large temp_inode, *w_inode; + char *ptr; + int clen, i, length; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + /* Check to see if user provided an override function */ + if (fs->write_inode) { + retval = (fs->write_inode)(fs, ino, inode); + if (retval != EXT2_ET_CALLBACK_NOTHANDLED) + return retval; + } + + /* Check to see if the inode cache needs to be updated */ + if (fs->icache) { + for (i=0; i < fs->icache->cache_size; i++) { + if (fs->icache->cache[i].ino == ino) { + fs->icache->cache[i].inode = *inode; + break; + } + } + } else { + retval = create_icache(fs); + if (retval) + return retval; + } + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + if ((ino == 0) || (ino > fs->super->s_inodes_count)) + return EXT2_ET_BAD_INODE_NUM; + + length = bufsize; + if (length < EXT2_INODE_SIZE(fs->super)) + length = EXT2_INODE_SIZE(fs->super); + + if (length > (int) sizeof(struct ext2_inode_large)) { + w_inode = malloc(length); + if (!w_inode) + return ENOMEM; + } else + w_inode = &temp_inode; + memset(w_inode, 0, length); + +#ifdef EXT2FS_ENABLE_SWAPFS + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) + ext2fs_swap_inode_full(fs, w_inode, + (struct ext2_inode_large *) inode, + 1, bufsize); + else +#endif + memcpy(w_inode, inode, bufsize); + + group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); + offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * + EXT2_INODE_SIZE(fs->super); + block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); + if (!fs->group_desc[(unsigned) group].bg_inode_table) + return EXT2_ET_MISSING_INODE_TABLE; + block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block; + + offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); + + length = EXT2_INODE_SIZE(fs->super); + if (length > bufsize) + length = bufsize; + + ptr = (char *) w_inode; + + while (length) { + clen = length; + if ((offset + length) > fs->blocksize) + clen = fs->blocksize - offset; + + if (fs->icache->buffer_blk != block_nr) { + retval = io_channel_read_blk(fs->io, block_nr, 1, + fs->icache->buffer); + if (retval) + goto errout; + fs->icache->buffer_blk = block_nr; + } + + + memcpy((char *) fs->icache->buffer + (unsigned) offset, + ptr, clen); + + retval = io_channel_write_blk(fs->io, block_nr, 1, + fs->icache->buffer); + if (retval) + goto errout; + + offset = 0; + ptr += clen; + length -= clen; + block_nr++; + } + + fs->flags |= EXT2_FLAG_CHANGED; +errout: + if (w_inode && w_inode != &temp_inode) + free(w_inode); + return retval; +} + +errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode) +{ + return ext2fs_write_inode_full(fs, ino, inode, + sizeof(struct ext2_inode)); +} + +/* + * This function should be called when writing a new inode. It makes + * sure that extra part of large inodes is initialized properly. + */ +errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode) +{ + struct ext2_inode *buf; + int size = EXT2_INODE_SIZE(fs->super); + struct ext2_inode_large *large_inode; + + if (size == sizeof(struct ext2_inode)) + return ext2fs_write_inode_full(fs, ino, inode, + sizeof(struct ext2_inode)); + + buf = malloc(size); + if (!buf) + return ENOMEM; + + memset(buf, 0, size); + *buf = *inode; + + large_inode = (struct ext2_inode_large *) buf; + large_inode->i_extra_isize = sizeof(struct ext2_inode_large) - + EXT2_GOOD_OLD_INODE_SIZE; + + return ext2fs_write_inode_full(fs, ino, buf, size); +} + + +errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks) +{ + struct ext2_inode inode; + int i; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ino > fs->super->s_inodes_count) + return EXT2_ET_BAD_INODE_NUM; + + if (fs->get_blocks) { + if (!(*fs->get_blocks)(fs, ino, blocks)) + return 0; + } + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + return retval; + for (i=0; i < EXT2_N_BLOCKS; i++) + blocks[i] = inode.i_block[i]; + return 0; +} + +errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino) +{ + struct ext2_inode inode; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ino > fs->super->s_inodes_count) + return EXT2_ET_BAD_INODE_NUM; + + if (fs->check_directory) { + retval = (fs->check_directory)(fs, ino); + if (retval != EXT2_ET_CALLBACK_NOTHANDLED) + return retval; + } + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + return retval; + if (!LINUX_S_ISDIR(inode.i_mode)) + return EXT2_ET_NO_DIRECTORY; + return 0; +} + diff -Naur silo-1.4.14.orig/libext2fs/inode_io.c silo-1.4.14/libext2fs/inode_io.c --- silo-1.4.14.orig/libext2fs/inode_io.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/inode_io.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,270 @@ +/* + * inode_io.c --- This is allows an inode in an ext2 filesystem image + * to be accessed via the I/O manager interface. + * + * Copyright (C) 2002 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +struct inode_private_data { + int magic; + char name[32]; + ext2_file_t file; + ext2_filsys fs; + ext2_ino_t ino; + struct ext2_inode inode; + int flags; + struct inode_private_data *next; +}; + +#define CHANNEL_HAS_INODE 0x8000 + +static struct inode_private_data *top_intern; +static int ino_unique = 0; + +static errcode_t inode_open(const char *name, int flags, io_channel *channel); +static errcode_t inode_close(io_channel channel); +static errcode_t inode_set_blksize(io_channel channel, int blksize); +static errcode_t inode_read_blk(io_channel channel, unsigned long block, + int count, void *data); +static errcode_t inode_write_blk(io_channel channel, unsigned long block, + int count, const void *data); +static errcode_t inode_flush(io_channel channel); +static errcode_t inode_write_byte(io_channel channel, unsigned long offset, + int size, const void *data); + +static struct struct_io_manager struct_inode_manager = { + EXT2_ET_MAGIC_IO_MANAGER, + "Inode I/O Manager", + inode_open, + inode_close, + inode_set_blksize, + inode_read_blk, + inode_write_blk, + inode_flush, + inode_write_byte +}; + +io_manager inode_io_manager = &struct_inode_manager; + +errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + char **name) +{ + struct inode_private_data *data; + errcode_t retval; + + if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data), + &data))) + return retval; + data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL; + sprintf(data->name, "%u:%d", ino, ino_unique++); + data->file = 0; + data->fs = fs; + data->ino = ino; + data->flags = 0; + if (inode) { + memcpy(&data->inode, inode, sizeof(struct ext2_inode)); + data->flags |= CHANNEL_HAS_INODE; + } + data->next = top_intern; + top_intern = data; + *name = data->name; + return 0; +} + +errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino, + char **name) +{ + return ext2fs_inode_io_intern2(fs, ino, NULL, name); +} + + +static errcode_t inode_open(const char *name, int flags, io_channel *channel) +{ + io_channel io = NULL; + struct inode_private_data *prev, *data = NULL; + errcode_t retval; + int open_flags; + + if (name == 0) + return EXT2_ET_BAD_DEVICE_NAME; + + for (data = top_intern, prev = NULL; data; + prev = data, data = data->next) + if (strcmp(name, data->name) == 0) + break; + if (!data) + return ENOENT; + if (prev) + prev->next = data->next; + else + top_intern = data->next; + + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); + if (retval) + goto cleanup; + memset(io, 0, sizeof(struct struct_io_channel)); + + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + io->manager = inode_io_manager; + retval = ext2fs_get_mem(strlen(name)+1, &io->name); + if (retval) + goto cleanup; + + strcpy(io->name, name); + io->private_data = data; + io->block_size = 1024; + io->read_error = 0; + io->write_error = 0; + io->refcount = 1; + + open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0; + retval = ext2fs_file_open2(data->fs, data->ino, + (data->flags & CHANNEL_HAS_INODE) ? + &data->inode : 0, open_flags, + &data->file); + if (retval) + goto cleanup; + + *channel = io; + return 0; + +cleanup: + if (data) { + ext2fs_free_mem(&data); + } + if (io) + ext2fs_free_mem(&io); + return retval; +} + +static errcode_t inode_close(io_channel channel) +{ + struct inode_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + if (--channel->refcount > 0) + return 0; + + retval = ext2fs_file_close(data->file); + + ext2fs_free_mem(&channel->private_data); + if (channel->name) + ext2fs_free_mem(&channel->name); + ext2fs_free_mem(&channel); + return retval; +} + +static errcode_t inode_set_blksize(io_channel channel, int blksize) +{ + struct inode_private_data *data; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + channel->block_size = blksize; + return 0; +} + + +static errcode_t inode_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + struct inode_private_data *data; + errcode_t retval; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + if ((retval = ext2fs_file_lseek(data->file, + block * channel->block_size, + EXT2_SEEK_SET, 0))) + return retval; + + count = (count < 0) ? -count : (count * channel->block_size); + + return ext2fs_file_read(data->file, buf, count, 0); +} + +static errcode_t inode_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + struct inode_private_data *data; + errcode_t retval; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + if ((retval = ext2fs_file_lseek(data->file, + block * channel->block_size, + EXT2_SEEK_SET, 0))) + return retval; + + count = (count < 0) ? -count : (count * channel->block_size); + + return ext2fs_file_write(data->file, buf, count, 0); +} + +static errcode_t inode_write_byte(io_channel channel, unsigned long offset, + int size, const void *buf) +{ + struct inode_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + if ((retval = ext2fs_file_lseek(data->file, offset, + EXT2_SEEK_SET, 0))) + return retval; + + return ext2fs_file_write(data->file, buf, size, 0); +} + +/* + * Flush data buffers to disk. + */ +static errcode_t inode_flush(io_channel channel) +{ + struct inode_private_data *data; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct inode_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); + + return ext2fs_file_flush(data->file); +} + diff -Naur silo-1.4.14.orig/libext2fs/io_manager.c silo-1.4.14/libext2fs/io_manager.c --- silo-1.4.14.orig/libext2fs/io_manager.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/io_manager.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,69 @@ +/* + * io_manager.c --- the I/O manager abstraction + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t io_channel_set_options(io_channel channel, const char *opts) +{ + errcode_t retval = 0; + char *next, *ptr, *options, *arg; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + + if (!opts) + return 0; + + if (!channel->manager->set_option) + return EXT2_ET_INVALID_ARGUMENT; + + options = malloc(strlen(opts)+1); + if (!options) + return EXT2_ET_NO_MEMORY; + strcpy(options, opts); + ptr = options; + + while (ptr && *ptr) { + next = strchr(ptr, '&'); + if (next) + *next++ = 0; + + arg = strchr(ptr, '='); + if (arg) + *arg++ = 0; + + retval = (channel->manager->set_option)(channel, ptr, arg); + if (retval) + break; + ptr = next; + } + free(options); + return retval; +} + +errcode_t io_channel_write_byte(io_channel channel, unsigned long offset, + int count, const void *data) +{ + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + + if (channel->manager->write_byte) + return channel->manager->write_byte(channel, offset, + count, data); + + return EXT2_ET_UNIMPLEMENTED; +} diff -Naur silo-1.4.14.orig/libext2fs/irel.h silo-1.4.14/libext2fs/irel.h --- silo-1.4.14.orig/libext2fs/irel.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/irel.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,114 @@ +/* + * irel.h + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +struct ext2_inode_reference { + blk_t block; + __u16 offset; +}; + +struct ext2_inode_relocate_entry { + ext2_ino_t new; + ext2_ino_t orig; + __u16 flags; + __u16 max_refs; +}; + +typedef struct ext2_inode_relocation_table *ext2_irel; + +struct ext2_inode_relocation_table { + __u32 magic; + char *name; + ext2_ino_t current; + void *priv_data; + + /* + * Add an inode relocation entry. + */ + errcode_t (*put)(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent); + /* + * Get an inode relocation entry. + */ + errcode_t (*get)(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent); + + /* + * Get an inode relocation entry by its original inode number + */ + errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent); + + /* + * Initialize for iterating over the inode relocation entries. + */ + errcode_t (*start_iter)(ext2_irel irel); + + /* + * The iterator function for the inode relocation entries. + * Returns an inode number of 0 when out of entries. + */ + errcode_t (*next)(ext2_irel irel, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent); + + /* + * Add an inode reference (i.e., note the fact that a + * particular block/offset contains a reference to an inode) + */ + errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino, + struct ext2_inode_reference *ref); + + /* + * Initialize for iterating over the inode references for a + * particular inode. + */ + errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino); + + /* + * The iterator function for the inode references for an + * inode. The references for only one inode can be interator + * over at a time, as the iterator state is stored in ext2_irel. + */ + errcode_t (*next_ref)(ext2_irel irel, + struct ext2_inode_reference *ref); + + /* + * Move the inode relocation table from one inode number to + * another. Note that the inode references also must move. + */ + errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); + + /* + * Remove an inode relocation entry, along with all of the + * inode references. + */ + errcode_t (*delete)(ext2_irel irel, ext2_ino_t old); + + /* + * Free the inode relocation table. + */ + errcode_t (*free)(ext2_irel irel); +}; + +errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode, + ext2_irel *irel); + +#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent)) +#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent)) +#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \ + ((irel)->get_by_orig((irel), orig, old, ent)) +#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel))) +#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent)) +#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref)) +#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino)) +#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref)) +#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new)) +#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old)) +#define ext2fs_irel_free(irel) ((irel)->free((irel))) diff -Naur silo-1.4.14.orig/libext2fs/irel_ma.c silo-1.4.14/libext2fs/irel_ma.c --- silo-1.4.14.orig/libext2fs/irel_ma.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/irel_ma.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,372 @@ +/* + * irel_ma.c + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "irel.h" + +static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent); +static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent); +static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent); +static errcode_t ima_start_iter(ext2_irel irel); +static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent); +static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, + struct ext2_inode_reference *ref); +static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino); +static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref); +static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); +static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old); +static errcode_t ima_free(ext2_irel irel); + +/* + * This data structure stores the array of inode references; there is + * a structure for each inode. + */ +struct inode_reference_entry { + __u16 num; + struct ext2_inode_reference *refs; +}; + +struct irel_ma { + __u32 magic; + ext2_ino_t max_inode; + ext2_ino_t ref_current; + int ref_iter; + ext2_ino_t *orig_map; + struct ext2_inode_relocate_entry *entries; + struct inode_reference_entry *ref_entries; +}; + +errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode, + ext2_irel *new_irel) +{ + ext2_irel irel = 0; + errcode_t retval; + struct irel_ma *ma = 0; + size_t size; + + *new_irel = 0; + + /* + * Allocate memory structures + */ + retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table), + &irel); + if (retval) + goto errout; + memset(irel, 0, sizeof(struct ext2_inode_relocation_table)); + + retval = ext2fs_get_mem(strlen(name)+1, &irel->name); + if (retval) + goto errout; + strcpy(irel->name, name); + + retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma); + if (retval) + goto errout; + memset(ma, 0, sizeof(struct irel_ma)); + irel->priv_data = ma; + + size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1)); + retval = ext2fs_get_mem(size, &ma->orig_map); + if (retval) + goto errout; + memset(ma->orig_map, 0, size); + + size = (size_t) (sizeof(struct ext2_inode_relocate_entry) * + (max_inode+1)); + retval = ext2fs_get_mem(size, &ma->entries); + if (retval) + goto errout; + memset(ma->entries, 0, size); + + size = (size_t) (sizeof(struct inode_reference_entry) * + (max_inode+1)); + retval = ext2fs_get_mem(size, &ma->ref_entries); + if (retval) + goto errout; + memset(ma->ref_entries, 0, size); + ma->max_inode = max_inode; + + /* + * Fill in the irel data structure + */ + irel->put = ima_put; + irel->get = ima_get; + irel->get_by_orig = ima_get_by_orig; + irel->start_iter = ima_start_iter; + irel->next = ima_next; + irel->add_ref = ima_add_ref; + irel->start_iter_ref = ima_start_iter_ref; + irel->next_ref = ima_next_ref; + irel->move = ima_move; + irel->delete = ima_delete; + irel->free = ima_free; + + *new_irel = irel; + return 0; + +errout: + ima_free(irel); + return retval; +} + +static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent) +{ + struct inode_reference_entry *ref_ent; + struct irel_ma *ma; + errcode_t retval; + size_t size, old_size; + + ma = irel->priv_data; + if (old > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + + /* + * Force the orig field to the correct value; the application + * program shouldn't be messing with this field. + */ + if (ma->entries[(unsigned) old].new == 0) + ent->orig = old; + else + ent->orig = ma->entries[(unsigned) old].orig; + + /* + * If max_refs has changed, reallocate the refs array + */ + ref_ent = ma->ref_entries + (unsigned) old; + if (ref_ent->refs && ent->max_refs != + ma->entries[(unsigned) old].max_refs) { + size = (sizeof(struct ext2_inode_reference) * ent->max_refs); + old_size = (sizeof(struct ext2_inode_reference) * + ma->entries[(unsigned) old].max_refs); + retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs); + if (retval) + return retval; + } + + ma->entries[(unsigned) old] = *ent; + ma->orig_map[(unsigned) ent->orig] = old; + return 0; +} + +static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, + struct ext2_inode_relocate_entry *ent) +{ + struct irel_ma *ma; + + ma = irel->priv_data; + if (old > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned) old].new == 0) + return ENOENT; + *ent = ma->entries[(unsigned) old]; + return 0; +} + +static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent) +{ + struct irel_ma *ma; + ext2_ino_t ino; + + ma = irel->priv_data; + if (orig > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + ino = ma->orig_map[(unsigned) orig]; + if (ino == 0) + return ENOENT; + *old = ino; + *ent = ma->entries[(unsigned) ino]; + return 0; +} + +static errcode_t ima_start_iter(ext2_irel irel) +{ + irel->current = 0; + return 0; +} + +static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, + struct ext2_inode_relocate_entry *ent) +{ + struct irel_ma *ma; + + ma = irel->priv_data; + while (++irel->current < ma->max_inode) { + if (ma->entries[(unsigned) irel->current].new == 0) + continue; + *old = irel->current; + *ent = ma->entries[(unsigned) irel->current]; + return 0; + } + *old = 0; + return 0; +} + +static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, + struct ext2_inode_reference *ref) +{ + struct irel_ma *ma; + size_t size; + struct inode_reference_entry *ref_ent; + struct ext2_inode_relocate_entry *ent; + errcode_t retval; + + ma = irel->priv_data; + if (ino > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + + ref_ent = ma->ref_entries + (unsigned) ino; + ent = ma->entries + (unsigned) ino; + + /* + * If the inode reference array doesn't exist, create it. + */ + if (ref_ent->refs == 0) { + size = (size_t) ((sizeof(struct ext2_inode_reference) * + ent->max_refs)); + retval = ext2fs_get_mem(size, &ref_ent->refs); + if (retval) + return retval; + memset(ref_ent->refs, 0, size); + ref_ent->num = 0; + } + + if (ref_ent->num >= ent->max_refs) + return EXT2_ET_TOO_MANY_REFS; + + ref_ent->refs[(unsigned) ref_ent->num++] = *ref; + return 0; +} + +static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino) +{ + struct irel_ma *ma; + + ma = irel->priv_data; + if (ino > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned) ino].new == 0) + return ENOENT; + ma->ref_current = ino; + ma->ref_iter = 0; + return 0; +} + +static errcode_t ima_next_ref(ext2_irel irel, + struct ext2_inode_reference *ref) +{ + struct irel_ma *ma; + struct inode_reference_entry *ref_ent; + + ma = irel->priv_data; + + ref_ent = ma->ref_entries + ma->ref_current; + + if ((ref_ent->refs == NULL) || + (ma->ref_iter >= ref_ent->num)) { + ref->block = 0; + ref->offset = 0; + return 0; + } + *ref = ref_ent->refs[ma->ref_iter++]; + return 0; +} + + +static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new) +{ + struct irel_ma *ma; + + ma = irel->priv_data; + if ((old > ma->max_inode) || (new > ma->max_inode)) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned) old].new == 0) + return ENOENT; + + ma->entries[(unsigned) new] = ma->entries[(unsigned) old]; + if (ma->ref_entries[(unsigned) new].refs) + ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs); + ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old]; + + ma->entries[(unsigned) old].new = 0; + ma->ref_entries[(unsigned) old].num = 0; + ma->ref_entries[(unsigned) old].refs = 0; + + ma->orig_map[ma->entries[new].orig] = new; + return 0; +} + +static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old) +{ + struct irel_ma *ma; + + ma = irel->priv_data; + if (old > ma->max_inode) + return EXT2_ET_INVALID_ARGUMENT; + if (ma->entries[(unsigned) old].new == 0) + return ENOENT; + + ma->entries[old].new = 0; + if (ma->ref_entries[(unsigned) old].refs) + ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs); + ma->orig_map[ma->entries[(unsigned) old].orig] = 0; + + ma->ref_entries[(unsigned) old].num = 0; + ma->ref_entries[(unsigned) old].refs = 0; + return 0; +} + +static errcode_t ima_free(ext2_irel irel) +{ + struct irel_ma *ma; + ext2_ino_t ino; + + if (!irel) + return 0; + + ma = irel->priv_data; + + if (ma) { + if (ma->orig_map) + ext2fs_free_mem(&ma->orig_map); + if (ma->entries) + ext2fs_free_mem(&ma->entries); + if (ma->ref_entries) { + for (ino = 0; ino <= ma->max_inode; ino++) { + if (ma->ref_entries[(unsigned) ino].refs) + ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs); + } + ext2fs_free_mem(&ma->ref_entries); + } + ext2fs_free_mem(&ma); + } + if (irel->name) + ext2fs_free_mem(&irel->name); + ext2fs_free_mem(&irel); + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/ismounted.c silo-1.4.14/libext2fs/ismounted.c --- silo-1.4.14.orig/libext2fs/ismounted.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/ismounted.c 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,377 @@ +/* + * ismounted.c --- Check to see if the filesystem was mounted + * + * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_LINUX_FD_H +#include +#endif +#ifdef HAVE_MNTENT_H +#include +#endif +#ifdef HAVE_GETMNTINFO +#include +#include +#include +#endif /* HAVE_GETMNTINFO */ +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +#ifdef HAVE_MNTENT_H +/* + * Helper function which checks a file in /etc/mtab format to see if a + * filesystem is mounted. Returns an error if the file doesn't exist + * or can't be opened. + */ +static errcode_t check_mntent_file(const char *mtab_file, const char *file, + int *mount_flags, char *mtpt, int mtlen) +{ + struct mntent *mnt; + struct stat st_buf; + errcode_t retval = 0; + dev_t file_dev=0, file_rdev=0; + ino_t file_ino=0; + FILE *f; + int fd; + + *mount_flags = 0; + if ((f = setmntent (mtab_file, "r")) == NULL) + return errno; + if (stat(file, &st_buf) == 0) { + if (S_ISBLK(st_buf.st_mode)) { +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ + file_rdev = st_buf.st_rdev; +#endif /* __GNU__ */ + } else { + file_dev = st_buf.st_dev; + file_ino = st_buf.st_ino; + } + } + while ((mnt = getmntent (f)) != NULL) { + if (strcmp(file, mnt->mnt_fsname) == 0) + break; + if (stat(mnt->mnt_fsname, &st_buf) == 0) { + if (S_ISBLK(st_buf.st_mode)) { +#ifndef __GNU__ + if (file_rdev && (file_rdev == st_buf.st_rdev)) + break; +#endif /* __GNU__ */ + } else { + if (file_dev && ((file_dev == st_buf.st_dev) && + (file_ino == st_buf.st_ino))) + break; + } + } + } + + if (mnt == 0) { +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ + /* + * Do an extra check to see if this is the root device. We + * can't trust /etc/mtab, and /proc/mounts will only list + * /dev/root for the root filesystem. Argh. Instead we + * check if the given device has the same major/minor number + * as the device that the root directory is on. + */ + if (file_rdev && stat("/", &st_buf) == 0) { + if (st_buf.st_dev == file_rdev) { + *mount_flags = EXT2_MF_MOUNTED; + if (mtpt) + strncpy(mtpt, "/", mtlen); + goto is_root; + } + } +#endif /* __GNU__ */ + goto errout; + } +#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */ + /* Validate the entry in case /etc/mtab is out of date */ + /* + * We need to be paranoid, because some broken distributions + * (read: Slackware) don't initialize /etc/mtab before checking + * all of the non-root filesystems on the disk. + */ + if (stat(mnt->mnt_dir, &st_buf) < 0) { + retval = errno; + if (retval == ENOENT) { +#ifdef DEBUG + printf("Bogus entry in %s! (%s does not exist)\n", + mtab_file, mnt->mnt_dir); +#endif /* DEBUG */ + retval = 0; + } + goto errout; + } + if (file_rdev && (st_buf.st_dev != file_rdev)) { +#ifdef DEBUG + printf("Bogus entry in %s! (%s not mounted on %s)\n", + mtab_file, file, mnt->mnt_dir); +#endif /* DEBUG */ + goto errout; + } +#endif /* __GNU__ */ + *mount_flags = EXT2_MF_MOUNTED; + +#ifdef MNTOPT_RO + /* Check to see if the ro option is set */ + if (hasmntopt(mnt, MNTOPT_RO)) + *mount_flags |= EXT2_MF_READONLY; +#endif + + if (mtpt) + strncpy(mtpt, mnt->mnt_dir, mtlen); + /* + * Check to see if we're referring to the root filesystem. + * If so, do a manual check to see if we can open /etc/mtab + * read/write, since if the root is mounted read/only, the + * contents of /etc/mtab may not be accurate. + */ + if (!strcmp(mnt->mnt_dir, "/")) { +is_root: +#define TEST_FILE "/.ismount-test-file" + *mount_flags |= EXT2_MF_ISROOT; + fd = open(TEST_FILE, O_RDWR|O_CREAT); + if (fd < 0) { + if (errno == EROFS) + *mount_flags |= EXT2_MF_READONLY; + } else + close(fd); + (void) unlink(TEST_FILE); + } + retval = 0; +errout: + endmntent (f); + return retval; +} + +static errcode_t check_mntent(const char *file, int *mount_flags, + char *mtpt, int mtlen) +{ + errcode_t retval; + +#ifdef DEBUG + retval = check_mntent_file("/tmp/mtab", file, mount_flags, + mtpt, mtlen); + if (retval == 0) + return 0; +#endif /* DEBUG */ +#ifdef __linux__ + retval = check_mntent_file("/proc/mounts", file, mount_flags, + mtpt, mtlen); + if (retval == 0 && (*mount_flags != 0)) + return 0; +#endif /* __linux__ */ +#if defined(MOUNTED) || defined(_PATH_MOUNTED) +#ifndef MOUNTED +#define MOUNTED _PATH_MOUNTED +#endif /* MOUNTED */ + retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen); + return retval; +#else + *mount_flags = 0; + return 0; +#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */ +} + +#else +#if defined(HAVE_GETMNTINFO) + +static errcode_t check_getmntinfo(const char *file, int *mount_flags, + char *mtpt, int mtlen) +{ + struct statfs *mp; + int len, n; + const char *s1; + char *s2; + + n = getmntinfo(&mp, MNT_NOWAIT); + if (n == 0) + return errno; + + len = sizeof(_PATH_DEV) - 1; + s1 = file; + if (strncmp(_PATH_DEV, s1, len) == 0) + s1 += len; + + *mount_flags = 0; + while (--n >= 0) { + s2 = mp->f_mntfromname; + if (strncmp(_PATH_DEV, s2, len) == 0) { + s2 += len - 1; + *s2 = 'r'; + } + if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) { + *mount_flags = EXT2_MF_MOUNTED; + break; + } + ++mp; + } + if (mtpt) + strncpy(mtpt, mp->f_mntonname, mtlen); + return 0; +} +#endif /* HAVE_GETMNTINFO */ +#endif /* HAVE_MNTENT_H */ + +/* + * Check to see if we're dealing with the swap device. + */ +static int is_swap_device(const char *file) +{ + FILE *f; + char buf[1024], *cp; + dev_t file_dev; + struct stat st_buf; + int ret = 0; + + file_dev = 0; +#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ + if ((stat(file, &st_buf) == 0) && + S_ISBLK(st_buf.st_mode)) + file_dev = st_buf.st_rdev; +#endif /* __GNU__ */ + + if (!(f = fopen("/proc/swaps", "r"))) + return 0; + /* Skip the first line */ + fgets(buf, sizeof(buf), f); + while (!feof(f)) { + if (!fgets(buf, sizeof(buf), f)) + break; + if ((cp = strchr(buf, ' ')) != NULL) + *cp = 0; + if ((cp = strchr(buf, '\t')) != NULL) + *cp = 0; + if (strcmp(buf, file) == 0) { + ret++; + break; + } +#ifndef __GNU__ + if (file_dev && (stat(buf, &st_buf) == 0) && + S_ISBLK(st_buf.st_mode) && + file_dev == st_buf.st_rdev) { + ret++; + break; + } +#endif /* __GNU__ */ + } + fclose(f); + return ret; +} + + +/* + * ext2fs_check_mount_point() fills determines if the device is + * mounted or otherwise busy, and fills in mount_flags with one or + * more of the following flags: EXT2_MF_MOUNTED, EXT2_MF_ISROOT, + * EXT2_MF_READONLY, EXT2_MF_SWAP, and EXT2_MF_BUSY. If mtpt is + * non-NULL, the directory where the device is mounted is copied to + * where mtpt is pointing, up to mtlen characters. + */ +#ifdef __TURBOC__ + #pragma argsused +#endif +errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, + char *mtpt, int mtlen) +{ + struct stat st_buf; + errcode_t retval = 0; + int fd; + + if (is_swap_device(device)) { + *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP; + strncpy(mtpt, "", mtlen); + } else { +#ifdef HAVE_MNTENT_H + retval = check_mntent(device, mount_flags, mtpt, mtlen); +#else +#ifdef HAVE_GETMNTINFO + retval = check_getmntinfo(device, mount_flags, mtpt, mtlen); +#else +#ifdef __GNUC__ + #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!" +#endif + *mount_flags = 0; +#endif /* HAVE_GETMNTINFO */ +#endif /* HAVE_MNTENT_H */ + } + if (retval) + return retval; + +#ifdef __linux__ /* This only works on Linux 2.6+ systems */ + if ((stat(device, &st_buf) != 0) || + !S_ISBLK(st_buf.st_mode)) + return 0; + fd = open(device, O_RDONLY | O_EXCL); + if (fd < 0) { + if (errno == EBUSY) + *mount_flags |= EXT2_MF_BUSY; + } else + close(fd); + + return 0; +#endif +} + +/* + * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED, + * EXT2_MF_READONLY, and EXT2_MF_ROOT + * + */ +errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags) +{ + return ext2fs_check_mount_point(file, mount_flags, NULL, 0); +} + +#ifdef DEBUG +int main(int argc, char **argv) +{ + int retval, mount_flags; + char mntpt[80]; + + if (argc < 2) { + fprintf(stderr, "Usage: %s device\n", argv[0]); + exit(1); + } + + mntpt[0] = 0; + retval = ext2fs_check_mount_point(argv[1], &mount_flags, + mntpt, sizeof(mntpt)); + if (retval) { + com_err(argv[0], retval, + "while calling ext2fs_check_if_mounted"); + exit(1); + } + printf("Device %s reports flags %02x\n", argv[1], mount_flags); + if (mount_flags & EXT2_MF_BUSY) + printf("\t%s is apparently in use.\n", argv[1]); + if (mount_flags & EXT2_MF_MOUNTED) + printf("\t%s is mounted.\n", argv[1]); + if (mount_flags & EXT2_MF_SWAP) + printf("\t%s is a swap device.\n", argv[1]); + if (mount_flags & EXT2_MF_READONLY) + printf("\t%s is read-only.\n", argv[1]); + if (mount_flags & EXT2_MF_ISROOT) + printf("\t%s is the root filesystem.\n", argv[1]); + if (mntpt[0]) + printf("\t%s is mounted on %s.\n", argv[1], mntpt); + exit(0); +} +#endif /* DEBUG */ diff -Naur silo-1.4.14.orig/libext2fs/jfs_compat.h silo-1.4.14/libext2fs/jfs_compat.h --- silo-1.4.14.orig/libext2fs/jfs_compat.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/jfs_compat.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,67 @@ + +#ifndef _JFS_COMPAT_H +#define _JFS_COMPAT_H + +#include "kernel-list.h" +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#define printk printf +#define KERN_ERR "" +#define KERN_DEBUG "" + +#define READ 0 +#define WRITE 1 + +#define cpu_to_be32(n) htonl(n) +#define be32_to_cpu(n) ntohl(n) + +typedef unsigned int tid_t; +typedef struct journal_s journal_t; + +struct buffer_head; +struct inode; + +struct journal_s +{ + unsigned long j_flags; + int j_errno; + struct buffer_head * j_sb_buffer; + struct journal_superblock_s *j_superblock; + int j_format_version; + unsigned long j_head; + unsigned long j_tail; + unsigned long j_free; + unsigned long j_first, j_last; + kdev_t j_dev; + kdev_t j_fs_dev; + int j_blocksize; + unsigned int j_blk_offset; + unsigned int j_maxlen; + struct inode * j_inode; + tid_t j_tail_sequence; + tid_t j_transaction_sequence; + __u8 j_uuid[16]; + struct jbd_revoke_table_s *j_revoke; +}; + +#define J_ASSERT(assert) \ + do { if (!(assert)) { \ + printf ("Assertion failure in %s() at %s line %d: " \ + "\"%s\"\n", \ + __FUNCTION__, __FILE__, __LINE__, # assert); \ + fatal_error(e2fsck_global_ctx, 0); \ + } } while (0) + +#define is_journal_abort(x) 0 + +#define BUFFER_TRACE(bh, info) do {} while (0) + +/* Need this so we can compile with configure --enable-gcc-wall */ +#ifdef NO_INLINE_FUNCS +#define inline +#endif + +#endif /* _JFS_COMPAT_H */ diff -Naur silo-1.4.14.orig/libext2fs/jfs_dat.h silo-1.4.14/libext2fs/jfs_dat.h --- silo-1.4.14.orig/libext2fs/jfs_dat.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/jfs_dat.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,64 @@ +/* + * jfs_dat.h --- stripped down header file which only contains the JFS + * on-disk data structures + */ + +#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ + +/* + * On-disk structures + */ + +/* + * Descriptor block types: + */ + +#define JFS_DESCRIPTOR_BLOCK 1 +#define JFS_COMMIT_BLOCK 2 +#define JFS_SUPERBLOCK 3 + +/* + * Standard header for all descriptor blocks: + */ +typedef struct journal_header_s +{ + __u32 h_magic; + __u32 h_blocktype; + __u32 h_sequence; +} journal_header_t; + + +/* + * The block tag: used to describe a single buffer in the journal + */ +typedef struct journal_block_tag_s +{ + __u32 t_blocknr; /* The on-disk block number */ + __u32 t_flags; /* See below */ +} journal_block_tag_t; + +/* Definitions for the journal tag flags word: */ +#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */ +#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */ +#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */ +#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ + + +/* + * The journal superblock + */ +typedef struct journal_superblock_s +{ + journal_header_t s_header; + + /* Static information describing the journal */ + __u32 s_blocksize; /* journal device blocksize */ + __u32 s_maxlen; /* total blocks in journal file */ + __u32 s_first; /* first block of log information */ + + /* Dynamic information describing the current state of the log */ + __u32 s_sequence; /* first commit ID expected in log */ + __u32 s_start; /* blocknr of start of log */ + +} journal_superblock_t; + diff -Naur silo-1.4.14.orig/libext2fs/jfs_user.h silo-1.4.14/libext2fs/jfs_user.h --- silo-1.4.14.orig/libext2fs/jfs_user.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/jfs_user.h 2009-01-07 15:07:56.000000000 -0800 @@ -0,0 +1,8 @@ +#ifndef _JFS_USER_H +#define _JFS_USER_H + +typedef unsigned short kdev_t; + +#include "kernel-jbd.h" + +#endif /* _JFS_USER_H */ diff -Naur silo-1.4.14.orig/libext2fs/kernel-jbd.h silo-1.4.14/libext2fs/kernel-jbd.h --- silo-1.4.14.orig/libext2fs/kernel-jbd.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/kernel-jbd.h 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,910 @@ +/* + * linux/include/linux/jbd.h + * + * Written by Stephen C. Tweedie + * + * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + * + * Definitions for transaction data structures for the buffer cache + * filesystem journaling support. + */ + +#ifndef _LINUX_JBD_H +#define _LINUX_JBD_H + +#if defined(CONFIG_JBD) || defined(CONFIG_JBD_MODULE) || !defined(__KERNEL__) + +/* Allow this file to be included directly into e2fsprogs */ +#ifndef __KERNEL__ +#include "jfs_compat.h" +#define JFS_DEBUG +#define jfs_debug jbd_debug +#else + +#include +#include +#include +#endif + +#ifndef __GNUC__ +#define __FUNCTION__ "" +#endif + +#define journal_oom_retry 1 + +#ifdef __STDC__ +#ifdef CONFIG_JBD_DEBUG +/* + * Define JBD_EXPENSIVE_CHECKING to enable more expensive internal + * consistency checks. By default we don't do this unless + * CONFIG_JBD_DEBUG is on. + */ +#define JBD_EXPENSIVE_CHECKING +extern int journal_enable_debug; + +#define jbd_debug(n, f, a...) \ + do { \ + if ((n) <= journal_enable_debug) { \ + printk (KERN_DEBUG "(%s, %d): %s: ", \ + __FILE__, __LINE__, __FUNCTION__); \ + printk (f, ## a); \ + } \ + } while (0) +#else +#ifdef __GNUC__ +#define jbd_debug(f, a...) /**/ +#else +#define jbd_debug(f, ...) /**/ +#endif +#endif +#else +#define jbd_debug(x) /* AIX doesn't do STDC */ +#endif + +extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry); +#define jbd_kmalloc(size, flags) \ + __jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry) +#define jbd_rep_kmalloc(size, flags) \ + __jbd_kmalloc(__FUNCTION__, (size), (flags), 1) + +#define JFS_MIN_JOURNAL_BLOCKS 1024 + +#ifdef __KERNEL__ +typedef struct handle_s handle_t; /* Atomic operation type */ +typedef struct journal_s journal_t; /* Journal control structure */ +#endif + +/* + * Internal structures used by the logging mechanism: + */ + +#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ + +/* + * On-disk structures + */ + +/* + * Descriptor block types: + */ + +#define JFS_DESCRIPTOR_BLOCK 1 +#define JFS_COMMIT_BLOCK 2 +#define JFS_SUPERBLOCK_V1 3 +#define JFS_SUPERBLOCK_V2 4 +#define JFS_REVOKE_BLOCK 5 + +/* + * Standard header for all descriptor blocks: + */ +typedef struct journal_header_s +{ + __u32 h_magic; + __u32 h_blocktype; + __u32 h_sequence; +} journal_header_t; + + +/* + * The block tag: used to describe a single buffer in the journal + */ +typedef struct journal_block_tag_s +{ + __u32 t_blocknr; /* The on-disk block number */ + __u32 t_flags; /* See below */ +} journal_block_tag_t; + +/* + * The revoke descriptor: used on disk to describe a series of blocks to + * be revoked from the log + */ +typedef struct journal_revoke_header_s +{ + journal_header_t r_header; + int r_count; /* Count of bytes used in the block */ +} journal_revoke_header_t; + + +/* Definitions for the journal tag flags word: */ +#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */ +#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */ +#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */ +#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ + + +/* + * The journal superblock. All fields are in big-endian byte order. + */ +typedef struct journal_superblock_s +{ +/* 0x0000 */ + journal_header_t s_header; + +/* 0x000C */ + /* Static information describing the journal */ + __u32 s_blocksize; /* journal device blocksize */ + __u32 s_maxlen; /* total blocks in journal file */ + __u32 s_first; /* first block of log information */ + +/* 0x0018 */ + /* Dynamic information describing the current state of the log */ + __u32 s_sequence; /* first commit ID expected in log */ + __u32 s_start; /* blocknr of start of log */ + +/* 0x0020 */ + /* Error value, as set by journal_abort(). */ + __s32 s_errno; + +/* 0x0024 */ + /* Remaining fields are only valid in a version-2 superblock */ + __u32 s_feature_compat; /* compatible feature set */ + __u32 s_feature_incompat; /* incompatible feature set */ + __u32 s_feature_ro_compat; /* readonly-compatible feature set */ +/* 0x0030 */ + __u8 s_uuid[16]; /* 128-bit uuid for journal */ + +/* 0x0040 */ + __u32 s_nr_users; /* Nr of filesystems sharing log */ + + __u32 s_dynsuper; /* Blocknr of dynamic superblock copy*/ + +/* 0x0048 */ + __u32 s_max_transaction; /* Limit of journal blocks per trans.*/ + __u32 s_max_trans_data; /* Limit of data blocks per trans. */ + +/* 0x0050 */ + __u32 s_padding[44]; + +/* 0x0100 */ + __u8 s_users[16*48]; /* ids of all fs'es sharing the log */ +/* 0x0400 */ +} journal_superblock_t; + +#define JFS_HAS_COMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask)))) +#define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask)))) +#define JFS_HAS_INCOMPAT_FEATURE(j,mask) \ + ((j)->j_format_version >= 2 && \ + ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask)))) + +#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001 + +/* Features known to this kernel version: */ +#define JFS_KNOWN_COMPAT_FEATURES 0 +#define JFS_KNOWN_ROCOMPAT_FEATURES 0 +#define JFS_KNOWN_INCOMPAT_FEATURES JFS_FEATURE_INCOMPAT_REVOKE + +#ifdef __KERNEL__ + +#include +#include + +#define JBD_ASSERTIONS +#ifdef JBD_ASSERTIONS +#define J_ASSERT(assert) \ +do { \ + if (!(assert)) { \ + printk (KERN_EMERG \ + "Assertion failure in %s() at %s:%d: \"%s\"\n", \ + __FUNCTION__, __FILE__, __LINE__, # assert); \ + BUG(); \ + } \ +} while (0) + +#if defined(CONFIG_BUFFER_DEBUG) +void buffer_assertion_failure(struct buffer_head *bh); +#define J_ASSERT_BH(bh, expr) \ + do { \ + if (!(expr)) \ + buffer_assertion_failure(bh); \ + J_ASSERT(expr); \ + } while (0) +#define J_ASSERT_JH(jh, expr) J_ASSERT_BH(jh2bh(jh), expr) +#else +#define J_ASSERT_BH(bh, expr) J_ASSERT(expr) +#define J_ASSERT_JH(jh, expr) J_ASSERT(expr) +#endif + +#else +#define J_ASSERT(assert) +#endif /* JBD_ASSERTIONS */ + +enum jbd_state_bits { + BH_JWrite + = BH_PrivateStart, /* 1 if being written to log (@@@ DEBUGGING) */ + BH_Freed, /* 1 if buffer has been freed (truncated) */ + BH_Revoked, /* 1 if buffer has been revoked from the log */ + BH_RevokeValid, /* 1 if buffer revoked flag is valid */ + BH_JBDDirty, /* 1 if buffer is dirty but journaled */ +}; + +/* Return true if the buffer is one which JBD is managing */ +static inline int buffer_jbd(struct buffer_head *bh) +{ + return __buffer_state(bh, JBD); +} + +static inline struct buffer_head *jh2bh(struct journal_head *jh) +{ + return jh->b_bh; +} + +static inline struct journal_head *bh2jh(struct buffer_head *bh) +{ + return bh->b_private; +} + +struct jbd_revoke_table_s; + +/* The handle_t type represents a single atomic update being performed + * by some process. All filesystem modifications made by the process go + * through this handle. Recursive operations (such as quota operations) + * are gathered into a single update. + * + * The buffer credits field is used to account for journaled buffers + * being modified by the running process. To ensure that there is + * enough log space for all outstanding operations, we need to limit the + * number of outstanding buffers possible at any time. When the + * operation completes, any buffer credits not used are credited back to + * the transaction, so that at all times we know how many buffers the + * outstanding updates on a transaction might possibly touch. */ + +struct handle_s +{ + /* Which compound transaction is this update a part of? */ + transaction_t * h_transaction; + + /* Number of remaining buffers we are allowed to dirty: */ + int h_buffer_credits; + + /* Reference count on this handle */ + int h_ref; + + /* Field for caller's use to track errors through large fs + operations */ + int h_err; + + /* Flags */ + unsigned int h_sync: 1; /* sync-on-close */ + unsigned int h_jdata: 1; /* force data journaling */ + unsigned int h_aborted: 1; /* fatal error on handle */ +}; + + +/* The transaction_t type is the guts of the journaling mechanism. It + * tracks a compound transaction through its various states: + * + * RUNNING: accepting new updates + * LOCKED: Updates still running but we don't accept new ones + * RUNDOWN: Updates are tidying up but have finished requesting + * new buffers to modify (state not used for now) + * FLUSH: All updates complete, but we are still writing to disk + * COMMIT: All data on disk, writing commit record + * FINISHED: We still have to keep the transaction for checkpointing. + * + * The transaction keeps track of all of the buffers modified by a + * running transaction, and all of the buffers committed but not yet + * flushed to home for finished transactions. + */ + +struct transaction_s +{ + /* Pointer to the journal for this transaction. */ + journal_t * t_journal; + + /* Sequence number for this transaction */ + tid_t t_tid; + + /* Transaction's current state */ + enum { + T_RUNNING, + T_LOCKED, + T_RUNDOWN, + T_FLUSH, + T_COMMIT, + T_FINISHED + } t_state; + + /* Where in the log does this transaction's commit start? */ + unsigned long t_log_start; + + /* Doubly-linked circular list of all inodes owned by this + transaction */ /* AKPM: unused */ + struct inode * t_ilist; + + /* Number of buffers on the t_buffers list */ + int t_nr_buffers; + + /* Doubly-linked circular list of all buffers reserved but not + yet modified by this transaction */ + struct journal_head * t_reserved_list; + + /* Doubly-linked circular list of all metadata buffers owned by this + transaction */ + struct journal_head * t_buffers; + + /* + * Doubly-linked circular list of all data buffers still to be + * flushed before this transaction can be committed. + * Protected by journal_datalist_lock. + */ + struct journal_head * t_sync_datalist; + + /* + * Doubly-linked circular list of all writepage data buffers + * still to be written before this transaction can be committed. + * Protected by journal_datalist_lock. + */ + struct journal_head * t_async_datalist; + + /* Doubly-linked circular list of all forget buffers (superceded + buffers which we can un-checkpoint once this transaction + commits) */ + struct journal_head * t_forget; + + /* + * Doubly-linked circular list of all buffers still to be + * flushed before this transaction can be checkpointed. + */ + /* Protected by journal_datalist_lock */ + struct journal_head * t_checkpoint_list; + + /* Doubly-linked circular list of temporary buffers currently + undergoing IO in the log */ + struct journal_head * t_iobuf_list; + + /* Doubly-linked circular list of metadata buffers being + shadowed by log IO. The IO buffers on the iobuf list and the + shadow buffers on this list match each other one for one at + all times. */ + struct journal_head * t_shadow_list; + + /* Doubly-linked circular list of control buffers being written + to the log. */ + struct journal_head * t_log_list; + + /* Number of outstanding updates running on this transaction */ + int t_updates; + + /* Number of buffers reserved for use by all handles in this + * transaction handle but not yet modified. */ + int t_outstanding_credits; + + /* + * Forward and backward links for the circular list of all + * transactions awaiting checkpoint. + */ + /* Protected by journal_datalist_lock */ + transaction_t *t_cpnext, *t_cpprev; + + /* When will the transaction expire (become due for commit), in + * jiffies ? */ + unsigned long t_expires; + + /* How many handles used this transaction? */ + int t_handle_count; +}; + + +/* The journal_t maintains all of the journaling state information for a + * single filesystem. It is linked to from the fs superblock structure. + * + * We use the journal_t to keep track of all outstanding transaction + * activity on the filesystem, and to manage the state of the log + * writing process. */ + +struct journal_s +{ + /* General journaling state flags */ + unsigned long j_flags; + + /* Is there an outstanding uncleared error on the journal (from + * a prior abort)? */ + int j_errno; + + /* The superblock buffer */ + struct buffer_head * j_sb_buffer; + journal_superblock_t * j_superblock; + + /* Version of the superblock format */ + int j_format_version; + + /* Number of processes waiting to create a barrier lock */ + int j_barrier_count; + + /* The barrier lock itself */ + struct semaphore j_barrier; + + /* Transactions: The current running transaction... */ + transaction_t * j_running_transaction; + + /* ... the transaction we are pushing to disk ... */ + transaction_t * j_committing_transaction; + + /* ... and a linked circular list of all transactions waiting + * for checkpointing. */ + /* Protected by journal_datalist_lock */ + transaction_t * j_checkpoint_transactions; + + /* Wait queue for waiting for a locked transaction to start + committing, or for a barrier lock to be released */ + wait_queue_head_t j_wait_transaction_locked; + + /* Wait queue for waiting for checkpointing to complete */ + wait_queue_head_t j_wait_logspace; + + /* Wait queue for waiting for commit to complete */ + wait_queue_head_t j_wait_done_commit; + + /* Wait queue to trigger checkpointing */ + wait_queue_head_t j_wait_checkpoint; + + /* Wait queue to trigger commit */ + wait_queue_head_t j_wait_commit; + + /* Wait queue to wait for updates to complete */ + wait_queue_head_t j_wait_updates; + + /* Semaphore for locking against concurrent checkpoints */ + struct semaphore j_checkpoint_sem; + + /* The main journal lock, used by lock_journal() */ + struct semaphore j_sem; + + /* Journal head: identifies the first unused block in the journal. */ + unsigned long j_head; + + /* Journal tail: identifies the oldest still-used block in the + * journal. */ + unsigned long j_tail; + + /* Journal free: how many free blocks are there in the journal? */ + unsigned long j_free; + + /* Journal start and end: the block numbers of the first usable + * block and one beyond the last usable block in the journal. */ + unsigned long j_first, j_last; + + /* Device, blocksize and starting block offset for the location + * where we store the journal. */ + kdev_t j_dev; + int j_blocksize; + unsigned int j_blk_offset; + + /* Device which holds the client fs. For internal journal this + * will be equal to j_dev. */ + kdev_t j_fs_dev; + + /* Total maximum capacity of the journal region on disk. */ + unsigned int j_maxlen; + + /* Optional inode where we store the journal. If present, all + * journal block numbers are mapped into this inode via + * bmap(). */ + struct inode * j_inode; + + /* Sequence number of the oldest transaction in the log */ + tid_t j_tail_sequence; + /* Sequence number of the next transaction to grant */ + tid_t j_transaction_sequence; + /* Sequence number of the most recently committed transaction */ + tid_t j_commit_sequence; + /* Sequence number of the most recent transaction wanting commit */ + tid_t j_commit_request; + + /* Journal uuid: identifies the object (filesystem, LVM volume + * etc) backed by this journal. This will eventually be + * replaced by an array of uuids, allowing us to index multiple + * devices within a single journal and to perform atomic updates + * across them. */ + + __u8 j_uuid[16]; + + /* Pointer to the current commit thread for this journal */ + struct task_struct * j_task; + + /* Maximum number of metadata buffers to allow in a single + * compound commit transaction */ + int j_max_transaction_buffers; + + /* What is the maximum transaction lifetime before we begin a + * commit? */ + unsigned long j_commit_interval; + + /* The timer used to wakeup the commit thread: */ + struct timer_list * j_commit_timer; + int j_commit_timer_active; + + /* Link all journals together - system-wide */ + struct list_head j_all_journals; + + /* The revoke table: maintains the list of revoked blocks in the + current transaction. */ + struct jbd_revoke_table_s *j_revoke; +}; + +/* + * Journal flag definitions + */ +#define JFS_UNMOUNT 0x001 /* Journal thread is being destroyed */ +#define JFS_ABORT 0x002 /* Journaling has been aborted for errors. */ +#define JFS_ACK_ERR 0x004 /* The errno in the sb has been acked */ +#define JFS_FLUSHED 0x008 /* The journal superblock has been flushed */ +#define JFS_LOADED 0x010 /* The journal superblock has been loaded */ + +/* + * Function declarations for the journaling transaction and buffer + * management + */ + +/* Filing buffers */ +extern void __journal_unfile_buffer(struct journal_head *); +extern void journal_unfile_buffer(struct journal_head *); +extern void __journal_refile_buffer(struct journal_head *); +extern void journal_refile_buffer(struct journal_head *); +extern void __journal_file_buffer(struct journal_head *, transaction_t *, int); +extern void __journal_free_buffer(struct journal_head *bh); +extern void journal_file_buffer(struct journal_head *, transaction_t *, int); +extern void __journal_clean_data_list(transaction_t *transaction); + +/* Log buffer allocation */ +extern struct journal_head * journal_get_descriptor_buffer(journal_t *); +extern unsigned long journal_next_log_block(journal_t *); + +/* Commit management */ +extern void journal_commit_transaction(journal_t *); + +/* Checkpoint list management */ +int __journal_clean_checkpoint_list(journal_t *journal); +extern void journal_remove_checkpoint(struct journal_head *); +extern void __journal_remove_checkpoint(struct journal_head *); +extern void journal_insert_checkpoint(struct journal_head *, transaction_t *); +extern void __journal_insert_checkpoint(struct journal_head *,transaction_t *); + +/* Buffer IO */ +extern int +journal_write_metadata_buffer(transaction_t *transaction, + struct journal_head *jh_in, + struct journal_head **jh_out, + int blocknr); + +/* Transaction locking */ +extern void __wait_on_journal (journal_t *); + +/* + * Journal locking. + * + * We need to lock the journal during transaction state changes so that + * nobody ever tries to take a handle on the running transaction while + * we are in the middle of moving it to the commit phase. + * + * Note that the locking is completely interrupt unsafe. We never touch + * journal structures from interrupts. + * + * In 2.2, the BKL was required for lock_journal. This is no longer + * the case. + */ + +static inline void lock_journal(journal_t *journal) +{ + down(&journal->j_sem); +} + +/* This returns zero if we acquired the semaphore */ +static inline int try_lock_journal(journal_t * journal) +{ + return down_trylock(&journal->j_sem); +} + +static inline void unlock_journal(journal_t * journal) +{ + up(&journal->j_sem); +} + + +static inline handle_t *journal_current_handle(void) +{ + return current->journal_info; +} + +/* The journaling code user interface: + * + * Create and destroy handles + * Register buffer modifications against the current transaction. + */ + +extern handle_t *journal_start(journal_t *, int nblocks); +extern handle_t *journal_try_start(journal_t *, int nblocks); +extern int journal_restart (handle_t *, int nblocks); +extern int journal_extend (handle_t *, int nblocks); +extern int journal_get_write_access (handle_t *, struct buffer_head *); +extern int journal_get_create_access (handle_t *, struct buffer_head *); +extern int journal_get_undo_access (handle_t *, struct buffer_head *); +extern int journal_dirty_data (handle_t *, + struct buffer_head *, int async); +extern int journal_dirty_metadata (handle_t *, struct buffer_head *); +extern void journal_release_buffer (handle_t *, struct buffer_head *); +extern void journal_forget (handle_t *, struct buffer_head *); +extern void journal_sync_buffer (struct buffer_head *); +extern int journal_flushpage(journal_t *, struct page *, unsigned long); +extern int journal_try_to_free_buffers(journal_t *, struct page *, int); +extern int journal_stop(handle_t *); +extern int journal_flush (journal_t *); + +extern void journal_lock_updates (journal_t *); +extern void journal_unlock_updates (journal_t *); + +extern journal_t * journal_init_dev(kdev_t dev, kdev_t fs_dev, + int start, int len, int bsize); +extern journal_t * journal_init_inode (struct inode *); +extern int journal_update_format (journal_t *); +extern int journal_check_used_features + (journal_t *, unsigned long, unsigned long, unsigned long); +extern int journal_check_available_features + (journal_t *, unsigned long, unsigned long, unsigned long); +extern int journal_set_features + (journal_t *, unsigned long, unsigned long, unsigned long); +extern int journal_create (journal_t *); +extern int journal_load (journal_t *journal); +extern void journal_destroy (journal_t *); +extern int journal_recover (journal_t *journal); +extern int journal_wipe (journal_t *, int); +extern int journal_skip_recovery (journal_t *); +extern void journal_update_superblock (journal_t *, int); +extern void __journal_abort (journal_t *); +extern void journal_abort (journal_t *, int); +extern int journal_errno (journal_t *); +extern void journal_ack_err (journal_t *); +extern int journal_clear_err (journal_t *); +extern unsigned long journal_bmap(journal_t *journal, unsigned long blocknr); +extern int journal_force_commit(journal_t *journal); + +/* + * journal_head management + */ +extern struct journal_head + *journal_add_journal_head(struct buffer_head *bh); +extern void journal_remove_journal_head(struct buffer_head *bh); +extern void __journal_remove_journal_head(struct buffer_head *bh); +extern void journal_unlock_journal_head(struct journal_head *jh); + +/* Primary revoke support */ +#define JOURNAL_REVOKE_DEFAULT_HASH 256 +extern int journal_init_revoke(journal_t *, int); +extern void journal_destroy_revoke_caches(void); +extern int journal_init_revoke_caches(void); + +extern void journal_destroy_revoke(journal_t *); +extern int journal_revoke (handle_t *, + unsigned long, struct buffer_head *); +extern int journal_cancel_revoke(handle_t *, struct journal_head *); +extern void journal_write_revoke_records(journal_t *, transaction_t *); + +/* Recovery revoke support */ +extern int journal_set_revoke(journal_t *, unsigned long, tid_t); +extern int journal_test_revoke(journal_t *, unsigned long, tid_t); +extern void journal_clear_revoke(journal_t *); +extern void journal_brelse_array(struct buffer_head *b[], int n); + +/* The log thread user interface: + * + * Request space in the current transaction, and force transaction commit + * transitions on demand. + */ + +extern int log_space_left (journal_t *); /* Called with journal locked */ +extern tid_t log_start_commit (journal_t *, transaction_t *); +extern void log_wait_commit (journal_t *, tid_t); +extern int log_do_checkpoint (journal_t *, int); + +extern void log_wait_for_space(journal_t *, int nblocks); +extern void __journal_drop_transaction(journal_t *, transaction_t *); +extern int cleanup_journal_tail(journal_t *); + +/* Reduce journal memory usage by flushing */ +extern void shrink_journal_memory(void); + +/* Debugging code only: */ + +#define jbd_ENOSYS() \ +do { \ + printk (KERN_ERR "JBD unimplemented function " __FUNCTION__); \ + current->state = TASK_UNINTERRUPTIBLE; \ + schedule(); \ +} while (1) + +/* + * is_journal_abort + * + * Simple test wrapper function to test the JFS_ABORT state flag. This + * bit, when set, indicates that we have had a fatal error somewhere, + * either inside the journaling layer or indicated to us by the client + * (eg. ext3), and that we and should not commit any further + * transactions. + */ + +static inline int is_journal_aborted(journal_t *journal) +{ + return journal->j_flags & JFS_ABORT; +} + +static inline int is_handle_aborted(handle_t *handle) +{ + if (handle->h_aborted) + return 1; + return is_journal_aborted(handle->h_transaction->t_journal); +} + +static inline void journal_abort_handle(handle_t *handle) +{ + handle->h_aborted = 1; +} + +/* Not all architectures define BUG() */ +#ifndef BUG +#define BUG() do { \ + printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + * ((char *) 0) = 0; \ + } while (0) +#endif /* BUG */ + +#else + +extern int journal_recover (journal_t *journal); +extern int journal_skip_recovery (journal_t *); + +/* Primary revoke support */ +extern int journal_init_revoke(journal_t *, int); +extern void journal_destroy_revoke_caches(void); +extern int journal_init_revoke_caches(void); + +/* Recovery revoke support */ +extern int journal_set_revoke(journal_t *, unsigned long, tid_t); +extern int journal_test_revoke(journal_t *, unsigned long, tid_t); +extern void journal_clear_revoke(journal_t *); +extern void journal_brelse_array(struct buffer_head *b[], int n); + +extern void journal_destroy_revoke(journal_t *); +#endif /* __KERNEL__ */ + +/* Comparison functions for transaction IDs: perform comparisons using + * modulo arithmetic so that they work over sequence number wraps. */ + +static inline int tid_gt(tid_t x, tid_t y) +{ + int difference = (x - y); + return (difference > 0); +} + +static inline int tid_geq(tid_t x, tid_t y) +{ + int difference = (x - y); + return (difference >= 0); +} + +extern int journal_blocks_per_page(struct inode *inode); + +/* + * Definitions which augment the buffer_head layer + */ + +/* journaling buffer types */ +#define BJ_None 0 /* Not journaled */ +#define BJ_SyncData 1 /* Normal data: flush before commit */ +#define BJ_AsyncData 2 /* writepage data: wait on it before commit */ +#define BJ_Metadata 3 /* Normal journaled metadata */ +#define BJ_Forget 4 /* Buffer superceded by this transaction */ +#define BJ_IO 5 /* Buffer is for temporary IO use */ +#define BJ_Shadow 6 /* Buffer contents being shadowed to the log */ +#define BJ_LogCtl 7 /* Buffer contains log descriptors */ +#define BJ_Reserved 8 /* Buffer is reserved for access by journal */ +#define BJ_Types 9 + +extern int jbd_blocks_per_page(struct inode *inode); + +#ifdef __KERNEL__ + +extern spinlock_t jh_splice_lock; +/* + * Once `expr1' has been found true, take jh_splice_lock + * and then reevaluate everything. + */ +#define SPLICE_LOCK(expr1, expr2) \ + ({ \ + int ret = (expr1); \ + if (ret) { \ + spin_lock(&jh_splice_lock); \ + ret = (expr1) && (expr2); \ + spin_unlock(&jh_splice_lock); \ + } \ + ret; \ + }) + +/* + * A number of buffer state predicates. They test for + * buffer_jbd() because they are used in core kernel code. + * + * These will be racy on SMP unless we're *sure* that the + * buffer won't be detached from the journalling system + * in parallel. + */ + +/* Return true if the buffer is on journal list `list' */ +static inline int buffer_jlist_eq(struct buffer_head *bh, int list) +{ + return SPLICE_LOCK(buffer_jbd(bh), bh2jh(bh)->b_jlist == list); +} + +/* Return true if this bufer is dirty wrt the journal */ +static inline int buffer_jdirty(struct buffer_head *bh) +{ + return buffer_jbd(bh) && __buffer_state(bh, JBDDirty); +} + +/* Return true if it's a data buffer which journalling is managing */ +static inline int buffer_jbd_data(struct buffer_head *bh) +{ + return SPLICE_LOCK(buffer_jbd(bh), + bh2jh(bh)->b_jlist == BJ_SyncData || + bh2jh(bh)->b_jlist == BJ_AsyncData); +} + +#ifdef CONFIG_SMP +#define assert_spin_locked(lock) J_ASSERT(spin_is_locked(lock)) +#else +#define assert_spin_locked(lock) do {} while(0) +#endif + +#define buffer_trace_init(bh) do {} while (0) +#define print_buffer_fields(bh) do {} while (0) +#define print_buffer_trace(bh) do {} while (0) +#define BUFFER_TRACE(bh, info) do {} while (0) +#define BUFFER_TRACE2(bh, bh2, info) do {} while (0) +#define JBUFFER_TRACE(jh, info) do {} while (0) + +#endif /* __KERNEL__ */ + +#endif /* CONFIG_JBD || CONFIG_JBD_MODULE || !__KERNEL__ */ + +/* + * Compatibility no-ops which allow the kernel to compile without CONFIG_JBD + * go here. + */ + +#if defined(__KERNEL__) && !(defined(CONFIG_JBD) || defined(CONFIG_JBD_MODULE)) + +#define J_ASSERT(expr) do {} while (0) +#define J_ASSERT_BH(bh, expr) do {} while (0) +#define buffer_jbd(bh) 0 +#define buffer_jlist_eq(bh, val) 0 +#define journal_buffer_journal_lru(bh) 0 + +#endif /* defined(__KERNEL__) && !defined(CONFIG_JBD) */ +#endif /* _LINUX_JBD_H */ diff -Naur silo-1.4.14.orig/libext2fs/kernel-list.h silo-1.4.14/libext2fs/kernel-list.h --- silo-1.4.14.orig/libext2fs/kernel-list.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/kernel-list.h 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,112 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = { &name, &name } + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +#if (!defined(__GNUC__) && !defined(__WATCOMC__)) +#define __inline__ +#endif + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline__ void __list_add(struct list_head * new, + struct list_head * prev, + struct list_head * next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/* + * Insert a new entry after the specified head.. + */ +static __inline__ void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/* + * Insert a new entry at the tail + */ +static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline__ void __list_del(struct list_head * prev, + struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +static __inline__ void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +static __inline__ int list_empty(struct list_head *head) +{ + return head->next == head; +} + +/* + * Splice in "list" into "head" + */ +static __inline__ void list_splice(struct list_head *list, struct list_head *head) +{ + struct list_head *first = list->next; + + if (first != list) { + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; + } +} + +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +#endif diff -Naur silo-1.4.14.orig/libext2fs/link.c silo-1.4.14/libext2fs/link.c --- silo-1.4.14.orig/libext2fs/link.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/link.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,134 @@ +/* + * link.c --- create links in a ext2fs directory + * + * Copyright (C) 1993, 1994 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct link_struct { + const char *name; + int namelen; + ext2_ino_t inode; + int flags; + int done; + struct ext2_super_block *sb; +}; + +static int link_proc(struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *priv_data) +{ + struct link_struct *ls = (struct link_struct *) priv_data; + struct ext2_dir_entry *next; + int rec_len, min_rec_len; + int ret = 0; + + rec_len = EXT2_DIR_REC_LEN(ls->namelen); + + /* + * See if the following directory entry (if any) is unused; + * if so, absorb it into this one. + */ + next = (struct ext2_dir_entry *) (buf + offset + dirent->rec_len); + if ((offset + dirent->rec_len < blocksize - 8) && + (next->inode == 0) && + (offset + dirent->rec_len + next->rec_len <= blocksize)) { + dirent->rec_len += next->rec_len; + ret = DIRENT_CHANGED; + } + + /* + * If the directory entry is used, see if we can split the + * directory entry to make room for the new name. If so, + * truncate it and return. + */ + if (dirent->inode) { + min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); + if (dirent->rec_len < (min_rec_len + rec_len)) + return ret; + rec_len = dirent->rec_len - min_rec_len; + dirent->rec_len = min_rec_len; + next = (struct ext2_dir_entry *) (buf + offset + + dirent->rec_len); + next->inode = 0; + next->name_len = 0; + next->rec_len = rec_len; + return DIRENT_CHANGED; + } + + /* + * If we get this far, then the directory entry is not used. + * See if we can fit the request entry in. If so, do it. + */ + if (dirent->rec_len < rec_len) + return ret; + dirent->inode = ls->inode; + dirent->name_len = ls->namelen; + strncpy(dirent->name, ls->name, ls->namelen); + if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) + dirent->name_len |= (ls->flags & 0x7) << 8; + + ls->done++; + return DIRENT_ABORT|DIRENT_CHANGED; +} + +/* + * Note: the low 3 bits of the flags field are used as the directory + * entry filetype. + */ +#ifdef __TURBOC__ + #pragma argsused +#endif +errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, + ext2_ino_t ino, int flags) +{ + errcode_t retval; + struct link_struct ls; + struct ext2_inode inode; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + ls.name = name; + ls.namelen = name ? strlen(name) : 0; + ls.inode = ino; + ls.flags = flags; + ls.done = 0; + ls.sb = fs->super; + + retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, + 0, link_proc, &ls); + if (retval) + return retval; + + if (!ls.done) + return EXT2_ET_DIR_NO_SPACE; + + if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0) + return retval; + + if (inode.i_flags & EXT2_INDEX_FL) { + inode.i_flags &= ~EXT2_INDEX_FL; + if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0) + return retval; + } + + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/llseek.c silo-1.4.14/libext2fs/llseek.c --- silo-1.4.14.orig/libext2fs/llseek.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/llseek.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,138 @@ +/* + * llseek.c -- stub calling the llseek system call + * + * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#if HAVE_SYS_TYPES_H +#include +#endif + +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#ifdef __MSDOS__ +#include +#endif +#include "et/com_err.h" +#include "ext2fs/ext2_io.h" + +#ifdef __linux__ + +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) + +#define my_llseek lseek64 + +#else +#if defined(HAVE_LLSEEK) +#include + +#ifndef HAVE_LLSEEK_PROTOTYPE +extern long long llseek (int fd, long long offset, int origin); +#endif + +#define my_llseek llseek + +#else /* ! HAVE_LLSEEK */ + +#if defined(__alpha__) || defined (__ia64__) + +#define llseek lseek + +#else /* !__alpha__ && !__ia64__*/ + +#include + +#ifndef __NR__llseek +#define __NR__llseek 140 +#endif + +#ifndef __i386__ +static int _llseek (unsigned int, unsigned long, + unsigned long, ext2_loff_t *, unsigned int); + +static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high, + unsigned long, offset_low,ext2_loff_t *,result, + unsigned int, origin) +#endif + +static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin) +{ + ext2_loff_t result; + int retval; + +#ifndef __i386__ + retval = _llseek(fd, ((unsigned long long) offset) >> 32, +#else + retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32), +#endif + ((unsigned long long) offset) & 0xffffffff, + &result, origin); + return (retval == -1 ? (ext2_loff_t) retval : result); +} + +#endif /* __alpha__ || __ia64__ */ + +#endif /* HAVE_LLSEEK */ +#endif /* defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) */ + +ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin) +{ + ext2_loff_t result; + static int do_compat = 0; + + if ((sizeof(off_t) >= sizeof(ext2_loff_t)) || + (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) + return lseek(fd, (off_t) offset, origin); + + if (do_compat) { + errno = EINVAL; + return -1; + } + + result = my_llseek (fd, offset, origin); + if (result == -1 && errno == ENOSYS) { + /* + * Just in case this code runs on top of an old kernel + * which does not support the llseek system call + */ + do_compat++; + errno = EINVAL; + } + return result; +} + +#else /* !linux */ + +#ifndef EINVAL +#define EINVAL EXT2_ET_INVALID_ARGUMENT +#endif + +ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin) +{ +#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) + return lseek64 (fd, offset, origin); +#else + if ((sizeof(off_t) < sizeof(ext2_loff_t)) && + (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) { + errno = EINVAL; + return -1; + } + return lseek (fd, (off_t) offset, origin); +#endif +} + +#endif /* linux */ + + diff -Naur silo-1.4.14.orig/libext2fs/lookup.c silo-1.4.14/libext2fs/lookup.c --- silo-1.4.14.orig/libext2fs/lookup.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/lookup.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,69 @@ +/* + * lookup.c --- ext2fs directory lookup operations + * + * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct lookup_struct { + const char *name; + int len; + ext2_ino_t *inode; + int found; +}; + +#ifdef __TURBOC__ + #pragma argsused +#endif +static int lookup_proc(struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct lookup_struct *ls = (struct lookup_struct *) priv_data; + + if (ls->len != (dirent->name_len & 0xFF)) + return 0; + if (strncmp(ls->name, dirent->name, (dirent->name_len & 0xFF))) + return 0; + *ls->inode = dirent->inode; + ls->found++; + return DIRENT_ABORT; +} + + +errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name, + int namelen, char *buf, ext2_ino_t *inode) +{ + errcode_t retval; + struct lookup_struct ls; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + ls.name = name; + ls.len = namelen; + ls.inode = inode; + ls.found = 0; + + retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls); + if (retval) + return retval; + + return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND; +} + + diff -Naur silo-1.4.14.orig/libext2fs/mkdir.c silo-1.4.14/libext2fs/mkdir.c --- silo-1.4.14.orig/libext2fs/mkdir.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/mkdir.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,142 @@ +/* + * mkdir.c --- make a directory in the filesystem + * + * Copyright (C) 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#ifndef EXT2_FT_DIR +#define EXT2_FT_DIR 2 +#endif + +errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, + const char *name) +{ + errcode_t retval; + struct ext2_inode parent_inode, inode; + ext2_ino_t ino = inum; + ext2_ino_t scratch_ino; + blk_t blk; + char *block = 0; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + /* + * Allocate an inode, if necessary + */ + if (!ino) { + retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, + 0, &ino); + if (retval) + goto cleanup; + } + + /* + * Allocate a data block for the directory + */ + retval = ext2fs_new_block(fs, 0, 0, &blk); + if (retval) + goto cleanup; + + /* + * Create a scratch template for the directory + */ + retval = ext2fs_new_dir_block(fs, ino, parent, &block); + if (retval) + goto cleanup; + + /* + * Get the parent's inode, if necessary + */ + if (parent != ino) { + retval = ext2fs_read_inode(fs, parent, &parent_inode); + if (retval) + goto cleanup; + } else + memset(&parent_inode, 0, sizeof(parent_inode)); + + /* + * Create the inode structure.... + */ + memset(&inode, 0, sizeof(struct ext2_inode)); + inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask); + inode.i_uid = inode.i_gid = 0; + inode.i_blocks = fs->blocksize / 512; + inode.i_block[0] = blk; + inode.i_links_count = 2; + inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL); + inode.i_size = fs->blocksize; + + /* + * Write out the inode and inode data block + */ + retval = ext2fs_write_dir_block(fs, blk, block); + if (retval) + goto cleanup; + retval = ext2fs_write_new_inode(fs, ino, &inode); + if (retval) + goto cleanup; + + /* + * Link the directory into the filesystem hierarchy + */ + if (name) { + retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, + &scratch_ino); + if (!retval) { + retval = EXT2_ET_DIR_EXISTS; + name = 0; + goto cleanup; + } + if (retval != EXT2_ET_FILE_NOT_FOUND) + goto cleanup; + retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); + if (retval) + goto cleanup; + } + + /* + * Update parent inode's counts + */ + if (parent != ino) { + parent_inode.i_links_count++; + retval = ext2fs_write_inode(fs, parent, &parent_inode); + if (retval) + goto cleanup; + } + + /* + * Update accounting.... + */ + ext2fs_block_alloc_stats(fs, blk, +1); + ext2fs_inode_alloc_stats2(fs, ino, +1, 1); + +cleanup: + if (block) + ext2fs_free_mem(&block); + return retval; + +} + + diff -Naur silo-1.4.14.orig/libext2fs/mkjournal.c silo-1.4.14/libext2fs/mkjournal.c --- silo-1.4.14.orig/libext2fs/mkjournal.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/mkjournal.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,425 @@ +/* + * mkjournal.c --- make a journal for a filesystem + * + * Copyright (C) 2000 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_IOCTL_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif + +#include "ext2_fs.h" +#include "e2p/e2p.h" +#include "ext2fs.h" +#include "jfs_user.h" + +/* + * This function automatically sets up the journal superblock and + * returns it as an allocated block. + */ +errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, + __u32 size, int flags, + char **ret_jsb) +{ + errcode_t retval; + journal_superblock_t *jsb; + + if (size < 1024) + return EXT2_ET_JOURNAL_TOO_SMALL; + + if ((retval = ext2fs_get_mem(fs->blocksize, &jsb))) + return retval; + + memset (jsb, 0, fs->blocksize); + + jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); + if (flags & EXT2_MKJOURNAL_V1_SUPER) + jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1); + else + jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2); + jsb->s_blocksize = htonl(fs->blocksize); + jsb->s_maxlen = htonl(size); + jsb->s_nr_users = htonl(1); + jsb->s_first = htonl(1); + jsb->s_sequence = htonl(1); + memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid)); + /* + * If we're creating an external journal device, we need to + * adjust these fields. + */ + if (fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { + jsb->s_nr_users = 0; + if (fs->blocksize == 1024) + jsb->s_first = htonl(3); + else + jsb->s_first = htonl(2); + } + + *ret_jsb = (char *) jsb; + return 0; +} + +/* + * This function writes a journal using POSIX routines. It is used + * for creating external journals and creating journals on live + * filesystems. + */ +static errcode_t write_journal_file(ext2_filsys fs, char *filename, + blk_t size, int flags) +{ + errcode_t retval; + char *buf = 0; + int fd, ret_size; + blk_t i; + + if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) + return retval; + + /* Open the device or journal file */ + if ((fd = open(filename, O_WRONLY)) < 0) { + retval = errno; + goto errout; + } + + /* Write the superblock out */ + retval = EXT2_ET_SHORT_WRITE; + ret_size = write(fd, buf, fs->blocksize); + if (ret_size < 0) { + retval = errno; + goto errout; + } + if (ret_size != (int) fs->blocksize) + goto errout; + memset(buf, 0, fs->blocksize); + + for (i = 1; i < size; i++) { + ret_size = write(fd, buf, fs->blocksize); + if (ret_size < 0) { + retval = errno; + goto errout; + } + if (ret_size != (int) fs->blocksize) + goto errout; + } + close(fd); + + retval = 0; +errout: + ext2fs_free_mem(&buf); + return retval; +} + +/* + * Helper function for creating the journal using direct I/O routines + */ +struct mkjournal_struct { + int num_blocks; + int newblocks; + char *buf; + errcode_t err; +}; + +static int mkjournal_proc(ext2_filsys fs, + blk_t *blocknr, + e2_blkcnt_t blockcnt, + blk_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data; + blk_t new_blk; + static blk_t last_blk = 0; + errcode_t retval; + + 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) + es->num_blocks--; + + es->newblocks++; + retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf); + + if (blockcnt == 0) + memset(es->buf, 0, fs->blocksize); + + if (retval) { + es->err = retval; + return BLOCK_ABORT; + } + *blocknr = new_blk; + last_blk = new_blk; + ext2fs_block_alloc_stats(fs, new_blk, +1); + + if (es->num_blocks == 0) + return (BLOCK_CHANGED | BLOCK_ABORT); + else + return BLOCK_CHANGED; + +} + +/* + * This function creates a journal using direct I/O routines. + */ +static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, + blk_t size, int flags) +{ + char *buf; + errcode_t retval; + struct ext2_inode inode; + struct mkjournal_struct es; + + if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) + return retval; + + if ((retval = ext2fs_read_bitmaps(fs))) + return retval; + + if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) + return retval; + + if (inode.i_blocks > 0) + return EEXIST; + + es.num_blocks = size; + es.newblocks = 0; + es.buf = buf; + es.err = 0; + + retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND, + 0, mkjournal_proc, &es); + if (es.err) { + retval = es.err; + goto errout; + } + + if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) + goto errout; + + inode.i_size += fs->blocksize * size; + inode.i_blocks += (fs->blocksize / 512) * es.newblocks; + inode.i_mtime = inode.i_ctime = time(0); + inode.i_links_count = 1; + inode.i_mode = LINUX_S_IFREG | 0600; + + if ((retval = ext2fs_write_inode(fs, journal_ino, &inode))) + goto errout; + retval = 0; + + memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); + fs->super->s_jnl_blocks[16] = inode.i_size; + fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; + ext2fs_mark_super_dirty(fs); + +errout: + ext2fs_free_mem(&buf); + return retval; +} + +/* + * This function adds a journal device to a filesystem + */ +errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev) +{ + struct stat st; + errcode_t retval; + char buf[1024]; + journal_superblock_t *jsb; + int start; + __u32 i, nr_users; + + /* Make sure the device exists and is a block device */ + if (stat(journal_dev->device_name, &st) < 0) + return errno; + + if (!S_ISBLK(st.st_mode)) + return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */ + + /* Get the journal superblock */ + start = 1; + if (journal_dev->blocksize == 1024) + start++; + if ((retval = io_channel_read_blk(journal_dev->io, start, -1024, buf))) + return retval; + + jsb = (journal_superblock_t *) buf; + if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || + (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) + return EXT2_ET_NO_JOURNAL_SB; + + if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize) + return EXT2_ET_UNEXPECTED_BLOCK_SIZE; + + /* Check and see if this filesystem has already been added */ + nr_users = ntohl(jsb->s_nr_users); + for (i=0; i < nr_users; i++) { + if (memcmp(fs->super->s_uuid, + &jsb->s_users[i*16], 16) == 0) + break; + } + if (i >= nr_users) { + memcpy(&jsb->s_users[nr_users*16], + fs->super->s_uuid, 16); + jsb->s_nr_users = htonl(nr_users+1); + } + + /* Writeback the journal superblock */ + if ((retval = io_channel_write_blk(journal_dev->io, start, -1024, buf))) + return retval; + + fs->super->s_journal_inum = 0; + fs->super->s_journal_dev = st.st_rdev; + memcpy(fs->super->s_journal_uuid, jsb->s_uuid, + sizeof(fs->super->s_journal_uuid)); + fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; + ext2fs_mark_super_dirty(fs); + return 0; +} + +/* + * This function adds a journal inode to a filesystem, using either + * POSIX routines if the filesystem is mounted, or using direct I/O + * functions if it is not. + */ +errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags) +{ + errcode_t retval; + ext2_ino_t journal_ino; + struct stat st; + char jfile[1024]; + int fd, mount_flags, f; + + if ((retval = ext2fs_check_mount_point(fs->device_name, &mount_flags, + jfile, sizeof(jfile)-10))) + return retval; + + if (mount_flags & EXT2_MF_MOUNTED) { + strcat(jfile, "/.journal"); + + /* + * If .../.journal already exists, make sure any + * immutable or append-only flags are cleared. + */ +#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) + (void) chflags (jfile, 0); +#else +#if HAVE_EXT2_IOCTLS + fd = open(jfile, O_RDONLY); + if (fd >= 0) { + f = 0; + ioctl(fd, EXT2_IOC_SETFLAGS, &f); + close(fd); + } +#endif +#endif + + /* Create the journal file */ + if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0) + return errno; + + if ((retval = write_journal_file(fs, jfile, size, flags))) + goto errout; + + /* Get inode number of the journal file */ + if (fstat(fd, &st) < 0) + goto errout; + +#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) + retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE); +#else +#if HAVE_EXT2_IOCTLS + f = EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL; + retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); +#endif +#endif + if (retval) + goto errout; + + close(fd); + journal_ino = st.st_ino; + } else { + journal_ino = EXT2_JOURNAL_INO; + if ((retval = write_journal_inode(fs, journal_ino, + size, flags))) + return retval; + } + + fs->super->s_journal_inum = journal_ino; + fs->super->s_journal_dev = 0; + memset(fs->super->s_journal_uuid, 0, + sizeof(fs->super->s_journal_uuid)); + fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; + + ext2fs_mark_super_dirty(fs); + return 0; +errout: + close(fd); + return retval; +} + +#ifdef DEBUG +main(int argc, char **argv) +{ + errcode_t retval; + char *device_name; + ext2_filsys fs; + + if (argc < 2) { + fprintf(stderr, "Usage: %s filesystem\n", argv[0]); + exit(1); + } + device_name = argv[1]; + + retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0, + unix_io_manager, &fs); + if (retval) { + com_err(argv[0], retval, "while opening %s", device_name); + exit(1); + } + + retval = ext2fs_add_journal_inode(fs, 1024); + if (retval) { + com_err(argv[0], retval, "while adding journal to %s", + device_name); + exit(1); + } + retval = ext2fs_flush(fs); + if (retval) { + printf("Warning, had trouble writing out superblocks.\n"); + } + ext2fs_close(fs); + exit(0); + +} +#endif diff -Naur silo-1.4.14.orig/libext2fs/namei.c silo-1.4.14/libext2fs/namei.c --- silo-1.4.14.orig/libext2fs/namei.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/namei.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,205 @@ +/* + * namei.c --- ext2fs directory lookup operations + * + * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +/* #define NAMEI_DEBUG */ + +#include "ext2_fs.h" +#include "ext2fs.h" + +static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base, + const char *pathname, size_t pathlen, int follow, + int link_count, char *buf, ext2_ino_t *res_inode); + +static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, + ext2_ino_t inode, int link_count, + char *buf, ext2_ino_t *res_inode) +{ + char *pathname; + char *buffer = 0; + errcode_t retval; + struct ext2_inode ei; + +#ifdef NAMEI_DEBUG + printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n", + root, dir, inode, link_count); + +#endif + retval = ext2fs_read_inode (fs, inode, &ei); + if (retval) return retval; + if (!LINUX_S_ISLNK (ei.i_mode)) { + *res_inode = inode; + return 0; + } + if (link_count++ > 5) { + return EXT2_ET_SYMLINK_LOOP; + } + if (ext2fs_inode_data_blocks(fs,&ei)) { + retval = ext2fs_get_mem(fs->blocksize, &buffer); + if (retval) + return retval; + retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer); + if (retval) { + ext2fs_free_mem(&buffer); + return retval; + } + pathname = buffer; + } else + pathname = (char *)&(ei.i_block[0]); + retval = open_namei(fs, root, dir, pathname, ei.i_size, 1, + link_count, buf, res_inode); + if (buffer) + ext2fs_free_mem(&buffer); + return retval; +} + +/* + * This routine interprets a pathname in the context of the current + * directory and the root directory, and returns the inode of the + * containing directory, and a pointer to the filename of the file + * (pointing into the pathname) and the length of the filename. + */ +static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, + const char *pathname, int pathlen, + int link_count, char *buf, + const char **name, int *namelen, + ext2_ino_t *res_inode) +{ + char c; + const char *thisname; + int len; + ext2_ino_t inode; + errcode_t retval; + + if ((c = *pathname) == '/') { + dir = root; + pathname++; + pathlen--; + } + while (1) { + thisname = pathname; + for (len=0; --pathlen >= 0;len++) { + c = *(pathname++); + if (c == '/') + break; + } + if (pathlen < 0) + break; + retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode); + if (retval) return retval; + retval = follow_link (fs, root, dir, inode, + link_count, buf, &dir); + if (retval) return retval; + } + *name = thisname; + *namelen = len; + *res_inode = dir; + return 0; +} + +static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base, + const char *pathname, size_t pathlen, int follow, + int link_count, char *buf, ext2_ino_t *res_inode) +{ + const char *basename; + int namelen; + ext2_ino_t dir, inode; + errcode_t retval; + +#ifdef NAMEI_DEBUG + printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n", + root, base, pathlen, pathname, link_count); +#endif + retval = dir_namei(fs, root, base, pathname, pathlen, + link_count, buf, &basename, &namelen, &dir); + if (retval) return retval; + if (!namelen) { /* special case: '/usr/' etc */ + *res_inode=dir; + return 0; + } + retval = ext2fs_lookup (fs, dir, basename, namelen, buf, &inode); + if (retval) + return retval; + if (follow) { + retval = follow_link(fs, root, dir, inode, link_count, + buf, &inode); + if (retval) + return retval; + } +#ifdef NAMEI_DEBUG + printf("open_namei: (link_count=%d) returns %lu\n", + link_count, inode); +#endif + *res_inode = inode; + return 0; +} + +errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + const char *name, ext2_ino_t *inode) +{ + char *buf; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + + retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0, + buf, inode); + + ext2fs_free_mem(&buf); + return retval; +} + +errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + const char *name, ext2_ino_t *inode) +{ + char *buf; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + + retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0, + buf, inode); + + ext2fs_free_mem(&buf); + return retval; +} + +errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + ext2_ino_t inode, ext2_ino_t *res_inode) +{ + char *buf; + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + + retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode); + + ext2fs_free_mem(&buf); + return retval; +} + diff -Naur silo-1.4.14.orig/libext2fs/native.c silo-1.4.14/libext2fs/native.c --- silo-1.4.14.orig/libext2fs/native.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/native.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,27 @@ +/* + * native.c --- returns the ext2_flag for a native byte order + * + * Copyright (C) 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +int ext2fs_native_flag(void) +{ +#ifdef WORDS_BIGENDIAN + return EXT2_FLAG_SWAP_BYTES; +#else + return 0; +#endif +} + + + diff -Naur silo-1.4.14.orig/libext2fs/newdir.c silo-1.4.14/libext2fs/newdir.c --- silo-1.4.14.orig/libext2fs/newdir.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/newdir.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,72 @@ +/* + * newdir.c --- create a new directory block + * + * Copyright (C) 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#ifndef EXT2_FT_DIR +#define EXT2_FT_DIR 2 +#endif + +/* + * Create new directory block + */ +errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino, + ext2_ino_t parent_ino, char **block) +{ + struct ext2_dir_entry *dir = NULL; + errcode_t retval; + char *buf; + int rec_len; + int filetype = 0; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + retval = ext2fs_get_mem(fs->blocksize, &buf); + if (retval) + return retval; + memset(buf, 0, fs->blocksize); + dir = (struct ext2_dir_entry *) buf; + dir->rec_len = fs->blocksize; + + if (dir_ino) { + if (fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_FILETYPE) + filetype = EXT2_FT_DIR << 8; + /* + * Set up entry for '.' + */ + dir->inode = dir_ino; + dir->name_len = 1 | filetype; + dir->name[0] = '.'; + rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1); + dir->rec_len = EXT2_DIR_REC_LEN(1); + + /* + * Set up entry for '..' + */ + dir = (struct ext2_dir_entry *) (buf + dir->rec_len); + dir->rec_len = rec_len; + dir->inode = parent_ino; + dir->name_len = 2 | filetype; + dir->name[0] = '.'; + dir->name[1] = '.'; + + } + *block = buf; + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/nt_io.c silo-1.4.14/libext2fs/nt_io.c --- silo-1.4.14.orig/libext2fs/nt_io.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/nt_io.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,1513 @@ +/* + * nt_io.c --- This is the Nt I/O interface to the I/O manager. + * + * Implements a one-block write-through cache. + * + * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. + * Copyright (C) 1998 Andrey Shedel (andreys@ns.cr.cyco.com) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + +// +// I need some warnings to disable... +// + + +#pragma warning(disable:4514) // unreferenced inline function has been removed +#pragma warning(push,4) + +#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union) +#pragma warning(disable:4214) // nonstandard extension used : bit field types other than int +#pragma warning(disable:4115) // named type definition in parentheses + +#include +#include +#include + +#pragma warning(pop) + + +// +// Some native APIs. +// + +NTSYSAPI +ULONG +NTAPI +RtlNtStatusToDosError( + IN NTSTATUS Status + ); + +NTSYSAPI +NTSTATUS +NTAPI +NtClose( + IN HANDLE Handle + ); + + +NTSYSAPI +NTSTATUS +NTAPI +NtOpenFile( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG ShareAccess, + IN ULONG OpenOptions + ); + +NTSYSAPI +NTSTATUS +NTAPI +NtFlushBuffersFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock + ); + + +NTSYSAPI +NTSTATUS +NTAPI +NtReadFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + OUT PVOID Buffer, + IN ULONG Length, + IN PLARGE_INTEGER ByteOffset OPTIONAL, + IN PULONG Key OPTIONAL + ); + +NTSYSAPI +NTSTATUS +NTAPI +NtWriteFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PVOID Buffer, + IN ULONG Length, + IN PLARGE_INTEGER ByteOffset OPTIONAL, + IN PULONG Key OPTIONAL + ); + +NTSYSAPI +NTSTATUS +NTAPI +NtDeviceIoControlFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength + ); + +NTSYSAPI +NTSTATUS +NTAPI +NtFsControlFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength + ); + + +NTSYSAPI +NTSTATUS +NTAPI +NtDelayExecution( + IN BOOLEAN Alertable, + IN PLARGE_INTEGER Interval + ); + + +#define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_IS_VOLUME_MOUNTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM,10, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +// +// useful macros +// + +#define BooleanFlagOn(Flags,SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0))) + + +// +// Include Win32 error codes. +// + +#include + +// +// standard stuff +// + +#include +#include +#include +#include +#include + +#include +#include "ext2_fs.h" +#include + +#include "et/com_err.h" +#include "ext2fs/ext2fs.h" +#include "ext2fs/ext2_err.h" + + + + +// +// For checking structure magic numbers... +// + + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +#define EXT2_ET_MAGIC_NT_IO_CHANNEL 0x10ed + + +// +// Private data block +// + +typedef struct _NT_PRIVATE_DATA { + int magic; + HANDLE Handle; + int Flags; + PCHAR Buffer; + __u32 BufferBlockNumber; + ULONG BufferSize; + BOOLEAN OpenedReadonly; + BOOLEAN Written; +}NT_PRIVATE_DATA, *PNT_PRIVATE_DATA; + + + +// +// Standard interface prototypes +// + +static errcode_t nt_open(const char *name, int flags, io_channel *channel); +static errcode_t nt_close(io_channel channel); +static errcode_t nt_set_blksize(io_channel channel, int blksize); +static errcode_t nt_read_blk(io_channel channel, unsigned long block, + int count, void *data); +static errcode_t nt_write_blk(io_channel channel, unsigned long block, + int count, const void *data); +static errcode_t nt_flush(io_channel channel); + +static struct struct_io_manager struct_nt_manager = { + EXT2_ET_MAGIC_IO_MANAGER, + "NT I/O Manager", + nt_open, + nt_close, + nt_set_blksize, + nt_read_blk, + nt_write_blk, + nt_flush +}; + + + +// +// function to get API +// + +io_manager nt_io_manager() +{ + return &struct_nt_manager; +} + + + + + +// +// This is a code to convert Win32 errors to unix errno +// + +typedef struct { + ULONG WinError; + int errnocode; +}ERROR_ENTRY; + +static ERROR_ENTRY ErrorTable[] = { + { ERROR_INVALID_FUNCTION, EINVAL }, + { ERROR_FILE_NOT_FOUND, ENOENT }, + { ERROR_PATH_NOT_FOUND, ENOENT }, + { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, + { ERROR_ACCESS_DENIED, EACCES }, + { ERROR_INVALID_HANDLE, EBADF }, + { ERROR_ARENA_TRASHED, ENOMEM }, + { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, + { ERROR_INVALID_BLOCK, ENOMEM }, + { ERROR_BAD_ENVIRONMENT, E2BIG }, + { ERROR_BAD_FORMAT, ENOEXEC }, + { ERROR_INVALID_ACCESS, EINVAL }, + { ERROR_INVALID_DATA, EINVAL }, + { ERROR_INVALID_DRIVE, ENOENT }, + { ERROR_CURRENT_DIRECTORY, EACCES }, + { ERROR_NOT_SAME_DEVICE, EXDEV }, + { ERROR_NO_MORE_FILES, ENOENT }, + { ERROR_LOCK_VIOLATION, EACCES }, + { ERROR_BAD_NETPATH, ENOENT }, + { ERROR_NETWORK_ACCESS_DENIED, EACCES }, + { ERROR_BAD_NET_NAME, ENOENT }, + { ERROR_FILE_EXISTS, EEXIST }, + { ERROR_CANNOT_MAKE, EACCES }, + { ERROR_FAIL_I24, EACCES }, + { ERROR_INVALID_PARAMETER, EINVAL }, + { ERROR_NO_PROC_SLOTS, EAGAIN }, + { ERROR_DRIVE_LOCKED, EACCES }, + { ERROR_BROKEN_PIPE, EPIPE }, + { ERROR_DISK_FULL, ENOSPC }, + { ERROR_INVALID_TARGET_HANDLE, EBADF }, + { ERROR_INVALID_HANDLE, EINVAL }, + { ERROR_WAIT_NO_CHILDREN, ECHILD }, + { ERROR_CHILD_NOT_COMPLETE, ECHILD }, + { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, + { ERROR_NEGATIVE_SEEK, EINVAL }, + { ERROR_SEEK_ON_DEVICE, EACCES }, + { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, + { ERROR_NOT_LOCKED, EACCES }, + { ERROR_BAD_PATHNAME, ENOENT }, + { ERROR_MAX_THRDS_REACHED, EAGAIN }, + { ERROR_LOCK_FAILED, EACCES }, + { ERROR_ALREADY_EXISTS, EEXIST }, + { ERROR_FILENAME_EXCED_RANGE, ENOENT }, + { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, + { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } +}; + + + + +static +unsigned +_MapDosError ( + IN ULONG WinError + ) +{ + int i; + + // + // Lookup + // + + for (i = 0; i < (sizeof(ErrorTable)/sizeof(ErrorTable[0])); ++i) + { + if (WinError == ErrorTable[i].WinError) + { + return ErrorTable[i].errnocode; + } + } + + // + // not in table. Check ranges + // + + if ((WinError >= ERROR_WRITE_PROTECT) && + (WinError <= ERROR_SHARING_BUFFER_EXCEEDED)) + { + return EACCES; + } + else if ((WinError >= ERROR_INVALID_STARTING_CODESEG) && + (WinError <= ERROR_INFLOOP_IN_RELOC_CHAIN)) + { + return ENOEXEC; + } + else + { + return EINVAL; + } +} + + + + + + + +// +// Function to map NT status to dos error. +// + +static +__inline +unsigned +_MapNtStatus( + IN NTSTATUS Status + ) +{ + return _MapDosError(RtlNtStatusToDosError(Status)); +} + + + + + +// +// Helper functions to make things easyer +// + +static +NTSTATUS +_OpenNtName( + IN PCSTR Name, + IN BOOLEAN Readonly, + OUT PHANDLE Handle, + OUT PBOOLEAN OpenedReadonly OPTIONAL + ) +{ + UNICODE_STRING UnicodeString; + ANSI_STRING AnsiString; + WCHAR Buffer[512]; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + + // + // Make Unicode name from inlut string + // + + UnicodeString.Buffer = &Buffer[0]; + UnicodeString.Length = 0; + UnicodeString.MaximumLength = sizeof(Buffer); // in bytes!!! + + RtlInitAnsiString(&AnsiString, Name); + + Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); + + if(!NT_SUCCESS(Status)) + { + return Status; // Unpappable character? + } + + // + // Initialize object + // + + InitializeObjectAttributes(&ObjectAttributes, + &UnicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + NULL ); + + // + // Try to open it in initial mode + // + + if(ARGUMENT_PRESENT(OpenedReadonly)) + { + *OpenedReadonly = Readonly; + } + + + Status = NtOpenFile(Handle, + SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA), + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_WRITE | FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + + if(!NT_SUCCESS(Status)) + { + // + // Maybe was just mounted? wait 0.5 sec and retry. + // + + LARGE_INTEGER Interval; + Interval.QuadPart = -5000000; // 0.5 sec. from now + + NtDelayExecution(FALSE, &Interval); + + Status = NtOpenFile(Handle, + SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA), + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_WRITE | FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + + // + // Try to satisfy mode + // + + if((STATUS_ACCESS_DENIED == Status) && !Readonly) + { + if(ARGUMENT_PRESENT(OpenedReadonly)) + { + *OpenedReadonly = TRUE; + } + + Status = NtOpenFile(Handle, + SYNCHRONIZE | FILE_READ_DATA, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_WRITE | FILE_SHARE_READ, + FILE_SYNCHRONOUS_IO_NONALERT); + } + } + + + + // + // done + // + + return Status; +} + + +static +NTSTATUS +_OpenDriveLetter( + IN CHAR Letter, + IN BOOLEAN ReadOnly, + OUT PHANDLE Handle, + OUT PBOOLEAN OpenedReadonly OPTIONAL + ) +{ + CHAR Buffer[100]; + + sprintf(Buffer, "\\DosDevices\\%c:", Letter); + + return _OpenNtName(Buffer, ReadOnly, Handle, OpenedReadonly); +} + + +// +// Flush device +// + +static +__inline +NTSTATUS +_FlushDrive( + IN HANDLE Handle + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + return NtFlushBuffersFile(Handle, &IoStatusBlock); +} + + +// +// lock drive +// + +static +__inline +NTSTATUS +_LockDrive( + IN HANDLE Handle + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_LOCK_VOLUME, 0, 0, 0, 0); +} + + +// +// unlock drive +// + +static +__inline +NTSTATUS +_UnlockDrive( + IN HANDLE Handle + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0); +} + +static +__inline +NTSTATUS +_DismountDrive( + IN HANDLE Handle + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0); +} + + +// +// is mounted +// + +static +__inline +BOOLEAN +_IsMounted( + IN HANDLE Handle + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + Status = NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_IS_VOLUME_MOUNTED, 0, 0, 0, 0); + return (BOOLEAN)(STATUS_SUCCESS == Status); +} + + +static +__inline +NTSTATUS +_CloseDisk( + IN HANDLE Handle + ) +{ + return NtClose(Handle); +} + + + + +// +// Make NT name from any recognized name +// + +static +PCSTR +_NormalizeDeviceName( + IN PCSTR Device, + IN PSTR NormalizedDeviceNameBuffer + ) +{ + int PartitionNumber = -1; + UCHAR DiskNumber; + PSTR p; + + + // + // Do not try to parse NT name + // + + if('\\' == *Device) + return Device; + + + + // + // Strip leading '/dev/' if any + // + + if(('/' == *(Device)) && + ('d' == *(Device + 1)) && + ('e' == *(Device + 2)) && + ('v' == *(Device + 3)) && + ('/' == *(Device + 4))) + { + Device += 5; + } + + if('\0' == *Device) + { + return NULL; + } + + + // + // forms: hda[n], fd[n] + // + + if('d' != *(Device + 1)) + { + return NULL; + } + + if('h' == *Device) + { + if((*(Device + 2) < 'a') || (*(Device + 2) > ('a' + 9)) || + ((*(Device + 3) != '\0') && + ((*(Device + 4) != '\0') || + ((*(Device + 3) < '0') || (*(Device + 3) > '9')) + ) + ) + ) + { + return NULL; + } + + DiskNumber = (UCHAR)(*(Device + 2) - 'a'); + + if(*(Device + 3) != '\0') + { + PartitionNumber = (*(Device + 3) - '0'); + } + + } + else if('f' == *Device) + { + // + // 3-d letted should be a digit. + // + + if((*(Device + 3) != '\0') || + (*(Device + 2) < '0') || (*(Device + 2) > '9')) + { + return NULL; + } + + DiskNumber = (UCHAR)(*(Device + 2) - '0'); + + } + else + { + // + // invalid prefix + // + + return NULL; + } + + + + // + // Prefix + // + + strcpy(NormalizedDeviceNameBuffer, "\\Device\\"); + + // + // Media name + // + + switch(*Device) + { + + case 'f': + strcat(NormalizedDeviceNameBuffer, "Floppy0"); + break; + + case 'h': + strcat(NormalizedDeviceNameBuffer, "Harddisk0"); + break; + } + + + p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1; + *p = (CHAR)(*p + DiskNumber); + + + // + // Partition nr. + // + + if(PartitionNumber >= 0) + { + strcat(NormalizedDeviceNameBuffer, "\\Partition0"); + + p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1; + *p = (CHAR)(*p + PartitionNumber); + } + + + return NormalizedDeviceNameBuffer; +} + + + + +static +VOID +_GetDeviceSize( + IN HANDLE h, + OUT unsigned __int64 *FsSize + ) +{ + PARTITION_INFORMATION pi; + DISK_GEOMETRY gi; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + + // + // Zero it + // + + *FsSize = 0; + + // + // Call driver + // + + RtlZeroMemory(&pi, sizeof(PARTITION_INFORMATION)); + + Status = NtDeviceIoControlFile( + h, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_PARTITION_INFO, + &pi, sizeof(PARTITION_INFORMATION), + &pi, sizeof(PARTITION_INFORMATION)); + + + if(NT_SUCCESS(Status)) + { + *FsSize = pi.PartitionLength.QuadPart; + } + else if(STATUS_INVALID_DEVICE_REQUEST == Status) + { + // + // No partitions: get device info. + // + + RtlZeroMemory(&gi, sizeof(DISK_GEOMETRY)); + + Status = NtDeviceIoControlFile( + h, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_DRIVE_GEOMETRY, + &gi, sizeof(DISK_GEOMETRY), + &gi, sizeof(DISK_GEOMETRY)); + + + if(NT_SUCCESS(Status)) + { + *FsSize = + gi.BytesPerSector * + gi.SectorsPerTrack * + gi.TracksPerCylinder * + gi.Cylinders.QuadPart; + } + + } +} + + + +// +// Open device by name. +// + +static +BOOLEAN +_Ext2OpenDevice( + IN PCSTR Name, + IN BOOLEAN ReadOnly, + OUT PHANDLE Handle, + OUT PBOOLEAN OpenedReadonly OPTIONAL, + OUT unsigned *Errno OPTIONAL + ) +{ + CHAR NormalizedDeviceName[512]; + NTSTATUS Status; + + if(NULL == Name) + { + // + // Set not found + // + + if(ARGUMENT_PRESENT(Errno)) + *Errno = ENOENT; + + return FALSE; + } + + + if((((*Name) | 0x20) >= 'a') && (((*Name) | 0x20) <= 'z') && + (':' == *(Name + 1)) && ('\0' == *(Name + 2))) + { + Status = _OpenDriveLetter(*Name, ReadOnly, Handle, OpenedReadonly); + } + else + { + // + // Make name + // + + Name = _NormalizeDeviceName(Name, NormalizedDeviceName); + + if(NULL == Name) + { + // + // Set not found + // + + if(ARGUMENT_PRESENT(Errno)) + *Errno = ENOENT; + + return FALSE; + } + + // + // Try to open it + // + + Status = _OpenNtName(Name, ReadOnly, Handle, OpenedReadonly); + } + + + if(!NT_SUCCESS(Status)) + { + if(ARGUMENT_PRESENT(Errno)) + *Errno = _MapNtStatus(Status); + + return FALSE; + } + + return TRUE; +} + + +// +// Raw block io. Sets dos errno +// + +static +BOOLEAN +_BlockIo( + IN HANDLE Handle, + IN LARGE_INTEGER Offset, + IN ULONG Bytes, + IN OUT PCHAR Buffer, + IN BOOLEAN Read, + OUT unsigned* Errno + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + // + // Should be aligned + // + + ASSERT(0 == (Bytes % 512)); + ASSERT(0 == (Offset.LowPart % 512)); + + + // + // perform io + // + + if(Read) + { + Status = NtReadFile(Handle, NULL, NULL, NULL, + &IoStatusBlock, Buffer, Bytes, &Offset, NULL); + } + else + { + Status = NtWriteFile(Handle, NULL, NULL, NULL, + &IoStatusBlock, Buffer, Bytes, &Offset, NULL); + } + + + // + // translate error + // + + if(NT_SUCCESS(Status)) + { + *Errno = 0; + return TRUE; + } + + *Errno = _MapNtStatus(Status); + + return FALSE; +} + + + +__inline +BOOLEAN +_RawWrite( + IN HANDLE Handle, + IN LARGE_INTEGER Offset, + IN ULONG Bytes, + OUT const CHAR* Buffer, + OUT unsigned* Errno + ) +{ + return _BlockIo(Handle, Offset, Bytes, (PCHAR)Buffer, FALSE, Errno); +} + +__inline +BOOLEAN +_RawRead( + IN HANDLE Handle, + IN LARGE_INTEGER Offset, + IN ULONG Bytes, + IN PCHAR Buffer, + OUT unsigned* Errno + ) +{ + return _BlockIo(Handle, Offset, Bytes, Buffer, TRUE, Errno); +} + + + +__inline +BOOLEAN +_SetPartType( + IN HANDLE Handle, + IN UCHAR Type + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + return STATUS_SUCCESS == NtDeviceIoControlFile( + Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_SET_PARTITION_INFO, + &Type, sizeof(Type), + NULL, 0); +} + + + +//--------------------- interface part + +// +// Interface functions. +// Is_mounted is set to 1 if the device is mounted, 0 otherwise +// + +errcode_t +ext2fs_check_if_mounted(const char *file, int *mount_flags) +{ + HANDLE h; + BOOLEAN Readonly; + + *mount_flags = 0; + + if(!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL)) + { + return 0; + } + + + __try{ + *mount_flags &= _IsMounted(h) ? EXT2_MF_MOUNTED : 0; + } + __finally{ + _CloseDisk(h); + } + + return 0; +} + + + +// +// Returns the number of blocks in a partition +// + +static __int64 FsSize = 0; +static char knowndevice[1024] = ""; + + +errcode_t +ext2fs_get_device_size(const char *file, int blocksize, + blk_t *retblocks) +{ + HANDLE h; + BOOLEAN Readonly; + + if((0 == FsSize) || (0 != strcmp(knowndevice, file))) + { + + if(!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL)) + { + return 0; + } + + + __try{ + + // + // Get size + // + + _GetDeviceSize(h, &FsSize); + strcpy(knowndevice, file); + } + __finally{ + _CloseDisk(h); + } + + } + + *retblocks = (blk_t)(unsigned __int64)(FsSize / blocksize); + UNREFERENCED_PARAMETER(file); + return 0; +} + + + + + + +// +// Table elements +// + + +static +errcode_t +nt_open(const char *name, int flags, io_channel *channel) +{ + io_channel io = NULL; + PNT_PRIVATE_DATA NtData = NULL; + errcode_t Errno = 0; + + // + // Check name + // + + if (NULL == name) + { + return EXT2_ET_BAD_DEVICE_NAME; + } + + __try{ + + // + // Allocate channel handle + // + + io = (io_channel) malloc(sizeof(struct struct_io_channel)); + + if (NULL == io) + { + Errno = ENOMEM; + __leave; + } + + RtlZeroMemory(io, sizeof(struct struct_io_channel)); + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + + NtData = (PNT_PRIVATE_DATA)malloc(sizeof(NT_PRIVATE_DATA)); + + if (NULL == NtData) + { + Errno = ENOMEM; + __leave; + } + + + io->manager = nt_io_manager(); + io->name = malloc(strlen(name) + 1); + if (NULL == io->name) + { + Errno = ENOMEM; + __leave; + } + + strcpy(io->name, name); + io->private_data = NtData; + io->block_size = 1024; + io->read_error = 0; + io->write_error = 0; + io->refcount = 1; + + // + // Initialize data + // + + RtlZeroMemory(NtData, sizeof(NT_PRIVATE_DATA)); + + NtData->magic = EXT2_ET_MAGIC_NT_IO_CHANNEL; + NtData->BufferBlockNumber = 0xffffffff; + NtData->BufferSize = 1024; + NtData->Buffer = malloc(NtData->BufferSize); + + if (NULL == NtData->Buffer) + { + Errno = ENOMEM; + __leave; + } + + // + // Open it + // + + if(!_Ext2OpenDevice(name, (BOOLEAN)!BooleanFlagOn(flags, EXT2_FLAG_RW), &NtData->Handle, &NtData->OpenedReadonly, &Errno)) + { + __leave; + } + + + // + // get size + // + + _GetDeviceSize(NtData->Handle, &FsSize); + strcpy(knowndevice, name); + + + // + // Lock/dismount + // + + if(!NT_SUCCESS(_LockDrive(NtData->Handle)) /*|| !NT_SUCCESS(_DismountDrive(NtData->Handle))*/) + { + NtData->OpenedReadonly = TRUE; + } + + // + // Done + // + + *channel = io; + + + } + __finally{ + + if(0 != Errno) + { + // + // Cleanup + // + + if (NULL != io) + { + if(NULL != io->name) + { + free(io->name); + } + + free(io); + } + + if (NULL != NtData) + { + if(NULL != NtData->Handle) + { + _UnlockDrive(NtData->Handle); + _CloseDisk(NtData->Handle); + } + + if(NULL != NtData->Buffer) + { + free(NtData->Buffer); + } + + free(NtData); + } + } + } + + return Errno; +} + + +// +// Close api +// + +static +errcode_t +nt_close(io_channel channel) +{ + PNT_PRIVATE_DATA NtData = NULL; + + if(NULL == channel) + { + return 0; + } + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + NtData = (PNT_PRIVATE_DATA) channel->private_data; + EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); + + if (--channel->refcount > 0) + { + return 0; + } + + if(NULL != channel->name) + { + free(channel->name); + } + + + free(channel); + + if (NULL != NtData) + { + if(NULL != NtData->Handle) + { + _DismountDrive(NtData->Handle); + _UnlockDrive(NtData->Handle); + _CloseDisk(NtData->Handle); + } + + if(NULL != NtData->Buffer) + { + free(NtData->Buffer); + } + + free(NtData); + } + + return 0; +} + + + +// +// set block size +// + +static +errcode_t +nt_set_blksize(io_channel channel, int blksize) +{ + PNT_PRIVATE_DATA NtData = NULL; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + NtData = (PNT_PRIVATE_DATA) channel->private_data; + EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); + + if (channel->block_size != blksize) + { + channel->block_size = blksize; + + free(NtData->Buffer); + NtData->BufferBlockNumber = 0xffffffff; + NtData->BufferSize = channel->block_size; + ASSERT(0 == (NtData->BufferSize % 512)); + + NtData->Buffer = malloc(NtData->BufferSize); + + if (NULL == NtData->Buffer) + { + return ENOMEM; + } + + } + + return 0; +} + + +// +// read block +// + +static +errcode_t +nt_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + PVOID BufferToRead; + ULONG SizeToRead; + ULONG Size; + LARGE_INTEGER Offset; + PNT_PRIVATE_DATA NtData = NULL; + unsigned Errno = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + NtData = (PNT_PRIVATE_DATA) channel->private_data; + EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); + + // + // If it's in the cache, use it! + // + + if ((1 == count) && + (block == NtData->BufferBlockNumber) && + (NtData->BufferBlockNumber != 0xffffffff)) + { + memcpy(buf, NtData->Buffer, channel->block_size); + return 0; + } + + Size = (count < 0) ? (ULONG)(-count) : (ULONG)(count * channel->block_size); + + Offset.QuadPart = block * channel->block_size; + + // + // If not fit to the block + // + + if(Size <= NtData->BufferSize) + { + // + // Update the cache + // + + NtData->BufferBlockNumber = block; + BufferToRead = NtData->Buffer; + SizeToRead = NtData->BufferSize; + } + else + { + SizeToRead = Size; + BufferToRead = buf; + ASSERT(0 == (SizeToRead % channel->block_size)); + } + + if(!_RawRead(NtData->Handle, Offset, SizeToRead, BufferToRead, &Errno)) + { + + if (channel->read_error) + { + return (channel->read_error)(channel, block, count, buf, + Size, 0, Errno); + } + else + { + return Errno; + } + } + + + if(BufferToRead != buf) + { + ASSERT(Size <= SizeToRead); + memcpy(buf, BufferToRead, Size); + } + + return 0; +} + + +// +// write block +// + +static +errcode_t +nt_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + ULONG SizeToWrite; + LARGE_INTEGER Offset; + PNT_PRIVATE_DATA NtData = NULL; + unsigned Errno = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + NtData = (PNT_PRIVATE_DATA) channel->private_data; + EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); + + if(NtData->OpenedReadonly) + { + return EACCES; + } + + if (count == 1) + { + SizeToWrite = channel->block_size; + } + else + { + NtData->BufferBlockNumber = 0xffffffff; + + if (count < 0) + { + SizeToWrite = (ULONG)(-count); + } + else + { + SizeToWrite = (ULONG)(count * channel->block_size); + } + } + + + ASSERT(0 == (SizeToWrite % 512)); + Offset.QuadPart = block * channel->block_size; + + if(!_RawWrite(NtData->Handle, Offset, SizeToWrite, buf, &Errno)) + { + if (channel->write_error) + { + return (channel->write_error)(channel, block, count, buf, + SizeToWrite, 0, Errno); + } + else + { + return Errno; + } + } + + + // + // Stash a copy. + // + + if(SizeToWrite >= NtData->BufferSize) + { + NtData->BufferBlockNumber = block; + memcpy(NtData->Buffer, buf, NtData->BufferSize); + } + + NtData->Written = TRUE; + + return 0; + +} + + + +// +// Flush data buffers to disk. Since we are currently using a +// write-through cache, this is a no-op. +// + +static +errcode_t +nt_flush(io_channel channel) +{ + PNT_PRIVATE_DATA NtData = NULL; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + NtData = (PNT_PRIVATE_DATA) channel->private_data; + EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); + + if(NtData->OpenedReadonly) + { + return 0; // EACCESS; + } + + + // + // Flush file buffers. + // + + _FlushDrive(NtData->Handle); + + + // + // Test and correct partition type. + // + + if(NtData->Written) + { + _SetPartType(NtData->Handle, 0x83); + } + + return 0; +} + + diff -Naur silo-1.4.14.orig/libext2fs/openfs.c silo-1.4.14/libext2fs/openfs.c --- silo-1.4.14.orig/libext2fs/openfs.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/openfs.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,326 @@ +/* + * openfs.c --- open an ext2 filesystem + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" + + +#include "ext2fs.h" +#include "e2image.h" + +blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i) +{ + int bg; + int has_super = 0; + int ret_blk; + + if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || + (i < fs->super->s_first_meta_bg)) + return (group_block + i + 1); + + bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i; + if (ext2fs_bg_has_super(fs, bg)) + has_super = 1; + ret_blk = (fs->super->s_first_data_block + has_super + + (bg * fs->super->s_blocks_per_group)); + /* + * If group_block is not the normal value, we're trying to use + * the backup group descriptors and superblock --- so use the + * alternate location of the second block group in the + * metablock group. Ideally we should be testing each bg + * descriptor block individually for correctness, but we don't + * have the infrastructure in place to do that. + */ + if (group_block != fs->super->s_first_data_block && + ((ret_blk + fs->super->s_blocks_per_group) < + fs->super->s_blocks_count)) + ret_blk += fs->super->s_blocks_per_group; + return ret_blk; +} + +errcode_t ext2fs_open(const char *name, int flags, int superblock, + unsigned int block_size, io_manager manager, + ext2_filsys *ret_fs) +{ + return ext2fs_open2(name, 0, flags, superblock, block_size, + manager, ret_fs); +} + +/* + * Note: if superblock is non-zero, block-size must also be non-zero. + * Superblock and block_size can be zero to use the default size. + * + * Valid flags for ext2fs_open() + * + * EXT2_FLAG_RW - Open the filesystem for read/write. + * EXT2_FLAG_FORCE - Open the filesystem even if some of the + * features aren't supported. + * EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device + */ +errcode_t ext2fs_open2(const char *name, const char *io_options, + int flags, int superblock, + unsigned int block_size, io_manager manager, + ext2_filsys *ret_fs) +{ + ext2_filsys fs; + errcode_t retval; + unsigned long i; + int j, groups_per_block, blocks_per_group; + blk_t group_block, blk; + char *dest, *cp; + struct ext2_group_desc *gdp; + + EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER); + + retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); + if (retval) + return retval; + + memset(fs, 0, sizeof(struct struct_ext2_filsys)); + fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; + fs->flags = flags; + fs->umask = 022; + retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name); + if (retval) + goto cleanup; + strcpy(fs->device_name, name); + cp = strchr(fs->device_name, '?'); + if (!io_options && cp) { + *cp++ = 0; + io_options = cp; + } + + retval = manager->open(fs->device_name, + (flags & EXT2_FLAG_RW) ? IO_FLAG_RW : 0, + &fs->io); + if (retval) + goto cleanup; + if (io_options && + (retval = io_channel_set_options(fs->io, io_options))) + goto cleanup; + fs->image_io = fs->io; + fs->io->app_data = fs; + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super); + if (retval) + goto cleanup; + if (flags & EXT2_FLAG_IMAGE_FILE) { + retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr), + &fs->image_header); + if (retval) + goto cleanup; + retval = io_channel_read_blk(fs->io, 0, + -sizeof(struct ext2_image_hdr), + fs->image_header); + if (retval) + goto cleanup; + if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE) + return EXT2_ET_MAGIC_E2IMAGE; + superblock = 1; + block_size = fs->image_header->fs_blocksize; + } + + /* + * If the user specifies a specific block # for the + * superblock, then he/she must also specify the block size! + * Otherwise, read the master superblock located at offset + * SUPERBLOCK_OFFSET from the start of the partition. + * + * Note: we only save a backup copy of the superblock if we + * are reading the superblock from the primary superblock location. + */ + if (superblock) { + if (!block_size) { + retval = EXT2_ET_INVALID_ARGUMENT; + goto cleanup; + } + io_channel_set_blksize(fs->io, block_size); + group_block = superblock; + fs->orig_super = 0; + } else { + io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); + superblock = 1; + group_block = 0; + retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super); + if (retval) + goto cleanup; + } + retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE, + fs->super); + if (retval) + goto cleanup; + if (fs->orig_super) + memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE); + +#ifdef EXT2FS_ENABLE_SWAPFS + if ((fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) || + (fs->flags & EXT2_FLAG_SWAP_BYTES)) { + fs->flags |= EXT2_FLAG_SWAP_BYTES; + + ext2fs_swap_super(fs->super); + } +#endif + + if (fs->super->s_magic != EXT2_SUPER_MAGIC) { + retval = EXT2_ET_BAD_MAGIC; + goto cleanup; + } + if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) { + retval = EXT2_ET_REV_TOO_HIGH; + goto cleanup; + } + + /* + * Check for feature set incompatibility + */ + if (!(flags & EXT2_FLAG_FORCE)) { + if (fs->super->s_feature_incompat & + ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { + retval = EXT2_ET_UNSUPP_FEATURE; + goto cleanup; + } + if ((flags & EXT2_FLAG_RW) && + (fs->super->s_feature_ro_compat & + ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) { + retval = EXT2_ET_RO_UNSUPP_FEATURE; + goto cleanup; + } + if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) && + (fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { + retval = EXT2_ET_UNSUPP_FEATURE; + goto cleanup; + } + } + + fs->blocksize = EXT2_BLOCK_SIZE(fs->super); + if (fs->blocksize == 0) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + fs->fragsize = EXT2_FRAG_SIZE(fs->super); + fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group * + EXT2_INODE_SIZE(fs->super) + + EXT2_BLOCK_SIZE(fs->super) - 1) / + EXT2_BLOCK_SIZE(fs->super)); + if (block_size) { + if (block_size != fs->blocksize) { + retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE; + goto cleanup; + } + } + /* + * Set the blocksize to the filesystem's blocksize. + */ + io_channel_set_blksize(fs->io, fs->blocksize); + + /* + * If this is an external journal device, don't try to read + * the group descriptors, because they're not there. + */ + if (fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { + fs->group_desc_count = 0; + *ret_fs = fs; + return 0; + } + + /* + * Read group descriptors + */ + blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super); + if (blocks_per_group == 0 || + blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) || + fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super)) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } + fs->group_desc_count = (fs->super->s_blocks_count - + fs->super->s_first_data_block + + blocks_per_group - 1) / blocks_per_group; + fs->desc_blocks = (fs->group_desc_count + + EXT2_DESC_PER_BLOCK(fs->super) - 1) + / EXT2_DESC_PER_BLOCK(fs->super); + retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize, + &fs->group_desc); + if (retval) + goto cleanup; + if (!group_block) + group_block = fs->super->s_first_data_block; + dest = (char *) fs->group_desc; + groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc); + for (i=0 ; i < fs->desc_blocks; i++) { + blk = ext2fs_descriptor_block_loc(fs, group_block, i); + retval = io_channel_read_blk(fs->io, blk, 1, dest); + if (retval) + goto cleanup; +#ifdef EXT2FS_ENABLE_SWAPFS + if (fs->flags & EXT2_FLAG_SWAP_BYTES) { + gdp = (struct ext2_group_desc *) dest; + for (j=0; j < groups_per_block; j++) + ext2fs_swap_group_desc(gdp++); + } +#endif + dest += fs->blocksize; + } + + *ret_fs = fs; + return 0; +cleanup: + ext2fs_free(fs); + return retval; +} + +/* + * Set/get the filesystem data I/O channel. + * + * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true. + */ +errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io) +{ + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) + return EXT2_ET_NOT_IMAGE_FILE; + if (old_io) { + *old_io = (fs->image_io == fs->io) ? 0 : fs->io; + } + return 0; +} + +errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io) +{ + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) + return EXT2_ET_NOT_IMAGE_FILE; + fs->io = new_io ? new_io : fs->image_io; + return 0; +} + +errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io) +{ + if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) + return EXT2_ET_NOT_IMAGE_FILE; + fs->io = fs->image_io = new_io; + fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW | + EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY; + fs->flags &= ~EXT2_FLAG_IMAGE_FILE; + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/read_bb.c silo-1.4.14/libext2fs/read_bb.c --- silo-1.4.14.orig/libext2fs/read_bb.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/read_bb.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,97 @@ +/* + * read_bb --- read the bad blocks inode + * + * Copyright (C) 1994 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct read_bb_record { + ext2_badblocks_list bb_list; + errcode_t err; +}; + +/* + * Helper function for ext2fs_read_bb_inode() + */ +#ifdef __TURBOC__ + #pragma argsused +#endif +static int mark_bad_block(ext2_filsys fs, blk_t *block_nr, + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct read_bb_record *rb = (struct read_bb_record *) priv_data; + + if (blockcnt < 0) + return 0; + + if ((*block_nr < fs->super->s_first_data_block) || + (*block_nr >= fs->super->s_blocks_count)) + return 0; /* Ignore illegal blocks */ + + rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr); + if (rb->err) + return BLOCK_ABORT; + return 0; +} + +/* + * Reads the current bad blocks from the bad blocks inode. + */ +errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list) +{ + errcode_t retval; + struct read_bb_record rb; + struct ext2_inode inode; + blk_t numblocks; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!*bb_list) { + retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode); + if (retval) + return retval; + if (inode.i_blocks < 500) + numblocks = (inode.i_blocks / + (fs->blocksize / 512)) + 20; + else + numblocks = 500; + retval = ext2fs_badblocks_list_create(bb_list, numblocks); + if (retval) + return retval; + } + + rb.bb_list = *bb_list; + rb.err = 0; + retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 0, 0, + mark_bad_block, &rb); + if (retval) + return retval; + + return rb.err; +} + + diff -Naur silo-1.4.14.orig/libext2fs/read_bb_file.c silo-1.4.14/libext2fs/read_bb_file.c --- silo-1.4.14.orig/libext2fs/read_bb_file.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/read_bb_file.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,97 @@ +/* + * read_bb_file.c --- read a list of bad blocks from a FILE * + * + * Copyright (C) 1994, 1995, 2000 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * Reads a list of bad blocks from a FILE * + */ +errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f, + ext2_badblocks_list *bb_list, + void *priv_data, + void (*invalid)(ext2_filsys fs, + blk_t blk, + char *badstr, + void *priv_data)) +{ + errcode_t retval; + blk_t blockno; + int count; + char buf[128]; + + if (fs) + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!*bb_list) { + retval = ext2fs_badblocks_list_create(bb_list, 10); + if (retval) + return retval; + } + + while (!feof (f)) { + if (fgets(buf, sizeof(buf), f) == NULL) + break; + count = sscanf(buf, "%u", &blockno); + if (count <= 0) + continue; + if (fs && + ((blockno < fs->super->s_first_data_block) || + (blockno >= fs->super->s_blocks_count))) { + if (invalid) + (invalid)(fs, blockno, buf, priv_data); + continue; + } + retval = ext2fs_badblocks_list_add(*bb_list, blockno); + if (retval) + return retval; + } + return 0; +} + +static void call_compat_invalid(ext2_filsys fs, blk_t blk, + char *badstr EXT2FS_ATTR((unused)), + void *priv_data) +{ + void (*invalid)(ext2_filsys, blk_t); + + invalid = (void (*)(ext2_filsys, blk_t)) priv_data; + if (invalid) + invalid(fs, blk); +} + + +/* + * Reads a list of bad blocks from a FILE * + */ +errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f, + ext2_badblocks_list *bb_list, + void (*invalid)(ext2_filsys fs, blk_t blk)) +{ + return ext2fs_read_bb_FILE2(fs, f, bb_list, (void *) invalid, + call_compat_invalid); +} + + diff -Naur silo-1.4.14.orig/libext2fs/res_gdt.c silo-1.4.14/libext2fs/res_gdt.c --- silo-1.4.14.orig/libext2fs/res_gdt.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/res_gdt.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,220 @@ +/* + * res_gdt.c --- reserve blocks for growing the group descriptor table + * during online resizing. + * + * Copyright (C) 2002 Andreas Dilger + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#include +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * Iterate through the groups which hold BACKUP superblock/GDT copies in an + * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before + * calling this for the first time. In a sparse filesystem it will be the + * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ... + * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ... + */ +static unsigned int list_backups(ext2_filsys fs, unsigned int *three, + unsigned int *five, unsigned int *seven) +{ + unsigned int *min = three; + int mult = 3; + unsigned int ret; + + if (!(fs->super->s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) { + ret = *min; + *min += 1; + return ret; + } + + if (*five < *min) { + min = five; + mult = 5; + } + if (*seven < *min) { + min = seven; + mult = 7; + } + + ret = *min; + *min *= mult; + + return ret; +} + +/* + * This code assumes that the reserved blocks have already been marked in-use + * during ext2fs_initialize(), so that they are not allocated for other + * uses before we can add them to the resize inode (which has to come + * after the creation of the inode table). + */ +errcode_t ext2fs_create_resize_inode(ext2_filsys fs) +{ + errcode_t retval, retval2; + struct ext2_super_block *sb; + struct ext2_inode inode; + __u32 *dindir_buf, *gdt_buf; + int rsv_add; + unsigned long long apb, inode_size; + blk_t dindir_blk, rsv_off, gdt_off, gdt_blk; + int dindir_dirty = 0, inode_dirty = 0; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + sb = fs->super; + + retval = ext2fs_get_mem(2 * fs->blocksize, (void **)&dindir_buf); + if (retval) + goto out_free; + gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize); + + retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); + if (retval) + goto out_free; + + /* Maximum possible file size (we donly use the dindirect blocks) */ + apb = EXT2_ADDR_PER_BLOCK(sb); + rsv_add = fs->blocksize / 512; + if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) { +#ifdef RES_GDT_DEBUG + printf("reading GDT dindir %u\n", dindir_blk); +#endif + retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf); + if (retval) + goto out_inode; + } else { + blk_t goal = 3 + sb->s_reserved_gdt_blocks + + fs->desc_blocks + fs->inode_blocks_per_group; + + retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk); + if (retval) + goto out_free; + inode.i_mode = LINUX_S_IFREG | 0600; + inode.i_links_count = 1; + inode.i_block[EXT2_DIND_BLOCK] = dindir_blk; + inode.i_blocks = rsv_add; + memset(dindir_buf, 0, fs->blocksize); +#ifdef RES_GDT_DEBUG + printf("allocated GDT dindir %u\n", dindir_blk); +#endif + dindir_dirty = inode_dirty = 1; + inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS; + inode_size *= fs->blocksize; + inode.i_size = inode_size & 0xFFFFFFFF; + inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF; + if(inode.i_size_high) { + sb->s_feature_ro_compat |= + EXT2_FEATURE_RO_COMPAT_LARGE_FILE; + } + inode.i_ctime = time(0); + } + + for (rsv_off = 0, gdt_off = fs->desc_blocks, + gdt_blk = sb->s_first_data_block + 1 + fs->desc_blocks; + rsv_off < sb->s_reserved_gdt_blocks; + rsv_off++, gdt_off++, gdt_blk++) { + unsigned int three = 1, five = 5, seven = 7; + unsigned int grp, last = 0; + int gdt_dirty = 0; + + gdt_off %= apb; + if (!dindir_buf[gdt_off]) { + /* FIXME XXX XXX + blk_t new_blk; + + retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk); + if (retval) + goto out_free; + if (new_blk != gdt_blk) { + // XXX free block + retval = -1; // XXX + } + */ + gdt_dirty = dindir_dirty = inode_dirty = 1; + memset(gdt_buf, 0, fs->blocksize); + dindir_buf[gdt_off] = gdt_blk; + inode.i_blocks += rsv_add; +#ifdef RES_GDT_DEBUG + printf("added primary GDT block %u at %u[%u]\n", + gdt_blk, dindir_blk, gdt_off); +#endif + } else if (dindir_buf[gdt_off] == gdt_blk) { +#ifdef RES_GDT_DEBUG + printf("reading primary GDT block %u\n", gdt_blk); +#endif + retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf); + if (retval) + goto out_dindir; + } else { +#ifdef RES_GDT_DEBUG + printf("bad primary GDT %u != %u at %u[%u]\n", + dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off); +#endif + retval = EXT2_ET_RESIZE_INODE_CORRUPT; + goto out_dindir; + } + + while ((grp = list_backups(fs, &three, &five, &seven)) < + fs->group_desc_count) { + blk_t expect = gdt_blk + grp * sb->s_blocks_per_group; + + if (!gdt_buf[last]) { +#ifdef RES_GDT_DEBUG + printf("added backup GDT %u grp %u@%u[%u]\n", + expect, grp, gdt_blk, last); +#endif + gdt_buf[last] = expect; + inode.i_blocks += rsv_add; + gdt_dirty = inode_dirty = 1; + } else if (gdt_buf[last] != expect) { +#ifdef RES_GDT_DEBUG + printf("bad backup GDT %u != %u at %u[%u]\n", + gdt_buf[last], expect, gdt_blk, last); +#endif + retval = EXT2_ET_RESIZE_INODE_CORRUPT; + goto out_dindir; + } + last++; + } + if (gdt_dirty) { +#ifdef RES_GDT_DEBUG + printf("writing primary GDT block %u\n", gdt_blk); +#endif + retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf); + if (retval) + goto out_dindir; + } + } + +out_dindir: + if (dindir_dirty) { + retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf); + if (!retval) + retval = retval2; + } +out_inode: +#ifdef RES_GDT_DEBUG + printf("inode.i_blocks = %u, i_size = %u\n", inode.i_blocks, + inode.i_size); +#endif + if (inode_dirty) { + inode.i_atime = inode.i_mtime = time(0); + retval2 = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode); + if (!retval) + retval = retval2; + } +out_free: + ext2fs_free_mem((void **)&dindir_buf); + return retval; +} + diff -Naur silo-1.4.14.orig/libext2fs/rs_bitmap.c silo-1.4.14/libext2fs/rs_bitmap.c --- silo-1.4.14.orig/libext2fs/rs_bitmap.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/rs_bitmap.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,106 @@ +/* + * rs_bitmap.c --- routine for changing the size of a bitmap + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end, + ext2fs_generic_bitmap bmap) +{ + errcode_t retval; + size_t size, new_size; + __u32 bitno; + + if (!bmap) + return EXT2_ET_INVALID_ARGUMENT; + + EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP); + + /* + * If we're expanding the bitmap, make sure all of the new + * parts of the bitmap are zero. + */ + if (new_end > bmap->end) { + bitno = bmap->real_end; + if (bitno > new_end) + bitno = new_end; + for (; bitno > bmap->end; bitno--) + ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap); + } + if (new_real_end == bmap->real_end) { + bmap->end = new_end; + return 0; + } + + size = ((bmap->real_end - bmap->start) / 8) + 1; + new_size = ((new_real_end - bmap->start) / 8) + 1; + + if (size != new_size) { + retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap); + if (retval) + return retval; + } + if (new_size > size) + memset(bmap->bitmap + size, 0, new_size - size); + + bmap->end = new_end; + bmap->real_end = new_real_end; + return 0; +} + +errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end, + ext2fs_inode_bitmap bmap) +{ + errcode_t retval; + + if (!bmap) + return EXT2_ET_INVALID_ARGUMENT; + + EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_INODE_BITMAP); + + bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; + retval = ext2fs_resize_generic_bitmap(new_end, new_real_end, + bmap); + bmap->magic = EXT2_ET_MAGIC_INODE_BITMAP; + return retval; +} + +errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end, + ext2fs_block_bitmap bmap) +{ + errcode_t retval; + + if (!bmap) + return EXT2_ET_INVALID_ARGUMENT; + + EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_BLOCK_BITMAP); + + bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; + retval = ext2fs_resize_generic_bitmap(new_end, new_real_end, + bmap); + bmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP; + return retval; +} + diff -Naur silo-1.4.14.orig/libext2fs/rw_bitmaps.c silo-1.4.14/libext2fs/rw_bitmaps.c --- silo-1.4.14.orig/libext2fs/rw_bitmaps.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/rw_bitmaps.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,300 @@ +/* + * rw_bitmaps.c --- routines to read and write the inode and block bitmaps. + * + * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "e2image.h" + +#if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS) +/* + * On the PowerPC, the big-endian variant of the ext2 filesystem + * has its bitmaps stored as 32-bit words with bit 0 as the LSB + * of each word. Thus a bitmap with only bit 0 set would be, as + * a string of bytes, 00 00 00 01 00 ... + * To cope with this, we byte-reverse each word of a bitmap if + * we have a big-endian filesystem, that is, if we are *not* + * byte-swapping other word-sized numbers. + */ +#define EXT2_BIG_ENDIAN_BITMAPS +#endif + +#ifdef EXT2_BIG_ENDIAN_BITMAPS +static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes) +{ + __u32 *p = (__u32 *) bitmap; + int n; + + for (n = nbytes / sizeof(__u32); n > 0; --n, ++p) + *p = ext2fs_swab32(*p); +} +#endif + +errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) +{ + dgrp_t i; + size_t nbytes; + errcode_t retval; + char * inode_bitmap = fs->inode_map->bitmap; + char * bitmap_block = NULL; + blk_t blk; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + if (!inode_bitmap) + return 0; + nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); + + retval = ext2fs_get_mem(fs->blocksize, &bitmap_block); + if (retval) + return retval; + memset(bitmap_block, 0xff, fs->blocksize); + for (i = 0; i < fs->group_desc_count; i++) { + memcpy(bitmap_block, inode_bitmap, nbytes); + blk = fs->group_desc[i].bg_inode_bitmap; + if (blk) { +#ifdef EXT2_BIG_ENDIAN_BITMAPS + if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) + ext2fs_swap_bitmap(fs, bitmap_block, nbytes); +#endif + retval = io_channel_write_blk(fs->io, blk, 1, + bitmap_block); + if (retval) + return EXT2_ET_INODE_BITMAP_WRITE; + } + inode_bitmap += nbytes; + } + fs->flags &= ~EXT2_FLAG_IB_DIRTY; + ext2fs_free_mem(&bitmap_block); + return 0; +} + +errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) +{ + dgrp_t i; + unsigned int j; + int nbytes; + unsigned int nbits; + errcode_t retval; + char * block_bitmap = fs->block_map->bitmap; + char * bitmap_block = NULL; + blk_t blk; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + if (!block_bitmap) + return 0; + nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; + retval = ext2fs_get_mem(fs->blocksize, &bitmap_block); + if (retval) + return retval; + 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)); + if (nbits) + for (j = nbits; j < fs->blocksize * 8; j++) + ext2fs_set_bit(j, bitmap_block); + } + blk = fs->group_desc[i].bg_block_bitmap; + if (blk) { +#ifdef EXT2_BIG_ENDIAN_BITMAPS + if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) + ext2fs_swap_bitmap(fs, bitmap_block, nbytes); +#endif + retval = io_channel_write_blk(fs->io, blk, 1, + bitmap_block); + if (retval) + return EXT2_ET_BLOCK_BITMAP_WRITE; + } + block_bitmap += nbytes; + } + fs->flags &= ~EXT2_FLAG_BB_DIRTY; + ext2fs_free_mem(&bitmap_block); + return 0; +} + +static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) +{ + dgrp_t i; + char *block_bitmap = 0, *inode_bitmap = 0; + char *buf; + errcode_t retval; + int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8; + int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8; + blk_t blk; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + fs->write_bitmaps = ext2fs_write_bitmaps; + + retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); + if (retval) + return retval; + if (do_block) { + if (fs->block_map) + ext2fs_free_block_bitmap(fs->block_map); + sprintf(buf, "block bitmap for %s", fs->device_name); + retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); + if (retval) + goto cleanup; + block_bitmap = fs->block_map->bitmap; + } + if (do_inode) { + if (fs->inode_map) + ext2fs_free_inode_bitmap(fs->inode_map); + sprintf(buf, "inode bitmap for %s", fs->device_name); + retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); + if (retval) + goto cleanup; + inode_bitmap = fs->inode_map->bitmap; + } + ext2fs_free_mem(&buf); + + if (fs->flags & EXT2_FLAG_IMAGE_FILE) { + if (inode_bitmap) { + blk = (fs->image_header->offset_inodemap / + fs->blocksize); + retval = io_channel_read_blk(fs->image_io, blk, + -(inode_nbytes * fs->group_desc_count), + inode_bitmap); + if (retval) + goto cleanup; + } + if (block_bitmap) { + blk = (fs->image_header->offset_blockmap / + fs->blocksize); + retval = io_channel_read_blk(fs->image_io, blk, + -(block_nbytes * fs->group_desc_count), + block_bitmap); + if (retval) + goto cleanup; + } + return 0; + } + + for (i = 0; i < fs->group_desc_count; i++) { + if (block_bitmap) { + blk = fs->group_desc[i].bg_block_bitmap; + if (blk) { + retval = io_channel_read_blk(fs->io, blk, + -block_nbytes, block_bitmap); + if (retval) { + retval = EXT2_ET_BLOCK_BITMAP_READ; + goto cleanup; + } +#ifdef EXT2_BIG_ENDIAN_BITMAPS + if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))) + ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes); +#endif + } else + memset(block_bitmap, 0, block_nbytes); + block_bitmap += block_nbytes; + } + if (inode_bitmap) { + blk = fs->group_desc[i].bg_inode_bitmap; + if (blk) { + retval = io_channel_read_blk(fs->io, blk, + -inode_nbytes, inode_bitmap); + if (retval) { + retval = EXT2_ET_INODE_BITMAP_READ; + goto cleanup; + } +#ifdef EXT2_BIG_ENDIAN_BITMAPS + if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))) + ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes); +#endif + } else + memset(inode_bitmap, 0, inode_nbytes); + inode_bitmap += inode_nbytes; + } + } + return 0; + +cleanup: + if (do_block) { + ext2fs_free_mem(&fs->block_map); + fs->block_map = 0; + } + if (do_inode) { + ext2fs_free_mem(&fs->inode_map); + fs->inode_map = 0; + } + if (buf) + ext2fs_free_mem(&buf); + return retval; +} + +errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs) +{ + return read_bitmaps(fs, 1, 0); +} + +errcode_t ext2fs_read_block_bitmap(ext2_filsys fs) +{ + return read_bitmaps(fs, 0, 1); +} + +errcode_t ext2fs_read_bitmaps(ext2_filsys fs) +{ + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (fs->inode_map && fs->block_map) + return 0; + + return read_bitmaps(fs, !fs->inode_map, !fs->block_map); +} + +errcode_t ext2fs_write_bitmaps(ext2_filsys fs) +{ + errcode_t retval; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + 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; +} + diff -Naur silo-1.4.14.orig/libext2fs/sparse.c silo-1.4.14/libext2fs/sparse.c --- silo-1.4.14.orig/libext2fs/sparse.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/sparse.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,78 @@ +/* + * sparse.c --- find the groups in an ext2 filesystem with metadata backups + * + * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. + * Copyright (C) 2002 Andreas Dilger. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include + +#include "ext2_fs.h" +#include "ext2fsP.h" + +static int test_root(int a, int b) +{ + if (a == 0) + return 1; + while (1) { + if (a == 1) + return 1; + if (a % b) + return 0; + a = a / b; + } +} + +int ext2fs_bg_has_super(ext2_filsys fs, int group_block) +{ + if (!(fs->super->s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) + return 1; + + if (test_root(group_block, 3) || (test_root(group_block, 5)) || + test_root(group_block, 7)) + return 1; + + return 0; +} + +/* + * Iterate through the groups which hold BACKUP superblock/GDT copies in an + * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before + * calling this for the first time. In a sparse filesystem it will be the + * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ... + * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ... + */ +unsigned int ext2fs_list_backups(ext2_filsys fs, unsigned int *three, + unsigned int *five, unsigned int *seven) +{ + unsigned int *min = three; + int mult = 3; + unsigned int ret; + + if (!(fs->super->s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) { + ret = *min; + *min += 1; + return ret; + } + + if (*five < *min) { + min = five; + mult = 5; + } + if (*seven < *min) { + min = seven; + mult = 7; + } + + ret = *min; + *min *= mult; + + return ret; +} diff -Naur silo-1.4.14.orig/libext2fs/swapfs.c silo-1.4.14/libext2fs/swapfs.c --- silo-1.4.14.orig/libext2fs/swapfs.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/swapfs.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,237 @@ +/* + * swapfs.c --- swap ext2 filesystem data structures + * + * Copyright (C) 1995, 1996, 2002 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" +#include + +#ifdef EXT2FS_ENABLE_SWAPFS +void ext2fs_swap_super(struct ext2_super_block * sb) +{ + int i; + sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count); + sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count); + sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count); + sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count); + sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count); + sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block); + sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size); + sb->s_log_frag_size = ext2fs_swab32(sb->s_log_frag_size); + sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group); + sb->s_frags_per_group = ext2fs_swab32(sb->s_frags_per_group); + sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group); + sb->s_mtime = ext2fs_swab32(sb->s_mtime); + sb->s_wtime = ext2fs_swab32(sb->s_wtime); + sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count); + sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count); + sb->s_magic = ext2fs_swab16(sb->s_magic); + sb->s_state = ext2fs_swab16(sb->s_state); + sb->s_errors = ext2fs_swab16(sb->s_errors); + sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level); + sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck); + sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval); + sb->s_creator_os = ext2fs_swab32(sb->s_creator_os); + sb->s_rev_level = ext2fs_swab32(sb->s_rev_level); + sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid); + sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid); + sb->s_first_ino = ext2fs_swab32(sb->s_first_ino); + sb->s_inode_size = ext2fs_swab16(sb->s_inode_size); + sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr); + sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat); + sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat); + sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat); + sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap); + sb->s_reserved_gdt_blocks = ext2fs_swab16(sb->s_reserved_gdt_blocks); + sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum); + sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev); + sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan); + sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts); + sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg); + sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time); + for (i=0; i < 4; i++) + sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]); + for (i=0; i < 17; i++) + sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]); + +} + +void ext2fs_swap_group_desc(struct ext2_group_desc *gdp) +{ + gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap); + gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap); + gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table); + gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count); + gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count); + gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count); +} + +void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header) +{ + struct ext2_ext_attr_header *from_header = + (struct ext2_ext_attr_header *)from; + struct ext2_ext_attr_header *to_header = + (struct ext2_ext_attr_header *)to; + struct ext2_ext_attr_entry *from_entry, *to_entry; + char *from_end = (char *)from_header + bufsize; + int n; + + if (to_header != from_header) + memcpy(to_header, from_header, bufsize); + + from_entry = (struct ext2_ext_attr_entry *)from_header; + to_entry = (struct ext2_ext_attr_entry *)to_header; + + if (has_header) { + to_header->h_magic = ext2fs_swab32(from_header->h_magic); + to_header->h_blocks = ext2fs_swab32(from_header->h_blocks); + to_header->h_refcount = ext2fs_swab32(from_header->h_refcount); + for (n=0; n<4; n++) + to_header->h_reserved[n] = + ext2fs_swab32(from_header->h_reserved[n]); + from_entry = (struct ext2_ext_attr_entry *)(from_header+1); + to_entry = (struct ext2_ext_attr_entry *)(to_header+1); + } + + while ((char *)from_entry < from_end && *(__u32 *)from_entry) { + to_entry->e_value_offs = + ext2fs_swab16(from_entry->e_value_offs); + to_entry->e_value_block = + ext2fs_swab32(from_entry->e_value_block); + to_entry->e_value_size = + ext2fs_swab32(from_entry->e_value_size); + from_entry = EXT2_EXT_ATTR_NEXT(from_entry); + to_entry = EXT2_EXT_ATTR_NEXT(to_entry); + } +} + +void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, + struct ext2_inode_large *f, int hostorder, + int bufsize) +{ + unsigned i; + int islnk = 0; + __u32 *eaf, *eat; + + if (hostorder && LINUX_S_ISLNK(f->i_mode)) + islnk = 1; + t->i_mode = ext2fs_swab16(f->i_mode); + if (!hostorder && LINUX_S_ISLNK(t->i_mode)) + islnk = 1; + t->i_uid = ext2fs_swab16(f->i_uid); + t->i_size = ext2fs_swab32(f->i_size); + t->i_atime = ext2fs_swab32(f->i_atime); + t->i_ctime = ext2fs_swab32(f->i_ctime); + t->i_mtime = ext2fs_swab32(f->i_mtime); + t->i_dtime = ext2fs_swab32(f->i_dtime); + t->i_gid = ext2fs_swab16(f->i_gid); + t->i_links_count = ext2fs_swab16(f->i_links_count); + t->i_blocks = ext2fs_swab32(f->i_blocks); + t->i_flags = ext2fs_swab32(f->i_flags); + t->i_file_acl = ext2fs_swab32(f->i_file_acl); + t->i_dir_acl = ext2fs_swab32(f->i_dir_acl); + if (!islnk || ext2fs_inode_data_blocks(fs, (struct ext2_inode *)t)) { + for (i = 0; i < EXT2_N_BLOCKS; i++) + t->i_block[i] = ext2fs_swab32(f->i_block[i]); + } else if (t != f) { + for (i = 0; i < EXT2_N_BLOCKS; i++) + t->i_block[i] = f->i_block[i]; + } + t->i_generation = ext2fs_swab32(f->i_generation); + t->i_faddr = ext2fs_swab32(f->i_faddr); + + switch (fs->super->s_creator_os) { + case EXT2_OS_LINUX: + t->osd1.linux1.l_i_reserved1 = + ext2fs_swab32(f->osd1.linux1.l_i_reserved1); + t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag; + t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize; + t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1); + t->osd2.linux2.l_i_uid_high = + ext2fs_swab16 (f->osd2.linux2.l_i_uid_high); + t->osd2.linux2.l_i_gid_high = + ext2fs_swab16 (f->osd2.linux2.l_i_gid_high); + t->osd2.linux2.l_i_reserved2 = + ext2fs_swab32(f->osd2.linux2.l_i_reserved2); + break; + case EXT2_OS_HURD: + t->osd1.hurd1.h_i_translator = + ext2fs_swab32 (f->osd1.hurd1.h_i_translator); + t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag; + t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize; + t->osd2.hurd2.h_i_mode_high = + ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high); + t->osd2.hurd2.h_i_uid_high = + ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high); + t->osd2.hurd2.h_i_gid_high = + ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high); + t->osd2.hurd2.h_i_author = + ext2fs_swab32 (f->osd2.hurd2.h_i_author); + break; + case EXT2_OS_MASIX: + t->osd1.masix1.m_i_reserved1 = + ext2fs_swab32(f->osd1.masix1.m_i_reserved1); + t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag; + t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize; + t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1); + t->osd2.masix2.m_i_reserved2[0] = + ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]); + t->osd2.masix2.m_i_reserved2[1] = + ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]); + break; + } + + if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16))) + return; /* no i_extra_isize field */ + + t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); + if (t->i_extra_isize > EXT2_INODE_SIZE(fs->super) - + sizeof(struct ext2_inode)) { + /* this is error case: i_extra_size is too large */ + return; + } + + i = sizeof(struct ext2_inode) + t->i_extra_isize + sizeof(__u32); + if (bufsize < (int) i) + return; /* no space for EA magic */ + + eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) + + f->i_extra_isize); + + if (ext2fs_swab32(*eaf) != EXT2_EXT_ATTR_MAGIC) + return; /* it seems no magic here */ + + eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) + + f->i_extra_isize); + *eat = ext2fs_swab32(*eaf); + + /* convert EA(s) */ + ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1), + bufsize - sizeof(struct ext2_inode) - + t->i_extra_isize - sizeof(__u32), 0); + +} + +void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t, + struct ext2_inode *f, int hostorder) +{ + ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t, + (struct ext2_inode_large *) f, hostorder, + sizeof(struct ext2_inode)); +} + +#endif diff -Naur silo-1.4.14.orig/libext2fs/test_io.c silo-1.4.14/libext2fs/test_io.c --- silo-1.4.14.orig/libext2fs/test_io.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/test_io.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,411 @@ +/* + * test_io.c --- This is the Test I/O interface. + * + * Copyright (C) 1996 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_PRCTL_H +#include +#else +#define PR_GET_DUMPABLE 3 +#endif +#if (!defined(HAVE_PRCTL) && defined(linux)) +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +struct test_private_data { + int magic; + io_channel real; + int flags; + FILE *outfile; + unsigned long block; + int read_abort_count, write_abort_count; + void (*read_blk)(unsigned long block, int count, errcode_t err); + void (*write_blk)(unsigned long block, int count, errcode_t err); + void (*set_blksize)(int blksize, errcode_t err); + void (*write_byte)(unsigned long block, int count, errcode_t err); +}; + +static errcode_t test_open(const char *name, int flags, io_channel *channel); +static errcode_t test_close(io_channel channel); +static errcode_t test_set_blksize(io_channel channel, int blksize); +static errcode_t test_read_blk(io_channel channel, unsigned long block, + int count, void *data); +static errcode_t test_write_blk(io_channel channel, unsigned long block, + int count, const void *data); +static errcode_t test_flush(io_channel channel); +static errcode_t test_write_byte(io_channel channel, unsigned long offset, + int count, const void *buf); +static errcode_t test_set_option(io_channel channel, const char *option, + const char *arg); + +static struct struct_io_manager struct_test_manager = { + EXT2_ET_MAGIC_IO_MANAGER, + "Test I/O Manager", + test_open, + test_close, + test_set_blksize, + test_read_blk, + test_write_blk, + test_flush, + test_write_byte, + test_set_option +}; + +io_manager test_io_manager = &struct_test_manager; + +/* + * These global variable can be set by the test program as + * necessary *before* calling test_open + */ +io_manager test_io_backing_manager = 0; +void (*test_io_cb_read_blk) + (unsigned long block, int count, errcode_t err) = 0; +void (*test_io_cb_write_blk) + (unsigned long block, int count, errcode_t err) = 0; +void (*test_io_cb_set_blksize) + (int blksize, errcode_t err) = 0; +void (*test_io_cb_write_byte) + (unsigned long block, int count, errcode_t err) = 0; + +/* + * Test flags + */ +#define TEST_FLAG_READ 0x01 +#define TEST_FLAG_WRITE 0x02 +#define TEST_FLAG_SET_BLKSIZE 0x04 +#define TEST_FLAG_FLUSH 0x08 +#define TEST_FLAG_DUMP 0x10 +#define TEST_FLAG_SET_OPTION 0x20 + +static void test_dump_block(io_channel channel, + struct test_private_data *data, + unsigned long block, const void *buf) +{ + const unsigned char *cp; + FILE *f = data->outfile; + int i; + unsigned long cksum = 0; + + for (i=0, cp = buf; i < channel->block_size; i++, cp++) { + cksum += *cp; + } + fprintf(f, "Contents of block %lu, checksum %08lu: \n", block, cksum); + for (i=0, cp = buf; i < channel->block_size; i++, cp++) { + if ((i % 16) == 0) + fprintf(f, "%04x: ", i); + fprintf(f, "%02x%c", *cp, ((i % 16) == 15) ? '\n' : ' '); + } +} + +static void test_abort(io_channel channel, unsigned long block) +{ + struct test_private_data *data; + FILE *f; + + data = (struct test_private_data *) channel->private_data; + f = data->outfile; + test_flush(channel); + + fprintf(f, "Aborting due to I/O to block %lu\n", block); + fflush(f); + abort(); +} + +static char *safe_getenv(const char *arg) +{ + if ((getuid() != geteuid()) || (getgid() != getegid())) + return NULL; +#if HAVE_PRCTL + if (prctl(PR_GET_DUMPABLE) == 0) + return NULL; +#else +#if (defined(linux) && defined(SYS_prctl)) + if (syscall(SYS_prctl, PR_GET_DUMPABLE) == 0) + return NULL; +#endif +#endif + +#ifdef HAVE___SECURE_GETENV + return __secure_getenv(arg); +#else + return getenv(arg); +#endif +} + +static errcode_t test_open(const char *name, int flags, io_channel *channel) +{ + io_channel io = NULL; + struct test_private_data *data = NULL; + errcode_t retval; + char *value; + + if (name == 0) + return EXT2_ET_BAD_DEVICE_NAME; + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); + if (retval) + return retval; + memset(io, 0, sizeof(struct struct_io_channel)); + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + retval = ext2fs_get_mem(sizeof(struct test_private_data), &data); + if (retval) { + retval = EXT2_ET_NO_MEMORY; + goto cleanup; + } + io->manager = test_io_manager; + retval = ext2fs_get_mem(strlen(name)+1, &io->name); + if (retval) + goto cleanup; + + strcpy(io->name, name); + io->private_data = data; + io->block_size = 1024; + io->read_error = 0; + io->write_error = 0; + io->refcount = 1; + + memset(data, 0, sizeof(struct test_private_data)); + data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL; + if (test_io_backing_manager) { + retval = test_io_backing_manager->open(name, flags, + &data->real); + if (retval) + goto cleanup; + } else + data->real = 0; + data->read_blk = test_io_cb_read_blk; + data->write_blk = test_io_cb_write_blk; + data->set_blksize = test_io_cb_set_blksize; + data->write_byte = test_io_cb_write_byte; + + data->outfile = NULL; + if ((value = safe_getenv("TEST_IO_LOGFILE")) != NULL) + data->outfile = fopen(value, "w"); + if (!data->outfile) + data->outfile = stderr; + + data->flags = 0; + if ((value = safe_getenv("TEST_IO_FLAGS")) != NULL) + data->flags = strtoul(value, NULL, 0); + + data->block = 0; + if ((value = safe_getenv("TEST_IO_BLOCK")) != NULL) + data->block = strtoul(value, NULL, 0); + + data->read_abort_count = 0; + if ((value = safe_getenv("TEST_IO_READ_ABORT")) != NULL) + data->read_abort_count = strtoul(value, NULL, 0); + + data->write_abort_count = 0; + if ((value = safe_getenv("TEST_IO_WRITE_ABORT")) != NULL) + data->write_abort_count = strtoul(value, NULL, 0); + + *channel = io; + return 0; + +cleanup: + if (io) + ext2fs_free_mem(&io); + if (data) + ext2fs_free_mem(&data); + return retval; +} + +static errcode_t test_close(io_channel channel) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (--channel->refcount > 0) + return 0; + + if (data->real) + retval = io_channel_close(data->real); + + if (data->outfile && data->outfile != stderr) + fclose(data->outfile); + + ext2fs_free_mem(&channel->private_data); + if (channel->name) + ext2fs_free_mem(&channel->name); + ext2fs_free_mem(&channel); + return retval; +} + +static errcode_t test_set_blksize(io_channel channel, int blksize) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_set_blksize(data->real, blksize); + if (data->set_blksize) + data->set_blksize(blksize, retval); + if (data->flags & TEST_FLAG_SET_BLKSIZE) + fprintf(data->outfile, + "Test_io: set_blksize(%d) returned %s\n", + blksize, retval ? error_message(retval) : "OK"); + channel->block_size = blksize; + return retval; +} + + +static errcode_t test_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_read_blk(data->real, block, count, buf); + if (data->read_blk) + data->read_blk(block, count, retval); + if (data->flags & TEST_FLAG_READ) + fprintf(data->outfile, + "Test_io: read_blk(%lu, %d) returned %s\n", + block, count, retval ? error_message(retval) : "OK"); + if (data->block && data->block == block) { + if (data->flags & TEST_FLAG_DUMP) + test_dump_block(channel, data, block, buf); + if (--data->read_abort_count == 0) + test_abort(channel, block); + } + return retval; +} + +static errcode_t test_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_write_blk(data->real, block, count, buf); + if (data->write_blk) + data->write_blk(block, count, retval); + if (data->flags & TEST_FLAG_WRITE) + fprintf(data->outfile, + "Test_io: write_blk(%lu, %d) returned %s\n", + block, count, retval ? error_message(retval) : "OK"); + if (data->block && data->block == block) { + if (data->flags & TEST_FLAG_DUMP) + test_dump_block(channel, data, block, buf); + if (--data->write_abort_count == 0) + test_abort(channel, block); + } + return retval; +} + +static errcode_t test_write_byte(io_channel channel, unsigned long offset, + int count, const void *buf) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real && data->real->manager->write_byte) + retval = io_channel_write_byte(data->real, offset, count, buf); + if (data->write_byte) + data->write_byte(offset, count, retval); + if (data->flags & TEST_FLAG_WRITE) + fprintf(data->outfile, + "Test_io: write_byte(%lu, %d) returned %s\n", + offset, count, retval ? error_message(retval) : "OK"); + return retval; +} + +/* + * Flush data buffers to disk. + */ +static errcode_t test_flush(io_channel channel) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + if (data->real) + retval = io_channel_flush(data->real); + + if (data->flags & TEST_FLAG_FLUSH) + fprintf(data->outfile, "Test_io: flush() returned %s\n", + retval ? error_message(retval) : "OK"); + + return retval; +} + +static errcode_t test_set_option(io_channel channel, const char *option, + const char *arg) +{ + struct test_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct test_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); + + + if (data->flags & TEST_FLAG_SET_OPTION) + fprintf(data->outfile, "Test_io: set_option(%s, %s) ", + option, arg); + if (data->real && data->real->manager->set_option) { + retval = (data->real->manager->set_option)(data->real, + option, arg); + if (data->flags & TEST_FLAG_SET_OPTION) + fprintf(data->outfile, "returned %s\n", + retval ? error_message(retval) : "OK"); + } else { + if (data->flags & TEST_FLAG_SET_OPTION) + fprintf(data->outfile, "not implemented\n"); + } + return retval; +} diff -Naur silo-1.4.14.orig/libext2fs/tst_badblocks.c silo-1.4.14/libext2fs/tst_badblocks.c --- silo-1.4.14.orig/libext2fs/tst_badblocks.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/tst_badblocks.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,293 @@ +/* + * This testing program makes sure the badblocks implementation works. + * + * Copyright (C) 1996 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +#define ADD_BLK 0x0001 +#define DEL_BLK 0x0002 + +blk_t test1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 }; +blk_t test2[] = { 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 1 }; +blk_t test3[] = { 3, 1, 4, 5, 9, 2, 7, 10, 5, 6, 10, 8, 0 }; +blk_t test4[] = { 20, 50, 12, 17, 13, 2, 66, 23, 56, 0 }; +blk_t test4a[] = { + 20, 1, + 50, 1, + 3, 0, + 17, 1, + 18, 0, + 16, 0, + 11, 0, + 12, 1, + 13, 1, + 14, 0, + 80, 0, + 45, 0, + 66, 1, + 0 }; +blk_t test5[] = { 31, 20, 17, 51, 23, 1, 56, 57, 0 }; +blk_t test5a[] = { + 50, ADD_BLK, + 51, DEL_BLK, + 57, DEL_BLK, + 66, ADD_BLK, + 31, DEL_BLK, + 12, ADD_BLK, + 2, ADD_BLK, + 13, ADD_BLK, + 1, DEL_BLK, + 0 + }; + + +static int test_fail = 0; + +static errcode_t create_test_list(blk_t *vec, badblocks_list *ret) +{ + errcode_t retval; + badblocks_list bb; + int i; + + retval = ext2fs_badblocks_list_create(&bb, 5); + if (retval) { + com_err("create_test_list", retval, "while creating list"); + return retval; + } + for (i=0; vec[i]; i++) { + retval = ext2fs_badblocks_list_add(bb, vec[i]); + if (retval) { + com_err("create_test_list", retval, + "while adding test vector %d", i); + ext2fs_badblocks_list_free(bb); + return retval; + } + } + *ret = bb; + return 0; +} + +static void print_list(badblocks_list bb, int verify) +{ + errcode_t retval; + badblocks_iterate iter; + blk_t blk; + int i, ok; + + retval = ext2fs_badblocks_list_iterate_begin(bb, &iter); + if (retval) { + com_err("print_list", retval, "while setting up iterator"); + return; + } + ok = i = 1; + while (ext2fs_badblocks_list_iterate(iter, &blk)) { + printf("%d ", blk); + if (i++ != blk) + ok = 0; + } + ext2fs_badblocks_list_iterate_end(iter); + if (verify) { + if (ok) + printf("--- OK"); + else { + printf("--- NOT OK"); + test_fail++; + } + } +} + +static void validate_test_seq(badblocks_list bb, blk_t *vec) +{ + int i, match, ok; + + for (i = 0; vec[i]; i += 2) { + match = ext2fs_badblocks_list_test(bb, vec[i]); + if (match == vec[i+1]) + ok = 1; + else { + ok = 0; + test_fail++; + } + printf("\tblock %d is %s --- %s\n", vec[i], + match ? "present" : "absent", + ok ? "OK" : "NOT OK"); + } +} + +static void do_test_seq(badblocks_list bb, blk_t *vec) +{ + int i, match; + + for (i = 0; vec[i]; i += 2) { + switch (vec[i+1]) { + case ADD_BLK: + ext2fs_badblocks_list_add(bb, vec[i]); + match = ext2fs_badblocks_list_test(bb, vec[i]); + printf("Adding block %d --- now %s\n", vec[i], + match ? "present" : "absent"); + if (!match) { + printf("FAILURE!\n"); + test_fail++; + } + break; + case DEL_BLK: + ext2fs_badblocks_list_del(bb, vec[i]); + match = ext2fs_badblocks_list_test(bb, vec[i]); + printf("Removing block %d --- now %s\n", vec[i], + ext2fs_badblocks_list_test(bb, vec[i]) ? + "present" : "absent"); + if (match) { + printf("FAILURE!\n"); + test_fail++; + } + break; + } + } +} + + +int file_test(badblocks_list bb) +{ + badblocks_list new_bb = 0; + errcode_t retval; + FILE *f; + + f = tmpfile(); + if (!f) { + fprintf(stderr, "Error opening temp file: %s\n", + error_message(errno)); + return 1; + } + retval = ext2fs_write_bb_FILE(bb, 0, f); + if (retval) { + com_err("file_test", retval, "while writing bad blocks"); + return 1; + } + + rewind(f); + retval = ext2fs_read_bb_FILE2(0, f, &new_bb, 0, 0); + if (retval) { + com_err("file_test", retval, "while reading bad blocks"); + return 1; + } + fclose(f); + + if (ext2fs_badblocks_equal(bb, new_bb)) { + printf("Block bitmap matched after reading and writing.\n"); + } else { + printf("Block bitmap NOT matched.\n"); + test_fail++; + } + return 0; +} + + +int main(int argc, char **argv) +{ + badblocks_list bb1, bb2, bb3, bb4, bb5; + int equal; + errcode_t retval; + + bb1 = bb2 = bb3 = bb4 = bb5 = 0; + + printf("test1: "); + retval = create_test_list(test1, &bb1); + if (retval == 0) + print_list(bb1, 1); + printf("\n"); + + printf("test2: "); + retval = create_test_list(test2, &bb2); + if (retval == 0) + print_list(bb2, 1); + printf("\n"); + + printf("test3: "); + retval = create_test_list(test3, &bb3); + if (retval == 0) + print_list(bb3, 1); + printf("\n"); + + printf("test4: "); + retval = create_test_list(test4, &bb4); + if (retval == 0) { + print_list(bb4, 0); + printf("\n"); + validate_test_seq(bb4, test4a); + } + printf("\n"); + + printf("test5: "); + retval = create_test_list(test5, &bb5); + if (retval == 0) { + print_list(bb5, 0); + printf("\n"); + do_test_seq(bb5, test5a); + printf("After test5 sequence: "); + print_list(bb5, 0); + printf("\n"); + } + printf("\n"); + + if (bb1 && bb2 && bb3 && bb4 && bb5) { + printf("Comparison tests:\n"); + equal = ext2fs_badblocks_equal(bb1, bb2); + printf("bb1 and bb2 are %sequal.\n", equal ? "" : "NOT "); + if (equal) + test_fail++; + + equal = ext2fs_badblocks_equal(bb1, bb3); + printf("bb1 and bb3 are %sequal.\n", equal ? "" : "NOT "); + if (!equal) + test_fail++; + + equal = ext2fs_badblocks_equal(bb1, bb4); + printf("bb1 and bb4 are %sequal.\n", equal ? "" : "NOT "); + if (equal) + test_fail++; + + equal = ext2fs_badblocks_equal(bb4, bb5); + printf("bb4 and bb5 are %sequal.\n", equal ? "" : "NOT "); + if (!equal) + test_fail++; + printf("\n"); + } + + file_test(bb4); + + if (test_fail == 0) + printf("ext2fs library badblocks tests checks out OK!\n"); + + if (bb1) + ext2fs_badblocks_list_free(bb1); + if (bb2) + ext2fs_badblocks_list_free(bb2); + if (bb3) + ext2fs_badblocks_list_free(bb3); + if (bb4) + ext2fs_badblocks_list_free(bb4); + + return test_fail; + +} diff -Naur silo-1.4.14.orig/libext2fs/tst_bitops.c silo-1.4.14/libext2fs/tst_bitops.c --- silo-1.4.14.orig/libext2fs/tst_bitops.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/tst_bitops.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,44 @@ +/* + * This testing program makes sure the bitops functions work + * + * Copyright (C) 2001 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +/* #define _EXT2_USE_C_VERSIONS_ */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +unsigned char bitarray[] = { + 0x80, 0xF0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x10, 0x20, 0x00, 0x00 + }; + +main(int argc, char **argv) +{ + int i, size; + + size = sizeof(bitarray)*8; + i = ext2fs_find_first_bit_set(bitarray, size); + while (i < size) { + printf("Bit set: %d\n", i); + i = ext2fs_find_next_bit_set(bitarray, size, i+1); + } +} diff -Naur silo-1.4.14.orig/libext2fs/tst_byteswap.c silo-1.4.14/libext2fs/tst_byteswap.c --- silo-1.4.14.orig/libext2fs/tst_byteswap.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/tst_byteswap.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,92 @@ +/* + * This testing program makes sure the byteswap functions work + * + * Copyright (C) 2000 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +__u16 test1[] = { + 0x0001, 0x0100, + 0x1234, 0x3412, + 0xff00, 0x00ff, + 0x4000, 0x0040, + 0xfeff, 0xfffe, + 0x0000, 0x0000 + }; + +__u32 test2[] = { + 0x00000001, 0x01000000, + 0x80000000, 0x00000080, + 0x12345678, 0x78563412, + 0xffff0000, 0x0000ffff, + 0x00ff0000, 0x0000ff00, + 0xff000000, 0x000000ff, + 0x00000000, 0x00000000 + }; + +int main(int argc, char **argv) +{ + int i; + int errors = 0; + + printf("Testing ext2fs_swab16\n"); + i=0; + do { + printf("swab16(0x%04x) = 0x%04x\n", test1[i], + ext2fs_swab16(test1[i])); + if (ext2fs_swab16(test1[i]) != test1[i+1]) { + printf("Error!!! %04x != %04x\n", + ext2fs_swab16(test1[i]), test1[i+1]); + errors++; + } + if (ext2fs_swab16(test1[i+1]) != test1[i]) { + printf("Error!!! %04x != %04x\n", + ext2fs_swab16(test1[i+1]), test1[i]); + errors++; + } + i += 2; + } while (test1[i] != 0); + + printf("Testing ext2fs_swab32\n"); + i = 0; + do { + printf("swab32(0x%08x) = 0x%08x\n", test2[i], + ext2fs_swab32(test2[i])); + if (ext2fs_swab32(test2[i]) != test2[i+1]) { + printf("Error!!! %04x != %04x\n", + ext2fs_swab32(test2[i]), test2[i+1]); + errors++; + } + if (ext2fs_swab32(test2[i+1]) != test2[i]) { + printf("Error!!! %04x != %04x\n", + ext2fs_swab32(test2[i+1]), test2[i]); + errors++; + } + i += 2; + } while (test2[i] != 0); + + if (!errors) + printf("No errors found in the byteswap implementation!\n"); + + return errors; +} diff -Naur silo-1.4.14.orig/libext2fs/tst_getsectsize.c silo-1.4.14/libext2fs/tst_getsectsize.c --- silo-1.4.14.orig/libext2fs/tst_getsectsize.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/tst_getsectsize.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,47 @@ +/* + * tst_getsize.c --- this function tests the getsize function + * + * Copyright (C) 1997 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +int main(int argc, char **argv) +{ + int sectsize; + int retval; + + if (argc < 2) { + fprintf(stderr, "Usage: %s device\n", argv[0]); + exit(1); + } + + retval = ext2fs_get_device_sectsize(argv[1], §size); + if (retval) { + com_err(argv[0], retval, + "while calling ext2fs_get_device_sectsize"); + exit(1); + } + printf("Device %s has a hardware sector size of %d.\n", + argv[1], sectsize); + exit(0); +} diff -Naur silo-1.4.14.orig/libext2fs/tst_getsize.c silo-1.4.14/libext2fs/tst_getsize.c --- silo-1.4.14.orig/libext2fs/tst_getsize.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/tst_getsize.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,44 @@ +/* + * tst_getsize.c --- this function tests the getsize function + * + * Copyright (C) 1997 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +int main(int argc, const char *argv[]) +{ + errcode_t retval; + blk_t blocks; + + if (argc < 2) { + fprintf(stderr, "%s device\n", argv[0]); + exit(1); + } + retval = ext2fs_get_device_size(argv[1], 1024, &blocks); + if (retval) { + com_err(argv[0], retval, "while getting device size"); + exit(1); + } + printf("%s is device has %d blocks.\n", argv[1], blocks); + return 0; +} diff -Naur silo-1.4.14.orig/libext2fs/tst_iscan.c silo-1.4.14/libext2fs/tst_iscan.c --- silo-1.4.14.orig/libext2fs/tst_iscan.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/tst_iscan.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,218 @@ +/* + * tst_inode.c --- this function tests the inode scan function + * + * Copyright (C) 1996 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#if HAVE_ERRNO_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +blk_t test_vec[] = { 8, 12, 24, 34, 43, 44, 100, 0 }; + +ext2_filsys test_fs; +ext2fs_block_bitmap bad_block_map, touched_map; +ext2fs_inode_bitmap bad_inode_map; +badblocks_list test_badblocks; + +int first_no_comma = 1; +int failed = 0; + +static void test_read_blk(unsigned long block, int count, errcode_t err) +{ + int i; + + if (first_no_comma) + first_no_comma = 0; + else + printf(", "); + + if (count > 1) + printf("%lu-%lu", block, block+count-1); + else + printf("%lu", block); + + for (i=0; i < count; i++, block++) { + if (ext2fs_test_block_bitmap(touched_map, block)) { + printf("\nDuplicate block?!? --- %lu\n", block); + failed++; + first_no_comma = 1; + } + ext2fs_mark_block_bitmap(touched_map, block); + } +} + +/* + * Setup the variables for doing the inode scan test. + */ +static void setup(void) +{ + errcode_t retval; + int i; + struct ext2_super_block param; + + initialize_ext2_error_table(); + + memset(¶m, 0, sizeof(param)); + param.s_blocks_count = 12000; + + + test_io_cb_read_blk = test_read_blk; + + retval = ext2fs_initialize("test fs", 0, ¶m, + test_io_manager, &test_fs); + if (retval) { + com_err("setup", retval, + "While initializing filesystem"); + exit(1); + } + retval = ext2fs_allocate_tables(test_fs); + if (retval) { + com_err("setup", retval, + "While allocating tables for test filesystem"); + exit(1); + } + retval = ext2fs_allocate_block_bitmap(test_fs, "bad block map", + &bad_block_map); + if (retval) { + com_err("setup", retval, + "While allocating bad_block bitmap"); + exit(1); + } + retval = ext2fs_allocate_block_bitmap(test_fs, "touched map", + &touched_map); + if (retval) { + com_err("setup", retval, + "While allocating touched block bitmap"); + exit(1); + } + retval = ext2fs_allocate_inode_bitmap(test_fs, "bad inode map", + &bad_inode_map); + if (retval) { + com_err("setup", retval, + "While allocating bad inode bitmap"); + exit(1); + } + + retval = ext2fs_badblocks_list_create(&test_badblocks, 5); + if (retval) { + com_err("setup", retval, "while creating badblocks list"); + exit(1); + } + for (i=0; test_vec[i]; i++) { + retval = ext2fs_badblocks_list_add(test_badblocks, test_vec[i]); + if (retval) { + com_err("setup", retval, + "while adding test vector %d", i); + exit(1); + } + ext2fs_mark_block_bitmap(bad_block_map, test_vec[i]); + } + test_fs->badblocks = test_badblocks; +} + +/* + * Iterate using inode_scan + */ +static void iterate(void) +{ + struct ext2_inode inode; + ext2_inode_scan scan; + errcode_t retval; + ext2_ino_t ino; + + retval = ext2fs_open_inode_scan(test_fs, 8, &scan); + if (retval) { + com_err("iterate", retval, "While opening inode scan"); + exit(1); + } + printf("Reading blocks: "); + retval = ext2fs_get_next_inode(scan, &ino, &inode); + if (retval) { + com_err("iterate", retval, "while reading first inode"); + exit(1); + } + while (ino) { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) { + ext2fs_mark_inode_bitmap(bad_inode_map, ino); + continue; + } + if (retval) { + com_err("iterate", retval, + "while getting next inode"); + exit(1); + } + } + printf("\n"); + ext2fs_close_inode_scan(scan); +} + +/* + * Verify the touched map + */ +static void check_map(void) +{ + int i, j, first=1; + unsigned long blk; + + for (i=0; test_vec[i]; i++) { + if (ext2fs_test_block_bitmap(touched_map, test_vec[i])) { + printf("Bad block was touched --- %d\n", test_vec[i]); + failed++; + first_no_comma = 1; + } + ext2fs_mark_block_bitmap(touched_map, test_vec[i]); + } + for (i = 0; i < test_fs->group_desc_count; i++) { + for (j=0, blk = test_fs->group_desc[i].bg_inode_table; + j < test_fs->inode_blocks_per_group; + j++, blk++) { + if (!ext2fs_test_block_bitmap(touched_map, blk) && + !ext2fs_test_block_bitmap(bad_block_map, blk)) { + printf("Missing block --- %lu\n", blk); + failed++; + } + } + } + printf("Bad inodes: "); + for (i=1; i <= test_fs->super->s_inodes_count; i++) { + if (ext2fs_test_inode_bitmap(bad_inode_map, i)) { + if (first) + first = 0; + else + printf(", "); + printf("%d", i); + } + } + printf("\n"); +} + + +int main(int argc, char **argv) +{ + setup(); + iterate(); + check_map(); + if (!failed) + printf("Inode scan tested OK!\n"); + return failed; +} + diff -Naur silo-1.4.14.orig/libext2fs/unix_io.c silo-1.4.14/libext2fs/unix_io.c --- silo-1.4.14.orig/libext2fs/unix_io.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/unix_io.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,710 @@ +/* + * unix_io.c --- This is the Unix (well, really POSIX) implementation + * of the I/O manager. + * + * Implements a one-block write-through cache. + * + * Includes support for Windows NT support under Cygwin. + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + * 2002 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#include +#include +#ifdef __linux__ +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_RESOURCE_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +struct unix_cache { + char *buf; + unsigned long block; + int access_time; + unsigned dirty:1; + unsigned in_use:1; +}; + +#define CACHE_SIZE 8 +#define WRITE_DIRECT_SIZE 4 /* Must be smaller than CACHE_SIZE */ +#define READ_DIRECT_SIZE 4 /* Should be smaller than CACHE_SIZE */ + +struct unix_private_data { + int magic; + int dev; + int flags; + int access_time; + ext2_loff_t offset; + struct unix_cache cache[CACHE_SIZE]; +}; + +static errcode_t unix_open(const char *name, int flags, io_channel *channel); +static errcode_t unix_close(io_channel channel); +static errcode_t unix_set_blksize(io_channel channel, int blksize); +static errcode_t unix_read_blk(io_channel channel, unsigned long block, + int count, void *data); +static errcode_t unix_write_blk(io_channel channel, unsigned long block, + int count, const void *data); +static errcode_t unix_flush(io_channel channel); +static errcode_t unix_write_byte(io_channel channel, unsigned long offset, + int size, const void *data); +static errcode_t unix_set_option(io_channel channel, const char *option, + const char *arg); + +static void reuse_cache(io_channel channel, struct unix_private_data *data, + struct unix_cache *cache, unsigned long block); + +/* __FreeBSD_kernel__ is defined by GNU/kFreeBSD - the FreeBSD kernel + * does not know buffered block devices - everything is raw. */ +#if defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#define NEED_BOUNCE_BUFFER +#else +#undef NEED_BOUNCE_BUFFER +#endif + +static struct struct_io_manager struct_unix_manager = { + EXT2_ET_MAGIC_IO_MANAGER, + "Unix I/O Manager", + unix_open, + unix_close, + unix_set_blksize, + unix_read_blk, + unix_write_blk, + unix_flush, +#ifdef NEED_BOUNCE_BUFFER + 0, +#else + unix_write_byte, +#endif + unix_set_option +}; + +io_manager unix_io_manager = &struct_unix_manager; + +/* + * Here are the raw I/O functions + */ +#ifndef NEED_BOUNCE_BUFFER +static errcode_t raw_read_blk(io_channel channel, + struct unix_private_data *data, + unsigned long block, + int count, void *buf) +{ + errcode_t retval; + ssize_t size; + ext2_loff_t location; + int actual = 0; + + size = (count < 0) ? -count : count * channel->block_size; + location = ((ext2_loff_t) block * channel->block_size) + data->offset; + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; + goto error_out; + } + actual = read(data->dev, buf, size); + if (actual != size) { + if (actual < 0) + actual = 0; + retval = EXT2_ET_SHORT_READ; + goto error_out; + } + return 0; + +error_out: + memset((char *) buf+actual, 0, size-actual); + if (channel->read_error) + retval = (channel->read_error)(channel, block, count, buf, + size, actual, retval); + return retval; +} +#else /* NEED_BOUNCE_BUFFER */ +/* + * Windows and FreeBSD block devices only allow sector alignment IO in offset and size + */ +static errcode_t raw_read_blk(io_channel channel, + struct unix_private_data *data, + unsigned long block, + int count, void *buf) +{ + errcode_t retval; + size_t size, alignsize, fragment; + ext2_loff_t location; + int total = 0, actual; +#define BLOCKALIGN 512 + char sector[BLOCKALIGN]; + + size = (count < 0) ? -count : count * channel->block_size; + location = ((ext2_loff_t) block * channel->block_size) + data->offset; +#ifdef DEBUG + printf("count=%d, size=%d, block=%d, blk_size=%d, location=%lx\n", + count, size, block, channel->block_size, location); +#endif + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; + goto error_out; + } + fragment = size % BLOCKALIGN; + alignsize = size - fragment; + if (alignsize) { + actual = read(data->dev, buf, alignsize); + if (actual != alignsize) + goto short_read; + } + if (fragment) { + actual = read(data->dev, sector, BLOCKALIGN); + if (actual != BLOCKALIGN) + goto short_read; + memcpy(buf+alignsize, sector, fragment); + } + return 0; + +short_read: + if (actual>0) + total += actual; + retval = EXT2_ET_SHORT_READ; + +error_out: + memset((char *) buf+total, 0, size-actual); + if (channel->read_error) + retval = (channel->read_error)(channel, block, count, buf, + size, actual, retval); + return retval; +} +#endif + +static errcode_t raw_write_blk(io_channel channel, + struct unix_private_data *data, + unsigned long block, + int count, const void *buf) +{ + ssize_t size; + ext2_loff_t location; + int actual = 0; + errcode_t retval; + + if (count == 1) + size = channel->block_size; + else { + if (count < 0) + size = -count; + else + size = count * channel->block_size; + } + + location = ((ext2_loff_t) block * channel->block_size) + data->offset; + if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; + goto error_out; + } + + actual = write(data->dev, buf, size); + if (actual != size) { + retval = EXT2_ET_SHORT_WRITE; + goto error_out; + } + return 0; + +error_out: + if (channel->write_error) + retval = (channel->write_error)(channel, block, count, buf, + size, actual, retval); + return retval; +} + + +/* + * Here we implement the cache functions + */ + +/* Allocate the cache buffers */ +static errcode_t alloc_cache(io_channel channel, + struct unix_private_data *data) +{ + errcode_t retval; + struct unix_cache *cache; + int i; + + data->access_time = 0; + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + cache->block = 0; + cache->access_time = 0; + cache->dirty = 0; + cache->in_use = 0; + if ((retval = ext2fs_get_mem(channel->block_size, + &cache->buf))) + return retval; + } + return 0; +} + +/* Free the cache buffers */ +static void free_cache(struct unix_private_data *data) +{ + struct unix_cache *cache; + int i; + + data->access_time = 0; + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + cache->block = 0; + cache->access_time = 0; + cache->dirty = 0; + cache->in_use = 0; + if (cache->buf) + ext2fs_free_mem(&cache->buf); + cache->buf = 0; + } +} + +#ifndef NO_IO_CACHE +/* + * Try to find a block in the cache. If the block is not found, and + * eldest is a non-zero pointer, then fill in eldest with the cache + * entry to that should be reused. + */ +static struct unix_cache *find_cached_block(struct unix_private_data *data, + unsigned long block, + struct unix_cache **eldest) +{ + struct unix_cache *cache, *unused_cache, *oldest_cache; + int i; + + unused_cache = oldest_cache = 0; + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + if (!cache->in_use) { + if (!unused_cache) + unused_cache = cache; + continue; + } + if (cache->block == block) { + cache->access_time = ++data->access_time; + return cache; + } + if (!oldest_cache || + (cache->access_time < oldest_cache->access_time)) + oldest_cache = cache; + } + if (eldest) + *eldest = (unused_cache) ? unused_cache : oldest_cache; + return 0; +} + +/* + * Reuse a particular cache entry for another block. + */ +static void reuse_cache(io_channel channel, struct unix_private_data *data, + struct unix_cache *cache, unsigned long block) +{ + if (cache->dirty && cache->in_use) + raw_write_blk(channel, data, cache->block, 1, cache->buf); + + cache->in_use = 1; + cache->dirty = 0; + cache->block = block; + cache->access_time = ++data->access_time; +} + +/* + * Flush all of the blocks in the cache + */ +static errcode_t flush_cached_blocks(io_channel channel, + struct unix_private_data *data, + int invalidate) + +{ + struct unix_cache *cache; + errcode_t retval, retval2; + int i; + + retval2 = 0; + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + if (!cache->in_use) + continue; + + if (invalidate) + cache->in_use = 0; + + if (!cache->dirty) + continue; + + retval = raw_write_blk(channel, data, + cache->block, 1, cache->buf); + if (retval) + retval2 = retval; + else + cache->dirty = 0; + } + return retval2; +} +#endif /* NO_IO_CACHE */ + +static errcode_t unix_open(const char *name, int flags, io_channel *channel) +{ + io_channel io = NULL; + struct unix_private_data *data = NULL; + errcode_t retval; + int open_flags; + struct stat st; +#ifdef __linux__ + struct utsname ut; +#endif + + if (name == 0) + return EXT2_ET_BAD_DEVICE_NAME; + retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); + if (retval) + return retval; + memset(io, 0, sizeof(struct struct_io_channel)); + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data); + if (retval) + goto cleanup; + + io->manager = unix_io_manager; + retval = ext2fs_get_mem(strlen(name)+1, &io->name); + if (retval) + goto cleanup; + + strcpy(io->name, name); + io->private_data = data; + io->block_size = 1024; + io->read_error = 0; + io->write_error = 0; + io->refcount = 1; + + memset(data, 0, sizeof(struct unix_private_data)); + data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; + + if ((retval = alloc_cache(io, data))) + goto cleanup; + + open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY; +#ifdef HAVE_OPEN64 + data->dev = open64(io->name, open_flags); +#else + data->dev = open(io->name, open_flags); +#endif + if (data->dev < 0) { + retval = errno; + goto cleanup; + } + +#ifdef __linux__ +#undef RLIM_INFINITY +#if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4))) +#define RLIM_INFINITY ((unsigned long)(~0UL>>1)) +#else +#define RLIM_INFINITY (~0UL) +#endif + /* + * Work around a bug in 2.4.10-2.4.18 kernels where writes to + * block devices are wrongly getting hit by the filesize + * limit. This workaround isn't perfect, since it won't work + * if glibc wasn't built against 2.2 header files. (Sigh.) + * + */ + if ((flags & IO_FLAG_RW) && + (uname(&ut) == 0) && + ((ut.release[0] == '2') && (ut.release[1] == '.') && + (ut.release[2] == '4') && (ut.release[3] == '.') && + (ut.release[4] == '1') && (ut.release[5] >= '0') && + (ut.release[5] < '8')) && + (fstat(data->dev, &st) == 0) && + (S_ISBLK(st.st_mode))) { + struct rlimit rlim; + + rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY; + setrlimit(RLIMIT_FSIZE, &rlim); + getrlimit(RLIMIT_FSIZE, &rlim); + if (((unsigned long) rlim.rlim_cur) < + ((unsigned long) rlim.rlim_max)) { + rlim.rlim_cur = rlim.rlim_max; + setrlimit(RLIMIT_FSIZE, &rlim); + } + } +#endif + *channel = io; + return 0; + +cleanup: + if (data) { + free_cache(data); + ext2fs_free_mem(&data); + } + if (io) + ext2fs_free_mem(&io); + return retval; +} + +static errcode_t unix_close(io_channel channel) +{ + struct unix_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (--channel->refcount > 0) + return 0; + +#ifndef NO_IO_CACHE + retval = flush_cached_blocks(channel, data, 0); +#endif + + if (close(data->dev) < 0) + retval = errno; + free_cache(data); + + ext2fs_free_mem(&channel->private_data); + if (channel->name) + ext2fs_free_mem(&channel->name); + ext2fs_free_mem(&channel); + return retval; +} + +static errcode_t unix_set_blksize(io_channel channel, int blksize) +{ + struct unix_private_data *data; + errcode_t retval; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (channel->block_size != blksize) { +#ifndef NO_IO_CACHE + if ((retval = flush_cached_blocks(channel, data, 0))) + return retval; +#endif + + channel->block_size = blksize; + free_cache(data); + if ((retval = alloc_cache(channel, data))) + return retval; + } + return 0; +} + + +static errcode_t unix_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + struct unix_private_data *data; + struct unix_cache *cache, *reuse[READ_DIRECT_SIZE]; + errcode_t retval; + char *cp; + int i, j; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + +#ifdef NO_IO_CACHE + return raw_read_blk(channel, data, block, count, buf); +#else + /* + * If we're doing an odd-sized read or a very large read, + * flush out the cache and then do a direct read. + */ + if (count < 0 || count > WRITE_DIRECT_SIZE) { + if ((retval = flush_cached_blocks(channel, data, 0))) + return retval; + return raw_read_blk(channel, data, block, count, buf); + } + + cp = buf; + while (count > 0) { + /* If it's in the cache, use it! */ + if ((cache = find_cached_block(data, block, &reuse[0]))) { +#ifdef DEBUG + printf("Using cached block %d\n", block); +#endif + memcpy(cp, cache->buf, channel->block_size); + count--; + block++; + cp += channel->block_size; + continue; + } + /* + * Find the number of uncached blocks so we can do a + * single read request + */ + for (i=1; i < count; i++) + if (find_cached_block(data, block+i, &reuse[i])) + break; +#ifdef DEBUG + printf("Reading %d blocks starting at %d\n", i, block); +#endif + if ((retval = raw_read_blk(channel, data, block, i, cp))) + return retval; + + /* Save the results in the cache */ + for (j=0; j < i; j++) { + count--; + cache = reuse[j]; + reuse_cache(channel, data, cache, block++); + memcpy(cache->buf, cp, channel->block_size); + cp += channel->block_size; + } + } + return 0; +#endif /* NO_IO_CACHE */ +} + +static errcode_t unix_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + struct unix_private_data *data; + struct unix_cache *cache, *reuse; + errcode_t retval = 0; + const char *cp; + int writethrough; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + +#ifdef NO_IO_CACHE + return raw_write_blk(channel, data, block, count, buf); +#else + /* + * If we're doing an odd-sized write or a very large write, + * flush out the cache completely and then do a direct write. + */ + if (count < 0 || count > WRITE_DIRECT_SIZE) { + if ((retval = flush_cached_blocks(channel, data, 1))) + return retval; + return raw_write_blk(channel, data, block, count, buf); + } + + /* + * For a moderate-sized multi-block write, first force a write + * if we're in write-through cache mode, and then fill the + * cache with the blocks. + */ + writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH; + if (writethrough) + retval = raw_write_blk(channel, data, block, count, buf); + + cp = buf; + while (count > 0) { + cache = find_cached_block(data, block, &reuse); + if (!cache) { + cache = reuse; + reuse_cache(channel, data, cache, block); + } + memcpy(cache->buf, cp, channel->block_size); + cache->dirty = !writethrough; + count--; + block++; + cp += channel->block_size; + } + return retval; +#endif /* NO_IO_CACHE */ +} + +static errcode_t unix_write_byte(io_channel channel, unsigned long offset, + int size, const void *buf) +{ + struct unix_private_data *data; + errcode_t retval = 0; + ssize_t actual; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + +#ifndef NO_IO_CACHE + /* + * Flush out the cache completely + */ + if ((retval = flush_cached_blocks(channel, data, 1))) + return retval; +#endif + + if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0) + return errno; + + actual = write(data->dev, buf, size); + if (actual != size) + return EXT2_ET_SHORT_WRITE; + + return 0; +} + +/* + * Flush data buffers to disk. + */ +static errcode_t unix_flush(io_channel channel) +{ + struct unix_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + +#ifndef NO_IO_CACHE + retval = flush_cached_blocks(channel, data, 0); +#endif + fsync(data->dev); + return retval; +} + +static errcode_t unix_set_option(io_channel channel, const char *option, + const char *arg) +{ + struct unix_private_data *data; + unsigned long tmp; + char *end; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct unix_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); + + if (!strcmp(option, "offset")) { + if (!arg) + return EXT2_ET_INVALID_ARGUMENT; + + tmp = strtoul(arg, &end, 0); + if (*end) + return EXT2_ET_INVALID_ARGUMENT; + data->offset = tmp; + return 0; + } + return EXT2_ET_INVALID_ARGUMENT; +} diff -Naur silo-1.4.14.orig/libext2fs/unlink.c silo-1.4.14/libext2fs/unlink.c --- silo-1.4.14.orig/libext2fs/unlink.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/unlink.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,99 @@ +/* + * unlink.c --- delete links in a ext2fs directory + * + * Copyright (C) 1993, 1994, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#if HAVE_UNISTD_H +#include +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" + +struct link_struct { + const char *name; + int namelen; + ext2_ino_t inode; + int flags; + struct ext2_dir_entry *prev; + int done; +}; + +#ifdef __TURBOC__ + #pragma argsused +#endif +static int unlink_proc(struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct link_struct *ls = (struct link_struct *) priv_data; + struct ext2_dir_entry *prev; + + prev = ls->prev; + ls->prev = dirent; + + if (ls->name) { + if ((dirent->name_len & 0xFF) != ls->namelen) + return 0; + if (strncmp(ls->name, dirent->name, dirent->name_len & 0xFF)) + return 0; + } + if (ls->inode) { + if (dirent->inode != ls->inode) + return 0; + } else { + if (!dirent->inode) + return 0; + } + + if (prev) + prev->rec_len += dirent->rec_len; + else + dirent->inode = 0; + ls->done++; + return DIRENT_ABORT|DIRENT_CHANGED; +} + +#ifdef __TURBOC__ + #pragma argsused +#endif +errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, + const char *name, ext2_ino_t ino, + int flags EXT2FS_ATTR((unused))) +{ + errcode_t retval; + struct link_struct ls; + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (!name && !ino) + return EXT2_ET_INVALID_ARGUMENT; + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + ls.name = name; + ls.namelen = name ? strlen(name) : 0; + ls.inode = ino; + ls.flags = 0; + ls.done = 0; + ls.prev = 0; + + retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, + 0, unlink_proc, &ls); + if (retval) + return retval; + + return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE; +} + diff -Naur silo-1.4.14.orig/libext2fs/valid_blk.c silo-1.4.14/libext2fs/valid_blk.c --- silo-1.4.14.orig/libext2fs/valid_blk.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/valid_blk.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,56 @@ +/* + * valid_blk.c --- does the inode have valid blocks? + * + * Copyright 1997 by Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + */ + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +/* + * This function returns 1 if the inode's block entries actually + * contain block entries. + */ +int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode) +{ + /* + * Only directories, regular files, and some symbolic links + * have valid block entries. + */ + if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) && + !LINUX_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 (LINUX_S_ISLNK (inode->i_mode)) { + if (inode->i_file_acl == 0) { + /* With no EA block, we can rely on i_blocks */ + if (inode->i_blocks == 0) + return 0; + } else { + /* With an EA block, life gets more tricky */ + if (inode->i_size >= EXT2_N_BLOCKS*4) + return 1; /* definitely using i_block[] */ + if (inode->i_size > 4 && inode->i_block[1] == 0) + return 1; /* definitely using i_block[] */ + return 0; /* Probably a fast symlink */ + } + } + return 1; +} diff -Naur silo-1.4.14.orig/libext2fs/version.c silo-1.4.14/libext2fs/version.c --- silo-1.4.14.orig/libext2fs/version.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/version.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,52 @@ +/* + * version.c --- Return the version of the ext2 library + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +#include "version.h" + +static const char *lib_version = E2FSPROGS_VERSION; +static const char *lib_date = E2FSPROGS_DATE; + +int ext2fs_parse_version_string(const char *ver_string) +{ + const char *cp; + int version = 0; + + for (cp = ver_string; *cp; cp++) { + if (*cp == '.') + continue; + if (!isdigit(*cp)) + break; + version = (version * 10) + (*cp - '0'); + } + return version; +} + + +int ext2fs_get_library_version(const char **ver_string, + const char **date_string) +{ + if (ver_string) + *ver_string = lib_version; + if (date_string) + *date_string = lib_date; + + return ext2fs_parse_version_string(lib_version); +} diff -Naur silo-1.4.14.orig/libext2fs/version.h silo-1.4.14/libext2fs/version.h --- silo-1.4.14.orig/libext2fs/version.h 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/version.h 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,11 @@ +/* + * version.h --- controls the version number printed by the e2fs + * programs. + * + * Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, + * 2004, 2005 by Theodore Ts'o. This file may be redistributed under + * the GNU Public License. + */ + +#define E2FSPROGS_VERSION "1.38" +#define E2FSPROGS_DATE "30-Jun-2005" diff -Naur silo-1.4.14.orig/libext2fs/write_bb_file.c silo-1.4.14/libext2fs/write_bb_file.c --- silo-1.4.14.orig/libext2fs/write_bb_file.c 1969-12-31 16:00:00.000000000 -0800 +++ silo-1.4.14/libext2fs/write_bb_file.c 2009-01-07 15:07:57.000000000 -0800 @@ -0,0 +1,34 @@ +/* + * write_bb_file.c --- write a list of bad blocks to a FILE * + * + * Copyright (C) 1994, 1995 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include + +#include "ext2_fs.h" +#include "ext2fs.h" + +errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list, + unsigned int flags EXT2FS_ATTR((unused)), + FILE *f) +{ + badblocks_iterate bb_iter; + blk_t blk; + errcode_t retval; + + retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); + if (retval) + return retval; + + while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) { + fprintf(f, "%d\n", blk); + } + ext2fs_badblocks_list_iterate_end(bb_iter); + return 0; +} diff -Naur silo-1.4.14.orig/second/Makefile silo-1.4.14/second/Makefile --- silo-1.4.14.orig/second/Makefile 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/second/Makefile 2009-01-07 15:07:57.000000000 -0800 @@ -27,10 +27,10 @@ LDFLAGS_LARGE=-N -Ttext $(LARGE_RELOC) .c.o: - $(CC) $(CFLAGS) -c $*.c -o $@ + $(CC-SILO) $(CFLAGS) -c $*.c -o $@ .S.o: - $(CC) $(CFLAGS) -c $*.S -o $@ + $(CC-SILO) $(CFLAGS) -c $*.S -o $@ # The ordering here is very significant. Please add new object files to OBJS5 only. OBJS1 = crt0.o @@ -43,8 +43,8 @@ OBJS4 = main.o OBJS4N = mainnet.o OBJS5 = cmdline.o disk.o file.o misc.o cfg.o strtol.o ranges.o timer.o \ - memory.o fs/libfs.a mul.o ../common/rem.o ../common/sdiv.o umul.o \ - ../common/stringops2.o ls.o muldi3.o + memory.o fs/libfs.a ../common/rem.o ../common/sdiv.o umul.o \ + ../common/stringops2.o ls.o muldi3.o ../libext2fs/libext2fs.a OBJS = $(OBJS1) $(OBJS2) $(OBJS3) bmark.o $(OBJS4) $(OBJS5) OBJSNET = $(OBJS1) $(OBJS2N) $(OBJS3) bmark.o $(OBJS4N) $(OBJS5) @@ -53,18 +53,21 @@ # Should really switch to autoconf... all: second.b silotftp.b +../libext2fs/libext2fs.a: + @make -C ../libext2fs + fs/libfs.a: $(FS_OBJS) $(RM) $@ $(AR) rc $@ $(FS_OBJS) second: $(OBJS) mark.o - $(LD) $(LDFLAGS_SMALL) -Bstatic -o second $(OBJS) -lext2fs mark.o - $(LD) $(LDFLAGS_LARGE) -Bstatic -o second2 $(OBJS) -lext2fs mark.o + $(LD) $(LDFLAGS_SMALL) -Bstatic -o second $(OBJS) mark.o + $(LD) $(LDFLAGS_LARGE) -Bstatic -o second2 $(OBJS) mark.o $(NM) second | grep -v '*ABS*' | sort > second.map silotftp: $(OBJSNET) mark.o - $(LD) $(LDFLAGS_SMALL) -Bstatic -o silotftp $(OBJSNET) -lext2fs mark.o - $(LD) $(LDFLAGS_LARGE) -Bstatic -o silotftp2 $(OBJSNET) -lext2fs mark.o + $(LD) $(LDFLAGS_SMALL) -Bstatic -o silotftp $(OBJSNET) mark.o + $(LD) $(LDFLAGS_LARGE) -Bstatic -o silotftp2 $(OBJSNET) mark.o $(NM) silotftp | grep -v '*ABS*' | sort > silotftp.map second.l: second @@ -73,31 +76,31 @@ file.o: file.c decompnet.o: decomp.c - $(CC) $(CFLAGS) -DTFTP -DVERSION='"$(VERSION)"' -c -o $@ $< + $(CC-SILO) $(CFLAGS) -DTFTP -DVERSION='"$(VERSION)"' -c -o $@ $< decomp.o: decomp.c - $(CC) $(CFLAGS) -DVERSION='"$(VERSION)"' -c $< + $(CC-SILO) $(CFLAGS) -DVERSION='"$(VERSION)"' -c $< mainnet.o: main.c - $(CC) $(CFLAGS) -DTFTP -c -o $@ $< + $(CC-SILO) $(CFLAGS) -DTFTP -c -o $@ $< malloc.o: ../common/malloc.c - $(CC) $(CFLAGS) -c -o $@ $< + $(CC-SILO) $(CFLAGS) -c -o $@ $< util: util.c - $(CC) -DSMALL_RELOC=$(SMALL_RELOC) -DLARGE_RELOC=$(LARGE_RELOC) -o $@ $< + $(BUILD_CC) -DSMALL_RELOC=$(SMALL_RELOC) -DLARGE_RELOC=$(LARGE_RELOC) -o $@ $< clean: $(RM) *.o fs/*.o second* silotftp* util fs/libfs.a crt0.o: crt0.S - $(CC) $(CFLAGS) -c -Wa,-Av9 -DIMGVERSION='"SILO$(IMGVERSION)"' crt0.S + $(CC-SILO) $(CFLAGS) -c -Wa,-Av9 -DIMGVERSION='"SILO$(IMGVERSION)"' crt0.S memory.o: memory.c - $(CC) $(CFLAGS) -c -Wa,-Av9 memory.c + $(CC-SILO) $(CFLAGS) -c -Wa,-Av9 memory.c timer.o: timer.c - $(CC) $(CFLAGS) -c -Wa,-Av9a timer.c + $(CC-SILO) $(CFLAGS) -c -Wa,-Av9a timer.c second.b: second util $(ELFTOAOUT) -o second.aout second diff -Naur silo-1.4.14.orig/second/ls.c silo-1.4.14/second/ls.c --- silo-1.4.14.orig/second/ls.c 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/second/ls.c 2009-01-07 15:07:57.000000000 -0800 @@ -19,10 +19,10 @@ USA. */ #include +#include #include typedef int FILE; -#include #include #include diff -Naur silo-1.4.14.orig/silo/silo.c silo-1.4.14/silo/silo.c --- silo-1.4.14.orig/silo/silo.c 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/silo/silo.c 2009-01-07 15:07:57.000000000 -0800 @@ -128,8 +128,8 @@ unsigned short nsect; /* Sectors per track */ unsigned char spare3[4]; /* Even more magic... */ struct sun_partition { - unsigned long start_cylinder; - unsigned long num_sectors; + unsigned int start_cylinder; + unsigned int num_sectors; } partitions[8]; unsigned short magic; /* Magic number */ unsigned short csum; /* Label xor'd checksum */ diff -Naur silo-1.4.14.orig/silo/silocheck.c silo-1.4.14/silo/silocheck.c --- silo-1.4.14.orig/silo/silocheck.c 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/silo/silocheck.c 2009-01-07 15:07:57.000000000 -0800 @@ -101,8 +101,8 @@ unsigned short nsect; /* Sectors per track */ unsigned char spare3[4]; /* Even more magic... */ struct sun_partition { - unsigned long start_cylinder; - unsigned long num_sectors; + unsigned int start_cylinder; + unsigned int num_sectors; } partitions[8]; unsigned short magic; /* Magic number */ unsigned short csum; /* Label xor'd checksum */ diff -Naur silo-1.4.14.orig/tilo/Makefile silo-1.4.14/tilo/Makefile --- silo-1.4.14.orig/tilo/Makefile 2008-06-12 09:39:12.000000000 -0700 +++ silo-1.4.14/tilo/Makefile 2009-01-07 15:07:57.000000000 -0800 @@ -14,10 +14,10 @@ all: maketilo .c.o: - $(CC) $(CFLAGS) -c $*.c + $(CC-SILO) $(CFLAGS) -c $*.c .S.o: - $(CC) $(CFLAGS) -c $*.S + $(CC-SILO) $(CFLAGS) -c $*.S OBJS_COMMON = ../common/printf.o ../common/jmp.o ../common/prom.o \ ../common/tree.o ../common/console.o ../common/stringops1.o \ @@ -45,19 +45,19 @@ mallocl.o: ../common/malloc.c - $(CC) $(CFLAGS) -DMALLOC_BASE=0x4D0000 -c -o $@ $< + $(CC-SILO) $(CFLAGS) -DMALLOC_BASE=0x4D0000 -c -o $@ $< malloc.o: ../common/malloc.c - $(CC) $(CFLAGS) -DMALLOC_BASE=0x3D0000 -c -o $@ $< + $(CC-SILO) $(CFLAGS) -DMALLOC_BASE=0x3D0000 -c -o $@ $< tilol.o: tilo.c - $(CC) $(CFLAGS) -DLARGETILO -c -o $@ $< + $(CC-SILO) $(CFLAGS) -DLARGETILO -c -o $@ $< crt0.o: crt0.S - $(CC) $(CFLAGS) -c -Wa,-Av9 -o $@ $< + $(CC-SILO) $(CFLAGS) -c -Wa,-Av9 -o $@ $< crt0l.o: crt0.S - $(CC) $(CFLAGS) -c -Wa,-Av9 -DLARGETILO -o $@ $< + $(CC-SILO) $(CFLAGS) -c -Wa,-Av9 -DLARGETILO -o $@ $< clean: $(RM) *.o boot boot2 *.out b.h b2.h maketilo