From 73193347133e750faf27f88fd3ab31ce43aff062 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 21 May 2024 06:59:33 +0200 Subject: Adding upstream version 1.47.1. Signed-off-by: Daniel Baumann --- lib/ext2fs/Android.bp | 1 + lib/ext2fs/Makefile.in | 81 ++++++++++++++++++++++++---------- lib/ext2fs/alloc_sb.c | 28 +++++++++++- lib/ext2fs/bb_inode.c | 14 +++--- lib/ext2fs/closefs.c | 2 +- lib/ext2fs/e2image.h | 5 ++- lib/ext2fs/ext2_fs.h | 6 +-- lib/ext2fs/ext2_io.h | 4 +- lib/ext2fs/ext2fs.h | 110 +++++++++++++++++++++++++++++++++++++++++++++- lib/ext2fs/ext2fsP.h | 7 +++ lib/ext2fs/ext_attr.c | 4 +- lib/ext2fs/gen_bitmap64.c | 19 ++++++-- lib/ext2fs/getenv.c | 57 ++++++++++++++++++++++++ lib/ext2fs/getsize.c | 31 +++++-------- lib/ext2fs/hashmap.c | 4 +- lib/ext2fs/imager.c | 4 +- lib/ext2fs/initialize.c | 63 ++++++++++++++++---------- lib/ext2fs/inode.c | 18 ++++---- lib/ext2fs/ismounted.c | 10 ++--- lib/ext2fs/llseek.c | 67 +++++++--------------------- lib/ext2fs/mkjournal.c | 8 ++-- lib/ext2fs/openfs.c | 21 ++++++--- lib/ext2fs/orphan.c | 28 ++++++------ lib/ext2fs/progress.c | 2 +- lib/ext2fs/qcow2.c | 30 +++++++++---- lib/ext2fs/qcow2.h | 2 + lib/ext2fs/rbtree.h | 2 +- lib/ext2fs/res_gdt.c | 43 +++++++++++------- lib/ext2fs/rw_bitmaps.c | 2 +- lib/ext2fs/swapfs.c | 16 +++---- lib/ext2fs/test_io.c | 43 +++--------------- lib/ext2fs/tst_bitmaps.c | 45 ++++++++++++------- lib/ext2fs/undo_io.c | 2 +- lib/ext2fs/unix_io.c | 74 ++++++++++++------------------- lib/ext2fs/windows_io.c | 29 ++++++------ 35 files changed, 549 insertions(+), 333 deletions(-) create mode 100644 lib/ext2fs/getenv.c (limited to 'lib/ext2fs') diff --git a/lib/ext2fs/Android.bp b/lib/ext2fs/Android.bp index db8b3b7..af4c2db 100644 --- a/lib/ext2fs/Android.bp +++ b/lib/ext2fs/Android.bp @@ -19,6 +19,7 @@ cc_library { host_supported: true, ramdisk_available: true, vendor_ramdisk_available: true, + vendor_available: true, recovery_available: true, unique_host_soname: true, defaults: ["e2fsprogs-defaults"], diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in index 798ff60..1b3a91b 100644 --- a/lib/ext2fs/Makefile.in +++ b/lib/ext2fs/Makefile.in @@ -24,8 +24,8 @@ COMPILE_ET= _ET_DIR_OVERRIDE=$(srcdir)/../et ../et/compile_et DEBUG_OBJS= debug_cmds.o extent_cmds.o tst_cmds.o debugfs.o util.o \ ncheck.o icheck.o ls.o lsdel.o dump.o set_fields.o logdump.o \ htree.o unused.o e2freefrag.o filefrag.o extent_inode.o zap.o \ - xattrs.o quota.o tst_libext2fs.o create_inode.o journal.o \ - revoke.o recovery.o do_journal.o + xattrs.o quota.o tst_libext2fs.o create_inode.o \ + create_inode_libarchive.o journal.o revoke.o recovery.o do_journal.o DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \ $(top_srcdir)/debugfs/debugfs.c \ @@ -46,6 +46,7 @@ DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \ $(top_srcdir)/debugfs/xattrs.c \ $(top_srcdir)/misc/e2freefrag.c \ $(top_srcdir)/misc/create_inode.c \ + $(top_srcdir)/misc/create_inode_libarchive.c \ $(top_srcdir)/debugfs/journal.c \ $(top_srcdir)/e2fsck/revoke.c \ $(top_srcdir)/e2fsck/recovery.c \ @@ -92,6 +93,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \ gen_bitmap64.o \ get_num_dirs.o \ get_pathname.o \ + getenv.o \ getsize.o \ getsectsize.o \ hashmap.o \ @@ -174,6 +176,7 @@ SRCS= ext2_err.c \ $(srcdir)/gen_bitmap64.c \ $(srcdir)/get_num_dirs.c \ $(srcdir)/get_pathname.c \ + $(srcdir)/getenv.c \ $(srcdir)/getsize.c \ $(srcdir)/getsectsize.c \ $(srcdir)/hashmap.c \ @@ -458,7 +461,13 @@ e2freefrag.o: $(top_srcdir)/misc/e2freefrag.c $(E) " CC $<" $(Q) $(CC) $(ALL_CFLAGS) -DDEBUGFS -I$(top_srcdir)/debugfs -c $< -o $@ -create_inode.o: $(top_srcdir)/misc/create_inode.c +create_inode.o: $(top_srcdir)/misc/create_inode.c \ + $(top_srcdir)/misc/create_inode_libarchive.c + $(E) " CC $<" + $(Q) $(CC) $(ALL_CFLAGS) -DDEBUGFS -c $< -o $@ + +create_inode_libarchive.o: $(top_srcdir)/misc/create_inode_libarchive.c \ + $(top_srcdir)/misc/create_inode_libarchive.c $(E) " CC $<" $(Q) $(CC) $(ALL_CFLAGS) -DDEBUGFS -c $< -o $@ @@ -499,7 +508,7 @@ tst_libext2fs: $(DEBUG_OBJS) \ $(Q) $(CC) -o tst_libext2fs $(ALL_LDFLAGS) -DDEBUG $(DEBUG_OBJS) \ $(STATIC_LIBSS) $(STATIC_LIBE2P) $(LIBSUPPORT) \ $(STATIC_LIBEXT2FS) $(LIBBLKID) $(LIBUUID) $(LIBMAGIC) \ - $(STATIC_LIBCOM_ERR) $(SYSLIBS) -I $(top_srcdir)/debugfs + $(STATIC_LIBCOM_ERR) $(SYSLIBS) $(LIBARCHIVE) -I $(top_srcdir)/debugfs tst_inline: $(srcdir)/inline.c $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR) $(E) " LD $@" @@ -699,10 +708,11 @@ bb_compat.o: $(srcdir)/bb_compat.c $(top_builddir)/lib/config.h \ $(srcdir)/hashmap.h $(srcdir)/bitops.h bb_inode.o: $(srcdir)/bb_inode.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ - $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ - $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ - $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ - $(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h + $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \ + $(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \ + $(srcdir)/hashmap.h $(srcdir)/bitops.h bitmaps.o: $(srcdir)/bitmaps.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ @@ -831,10 +841,10 @@ expanddir.o: $(srcdir)/expanddir.c $(top_builddir)/lib/config.h \ ext_attr.o: $(srcdir)/ext_attr.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2_ext_attr.h \ - $(srcdir)/ext4_acl.h $(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h \ - $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ - $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \ - $(srcdir)/hashmap.h $(srcdir)/bitops.h + $(srcdir)/ext4_acl.h $(srcdir)/ext2fsP.h $(srcdir)/ext2fs.h \ + $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h extent.o: $(srcdir)/extent.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \ @@ -896,6 +906,12 @@ get_pathname.o: $(srcdir)/get_pathname.c $(top_builddir)/lib/config.h \ $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ $(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h +getenv.o: $(srcdir)/getenv.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2_fs.h \ + $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \ + $(srcdir)/hashmap.h $(srcdir)/bitops.h getsize.o: $(srcdir)/getsize.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ @@ -930,10 +946,11 @@ ind_block.o: $(srcdir)/ind_block.c $(top_builddir)/lib/config.h \ $(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h initialize.o: $(srcdir)/initialize.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ - $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ - $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ - $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ - $(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h + $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \ + $(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \ + $(srcdir)/hashmap.h $(srcdir)/bitops.h inline.o: $(srcdir)/inline.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ @@ -1005,8 +1022,8 @@ mkdir.o: $(srcdir)/mkdir.c $(top_builddir)/lib/config.h \ mkjournal.o: $(srcdir)/mkjournal.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/e2p/e2p.h \ - $(srcdir)/ext2_fs.h $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h \ - $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ + $(srcdir)/ext2_fs.h $(srcdir)/ext2fsP.h $(srcdir)/ext2fs.h \ + $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \ $(srcdir)/hashmap.h $(srcdir)/bitops.h $(srcdir)/kernel-jbd.h \ $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h $(srcdir)/compiler.h @@ -1049,6 +1066,13 @@ openfs.o: $(srcdir)/openfs.c $(top_builddir)/lib/config.h \ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ $(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h \ $(srcdir)/e2image.h +orphan.o: $(srcdir)/orphan.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \ + $(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \ + $(srcdir)/hashmap.h $(srcdir)/bitops.h progress.o: $(srcdir)/progress.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2_fs.h \ @@ -1082,10 +1106,11 @@ read_bb_file.o: $(srcdir)/read_bb_file.c $(top_builddir)/lib/config.h \ $(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h res_gdt.o: $(srcdir)/res_gdt.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ - $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ - $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ - $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ - $(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h + $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fsP.h \ + $(srcdir)/ext2fs.h $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \ + $(srcdir)/hashmap.h $(srcdir)/bitops.h rw_bitmaps.o: $(srcdir)/rw_bitmaps.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ @@ -1419,7 +1444,17 @@ create_inode.o: $(top_srcdir)/misc/create_inode.c \ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ $(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h \ $(srcdir)/fiemap.h $(top_srcdir)/misc/create_inode.h \ - $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/support/nls-enable.h + $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/support/nls-enable.h \ + $(top_srcdir)/misc/create_inode_libarchive.h +create_inode_libarchive.o: $(top_srcdir)/misc/create_inode_libarchive.c \ + $(top_builddir)/lib/config.h $(top_builddir)/lib/dirpaths.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/misc/create_inode.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/e2p/e2p.h \ + $(srcdir)/ext2_fs.h $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h \ + $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h \ + $(top_srcdir)/misc/create_inode_libarchive.h \ + $(top_srcdir)/lib/support/nls-enable.h journal.o: $(top_srcdir)/debugfs/journal.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/debugfs/journal.h \ $(srcdir)/../../e2fsck/jfs_user.h $(srcdir)/ext2_fs.h \ diff --git a/lib/ext2fs/alloc_sb.c b/lib/ext2fs/alloc_sb.c index 8530b40..e92739e 100644 --- a/lib/ext2fs/alloc_sb.c +++ b/lib/ext2fs/alloc_sb.c @@ -46,8 +46,7 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs, ext2fs_block_bitmap bmap) { blk64_t super_blk, old_desc_blk, new_desc_blk; - blk_t used_blks; - int old_desc_blocks, num_blocks; + blk_t used_blks, old_desc_blocks, num_blocks; ext2fs_super_and_bgd_loc2(fs, group, &super_blk, &old_desc_blk, &new_desc_blk, &used_blks); @@ -79,3 +78,28 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs, return num_blocks ; } + +/* + * This function reserves the superblock and block group descriptors + * for a given block group and returns the number of blocks used by the + * super block and group descriptors by looking up the block bitmap. + */ +errcode_t ext2fs_reserve_super_and_bgd2(ext2_filsys fs, + dgrp_t group, + ext2fs_block_bitmap bmap, + blk_t *desc_blocks) +{ + blk64_t num_blocks; + errcode_t retval = 0; + + ext2fs_reserve_super_and_bgd(fs, group, bmap); + + retval = ext2fs_count_used_blocks(fs, + ext2fs_group_first_block2(fs, group), + ext2fs_group_last_block2(fs, group), + &num_blocks); + if (!retval) + *desc_blocks = num_blocks; + + return retval; +} diff --git a/lib/ext2fs/bb_inode.c b/lib/ext2fs/bb_inode.c index 11f10eb..8b29e1c 100644 --- a/lib/ext2fs/bb_inode.c +++ b/lib/ext2fs/bb_inode.c @@ -20,7 +20,6 @@ #include #endif #include -#include #if HAVE_SYS_STAT_H #include #endif @@ -29,7 +28,7 @@ #endif #include "ext2_fs.h" -#include "ext2fs.h" +#include "ext2fsP.h" struct set_badblock_record { ext2_badblocks_iterate bb_iter; @@ -58,8 +57,9 @@ static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list) { errcode_t retval; - struct set_badblock_record rec; + struct set_badblock_record rec; struct ext2_inode inode; + time_t now; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -124,9 +124,11 @@ errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list) if (retval) goto cleanup; - inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0); - if (!inode.i_ctime) - inode.i_ctime = fs->now ? fs->now : time(0); + now = ext2fsP_get_time(fs); + ext2fs_inode_xtime_set(&inode, i_atime, now); + if (!ext2fs_inode_xtime_get(&inode, i_ctime)) + ext2fs_inode_xtime_set(&inode, i_ctime, now); + ext2fs_inode_xtime_set(&inode, i_mtime, now); ext2fs_iblk_set(fs, &inode, rec.bad_block_count); retval = ext2fs_inode_size_set(fs, &inode, rec.bad_block_count * fs->blocksize); diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c index 69cbdd8..8e5bec0 100644 --- a/lib/ext2fs/closefs.c +++ b/lib/ext2fs/closefs.c @@ -301,7 +301,7 @@ errcode_t ext2fs_flush2(ext2_filsys fs, int flags) fs_state = fs->super->s_state; feature_incompat = fs->super->s_feature_incompat; - fs->super->s_wtime = fs->now ? fs->now : time(NULL); + ext2fs_set_tstamp(fs->super, s_wtime, ext2fsP_get_time(fs)); fs->super->s_block_group_nr = 0; /* diff --git a/lib/ext2fs/e2image.h b/lib/ext2fs/e2image.h index 53b20cc..143e0dc 100644 --- a/lib/ext2fs/e2image.h +++ b/lib/ext2fs/e2image.h @@ -26,8 +26,9 @@ struct ext2_image_hdr { __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 image_time_lo; /* Time of image creation */ + __u32 image_time_hi; /* High bits of image test creation */ + __u32 image_reserved[7]; __u32 offset_super; /* Byte offset of the sb and descriptors */ __u32 offset_inode; /* Byte offset of the inode table */ diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index 0fc9c09..586141f 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -512,9 +512,9 @@ struct ext2_inode_large { #define i_checksum_lo osd2.linux2.l_i_checksum_lo -#define inode_includes(size, field) \ - (size >= (sizeof(((struct ext2_inode_large *)0)->field) + \ - offsetof(struct ext2_inode_large, field))) +#define ext2fs_inode_includes(size, field) \ + ((size) >= (sizeof(((struct ext2_inode_large *)0)->field) + \ + offsetof(struct ext2_inode_large, field))) #if defined(__KERNEL__) || defined(__linux__) #define i_reserved1 osd1.linux1.l_i_reserved1 diff --git a/lib/ext2fs/ext2_io.h b/lib/ext2fs/ext2_io.h index 679184e..27eaaf1 100644 --- a/lib/ext2fs/ext2_io.h +++ b/lib/ext2fs/ext2_io.h @@ -34,6 +34,8 @@ typedef struct struct_io_stats *io_stats; #define CHANNEL_FLAGS_DISCARD_ZEROES 0x02 #define CHANNEL_FLAGS_BLOCK_DEVICE 0x04 #define CHANNEL_FLAGS_THREADS 0x08 +#define CHANNEL_FLAGS_NODISCARD 0x10 +#define CHANNEL_FLAGS_NOZEROOUT 0x20 #define io_channel_discard_zeroes_data(i) (i->flags & CHANNEL_FLAGS_DISCARD_ZEROES) @@ -57,7 +59,7 @@ struct struct_io_channel { int actual_bytes_written, errcode_t error); int refcount; - int flags; + unsigned int flags; long reserved[14]; void *private_data; void *app_data; diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 72c60d2..6e87829 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -221,6 +221,11 @@ typedef struct ext2_file *ext2_file_t; #define EXT2_FLAG_THREADS 0x4000000 #define EXT2_FLAG_IGNORE_SWAP_DIRENT 0x8000000 +/* + * Internal flags for use by the ext2fs library only + */ +#define EXT2_FLAG2_USE_FAKE_TIME 0x000000001 + /* * 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.) @@ -275,10 +280,11 @@ struct struct_ext2_filsys { int cluster_ratio_bits; __u16 default_bitmap_type; __u16 pad; + __u32 flags2; /* * Reserved for future expansion */ - __u32 reserved[5]; + __u32 reserved[4]; /* * Reserved for the use of the calling application. @@ -579,6 +585,73 @@ typedef struct ext2_struct_inode_scan *ext2_inode_scan; */ #define EXT2_I_SIZE(i) ((i)->i_size | ((__u64) (i)->i_size_high << 32)) +static inline __u32 __encode_extra_time(time_t seconds, __u32 nsec) +{ + __u32 extra = 0; + +#if (SIZEOF_TIME_T > 4) + extra = ((seconds - (__s32)(seconds & 0xffffffff)) >> 32) & + EXT4_EPOCH_MASK; +#endif + return extra | (nsec << EXT4_EPOCH_BITS); +} +static inline time_t __decode_extra_sec(time_t seconds, __u32 extra) +{ +#if (SIZEOF_TIME_T > 4) + if (extra & EXT4_EPOCH_MASK) + seconds += ((time_t)(extra & EXT4_EPOCH_MASK) << 32); +#endif + return seconds; +} +static inline __u32 __decode_extra_nsec(__u32 extra) +{ + return (extra & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS; +} +#define ext2fs_inode_actual_size(inode) \ + ((size_t)(EXT2_GOOD_OLD_INODE_SIZE + \ + (sizeof(*inode) > EXT2_GOOD_OLD_INODE_SIZE ? \ + ((struct ext2_inode_large *)(inode))->i_extra_isize : 0))) +#define clamp(val, min, max) ((val) < (min) ? (min) : ((val) > (max) ? \ + (max) : (val))) +#define ext2fs_inode_xtime_set(inode, field, sec) \ +do { \ + if (ext2fs_inode_includes(ext2fs_inode_actual_size(inode), \ + field ## _extra)) { \ + (inode)->field = (__s32)(sec & 0xfffffff); \ + ((struct ext2_inode_large *)(inode))->field ## _extra = \ + __encode_extra_time(sec, 0); \ + } else { \ + (inode)->field = clamp(sec, INT32_MIN, INT32_MAX); \ + } \ +} while (0) +#define ext2fs_inode_xtime_get(inode, field) \ +(ext2fs_inode_includes(ext2fs_inode_actual_size(inode), field ## _extra) ? \ + __decode_extra_sec((inode)->field, \ + ((struct ext2_inode_large *)(inode))->field ## _extra) : \ + (time_t)(inode)->field) + +static inline void __sb_set_tstamp(__u32 *lo, __u8 *hi, time_t seconds) +{ + *lo = seconds & 0xffffffff; +#if (SIZEOF_TIME_T > 4) + *hi = (seconds >> 32) & EXT4_EPOCH_MASK; +#else + *hi = 0; +#endif +} +static inline time_t __sb_get_tstamp(__u32 *lo, __u8 *hi) +{ +#if (SIZEOF_TIME_T == 4) + return *lo; +#else + return ((time_t)(*hi) << 32) | *lo; +#endif +} +#define ext2fs_set_tstamp(sb, field, seconds) \ + __sb_set_tstamp(&(sb)->field, &(sb)->field ## _hi, seconds) +#define ext2fs_get_tstamp(sb, field) \ + __sb_get_tstamp(&(sb)->field, &(sb)->field ## _hi) + /* * ext2_icount_t abstraction */ @@ -795,6 +868,10 @@ errcode_t ext2fs_alloc_range(ext2_filsys fs, int flags, blk64_t goal, extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs, dgrp_t group, ext2fs_block_bitmap bmap); +extern errcode_t ext2fs_reserve_super_and_bgd2(ext2_filsys fs, + dgrp_t group, + ext2fs_block_bitmap bmap, + blk_t *desc_blocks); extern void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs, void (*func)(ext2_filsys fs, blk64_t blk, @@ -1483,6 +1560,13 @@ errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs, ext2fs_block_bitmap *bitmap); errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start, blk64_t end, blk64_t *out); +errcode_t ext2fs_count_used_blocks(ext2_filsys fs, blk64_t start, + blk64_t end, blk64_t *out); +extern unsigned int ext2fs_list_backups(ext2_filsys fs, unsigned int *three, + unsigned int *five, unsigned int *seven); + +/* getenv.c */ +extern char *ext2fs_safe_getenv(const char *arg); /* get_num_dirs.c */ extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs); @@ -2217,6 +2301,30 @@ static inline unsigned int ext2_dir_htree_level(ext2_filsys fs) return EXT4_HTREE_LEVEL_COMPAT; } +/* + * We explicitly decided not to reserve space for a 64-bit dtime, + * since it's never displayed or exposed to userspace. The dtime + * field is used a linked list for the ophan list, and for forensic + * purposes when trying to determine when an inode was deleted. So + * right after the 2038 epoch, a deleted inode might end up with a + * dtime which is zero or smaller than the number of inodes, which + * will result in e2fsck reporting a potential problems. So when we + * set the dtime, make sure that the dtime won't be mistaken for an + * inode number. + */ +static inline void ext2fs_set_dtime(ext2_filsys fs, struct ext2_inode *inode) +{ + __u32 t; + + if (fs->now || (fs->flags2 & EXT2_FLAG2_USE_FAKE_TIME)) + t = fs->now & 0xFFFFFFFF; + else + t = time(NULL) & 0xFFFFFFFF; + if (t < fs->super->s_inodes_count) + t = fs->super->s_inodes_count; + inode->i_dtime = t; +} + #ifdef __cplusplus } #endif diff --git a/lib/ext2fs/ext2fsP.h b/lib/ext2fs/ext2fsP.h index 0687384..d1f2105 100644 --- a/lib/ext2fs/ext2fsP.h +++ b/lib/ext2fs/ext2fsP.h @@ -26,6 +26,13 @@ static inline int ext2fsP_is_disk_device(mode_t mode) #endif } +static inline time_t ext2fsP_get_time(ext2_filsys fs) +{ + if (fs->now || (fs->flags2 & EXT2_FLAG2_USE_FAKE_TIME)) + return fs->now; + return time(NULL); +} + /* * Badblocks list */ diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c index 3494046..1b5f90d 100644 --- a/lib/ext2fs/ext_attr.c +++ b/lib/ext2fs/ext_attr.c @@ -23,7 +23,7 @@ #include "ext2_ext_attr.h" #include "ext4_acl.h" -#include "ext2fs.h" +#include "ext2fsP.h" static errcode_t read_ea_inode_hash(ext2_filsys fs, ext2_ino_t ino, __u32 *hash) { @@ -1342,7 +1342,7 @@ static errcode_t xattr_inode_dec_ref(ext2_filsys fs, ext2_ino_t ino) goto write_out; inode.i_links_count = 0; - inode.i_dtime = fs->now ? fs->now : time(0); + ext2fs_set_dtime(fs, EXT2_INODE(&inode)); ret = ext2fs_free_ext_attr(fs, ino, &inode); if (ret) diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c index 4289e81..4874555 100644 --- a/lib/ext2fs/gen_bitmap64.c +++ b/lib/ext2fs/gen_bitmap64.c @@ -257,7 +257,7 @@ void ext2fs_free_generic_bmap(ext2fs_generic_bitmap gen_bmap) return; #ifdef ENABLE_BMAP_STATS - if (getenv("E2FSPROGS_BITMAP_STATS")) { + if (ext2fs_safe_getenv("E2FSPROGS_BITMAP_STATS")) { ext2fs_print_bmap_statistics(bmap); bmap->bitmap_ops->print_stats(bmap); } @@ -945,8 +945,8 @@ errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap, return ENOENT; } -errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start, - blk64_t end, blk64_t *out) +errcode_t ext2fs_count_used_blocks(ext2_filsys fs, blk64_t start, + blk64_t end, blk64_t *out) { blk64_t next; blk64_t tot_set = 0; @@ -975,6 +975,19 @@ errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start, break; } + if (!retval) + *out = tot_set; + return retval; +} + +errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start, + blk64_t end, blk64_t *out) +{ + blk64_t tot_set = 0; + errcode_t retval = 0; + + retval = ext2fs_count_used_blocks(fs, start, end, &tot_set); + if (!retval) *out = EXT2FS_NUM_B2C(fs, tot_set); return retval; diff --git a/lib/ext2fs/getenv.c b/lib/ext2fs/getenv.c new file mode 100644 index 0000000..409a78a --- /dev/null +++ b/lib/ext2fs/getenv.c @@ -0,0 +1,57 @@ +/* + * getenv.c --- implement a safe getenv for use by the ext2fs library + * + * 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 Library + * General Public License, version 2. + * %End-Header% + */ +#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) +#define _XOPEN_SOURCE 600 +#define _DARWIN_C_SOURCE +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#endif + +#include "config.h" +#include +#if HAVE_UNISTD_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 "ext2fs.h" + +char *ext2fs_safe_getenv(const char *arg) +{ + if ((getuid() != geteuid()) || (getgid() != getegid())) + return NULL; +#ifdef HAVE_PRCTL + if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#else +#if (defined(linux) && defined(SYS_prctl)) + if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#endif +#endif + +#if defined(HAVE_SECURE_GETENV) + return secure_getenv(arg); +#elif defined(HAVE___SECURE_GETENV) + return __secure_getenv(arg); +#else + return getenv(arg); +#endif +} diff --git a/lib/ext2fs/getsize.c b/lib/ext2fs/getsize.c index bcf3020..a028634 100644 --- a/lib/ext2fs/getsize.c +++ b/lib/ext2fs/getsize.c @@ -71,12 +71,11 @@ #define HAVE_GET_FILE_SIZE_EX 1 #endif -HANDLE windows_get_handle(io_channel channel); - errcode_t ext2fs_get_device_size2(const char *file, int blocksize, blk64_t *retblocks) { - HANDLE dev; + int fd; + HANDLE h; PARTITION_INFORMATION pi; DISK_GEOMETRY gi; DWORD retbytes; @@ -86,25 +85,18 @@ errcode_t ext2fs_get_device_size2(const char *file, int blocksize, DWORD filesize; #endif /* HAVE_GET_FILE_SIZE_EX */ - io_channel data_io = 0; - int retval; - - retval = windows_io_manager->open(file, 0, &data_io); - if (retval) - return retval; - - dev = windows_get_handle(data_io); - if (dev == INVALID_HANDLE_VALUE) - return EBADF; - - if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO, + fd = ext2fs_open_file(file, O_RDONLY, 0); + if (fd < 0) + return errno; + h = (HANDLE)_get_osfhandle(fd); + if (DeviceIoControl(h, 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, + } else if (DeviceIoControl(h, IOCTL_DISK_GET_DRIVE_GEOMETRY, &gi, sizeof(DISK_GEOMETRY), &gi, sizeof(DISK_GEOMETRY), &retbytes, NULL)) { @@ -115,20 +107,19 @@ errcode_t ext2fs_get_device_size2(const char *file, int blocksize, gi.Cylinders.QuadPart / blocksize; #ifdef HAVE_GET_FILE_SIZE_EX - } else if (GetFileSizeEx(dev, &filesize)) { + } else if (GetFileSizeEx(h, &filesize)) { *retblocks = filesize.QuadPart / blocksize; } #else } else { - filesize = GetFileSize(dev, NULL); + filesize = GetFileSize(h, NULL); if (INVALID_FILE_SIZE != filesize) { *retblocks = filesize / blocksize; } } #endif /* HAVE_GET_FILE_SIZE_EX */ - windows_io_manager->close(data_io); - + close(fd); return 0; } diff --git a/lib/ext2fs/hashmap.c b/lib/ext2fs/hashmap.c index 697b2bc..1579467 100644 --- a/lib/ext2fs/hashmap.c +++ b/lib/ext2fs/hashmap.c @@ -34,8 +34,8 @@ struct ext2fs_hashmap *ext2fs_hashmap_create( uint32_t(*hash_fct)(const void*, size_t), void(*free_fct)(void*), size_t size) { - struct ext2fs_hashmap *h = calloc(sizeof(struct ext2fs_hashmap) + - sizeof(struct ext2fs_hashmap_entry) * size, 1); + struct ext2fs_hashmap *h = calloc(1, sizeof(struct ext2fs_hashmap) + + sizeof(struct ext2fs_hashmap_entry) * size); if (!h) return NULL; diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c index 23290a6..16b0977 100644 --- a/lib/ext2fs/imager.c +++ b/lib/ext2fs/imager.c @@ -299,7 +299,7 @@ errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, ssize_t actual, size; errcode_t retval; - size = (ssize_t)fs->blocksize * (fs->group_desc_count + 1); + size = (ssize_t)fs->blocksize * (fs->desc_blocks + 1); buf = malloc(size); if (!buf) return ENOMEM; @@ -323,7 +323,7 @@ errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, memcpy(fs->super, buf, SUPERBLOCK_SIZE); memcpy(fs->group_desc, buf + fs->blocksize, - (ssize_t)fs->blocksize * fs->group_desc_count); + (ssize_t)fs->blocksize * fs->desc_blocks); retval = 0; diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c index edd692b..b9cfd1b 100644 --- a/lib/ext2fs/initialize.c +++ b/lib/ext2fs/initialize.c @@ -26,7 +26,7 @@ #endif #include "ext2_fs.h" -#include "ext2fs.h" +#include "ext2fsP.h" #ifndef O_BINARY #define O_BINARY 0 @@ -125,9 +125,15 @@ errcode_t ext2fs_initialize(const char *name, int flags, fs->flags |= EXT2_FLAG_SWAP_BYTES; #endif - time_env = getenv("E2FSPROGS_FAKE_TIME"); - if (time_env) + time_env = ext2fs_safe_getenv("SOURCE_DATE_EPOCH"); + if (time_env) { fs->now = strtoul(time_env, NULL, 0); + fs->flags2 |= EXT2_FLAG2_USE_FAKE_TIME; + } else { + time_env = ext2fs_safe_getenv("E2FSPROGS_FAKE_TIME"); + if (time_env) + fs->now = strtoul(time_env, NULL, 0); + } io_flags = IO_FLAG_RW; if (flags & EXT2_FLAG_EXCLUSIVE) @@ -218,7 +224,8 @@ errcode_t ext2fs_initialize(const char *name, int flags, } set_field(s_checkinterval, 0); - super->s_mkfs_time = super->s_lastcheck = fs->now ? fs->now : time(NULL); + ext2fs_set_tstamp(super, s_mkfs_time, ext2fsP_get_time(fs)); + ext2fs_set_tstamp(super, s_lastcheck, ext2fsP_get_time(fs)); super->s_creator_os = CREATOR_OS; @@ -307,13 +314,6 @@ retry: else set_field(s_inodes_count, ext2fs_blocks_count(super) / 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 @@ -375,6 +375,15 @@ ipg_retry: } super->s_inodes_count = super->s_inodes_per_group * fs->group_desc_count; + /* + * 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) { + ipg += 8; + goto ipg_retry; + } + super->s_free_inodes_count = super->s_inodes_count; /* @@ -521,33 +530,43 @@ ipg_retry: csum_flag = ext2fs_has_group_desc_csum(fs); reserved_inos = super->s_first_ino; for (i = 0; i < fs->group_desc_count; i++) { + blk_t grp_free_blocks; + ext2_ino_t inodes; + + retval = ext2fs_reserve_super_and_bgd2(fs, i, + fs->block_map, + &numblocks); + if (retval) + goto cleanup; + /* * Don't set the BLOCK_UNINIT group for the last group * because the block bitmap needs to be padded. */ if (csum_flag) { - if (i != fs->group_desc_count - 1) + if (i != fs->group_desc_count - 1 && numblocks == 0) ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT); ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT); - numblocks = super->s_inodes_per_group; + inodes = super->s_inodes_per_group; if (reserved_inos) { - if (numblocks > reserved_inos) { - numblocks -= reserved_inos; + if (inodes > reserved_inos) { + inodes -= reserved_inos; reserved_inos = 0; } else { - reserved_inos -= numblocks; - numblocks = 0; + reserved_inos -= inodes; + inodes = 0; } } - ext2fs_bg_itable_unused_set(fs, i, numblocks); + ext2fs_bg_itable_unused_set(fs, i, inodes); } - numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map); - if (fs->super->s_log_groups_per_flex) + + if (!fs->super->s_log_groups_per_flex) numblocks += 2 + fs->inode_blocks_per_group; - free_blocks += numblocks; - ext2fs_bg_free_blocks_count_set(fs, i, numblocks); + grp_free_blocks = ext2fs_group_blocks_count(fs, i) - numblocks; + free_blocks += grp_free_blocks; + ext2fs_bg_free_blocks_count_set(fs, i, grp_free_blocks); ext2fs_bg_free_inodes_count_set(fs, i, fs->super->s_inodes_per_group); ext2fs_bg_used_dirs_count_set(fs, i, 0); ext2fs_group_desc_csum_set(fs, i); diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c index 957d5aa..c9389a2 100644 --- a/lib/ext2fs/inode.c +++ b/lib/ext2fs/inode.c @@ -1039,17 +1039,17 @@ 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); + int size = EXT2_INODE_SIZE(fs->super); struct ext2_inode_large *large_inode; errcode_t retval; - __u32 t = fs->now ? fs->now : time(NULL); - - if (!inode->i_ctime) - inode->i_ctime = t; - if (!inode->i_mtime) - inode->i_mtime = t; - if (!inode->i_atime) - inode->i_atime = t; + time_t t = ext2fsP_get_time(fs); + + if (!ext2fs_inode_xtime_get(inode, i_atime)) + ext2fs_inode_xtime_set(inode, i_atime, t); + if (!ext2fs_inode_xtime_get(inode, i_ctime)) + ext2fs_inode_xtime_set(inode, i_ctime, t); + if (!ext2fs_inode_xtime_get(inode, i_mtime)) + ext2fs_inode_xtime_set(inode, i_mtime, t); if (size == sizeof(struct ext2_inode)) return ext2fs_write_inode_full(fs, ino, inode, diff --git a/lib/ext2fs/ismounted.c b/lib/ext2fs/ismounted.c index a7db1a5..c1c3102 100644 --- a/lib/ext2fs/ismounted.c +++ b/lib/ext2fs/ismounted.c @@ -108,7 +108,7 @@ static errcode_t check_mntent_file(const char *mtab_file, const char *file, if ((f = setmntent (mtab_file, "r")) == NULL) { if (errno == ENOENT) { - if (getenv("EXT2FS_NO_MTAB_OK")) + if (ext2fs_safe_getenv("EXT2FS_NO_MTAB_OK")) return 0; else return EXT2_ET_NO_MTAB_FILE; @@ -366,15 +366,15 @@ errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, errcode_t retval = 0; int busy = 0; - if (getenv("EXT2FS_PRETEND_RO_MOUNT")) { + if (ext2fs_safe_getenv("EXT2FS_PRETEND_RO_MOUNT")) { *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_READONLY; - if (getenv("EXT2FS_PRETEND_ROOTFS")) + if (ext2fs_safe_getenv("EXT2FS_PRETEND_ROOTFS")) *mount_flags = EXT2_MF_ISROOT; return 0; } - if (getenv("EXT2FS_PRETEND_RW_MOUNT")) { + if (ext2fs_safe_getenv("EXT2FS_PRETEND_RW_MOUNT")) { *mount_flags = EXT2_MF_MOUNTED; - if (getenv("EXT2FS_PRETEND_ROOTFS")) + if (ext2fs_safe_getenv("EXT2FS_PRETEND_ROOTFS")) *mount_flags = EXT2_MF_ISROOT; return 0; } diff --git a/lib/ext2fs/llseek.c b/lib/ext2fs/llseek.c index 45f21d0..9118b23 100644 --- a/lib/ext2fs/llseek.c +++ b/lib/ext2fs/llseek.c @@ -35,68 +35,32 @@ #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 SIZEOF_LONG == SIZEOF_LONG_LONG || _FILE_OFFSET_BITS+0 == 64 - -#define my_llseek lseek - -#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */ - #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; +#if SIZEOF_OFF_T >= 8 + return lseek(fd, offset, origin); +#elif HAVE_LSEEK64_PROTOTYPE + return lseek64(fd, offset, origin); +#elif HAVE_LLSEEK_PROTOTYPE + return llseek(fd, offset, origin); +#elif defined(__NR__llseek) + loff_t result; int retval; - -#ifndef __i386__ - retval = _llseek(fd, ((unsigned long long) offset) >> 32, + retval = syscall(__NR__llseek, fd, + (unsigned long)(offset >> 32), + (unsigned long)(offset & 0xffffffff), + &result, origin); + return (retval == -1 ? retval : result); #else - retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32), + errno = ENOSYS; + return -1; #endif - ((unsigned long long) offset) & 0xffffffff, - &result, origin); - return (retval == -1 ? (ext2_loff_t) retval : result); } -#endif /* SIZE_LONG == SIZEOF_LONG_LONG */ - -#endif /* HAVE_LLSEEK */ -#endif /* defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) */ - ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin) { -#if SIZEOF_OFF_T >= SIZEOF_LONG_LONG - return my_llseek (fd, offset, origin); -#else ext2_loff_t result; static int do_compat = 0; @@ -117,7 +81,6 @@ ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin) return -1; } return result; -#endif } #else /* !linux */ diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c index 54772dd..27cdfa0 100644 --- a/lib/ext2fs/mkjournal.c +++ b/lib/ext2fs/mkjournal.c @@ -20,7 +20,6 @@ #include #endif #include -#include #if HAVE_SYS_STAT_H #include #endif @@ -36,7 +35,7 @@ #include "ext2_fs.h" #include "e2p/e2p.h" -#include "ext2fs.h" +#include "ext2fsP.h" #include "kernel-jbd.h" @@ -285,6 +284,7 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, unsigned long long inode_size; int falloc_flags = EXT2_FALLOCATE_FORCE_INIT; blk64_t zblk; + time_t now; if ((retval = ext2fs_create_journal_superblock2(fs, jparams, flags, &buf))) @@ -312,7 +312,9 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, inode_size = (unsigned long long)fs->blocksize * (jparams->num_journal_blocks + jparams->num_fc_blocks); - inode.i_mtime = inode.i_ctime = fs->now ? fs->now : time(0); + now = ext2fsP_get_time(fs); + ext2fs_inode_xtime_set(&inode, i_mtime, now); + ext2fs_inode_xtime_set(&inode, i_ctime, now); inode.i_links_count = 1; inode.i_mode = LINUX_S_IFREG | 0600; retval = ext2fs_inode_size_set(fs, &inode, inode_size); diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index fd56a9a..2b8e0e7 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -149,9 +149,15 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; fs->umask = 022; - time_env = getenv("E2FSPROGS_FAKE_TIME"); - if (time_env) + time_env = ext2fs_safe_getenv("SOURCE_DATE_EPOCH"); + if (time_env) { fs->now = strtoul(time_env, NULL, 0); + fs->flags2 |= EXT2_FLAG2_USE_FAKE_TIME; + } else { + time_env = ext2fs_safe_getenv("E2FSPROGS_FAKE_TIME"); + if (time_env) + fs->now = strtoul(time_env, NULL, 0); + } retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name); if (retval) @@ -330,13 +336,14 @@ retry: } /* Enforce the block group descriptor size */ - if (!(flags & EXT2_FLAG_IGNORE_SB_ERRORS) && - ext2fs_has_feature_64bit(fs->super)) { + if (ext2fs_has_feature_64bit(fs->super)) { unsigned desc_size = fs->super->s_desc_size; - if ((desc_size < EXT2_MIN_DESC_SIZE_64BIT) || - (desc_size > EXT2_MAX_DESC_SIZE) || - (desc_size & (desc_size - 1)) != 0) { + if (desc_size == 0 || + (!(flags & EXT2_FLAG_IGNORE_SB_ERRORS) && + ((desc_size > EXT2_MAX_DESC_SIZE) || + (desc_size < EXT2_MIN_DESC_SIZE_64BIT) || + (desc_size & (desc_size - 1)) != 0))) { retval = EXT2_ET_BAD_DESC_SIZE; goto cleanup; } diff --git a/lib/ext2fs/orphan.c b/lib/ext2fs/orphan.c index e25f20c..913eb9a 100644 --- a/lib/ext2fs/orphan.c +++ b/lib/ext2fs/orphan.c @@ -126,23 +126,23 @@ errcode_t ext2fs_create_orphan_file(ext2_filsys fs, blk_t num_blocks) char *buf = NULL, *zerobuf = NULL; struct mkorphan_info oi; struct ext4_orphan_block_tail *ob_tail; + time_t now; - if (!ino) { + if (ino) { + err = ext2fs_read_inode(fs, ino, &inode); + if (err) + return err; + if (EXT2_I_SIZE(&inode)) { + err = ext2fs_truncate_orphan_file(fs); + if (err) + return err; + } + } else { err = ext2fs_new_inode(fs, EXT2_ROOT_INO, LINUX_S_IFREG | 0600, 0, &ino); if (err) return err; ext2fs_inode_alloc_stats2(fs, ino, +1, 0); - ext2fs_mark_ib_dirty(fs); - } - - err = ext2fs_read_inode(fs, ino, &inode); - if (err) - return err; - if (EXT2_I_SIZE(&inode)) { - err = ext2fs_truncate_orphan_file(fs); - if (err) - return err; } memset(&inode, 0, sizeof(struct ext2_inode)); @@ -185,8 +185,10 @@ errcode_t ext2fs_create_orphan_file(ext2_filsys fs, blk_t num_blocks) if (err) goto out; ext2fs_iblk_set(fs, &inode, 0); - inode.i_atime = inode.i_mtime = - inode.i_ctime = fs->now ? fs->now : time(0); + now = ext2fsP_get_time(fs); + ext2fs_inode_xtime_set(&inode, i_atime, now); + ext2fs_inode_xtime_set(&inode, i_ctime, now); + ext2fs_inode_xtime_set(&inode, i_mtime, now); inode.i_links_count = 1; inode.i_mode = LINUX_S_IFREG | 0600; ext2fs_iblk_add_blocks(fs, &inode, oi.alloc_blocks); diff --git a/lib/ext2fs/progress.c b/lib/ext2fs/progress.c index fe4292f..61ab3f0 100644 --- a/lib/ext2fs/progress.c +++ b/lib/ext2fs/progress.c @@ -53,7 +53,7 @@ void ext2fs_numeric_progress_init(ext2_filsys fs, backspaces[sizeof(backspaces)-1] = 0; memset(progress, 0, sizeof(*progress)); - if (getenv("E2FSPROGS_SKIP_PROGRESS")) + if (ext2fs_safe_getenv("E2FSPROGS_SKIP_PROGRESS")) progress->skip_progress++; diff --git a/lib/ext2fs/qcow2.c b/lib/ext2fs/qcow2.c index 2082417..8f96eee 100644 --- a/lib/ext2fs/qcow2.c +++ b/lib/ext2fs/qcow2.c @@ -134,7 +134,9 @@ static int qcow2_read_l2_table(struct ext2_qcow2_image *img, static int qcow2_copy_data(int fdin, int fdout, __u64 off_in, __u64 off_out, void *buf, size_t count) { - size_t size; + ssize_t c1, c2, c; + void *ptr; + int retries = 10; assert(buf); @@ -144,14 +146,24 @@ static int qcow2_copy_data(int fdin, int fdout, __u64 off_in, if (ext2fs_llseek(fdin, off_in, SEEK_SET) < 0) return errno; - size = read(fdin, buf, count); - if (size != count) - return errno; - - size = write(fdout, buf, count); - if (size != count) - return errno; - + while (count > 0) { + errno = 0; + c1 = read(fdin, buf, count); + if (c1 < 0 || ((c1 == 0) && errno)) + return errno; + if (c1 == 0) + break; /* EOF */ + + for (ptr = buf, c = c1; c > 0; ptr += c2, c -= c2) { + errno = 0; + c2 = write(fdout, ptr, c1); + if (c2 < 0 || ((c2 == 0) && errno)) + return errno; + if (c2 == 0 && --retries <= 0) + break; /* This should never happen... */ + } + count -= c1; + } return 0; } diff --git a/lib/ext2fs/qcow2.h b/lib/ext2fs/qcow2.h index b649c9c..343e85a 100644 --- a/lib/ext2fs/qcow2.h +++ b/lib/ext2fs/qcow2.h @@ -24,6 +24,8 @@ * %End-Header% */ +#include + /* Number of l2 tables in memory before writeback */ #define L2_CACHE_PREALLOC 512 diff --git a/lib/ext2fs/rbtree.h b/lib/ext2fs/rbtree.h index 790f5c1..b96e6f2 100644 --- a/lib/ext2fs/rbtree.h +++ b/lib/ext2fs/rbtree.h @@ -163,7 +163,7 @@ extern struct rb_node *ext2fs_rb_first(const struct rb_root *); extern struct rb_node *ext2fs_rb_last(const struct rb_root *); /* Fast replacement of a single node without remove/rebalance/add/rebalance */ -extern void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new, +extern void ext2fs_rb_replace_node(struct rb_node *victim, struct rb_node *new_, struct rb_root *root); static inline void ext2fs_rb_link_node(struct rb_node * node, diff --git a/lib/ext2fs/res_gdt.c b/lib/ext2fs/res_gdt.c index fa8d8d6..3349648 100644 --- a/lib/ext2fs/res_gdt.c +++ b/lib/ext2fs/res_gdt.c @@ -15,23 +15,24 @@ #include #include #include "ext2_fs.h" -#include "ext2fs.h" +#include "ext2fsP.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, ... + * calling this for the first time. In a sparse_super 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, ... + * For a sparse_super2 filesystem there are two backups in specific groups. */ -static unsigned int list_backups(ext2_filsys fs, unsigned int *three, - unsigned int *five, unsigned int *seven) +dgrp_t ext2fs_list_backups(ext2_filsys fs, dgrp_t *three, + dgrp_t *five, dgrp_t *seven) { - unsigned int *min = three; - int mult = 3; - unsigned int ret; + dgrp_t *min = three; + unsigned long long mult = 3; + dgrp_t ret; - if (ext2fs_has_feature_sparse_super2(fs->super)) { + if (fs && ext2fs_has_feature_sparse_super2(fs->super)) { if (*min == 1) { *min += 1; if (fs->super->s_backup_bgs[0]) @@ -42,11 +43,14 @@ static unsigned int list_backups(ext2_filsys fs, unsigned int *three, if (fs->super->s_backup_bgs[1]) return fs->super->s_backup_bgs[1]; } + return fs->group_desc_count; } - if (!ext2fs_has_feature_sparse_super(fs->super)) { + + if (fs && !ext2fs_has_feature_sparse_super(fs->super)) { ret = *min; *min += 1; + return ret; } @@ -60,7 +64,11 @@ static unsigned int list_backups(ext2_filsys fs, unsigned int *three, } ret = *min; - *min *= mult; + mult *= *min; + if (mult > (dgrp_t)-1) + *min = (dgrp_t)-1; + else + *min = mult; return ret; } @@ -135,15 +143,15 @@ errcode_t ext2fs_create_resize_inode(ext2_filsys fs) retval = ext2fs_inode_size_set(fs, &inode, inode_size); if (retval) goto out_free; - inode.i_ctime = fs->now ? fs->now : time(0); + inode.i_ctime = ext2fsP_get_time(fs); } for (rsv_off = 0, gdt_off = fs->desc_blocks, gdt_blk = sb_blk + 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; + dgrp_t three = 1, five = 5, seven = 7; + dgrp_t grp, last = 0; int gdt_dirty = 0; gdt_off %= apb; @@ -183,7 +191,7 @@ errcode_t ext2fs_create_resize_inode(ext2_filsys fs) goto out_dindir; } - while ((grp = list_backups(fs, &three, &five, &seven)) < + while ((grp = ext2fs_list_backups(fs, &three, &five, &seven)) < fs->group_desc_count) { blk_t expect = gdt_blk + grp * sb->s_blocks_per_group; @@ -227,7 +235,10 @@ out_inode: EXT2_I_SIZE(&inode)); #endif if (inode_dirty) { - inode.i_atime = inode.i_mtime = fs->now ? fs->now : time(0); + time_t now = ext2fsP_get_time(fs); + + ext2fs_inode_xtime_set(&inode, i_atime, now); + ext2fs_inode_xtime_set(&inode, i_mtime, now); retval2 = ext2fs_write_new_inode(fs, EXT2_RESIZE_INO, &inode); if (!retval) retval = retval2; diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c index 1fe65f7..1da75e4 100644 --- a/lib/ext2fs/rw_bitmaps.c +++ b/lib/ext2fs/rw_bitmaps.c @@ -557,7 +557,7 @@ errcode_t ext2fs_rw_bitmaps(ext2_filsys fs, int flags, int num_threads) * MacOS, FreeBSD, etc. * ref: https://stackoverflow.com/questions/150355 */ - if (num_threads < 0) + if (num_threads <= 0) num_threads = 4; if ((unsigned) num_threads > fs->group_desc_count) diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c index fe764b9..d8d2140 100644 --- a/lib/ext2fs/swapfs.c +++ b/lib/ext2fs/swapfs.c @@ -345,21 +345,21 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, return; /* Illegal inode extra_isize */ inode_size = EXT2_GOOD_OLD_INODE_SIZE + extra_isize; - if (inode_includes(inode_size, i_checksum_hi)) + if (ext2fs_inode_includes(inode_size, i_checksum_hi)) t->i_checksum_hi = ext2fs_swab16(f->i_checksum_hi); - if (inode_includes(inode_size, i_ctime_extra)) + if (ext2fs_inode_includes(inode_size, i_ctime_extra)) t->i_ctime_extra = ext2fs_swab32(f->i_ctime_extra); - if (inode_includes(inode_size, i_mtime_extra)) + if (ext2fs_inode_includes(inode_size, i_mtime_extra)) t->i_mtime_extra = ext2fs_swab32(f->i_mtime_extra); - if (inode_includes(inode_size, i_atime_extra)) + if (ext2fs_inode_includes(inode_size, i_atime_extra)) t->i_atime_extra = ext2fs_swab32(f->i_atime_extra); - if (inode_includes(inode_size, i_crtime)) + if (ext2fs_inode_includes(inode_size, i_crtime)) t->i_crtime = ext2fs_swab32(f->i_crtime); - if (inode_includes(inode_size, i_crtime_extra)) + if (ext2fs_inode_includes(inode_size, i_crtime_extra)) t->i_crtime_extra = ext2fs_swab32(f->i_crtime_extra); - if (inode_includes(inode_size, i_version_hi)) + if (ext2fs_inode_includes(inode_size, i_version_hi)) t->i_version_hi = ext2fs_swab32(f->i_version_hi); - if (inode_includes(inode_size, i_projid)) + if (ext2fs_inode_includes(inode_size, i_projid)) t->i_projid = ext2fs_swab32(f->i_projid); /* catch new static fields added after i_projid */ EXT2FS_BUILD_BUG_ON(sizeof(struct ext2_inode_large) != 160); diff --git a/lib/ext2fs/test_io.c b/lib/ext2fs/test_io.c index 6843edb..0324e53 100644 --- a/lib/ext2fs/test_io.c +++ b/lib/ext2fs/test_io.c @@ -23,14 +23,6 @@ #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" @@ -144,31 +136,6 @@ static void test_abort(io_channel channel, unsigned long block) abort(); } -static char *safe_getenv(const char *arg) -{ -#if !defined(_WIN32) - if ((getuid() != geteuid()) || (getgid() != getegid())) - return NULL; -#endif -#if HAVE_PRCTL - if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) - return NULL; -#else -#if (defined(linux) && defined(SYS_prctl)) - if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) - return NULL; -#endif -#endif - -#if defined(HAVE_SECURE_GETENV) - return secure_getenv(arg); -#elif defined(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; @@ -217,25 +184,25 @@ static errcode_t test_open(const char *name, int flags, io_channel *channel) data->write_blk64 = test_io_cb_write_blk64; data->outfile = NULL; - if ((value = safe_getenv("TEST_IO_LOGFILE")) != NULL) + if ((value = ext2fs_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) + if ((value = ext2fs_safe_getenv("TEST_IO_FLAGS")) != NULL) data->flags = strtoul(value, NULL, 0); data->block = 0; - if ((value = safe_getenv("TEST_IO_BLOCK")) != NULL) + if ((value = ext2fs_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) + if ((value = ext2fs_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) + if ((value = ext2fs_safe_getenv("TEST_IO_WRITE_ABORT")) != NULL) data->write_abort_count = strtoul(value, NULL, 0); if (data->real) { diff --git a/lib/ext2fs/tst_bitmaps.c b/lib/ext2fs/tst_bitmaps.c index cb3c70d..eaf2c59 100644 --- a/lib/ext2fs/tst_bitmaps.c +++ b/lib/ext2fs/tst_bitmaps.c @@ -140,7 +140,7 @@ unsigned long parse_ulong(const char *str, const char *cmd, } -int check_fs_open(char *name) +int check_fs_open(const char *name) { if (!test_fs) { com_err(name, 0, "Filesystem not open"); @@ -190,7 +190,8 @@ errout: ext2fs_close_free(&test_fs); } -void setup_cmd(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), +void setup_cmd(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { int c, err; @@ -271,7 +272,7 @@ void dump_bitmap(ext2fs_generic_bitmap bmap, unsigned int start, unsigned num) free(buf); } -void dump_inode_bitmap_cmd(int argc, char **argv, +void dump_inode_bitmap_cmd(int argc, ss_argv_t argv, int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { @@ -282,7 +283,7 @@ void dump_inode_bitmap_cmd(int argc, char **argv, dump_bitmap(test_fs->inode_map, 1, test_fs->super->s_inodes_count); } -void dump_block_bitmap_cmd(int argc, char **argv, +void dump_block_bitmap_cmd(int argc, ss_argv_t argv, int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { @@ -294,7 +295,8 @@ void dump_block_bitmap_cmd(int argc, char **argv, test_fs->super->s_blocks_count); } -void do_setb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_setb(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { unsigned int block, num; @@ -333,7 +335,8 @@ void do_setb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), test_result, op_result); } -void do_clearb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_clearb(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { unsigned int block, num; @@ -372,7 +375,8 @@ void do_clearb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), test_result, op_result); } -void do_testb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_testb(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { unsigned int block, num; @@ -408,7 +412,8 @@ void do_testb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), printf("Block %u is %s\n", block, test_result ? "set" : "clear"); } -void do_ffzb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_ffzb(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { unsigned int start, end; @@ -442,7 +447,8 @@ void do_ffzb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), printf("First unmarked block is %llu\n", (unsigned long long) out); } -void do_ffsb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_ffsb(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { unsigned int start, end; @@ -477,7 +483,8 @@ void do_ffsb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), } -void do_zerob(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_zerob(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { if (check_fs_open(argv[0])) @@ -487,7 +494,8 @@ void do_zerob(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), ext2fs_clear_block_bitmap(test_fs->block_map); } -void do_seti(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_seti(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { unsigned int inode; @@ -517,7 +525,8 @@ void do_seti(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), } } -void do_cleari(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_cleari(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { unsigned int inode; @@ -547,7 +556,8 @@ void do_cleari(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), } } -void do_testi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_testi(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { unsigned int inode; @@ -570,7 +580,8 @@ void do_testi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), printf("Inode %u is %s\n", inode, test_result ? "set" : "clear"); } -void do_ffzi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_ffzi(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { unsigned int start, end; @@ -604,7 +615,8 @@ void do_ffzi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), printf("First unmarked inode is %u\n", out); } -void do_ffsi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_ffsi(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { unsigned int start, end; @@ -638,7 +650,8 @@ void do_ffsi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), printf("First marked inode is %u\n", out); } -void do_zeroi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), +void do_zeroi(int argc, ss_argv_t argv, + int sci_idx EXT2FS_ATTR((unused)), void *infop EXT2FS_ATTR((unused))) { if (check_fs_open(argv[0])) diff --git a/lib/ext2fs/undo_io.c b/lib/ext2fs/undo_io.c index f4a6d52..a1bb405 100644 --- a/lib/ext2fs/undo_io.c +++ b/lib/ext2fs/undo_io.c @@ -809,7 +809,7 @@ static errcode_t undo_close(io_channel channel) if (--channel->refcount > 0) return 0; /* Before closing write the file system identity */ - if (!getenv("UNDO_IO_SIMULATE_UNFINISHED")) + if (!ext2fs_safe_getenv("UNDO_IO_SIMULATE_UNFINISHED")) data->hdr.state = ext2fs_cpu_to_le32(E2UNDO_STATE_FINISHED); err = write_undo_indexes(data, 1); ext2fs_remove_exit_fn(undo_atexit, data); diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index 3171c73..4b4f25a 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -18,7 +18,6 @@ #if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) #define _XOPEN_SOURCE 600 #define _DARWIN_C_SOURCE -#define _FILE_OFFSET_BITS 64 #ifndef _LARGEFILE_SOURCE #define _LARGEFILE_SOURCE #endif @@ -53,11 +52,6 @@ #ifdef HAVE_SYS_MOUNT_H #include #endif -#ifdef HAVE_SYS_PRCTL_H -#include -#else -#define PR_GET_DUMPABLE 3 -#endif #if HAVE_SYS_STAT_H #include #endif @@ -182,29 +176,6 @@ static errcode_t unix_get_stats(io_channel channel, io_stats *stats) return retval; } -static char *safe_getenv(const char *arg) -{ - if ((getuid() != geteuid()) || (getgid() != getegid())) - return NULL; -#ifdef HAVE_PRCTL - if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) - return NULL; -#else -#if (defined(linux) && defined(SYS_prctl)) - if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) - return NULL; -#endif -#endif - -#if defined(HAVE_SECURE_GETENV) - return secure_getenv(arg); -#elif defined(HAVE___SECURE_GETENV) - return __secure_getenv(arg); -#else - return getenv(arg); -#endif -} - /* * Here are the raw I/O functions */ @@ -728,7 +699,7 @@ static errcode_t unix_open_channel(const char *name, int fd, struct utsname ut; #endif - if (safe_getenv("UNIX_IO_FORCE_BOUNCE")) + if (ext2fs_safe_getenv("UNIX_IO_FORCE_BOUNCE")) flags |= IO_FLAG_FORCE_BOUNCE; #ifdef __linux__ @@ -761,6 +732,9 @@ static errcode_t unix_open_channel(const char *name, int fd, io->refcount = 1; io->flags = 0; + if (ext2fs_safe_getenv("UNIX_IO_NOZEROOUT")) + io->flags |= CHANNEL_FLAGS_NOZEROOUT; + memset(data, 0, sizeof(struct unix_private_data)); data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; data->io_stats.num_fields = 2; @@ -783,20 +757,19 @@ static errcode_t unix_open_channel(const char *name, int fd, * zero. */ if (ext2fs_fstat(data->dev, &st) == 0) { - if (ext2fsP_is_disk_device(st.st_mode)) - io->flags |= CHANNEL_FLAGS_BLOCK_DEVICE; - else - io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; - } - + if (ext2fsP_is_disk_device(st.st_mode)) { #ifdef BLKDISCARDZEROES - { - int zeroes = 0; - if (ioctl(data->dev, BLKDISCARDZEROES, &zeroes) == 0 && - zeroes) + int zeroes = 0; + + if (ioctl(data->dev, BLKDISCARDZEROES, &zeroes) == 0 && + zeroes) + io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; +#endif + io->flags |= CHANNEL_FLAGS_BLOCK_DEVICE; + } else { io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; + } } -#endif #if defined(__CYGWIN__) /* @@ -1344,12 +1317,15 @@ static errcode_t unix_discard(io_channel channel, unsigned long long block, unsigned long long count) { struct unix_private_data *data; - int ret; + int ret = EOPNOTSUPP; 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->flags & CHANNEL_FLAGS_NODISCARD) + goto unimplemented; + if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) { #ifdef BLKDISCARD __u64 range[2]; @@ -1376,8 +1352,10 @@ static errcode_t unix_discard(io_channel channel, unsigned long long block, #endif } if (ret < 0) { - if (errno == EOPNOTSUPP) + if (errno == EOPNOTSUPP) { + channel->flags |= CHANNEL_FLAGS_NODISCARD; goto unimplemented; + } return errno; } return 0; @@ -1425,9 +1403,6 @@ static errcode_t unix_zeroout(io_channel channel, unsigned long long block, data = (struct unix_private_data *) channel->private_data; EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - if (safe_getenv("UNIX_IO_NOZEROOUT")) - goto unimplemented; - if (!(channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE)) { /* Regular file, try to use truncate/punch/zero. */ struct stat statbuf; @@ -1450,13 +1425,18 @@ static errcode_t unix_zeroout(io_channel channel, unsigned long long block, } } + if (channel->flags & CHANNEL_FLAGS_NOZEROOUT) + goto unimplemented; + ret = __unix_zeroout(data->dev, (off_t)(block) * channel->block_size + data->offset, (off_t)(count) * channel->block_size); err: if (ret < 0) { - if (errno == EOPNOTSUPP) + if (errno == EOPNOTSUPP) { + channel->flags |= CHANNEL_FLAGS_NOZEROOUT; goto unimplemented; + } return errno; } return 0; diff --git a/lib/ext2fs/windows_io.c b/lib/ext2fs/windows_io.c index 83aea68..4bff074 100644 --- a/lib/ext2fs/windows_io.c +++ b/lib/ext2fs/windows_io.c @@ -154,6 +154,14 @@ static errcode_t windows_get_stats(io_channel channel, io_stats *stats) return retval; } +static LARGE_INTEGER make_large_integer(LONGLONG value) +{ + LARGE_INTEGER li; + + li.QuadPart = value; + return li; +} + /* * Here are the raw I/O functions */ @@ -174,14 +182,14 @@ static errcode_t raw_read_blk(io_channel channel, location = ((ext2_loff_t) block * channel->block_size) + data->offset; if (data->flags & IO_FLAG_FORCE_BOUNCE) { - if (SetFilePointer(data->handle, location, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + if (!SetFilePointerEx(data->handle, make_large_integer(location), NULL, FILE_BEGIN)) { retval = GetLastError(); goto error_out; } goto bounce_read; } - if (SetFilePointer(data->handle, location, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + if (!SetFilePointerEx(data->handle, make_large_integer(location), NULL, FILE_BEGIN)) { retval = GetLastError(); goto error_out; } @@ -261,14 +269,14 @@ static errcode_t raw_write_blk(io_channel channel, location = ((ext2_loff_t) block * channel->block_size) + data->offset; if (data->flags & IO_FLAG_FORCE_BOUNCE) { - if (SetFilePointer(data->handle, location, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + if (!SetFilePointerEx(data->handle, make_large_integer(location), NULL, FILE_BEGIN)) { retval = GetLastError(); goto error_out; } goto bounce_write; } - if (SetFilePointer(data->handle, location, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + if (!SetFilePointerEx(data->handle, make_large_integer(location), NULL, FILE_BEGIN)) { retval = GetLastError(); goto error_out; } @@ -313,7 +321,7 @@ bounce_write: if (size > channel->block_size) actual = channel->block_size; memcpy(data->bounce, buf, actual); - if (SetFilePointer(data->handle, location, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + if (!SetFilePointerEx(data->handle, make_large_integer(location), NULL, FILE_BEGIN)) { retval = GetLastError(); goto error_out; } @@ -857,17 +865,6 @@ static errcode_t windows_write_byte(io_channel channel, unsigned long offset, return EXT2_ET_UNIMPLEMENTED; } -HANDLE windows_get_handle(io_channel channel) -{ - struct windows_private_data *data; - - EXT2_CHECK_MAGIC_RETURN(channel, EXT2_ET_MAGIC_IO_CHANNEL, INVALID_HANDLE_VALUE); - data = (struct windows_private_data *) channel->private_data; - EXT2_CHECK_MAGIC_RETURN(data, EXT2_ET_MAGIC_WINDOWS_IO_CHANNEL, INVALID_HANDLE_VALUE); - - return data->handle; -} - /* * Flush data buffers to disk. */ -- cgit v1.2.3