summaryrefslogtreecommitdiffstats
path: root/lib/ext2fs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ext2fs')
-rw-r--r--lib/ext2fs/Android.bp1
-rw-r--r--lib/ext2fs/Makefile.in81
-rw-r--r--lib/ext2fs/alloc_sb.c28
-rw-r--r--lib/ext2fs/bb_inode.c14
-rw-r--r--lib/ext2fs/closefs.c2
-rw-r--r--lib/ext2fs/e2image.h5
-rw-r--r--lib/ext2fs/ext2_fs.h6
-rw-r--r--lib/ext2fs/ext2_io.h4
-rw-r--r--lib/ext2fs/ext2fs.h110
-rw-r--r--lib/ext2fs/ext2fsP.h7
-rw-r--r--lib/ext2fs/ext_attr.c4
-rw-r--r--lib/ext2fs/gen_bitmap64.c19
-rw-r--r--lib/ext2fs/getenv.c57
-rw-r--r--lib/ext2fs/getsize.c31
-rw-r--r--lib/ext2fs/hashmap.c4
-rw-r--r--lib/ext2fs/imager.c4
-rw-r--r--lib/ext2fs/initialize.c63
-rw-r--r--lib/ext2fs/inode.c18
-rw-r--r--lib/ext2fs/ismounted.c10
-rw-r--r--lib/ext2fs/llseek.c67
-rw-r--r--lib/ext2fs/mkjournal.c8
-rw-r--r--lib/ext2fs/openfs.c21
-rw-r--r--lib/ext2fs/orphan.c28
-rw-r--r--lib/ext2fs/progress.c2
-rw-r--r--lib/ext2fs/qcow2.c30
-rw-r--r--lib/ext2fs/qcow2.h2
-rw-r--r--lib/ext2fs/rbtree.h2
-rw-r--r--lib/ext2fs/res_gdt.c43
-rw-r--r--lib/ext2fs/rw_bitmaps.c2
-rw-r--r--lib/ext2fs/swapfs.c16
-rw-r--r--lib/ext2fs/test_io.c43
-rw-r--r--lib/ext2fs/tst_bitmaps.c45
-rw-r--r--lib/ext2fs/undo_io.c2
-rw-r--r--lib/ext2fs/unix_io.c74
-rw-r--r--lib/ext2fs/windows_io.c29
35 files changed, 549 insertions, 333 deletions
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 <unistd.h>
#endif
#include <fcntl.h>
-#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#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
@@ -222,6 +222,11 @@ typedef struct ext2_file *ext2_file_t;
#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;
@@ -976,6 +976,19 @@ errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start,
}
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 <stdlib.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#else
+#define PR_GET_DUMPABLE 3
+#endif
+#if (!defined(HAVE_PRCTL) && defined(linux))
+#include <sys/syscall.h>
+#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;
@@ -308,13 +315,6 @@ retry:
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
* should be. But make sure that we don't allocate more than
@@ -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 <sys/syscall.h>
-
-#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 <linux/unistd.h>
-#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 <errno.h>
#endif
#include <fcntl.h>
-#include <time.h>
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#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 <ext2fs/ext2_types.h>
+
/* 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 <string.h>
#include <time.h>
#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 <sys/types.h>
#endif
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#else
-#define PR_GET_DUMPABLE 3
-#endif
-#if (!defined(HAVE_PRCTL) && defined(linux))
-#include <sys/syscall.h>
-#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 <sys/mount.h>
#endif
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#else
-#define PR_GET_DUMPABLE 3
-#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#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.
*/