Submitted By: Joe Ciccone Date: 2007-04-05 Initial Package Version: 1.4.13 Upstream Status: Unknown Origin: Rocklinux and Jim Gifford and Joe Ciccone 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. diff -Naur silo-1.4.13.orig/common/Makefile silo-1.4.13/common/Makefile --- silo-1.4.13.orig/common/Makefile 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/common/Makefile 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/first/Makefile silo-1.4.13/first/Makefile --- silo-1.4.13.orig/first/Makefile 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/first/Makefile 2007-04-05 19:48:31.000000000 -0400 @@ -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 echo -n 'SILO'$(IMGVERSION) | $(DD) of=ultra.b bs=8 conv=notrunc seek=3 count=1 - echo -n -e '\340' | $(DD) of=ultra.b bs=1 count=1 seek=7 conv=notrunc + echo -n -e '\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 echo -n 'SILO'$(IMGVERSION) | $(DD) of=generic.b bs=8 conv=notrunc seek=3 count=1 - echo -n -e '\340' | $(DD) of=generic.b bs=1 count=1 seek=7 conv=notrunc + echo -n -e '\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 echo -n 'SILO'$(IMGVERSION) | $(DD) of=fd.b bs=8 conv=notrunc seek=3 count=1 - echo -n -e '\340' | $(DD) of=fd.b bs=1 count=1 seek=7 conv=notrunc + echo -n -e '\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.13.orig/first-isofs/Makefile silo-1.4.13/first-isofs/Makefile --- silo-1.4.13.orig/first-isofs/Makefile 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/first-isofs/Makefile 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/include/emul_32/asm/elf.h silo-1.4.13/include/emul_32/asm/elf.h --- silo-1.4.13.orig/include/emul_32/asm/elf.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/include/emul_32/asm/elf.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/include/emul_32/asm/posix_types.h silo-1.4.13/include/emul_32/asm/posix_types.h --- silo-1.4.13.orig/include/emul_32/asm/posix_types.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/include/emul_32/asm/posix_types.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/include/emul_32/asm/types.h silo-1.4.13/include/emul_32/asm/types.h --- silo-1.4.13.orig/include/emul_32/asm/types.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/include/emul_32/asm/types.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/include/ext2fs/ext2_err.h silo-1.4.13/include/ext2fs/ext2_err.h --- silo-1.4.13.orig/include/ext2fs/ext2_err.h 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/include/ext2fs/ext2_err.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/include/ext2fs/ext2_io.h silo-1.4.13/include/ext2fs/ext2_io.h --- silo-1.4.13.orig/include/ext2fs/ext2_io.h 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/include/ext2fs/ext2_io.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/alloc.c silo-1.4.13/libext2fs/alloc.c --- silo-1.4.13.orig/libext2fs/alloc.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/alloc.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/alloc_sb.c silo-1.4.13/libext2fs/alloc_sb.c --- silo-1.4.13.orig/libext2fs/alloc_sb.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/alloc_sb.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/alloc_stats.c silo-1.4.13/libext2fs/alloc_stats.c --- silo-1.4.13.orig/libext2fs/alloc_stats.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/alloc_stats.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/alloc_tables.c silo-1.4.13/libext2fs/alloc_tables.c --- silo-1.4.13.orig/libext2fs/alloc_tables.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/alloc_tables.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/badblocks.c silo-1.4.13/libext2fs/badblocks.c --- silo-1.4.13.orig/libext2fs/badblocks.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/badblocks.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/bb_compat.c silo-1.4.13/libext2fs/bb_compat.c --- silo-1.4.13.orig/libext2fs/bb_compat.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/bb_compat.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/bb_inode.c silo-1.4.13/libext2fs/bb_inode.c --- silo-1.4.13.orig/libext2fs/bb_inode.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/bb_inode.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/bitmaps.c silo-1.4.13/libext2fs/bitmaps.c --- silo-1.4.13.orig/libext2fs/bitmaps.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/bitmaps.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/bitops.c silo-1.4.13/libext2fs/bitops.c --- silo-1.4.13.orig/libext2fs/bitops.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/bitops.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/bitops.h silo-1.4.13/libext2fs/bitops.h --- silo-1.4.13.orig/libext2fs/bitops.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/bitops.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/block.c silo-1.4.13/libext2fs/block.c --- silo-1.4.13.orig/libext2fs/block.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/block.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/bmap.c silo-1.4.13/libext2fs/bmap.c --- silo-1.4.13.orig/libext2fs/bmap.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/bmap.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/bmove.c silo-1.4.13/libext2fs/bmove.c --- silo-1.4.13.orig/libext2fs/bmove.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/bmove.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/brel.h silo-1.4.13/libext2fs/brel.h --- silo-1.4.13.orig/libext2fs/brel.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/brel.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/brel_ma.c silo-1.4.13/libext2fs/brel_ma.c --- silo-1.4.13.orig/libext2fs/brel_ma.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/brel_ma.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/ChangeLog silo-1.4.13/libext2fs/ChangeLog --- silo-1.4.13.orig/libext2fs/ChangeLog 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/ChangeLog 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/check_desc.c silo-1.4.13/libext2fs/check_desc.c --- silo-1.4.13.orig/libext2fs/check_desc.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/check_desc.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/closefs.c silo-1.4.13/libext2fs/closefs.c --- silo-1.4.13.orig/libext2fs/closefs.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/closefs.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/cmp_bitmaps.c silo-1.4.13/libext2fs/cmp_bitmaps.c --- silo-1.4.13.orig/libext2fs/cmp_bitmaps.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/cmp_bitmaps.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/dblist.c silo-1.4.13/libext2fs/dblist.c --- silo-1.4.13.orig/libext2fs/dblist.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/dblist.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/dblist_dir.c silo-1.4.13/libext2fs/dblist_dir.c --- silo-1.4.13.orig/libext2fs/dblist_dir.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/dblist_dir.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/dirblock.c silo-1.4.13/libext2fs/dirblock.c --- silo-1.4.13.orig/libext2fs/dirblock.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/dirblock.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/dirhash.c silo-1.4.13/libext2fs/dirhash.c --- silo-1.4.13.orig/libext2fs/dirhash.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/dirhash.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/dir_iterate.c silo-1.4.13/libext2fs/dir_iterate.c --- silo-1.4.13.orig/libext2fs/dir_iterate.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/dir_iterate.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/dosio.c silo-1.4.13/libext2fs/dosio.c --- silo-1.4.13.orig/libext2fs/dosio.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/dosio.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/dosio.h silo-1.4.13/libext2fs/dosio.h --- silo-1.4.13.orig/libext2fs/dosio.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/dosio.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/dupfs.c silo-1.4.13/libext2fs/dupfs.c --- silo-1.4.13.orig/libext2fs/dupfs.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/dupfs.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/e2image.h silo-1.4.13/libext2fs/e2image.h --- silo-1.4.13.orig/libext2fs/e2image.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/e2image.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/expanddir.c silo-1.4.13/libext2fs/expanddir.c --- silo-1.4.13.orig/libext2fs/expanddir.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/expanddir.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/ext2_err.c silo-1.4.13/libext2fs/ext2_err.c --- silo-1.4.13.orig/libext2fs/ext2_err.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/ext2_err.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/ext2_ext_attr.h silo-1.4.13/libext2fs/ext2_ext_attr.h --- silo-1.4.13.orig/libext2fs/ext2_ext_attr.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/ext2_ext_attr.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/ext2_fs.h silo-1.4.13/libext2fs/ext2_fs.h --- silo-1.4.13.orig/libext2fs/ext2_fs.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/ext2_fs.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/ext2fs.h silo-1.4.13/libext2fs/ext2fs.h --- silo-1.4.13.orig/libext2fs/ext2fs.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/ext2fs.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/ext2fsP.h silo-1.4.13/libext2fs/ext2fsP.h --- silo-1.4.13.orig/libext2fs/ext2fsP.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/ext2fsP.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/ext2_io.h silo-1.4.13/libext2fs/ext2_io.h --- silo-1.4.13.orig/libext2fs/ext2_io.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/ext2_io.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/ext_attr.c silo-1.4.13/libext2fs/ext_attr.c --- silo-1.4.13.orig/libext2fs/ext_attr.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/ext_attr.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/fileio.c silo-1.4.13/libext2fs/fileio.c --- silo-1.4.13.orig/libext2fs/fileio.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/fileio.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/finddev.c silo-1.4.13/libext2fs/finddev.c --- silo-1.4.13.orig/libext2fs/finddev.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/finddev.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/flushb.c silo-1.4.13/libext2fs/flushb.c --- silo-1.4.13.orig/libext2fs/flushb.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/flushb.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/freefs.c silo-1.4.13/libext2fs/freefs.c --- silo-1.4.13.orig/libext2fs/freefs.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/freefs.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/gen_bitmap.c silo-1.4.13/libext2fs/gen_bitmap.c --- silo-1.4.13.orig/libext2fs/gen_bitmap.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/gen_bitmap.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/get_pathname.c silo-1.4.13/libext2fs/get_pathname.c --- silo-1.4.13.orig/libext2fs/get_pathname.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/get_pathname.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/getsectsize.c silo-1.4.13/libext2fs/getsectsize.c --- silo-1.4.13.orig/libext2fs/getsectsize.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/getsectsize.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/getsize.c silo-1.4.13/libext2fs/getsize.c --- silo-1.4.13.orig/libext2fs/getsize.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/getsize.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/icount.c silo-1.4.13/libext2fs/icount.c --- silo-1.4.13.orig/libext2fs/icount.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/icount.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/imager.c silo-1.4.13/libext2fs/imager.c --- silo-1.4.13.orig/libext2fs/imager.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/imager.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/ind_block.c silo-1.4.13/libext2fs/ind_block.c --- silo-1.4.13.orig/libext2fs/ind_block.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/ind_block.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/initialize.c silo-1.4.13/libext2fs/initialize.c --- silo-1.4.13.orig/libext2fs/initialize.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/initialize.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/inline.c silo-1.4.13/libext2fs/inline.c --- silo-1.4.13.orig/libext2fs/inline.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/inline.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/inode.c silo-1.4.13/libext2fs/inode.c --- silo-1.4.13.orig/libext2fs/inode.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/inode.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/inode_io.c silo-1.4.13/libext2fs/inode_io.c --- silo-1.4.13.orig/libext2fs/inode_io.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/inode_io.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/io_manager.c silo-1.4.13/libext2fs/io_manager.c --- silo-1.4.13.orig/libext2fs/io_manager.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/io_manager.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/irel.h silo-1.4.13/libext2fs/irel.h --- silo-1.4.13.orig/libext2fs/irel.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/irel.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/irel_ma.c silo-1.4.13/libext2fs/irel_ma.c --- silo-1.4.13.orig/libext2fs/irel_ma.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/irel_ma.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/ismounted.c silo-1.4.13/libext2fs/ismounted.c --- silo-1.4.13.orig/libext2fs/ismounted.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/ismounted.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/jfs_compat.h silo-1.4.13/libext2fs/jfs_compat.h --- silo-1.4.13.orig/libext2fs/jfs_compat.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/jfs_compat.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/jfs_dat.h silo-1.4.13/libext2fs/jfs_dat.h --- silo-1.4.13.orig/libext2fs/jfs_dat.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/jfs_dat.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/jfs_user.h silo-1.4.13/libext2fs/jfs_user.h --- silo-1.4.13.orig/libext2fs/jfs_user.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/jfs_user.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/kernel-jbd.h silo-1.4.13/libext2fs/kernel-jbd.h --- silo-1.4.13.orig/libext2fs/kernel-jbd.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/kernel-jbd.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/kernel-list.h silo-1.4.13/libext2fs/kernel-list.h --- silo-1.4.13.orig/libext2fs/kernel-list.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/kernel-list.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/link.c silo-1.4.13/libext2fs/link.c --- silo-1.4.13.orig/libext2fs/link.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/link.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/llseek.c silo-1.4.13/libext2fs/llseek.c --- silo-1.4.13.orig/libext2fs/llseek.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/llseek.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/lookup.c silo-1.4.13/libext2fs/lookup.c --- silo-1.4.13.orig/libext2fs/lookup.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/lookup.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/Makefile silo-1.4.13/libext2fs/Makefile --- silo-1.4.13.orig/libext2fs/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/Makefile 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/mkdir.c silo-1.4.13/libext2fs/mkdir.c --- silo-1.4.13.orig/libext2fs/mkdir.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/mkdir.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/mkjournal.c silo-1.4.13/libext2fs/mkjournal.c --- silo-1.4.13.orig/libext2fs/mkjournal.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/mkjournal.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/namei.c silo-1.4.13/libext2fs/namei.c --- silo-1.4.13.orig/libext2fs/namei.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/namei.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/native.c silo-1.4.13/libext2fs/native.c --- silo-1.4.13.orig/libext2fs/native.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/native.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/newdir.c silo-1.4.13/libext2fs/newdir.c --- silo-1.4.13.orig/libext2fs/newdir.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/newdir.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/nt_io.c silo-1.4.13/libext2fs/nt_io.c --- silo-1.4.13.orig/libext2fs/nt_io.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/nt_io.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/openfs.c silo-1.4.13/libext2fs/openfs.c --- silo-1.4.13.orig/libext2fs/openfs.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/openfs.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/read_bb.c silo-1.4.13/libext2fs/read_bb.c --- silo-1.4.13.orig/libext2fs/read_bb.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/read_bb.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/read_bb_file.c silo-1.4.13/libext2fs/read_bb_file.c --- silo-1.4.13.orig/libext2fs/read_bb_file.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/read_bb_file.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/res_gdt.c silo-1.4.13/libext2fs/res_gdt.c --- silo-1.4.13.orig/libext2fs/res_gdt.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/res_gdt.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/rs_bitmap.c silo-1.4.13/libext2fs/rs_bitmap.c --- silo-1.4.13.orig/libext2fs/rs_bitmap.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/rs_bitmap.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/rw_bitmaps.c silo-1.4.13/libext2fs/rw_bitmaps.c --- silo-1.4.13.orig/libext2fs/rw_bitmaps.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/rw_bitmaps.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/sparse.c silo-1.4.13/libext2fs/sparse.c --- silo-1.4.13.orig/libext2fs/sparse.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/sparse.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/swapfs.c silo-1.4.13/libext2fs/swapfs.c --- silo-1.4.13.orig/libext2fs/swapfs.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/swapfs.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/test_io.c silo-1.4.13/libext2fs/test_io.c --- silo-1.4.13.orig/libext2fs/test_io.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/test_io.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/tst_badblocks.c silo-1.4.13/libext2fs/tst_badblocks.c --- silo-1.4.13.orig/libext2fs/tst_badblocks.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/tst_badblocks.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/tst_bitops.c silo-1.4.13/libext2fs/tst_bitops.c --- silo-1.4.13.orig/libext2fs/tst_bitops.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/tst_bitops.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/tst_byteswap.c silo-1.4.13/libext2fs/tst_byteswap.c --- silo-1.4.13.orig/libext2fs/tst_byteswap.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/tst_byteswap.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/tst_getsectsize.c silo-1.4.13/libext2fs/tst_getsectsize.c --- silo-1.4.13.orig/libext2fs/tst_getsectsize.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/tst_getsectsize.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/tst_getsize.c silo-1.4.13/libext2fs/tst_getsize.c --- silo-1.4.13.orig/libext2fs/tst_getsize.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/tst_getsize.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/tst_iscan.c silo-1.4.13/libext2fs/tst_iscan.c --- silo-1.4.13.orig/libext2fs/tst_iscan.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/tst_iscan.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/unix_io.c silo-1.4.13/libext2fs/unix_io.c --- silo-1.4.13.orig/libext2fs/unix_io.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/unix_io.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/unlink.c silo-1.4.13/libext2fs/unlink.c --- silo-1.4.13.orig/libext2fs/unlink.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/unlink.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/valid_blk.c silo-1.4.13/libext2fs/valid_blk.c --- silo-1.4.13.orig/libext2fs/valid_blk.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/valid_blk.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/version.c silo-1.4.13/libext2fs/version.c --- silo-1.4.13.orig/libext2fs/version.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/version.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/version.h silo-1.4.13/libext2fs/version.h --- silo-1.4.13.orig/libext2fs/version.h 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/version.h 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/libext2fs/write_bb_file.c silo-1.4.13/libext2fs/write_bb_file.c --- silo-1.4.13.orig/libext2fs/write_bb_file.c 1969-12-31 19:00:00.000000000 -0500 +++ silo-1.4.13/libext2fs/write_bb_file.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/Makefile silo-1.4.13/Makefile --- silo-1.4.13.orig/Makefile 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/Makefile 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/Rules.make silo-1.4.13/Rules.make --- silo-1.4.13.orig/Rules.make 2006-06-21 03:51:03.000000000 -0400 +++ silo-1.4.13/Rules.make 2007-04-03 17:02:53.000000000 -0400 @@ -1,12 +1,14 @@ VERSION=1.4.13 IMGVERSION=0.99 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.13.orig/second/fs/ufs.c silo-1.4.13/second/fs/ufs.c --- silo-1.4.13.orig/second/fs/ufs.c 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/second/fs/ufs.c 2007-04-03 17:02:53.000000000 -0400 @@ -40,28 +40,18 @@ ino_t inode = 0; -#ifdef UFS_CIGAM -/* Apparently new header */ - #define ufsi_size(x) ((unsigned int)((x)->ui_size)) #define ufsi_db(x) ((unsigned int *)((x)->ui_u2.ui_addr.ui_db)) #define ufsi_ib(x) ((unsigned int *)((x)->ui_u2.ui_addr.ui_ib)) #define ufsd_namlen(x) ((unsigned char)((x)->d_u.d_44.d_namlen)) -#ifdef UFS_MINFREE -/* Apparently even newer header */ -#define ufs_superblock ufs_super_block +struct ufs_superblock_full { + struct ufs_super_block_first first; + struct ufs_super_block_second second; + struct ufs_super_block_third third; +}; +#define ufs_superblock ufs_super_block_first #define ufs_direct ufs_dir_entry -#endif - -#else - -#define ufsi_size(x) (((x)->ui_size.val[1])) -#define ufsi_db(x) ((unsigned int *)((x)->ui_db)) -#define ufsi_ib(x) ((unsigned int *)((x)->ui_ib)) -#define ufsd_namlen(x) ((unsigned char)((x)->d_namlen)) - -#endif #ifndef S_ISLNK #include @@ -92,25 +82,22 @@ return p; } -static struct ufs_superblock *ufs_read_super(ufs_filsys fs) +static struct ufs_superblock_full *ufs_read_super(ufs_filsys fs) { - struct ufs_superblock *usb; + struct ufs_superblock_full *usb; - usb = (struct ufs_superblock *) malloc (2048); + usb = (struct ufs_superblock_full *) malloc (2048); if (!usb) return 0; if (io_channel_read_blk (fs->io, UFS_SBLOCK/1024, -2048, (char *)usb)) return 0; - if (usb->fs_magic != UFS_MAGIC) { - /* XXX - replace hard-coded constant with a byte-swap macro */ - if (usb->fs_magic == 0x54190100) { - } + if (usb->third.fs_magic != UFS_MAGIC) { return 0; } - if (usb->fs_bsize != UFS_BSIZE) + if (usb->first.fs_bsize != UFS_BSIZE) return 0; - if (usb->fs_fsize != UFS_FSIZE) + if (usb->first.fs_fsize != UFS_FSIZE) return 0; - io_channel_set_blksize (fs->io, usb->fs_fsize); + io_channel_set_blksize (fs->io, usb->first.fs_fsize); return usb; } diff -Naur silo-1.4.13.orig/second/ls.c silo-1.4.13/second/ls.c --- silo-1.4.13.orig/second/ls.c 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/second/ls.c 2007-04-03 17:02:53.000000000 -0400 @@ -19,10 +19,10 @@ USA. */ #include +#include #include typedef int FILE; -#include #include #include diff -Naur silo-1.4.13.orig/second/Makefile silo-1.4.13/second/Makefile --- silo-1.4.13.orig/second/Makefile 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/second/Makefile 2007-04-05 19:48:45.000000000 -0400 @@ -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.13.orig/silo/silo.c silo-1.4.13/silo/silo.c --- silo-1.4.13.orig/silo/silo.c 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/silo/silo.c 2007-04-03 17:02:53.000000000 -0400 @@ -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.13.orig/silo/silocheck.c silo-1.4.13/silo/silocheck.c --- silo-1.4.13.orig/silo/silocheck.c 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/silo/silocheck.c 2007-04-03 17:02:53.000000000 -0400 @@ -100,8 +100,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.13.orig/tilo/Makefile silo-1.4.13/tilo/Makefile --- silo-1.4.13.orig/tilo/Makefile 2006-06-01 13:24:53.000000000 -0400 +++ silo-1.4.13/tilo/Makefile 2007-04-03 17:02:53.000000000 -0400 @@ -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