--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+subdirs = [
+ "contrib",
+ "debugfs",
+ "e2fsck",
+ "lib",
+ "misc",
+ "resize",
+]
+++ /dev/null
-include $(call all-subdir-makefiles)
check::
+fullcheck::
+
SHELL = /bin/sh
COMPRESS_EXT = gz bz2 bz Z
check-recursive: all
-TAGS clean-recursive distclean-recursive depend-recursive check-recursive \
- mostlyclean-recursive realclean-recursive coverage.txt-recursive:
+TAGS clean-recursive distclean-recursive depend-recursive fullcheck-recursive \
+ check-recursive mostlyclean-recursive realclean-recursive \
+ coverage.txt-recursive:
@for subdir in $(SUBDIRS); do \
if test -d $$subdir ; then \
target=`echo $@|$(SED) 's/-recursive//'`; \
check:: all check-recursive
+fullcheck:: all fullcheck-recursive
done
fi
-for ac_header in dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h attr/xattr.h linux/falloc.h linux/fd.h linux/major.h linux/loop.h net/if_dl.h netinet/in.h sys/acl.h sys/disklabel.h sys/disk.h sys/file.h sys/ioctl.h sys/key.h sys/mkdev.h sys/mman.h sys/mount.h sys/prctl.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysctl.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h
+for ac_header in dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h attr/xattr.h linux/falloc.h linux/fd.h linux/major.h linux/loop.h linux/types.h net/if_dl.h netinet/in.h sys/acl.h sys/disklabel.h sys/disk.h sys/file.h sys/ioctl.h sys/key.h sys/mkdev.h sys/mman.h sys/mount.h sys/prctl.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysctl.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
if test -n "$DLOPEN_LIB" ; then
ac_cv_func_dlopen=yes
fi
-for ac_func in __secure_getenv add_key backtrace blkid_probe_get_topology blkid_probe_enable_partitions chflags dlopen fadvise64 fallocate fallocate64 fchown fdatasync fstat64 ftruncate64 futimes getcwd getdtablesize getmntinfo getpwuid_r getrlimit getrusage jrand48 keyctl llistxattr llseek lseek64 mallinfo mbstowcs memalign mempcpy mmap msync nanosleep open64 pathconf posix_fadvise posix_fadvise64 posix_memalign prctl pread pwrite pread64 pwrite64 secure_getenv setmntent setresgid setresuid snprintf srandom stpcpy strcasecmp strdup strnlen strptime strtoull sync_file_range sysconf usleep utime utimes valloc
+for ac_func in __secure_getenv add_key backtrace blkid_probe_get_topology blkid_probe_enable_partitions chflags dlopen fadvise64 fallocate fallocate64 fchown fcntl fdatasync fstat64 fsync ftruncate64 futimes getcwd getdtablesize getmntinfo getpwuid_r getrlimit getrusage jrand48 keyctl llistxattr llseek lseek64 mallinfo mbstowcs memalign mempcpy mmap msync nanosleep open64 pathconf posix_fadvise posix_fadvise64 posix_memalign prctl pread pwrite pread64 pwrite64 secure_getenv setmntent setresgid setresuid snprintf srandom stpcpy strcasecmp strdup strnlen strptime strtoull sync_file_range sysconf usleep utime utimes valloc
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
linux/fd.h
linux/major.h
linux/loop.h
+ linux/types.h
net/if_dl.h
netinet/in.h
sys/acl.h
fallocate
fallocate64
fchown
+ fcntl
fdatasync
fstat64
+ fsync
ftruncate64
futimes
getcwd
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+subdirs = ["android"]
+
+//##########################################################################
+// Build fsstress
+
+cc_binary {
+ name: "fsstress",
+ host_supported: true,
+
+ srcs: ["fsstress.c"],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+ system_shared_libs: ["libc"],
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+//########################################################################
+// Build add_ext4_encrypt
+
+cc_binary {
+ name: "add_ext4_encrypt",
+ host_supported: true,
+
+ srcs: ["add_ext4_encrypt.c"],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+ shared_libs: [
+ "libext2fs",
+ "libext2_com_err",
+ ],
+ system_shared_libs: ["libc"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-###########################################################################
-# Build fsstress
-#
-fsstress_src_files := \
- fsstress.c
-
-fsstress_c_includes :=
-
-fsstress_cflags := -O2 -g -W -Wall
-
-fsstress_shared_libraries :=
-
-fsstress_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(fsstress_src_files)
-mke2fs_c_includesLOCAL_CFLAGS := $(fsstress_cflags)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(fsstress_system_shared_libraries)
-LOCAL_MODULE := fsstress
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(fsstress_src_files)
-LOCAL_CFLAGS := $(fsstress_cflags)
-LOCAL_MODULE := fsstress_host
-LOCAL_MODULE_STEM := fsstress
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_HOST_OS := linux
-
-include $(BUILD_HOST_EXECUTABLE)
-
-#########################################################################
-# Build add_ext4_encrypt
-#
-include $(CLEAR_VARS)
-
-add_ext4_encrypt_src_files := \
- add_ext4_encrypt.c
-
-add_ext4_encrypt_c_includes := \
- external/e2fsprogs/lib
-
-add_ext4_encrypt_cflags := -O2 -g -W -Wall
-
-add_ext4_encrypt_shared_libraries := \
- libext2fs \
- libext2_com_err
-
-add_ext4_encrypt_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(add_ext4_encrypt_src_files)
-LOCAL_C_INCLUDES := $(add_ext4_encrypt_c_includes)
-LOCAL_CFLAGS := $(add_ext4_encrypt_cflags)
-LOCAL_SHARED_LIBRARIES := $(add_ext4_encrypt_shared_libraries)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(add_ext4_encrypt_system_shared_libraries)
-LOCAL_MODULE := add_ext4_encrypt
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(add_ext4_encrypt_src_files)
-LOCAL_C_INCLUDES := $(add_ext4_encrypt_c_includes)
-LOCAL_CFLAGS := $(add_ext4_encrypt_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(add_ext4_encrypt_shared_libraries))
-LOCAL_MODULE := add_ext4_encrypt_host
-LOCAL_MODULE_STEM := add_ext4_encrypt
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
-
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+//##########################################################################
+// Build e2fsdroid
+
+cc_binary {
+ name: "e2fsdroid",
+ host_supported: true,
+
+ srcs: [
+ "e2fsdroid.c",
+ "block_range.c",
+ "fsmap.c",
+ "block_list.c",
+ "base_fs.c",
+ "perms.c",
+ "basefs_allocator.c",
+ "hashmap.c",
+ ],
+ cflags: ["-W", "-Wall"],
+ shared_libs: [
+ "libext2fs",
+ "libext2_com_err",
+ "libext2_misc",
+ "libcutils",
+ "libbase",
+ "libselinux",
+ "libcrypto",
+ ],
+}
+
+//##########################################################################
+// Build ext2simg
+
+cc_binary {
+ name: "ext2simg",
+ host_supported: true,
+
+ srcs: ["ext2simg.c"],
+ cflags: ["-W", "-Wall"],
+ shared_libs: [
+ "libext2fs",
+ "libext2_com_err",
+ "libsparse",
+ ],
+
+ target: {
+ host: {
+ shared_libs: ["libz-host"],
+ },
+ android: {
+ shared_libs: ["libz"],
+ },
+ },
+}
--- /dev/null
+#include "base_fs.h"
+#include <stdio.h>
+
+#define BASE_FS_VERSION "Base EXT4 version 1.0"
+
+struct base_fs {
+ FILE *file;
+ const char *mountpoint;
+ struct basefs_entry entry;
+};
+
+static FILE *basefs_open(const char *file)
+{
+ char *line = NULL;
+ size_t len;
+ FILE *f = fopen(file, "r");
+ if (!f)
+ return NULL;
+
+ if (getline(&line, &len, f) == -1 || !line)
+ goto err_getline;
+
+ if (strncmp(line, BASE_FS_VERSION, strlen(BASE_FS_VERSION)))
+ goto err_header;
+
+ free(line);
+ return f;
+
+err_header:
+ free(line);
+err_getline:
+ fclose(f);
+ return NULL;
+}
+
+static struct basefs_entry *basefs_readline(FILE *f, const char *mountpoint,
+ int *err)
+{
+ char *line = NULL, *saveptr1, *saveptr2, *block_range, *block;
+ int offset;
+ size_t len;
+ struct basefs_entry *entry = NULL;
+ blk64_t range_start, range_end;
+
+ if (getline(&line, &len, f) == -1) {
+ if (feof(f))
+ goto end;
+ goto err_getline;
+ }
+
+ entry = calloc(1, sizeof(*entry));
+ if (!entry)
+ goto err_alloc;
+
+ /*
+ * With BASEFS version 1.0, a typical line looks like this:
+ * /bin/mke2fs 5000-5004,8000,9000-9990
+ */
+ if (sscanf(line, "%ms%n", &entry->path, &offset) != 1)
+ goto err_sscanf;
+ len = strlen(mountpoint);
+ memmove(entry->path, entry->path + len, strlen(entry->path) - len + 1);
+
+ while (line[offset] == ' ')
+ ++offset;
+
+ block_range = strtok_r(line + offset, ",\n", &saveptr1);
+ while (block_range) {
+ block = strtok_r(block_range, "-", &saveptr2);
+ if (!block)
+ break;
+ range_start = atoll(block);
+ block = strtok_r(NULL, "-", &saveptr2);
+ range_end = block ? atoll(block) : range_start;
+ add_blocks_to_range(&entry->head, &entry->tail, range_start,
+ range_end);
+ block_range = strtok_r(NULL, ",\n", &saveptr1);
+ }
+end:
+ *err = 0;
+ free(line);
+ return entry;
+
+err_sscanf:
+ free(entry);
+err_alloc:
+ free(line);
+err_getline:
+ *err = 1;
+ return NULL;
+}
+
+static void free_base_fs_entry(void *e)
+{
+ struct basefs_entry *entry = e;
+ if (entry) {
+ free(entry->path);
+ free(entry);
+ }
+}
+
+struct hashmap *basefs_parse(const char *file, const char *mountpoint)
+{
+ int err;
+ struct hashmap *entries = NULL;
+ struct basefs_entry *entry;
+ FILE *f = basefs_open(file);
+ if (!f)
+ return NULL;
+ entries = hashmap_create(djb2_hash, free_base_fs_entry, 1024);
+ if (!entries)
+ goto end;
+
+ while ((entry = basefs_readline(f, mountpoint, &err)))
+ hashmap_add(entries, entry, entry->path);
+
+ if (err) {
+ fclose(f);
+ hashmap_free(entries);
+ return NULL;
+ }
+end:
+ fclose(f);
+ return entries;
+}
+
+static void *init(const char *file, const char *mountpoint)
+{
+ struct base_fs *params = malloc(sizeof(*params));
+
+ if (!params)
+ return NULL;
+ params->mountpoint = mountpoint;
+ params->file = fopen(file, "w+");
+ if (!params->file) {
+ free(params);
+ return NULL;
+ }
+ if (fwrite(BASE_FS_VERSION"\n", 1, strlen(BASE_FS_VERSION"\n"),
+ params->file) != strlen(BASE_FS_VERSION"\n")) {
+ fclose(params->file);
+ free(params);
+ return NULL;
+ }
+ return params;
+}
+
+static int start_new_file(char *path, ext2_ino_t ino EXT2FS_ATTR((unused)),
+ struct ext2_inode *inode, void *data)
+{
+ struct base_fs *params = data;
+
+ params->entry.head = params->entry.tail = NULL;
+ params->entry.path = LINUX_S_ISREG(inode->i_mode) ? path : NULL;
+ return 0;
+}
+
+static int add_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk64_t blocknr,
+ int metadata, void *data)
+{
+ struct base_fs *params = data;
+
+ if (params->entry.path && !metadata)
+ add_blocks_to_range(¶ms->entry.head, ¶ms->entry.tail,
+ blocknr, blocknr);
+ return 0;
+}
+
+static int inline_data(void *inline_data EXT2FS_ATTR((unused)),
+ void *data EXT2FS_ATTR((unused)))
+{
+ return 0;
+}
+
+static int end_new_file(void *data)
+{
+ struct base_fs *params = data;
+
+ if (!params->entry.path)
+ return 0;
+ if (fprintf(params->file, "%s%s ", params->mountpoint,
+ params->entry.path) < 0
+ || write_block_ranges(params->file, params->entry.head, ",")
+ || fwrite("\n", 1, 1, params->file) != 1)
+ return -1;
+
+ delete_block_ranges(params->entry.head);
+ return 0;
+}
+
+static int cleanup(void *data)
+{
+ struct base_fs *params = data;
+
+ fclose(params->file);
+ free(params);
+ return 0;
+}
+
+struct fsmap_format base_fs_format = {
+ .init = init,
+ .start_new_file = start_new_file,
+ .add_block = add_block,
+ .inline_data = inline_data,
+ .end_new_file = end_new_file,
+ .cleanup = cleanup,
+};
--- /dev/null
+#ifndef BASE_FS_H
+# define BASE_FS_H
+
+# include "fsmap.h"
+# include "hashmap.h"
+# include "block_range.h"
+
+struct basefs_entry {
+ char *path;
+ struct block_range *head;
+ struct block_range *tail;
+};
+
+extern struct fsmap_format base_fs_format;
+
+struct hashmap *basefs_parse(const char *file, const char *mountpoint);
+
+#endif /* !BASE_FS_H */
--- /dev/null
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "basefs_allocator.h"
+#include "block_range.h"
+#include "hashmap.h"
+#include "base_fs.h"
+
+struct base_fs_allocator {
+ struct hashmap *entries;
+ struct basefs_entry *cur_entry;
+};
+
+static errcode_t basefs_block_allocator(ext2_filsys, blk64_t, blk64_t *,
+ struct blk_alloc_ctx *ctx);
+
+static void fs_free_blocks_range(ext2_filsys fs, struct block_range *blocks)
+{
+ while (blocks) {
+ ext2fs_unmark_block_bitmap_range2(fs->block_map, blocks->start,
+ blocks->end - blocks->start + 1);
+ blocks = blocks->next;
+ }
+}
+
+static void fs_reserve_blocks_range(ext2_filsys fs, struct block_range *blocks)
+{
+ while (blocks) {
+ ext2fs_mark_block_bitmap_range2(fs->block_map,
+ blocks->start, blocks->end - blocks->start + 1);
+ blocks = blocks->next;
+ }
+}
+
+errcode_t base_fs_alloc_load(ext2_filsys fs, const char *file,
+ const char *mountpoint)
+{
+ errcode_t retval;
+ struct basefs_entry *e;
+ struct hashmap_entry *it = NULL;
+ struct base_fs_allocator *allocator;
+ struct hashmap *entries = basefs_parse(file, mountpoint);
+ if (!entries)
+ return -1;
+
+ allocator = malloc(sizeof(*allocator));
+ if (!allocator)
+ goto err_alloc;
+
+ retval = ext2fs_read_bitmaps(fs);
+ if (retval)
+ goto err_bitmap;
+ while ((e = hashmap_iter_in_order(entries, &it)))
+ fs_reserve_blocks_range(fs, e->head);
+
+ allocator->cur_entry = NULL;
+ allocator->entries = entries;
+
+ /* Overhide the default allocator */
+ fs->get_alloc_block2 = basefs_block_allocator;
+ fs->priv_data = allocator;
+
+ return 0;
+
+err_bitmap:
+ free(allocator);
+err_alloc:
+ hashmap_free(entries);
+ return EXIT_FAILURE;
+}
+
+static errcode_t basefs_block_allocator(ext2_filsys fs, blk64_t goal,
+ blk64_t *ret, struct blk_alloc_ctx *ctx)
+{
+ errcode_t retval;
+ struct block_range *next_range;
+ struct base_fs_allocator *allocator = fs->priv_data;
+ struct basefs_entry *e = allocator->cur_entry;
+
+ /* Try to get a block from the base_fs */
+ if (e && e->head && ctx && (ctx->flags & BLOCK_ALLOC_DATA)) {
+ *ret = e->head->start;
+ e->head->start += 1;
+ if (e->head->start > e->head->end) {
+ next_range = e->head->next;
+ free(e->head);
+ e->head = next_range;
+ }
+ } else { /* Allocate a new block */
+ retval = ext2fs_new_block2(fs, goal, fs->block_map, ret);
+ if (retval)
+ return retval;
+ ext2fs_mark_block_bitmap2(fs->block_map, *ret);
+ }
+ return 0;
+}
+
+void base_fs_alloc_cleanup(ext2_filsys fs)
+{
+ struct basefs_entry *e;
+ struct hashmap_entry *it = NULL;
+ struct base_fs_allocator *allocator = fs->priv_data;
+
+ while ((e = hashmap_iter_in_order(allocator->entries, &it))) {
+ fs_free_blocks_range(fs, e->head);
+ delete_block_ranges(e->head);
+ e->head = e->tail = NULL;
+ }
+
+ fs->priv_data = NULL;
+ fs->get_alloc_block2 = NULL;
+ hashmap_free(allocator->entries);
+ free(allocator);
+}
+
+errcode_t base_fs_alloc_set_target(ext2_filsys fs, const char *target_path,
+ const char *name EXT2FS_ATTR((unused)),
+ ext2_ino_t parent_ino EXT2FS_ATTR((unused)),
+ ext2_ino_t root EXT2FS_ATTR((unused)), mode_t mode)
+{
+ struct base_fs_allocator *allocator = fs->priv_data;
+
+ if (mode != S_IFREG)
+ return 0;
+
+ if (allocator)
+ allocator->cur_entry = hashmap_lookup(allocator->entries,
+ target_path);
+ return 0;
+}
+
+errcode_t base_fs_alloc_unset_target(ext2_filsys fs,
+ const char *target_path EXT2FS_ATTR((unused)),
+ const char *name EXT2FS_ATTR((unused)),
+ ext2_ino_t parent_ino EXT2FS_ATTR((unused)),
+ ext2_ino_t root EXT2FS_ATTR((unused)), mode_t mode)
+{
+ struct base_fs_allocator *allocator = fs->priv_data;
+
+ if (!allocator || !allocator->cur_entry || mode != S_IFREG)
+ return 0;
+
+ fs_free_blocks_range(fs, allocator->cur_entry->head);
+ delete_block_ranges(allocator->cur_entry->head);
+ allocator->cur_entry->head = allocator->cur_entry->tail = NULL;
+ allocator->cur_entry = NULL;
+ return 0;
+}
--- /dev/null
+#ifndef BASE_FS_ALLOCATOR_H
+# define BASE_FS_ALLOCATOR_H
+
+# include <time.h>
+# include <ext2fs/ext2fs.h>
+
+errcode_t base_fs_alloc_load(ext2_filsys fs, const char *file,
+ const char *mountpoint);
+void base_fs_alloc_cleanup(ext2_filsys fs);
+
+errcode_t base_fs_alloc_set_target(ext2_filsys fs, const char *target_path,
+ const char *name, ext2_ino_t parent_ino, ext2_ino_t root, mode_t mode);
+errcode_t base_fs_alloc_unset_target(ext2_filsys fs, const char *target_path,
+ const char *name, ext2_ino_t parent_ino, ext2_ino_t root, mode_t mode);
+
+#endif /* !BASE_FS_ALLOCATOR_H */
--- /dev/null
+#include "block_list.h"
+#include "block_range.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+struct block_list {
+ FILE *f;
+ const char *mountpoint;
+
+ struct {
+ const char *filename;
+ struct block_range *head;
+ struct block_range *tail;
+ } entry;
+};
+
+static void *init(const char *file, const char *mountpoint)
+{
+ struct block_list *params = malloc(sizeof(*params));
+
+ if (!params)
+ return NULL;
+ params->mountpoint = mountpoint;
+ params->f = fopen(file, "w+");
+ if (!params->f) {
+ free(params);
+ return NULL;
+ }
+ return params;
+}
+
+static int start_new_file(char *path, ext2_ino_t ino EXT2FS_ATTR((unused)),
+ struct ext2_inode *inode EXT2FS_ATTR((unused)),
+ void *data)
+{
+ struct block_list *params = data;
+
+ params->entry.head = params->entry.tail = NULL;
+ params->entry.filename = LINUX_S_ISREG(inode->i_mode) ? path : NULL;
+ return 0;
+}
+
+static int add_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk64_t blocknr,
+ int metadata, void *data)
+{
+ struct block_list *params = data;
+
+ if (params->entry.filename && !metadata)
+ add_blocks_to_range(¶ms->entry.head, ¶ms->entry.tail,
+ blocknr, blocknr);
+ return 0;
+}
+
+static int inline_data(void *inline_data EXT2FS_ATTR((unused)),
+ void *data EXT2FS_ATTR((unused)))
+{
+ return 0;
+}
+
+static int end_new_file(void *data)
+{
+ struct block_list *params = data;
+
+ if (!params->entry.filename || !params->entry.head)
+ return 0;
+ if (fprintf(params->f, "%s%s ", params->mountpoint,
+ params->entry.filename) < 0
+ || write_block_ranges(params->f, params->entry.head, " ")
+ || fwrite("\n", 1, 1, params->f) != 1)
+ return -1;
+
+ delete_block_ranges(params->entry.head);
+ return 0;
+}
+
+static int cleanup(void *data)
+{
+ struct block_list *params = data;
+
+ fclose(params->f);
+ free(params);
+ return 0;
+}
+
+struct fsmap_format block_list_format = {
+ .init = init,
+ .start_new_file = start_new_file,
+ .add_block = add_block,
+ .inline_data = inline_data,
+ .end_new_file = end_new_file,
+ .cleanup = cleanup,
+};
--- /dev/null
+#ifndef BLOCK_LIST_H
+# define BLOCK_LIST_H
+
+# include "fsmap.h"
+
+extern struct fsmap_format block_list_format;
+
+#endif /* !BLOCK_LIST_H */
--- /dev/null
+#define _GNU_SOURCE
+
+#include "block_range.h"
+#include <stdio.h>
+
+struct block_range *new_block_range(blk64_t start, blk64_t end)
+{
+ struct block_range *range = malloc(sizeof(*range));
+ range->start = start;
+ range->end = end;
+ range->next = NULL;
+ return range;
+}
+
+void add_blocks_to_range(struct block_range **head, struct block_range **tail,
+ blk64_t blk_start, blk64_t blk_end)
+{
+ if (*head == NULL)
+ *head = *tail = new_block_range(blk_start, blk_end);
+ else if ((*tail)->end + 1 == blk_start)
+ (*tail)->end += (blk_end - blk_start + 1);
+ else {
+ struct block_range *range = new_block_range(blk_start, blk_end);
+ (*tail)->next = range;
+ *tail = range;
+ }
+}
+
+void delete_block_ranges(struct block_range *head)
+{
+ struct block_range *tmp;
+
+ while (head) {
+ tmp = head->next;
+ free(head);
+ head = tmp;
+ }
+}
+
+int write_block_ranges(FILE *f, struct block_range *range,
+ char *sep)
+{
+ int len;
+ char *buf;
+
+ while (range) {
+ if (range->start == range->end)
+ len = asprintf(&buf, "%llu%s", range->start, sep);
+ else
+ len = asprintf(&buf, "%llu-%llu%s", range->start,
+ range->end, sep);
+ if (fwrite(buf, 1, len, f) != (size_t)len) {
+ free(buf);
+ return -1;
+ }
+ free(buf);
+ range = range->next;
+ }
+
+ len = strlen(sep);
+ if (fseek(f, -len, SEEK_CUR) == -len)
+ return -1;
+ return 0;
+}
--- /dev/null
+#ifndef BLOCK_RANGE_H
+# define BLOCK_RANGE_H
+
+# include <sys/types.h>
+# include <ext2fs/ext2fs.h>
+
+struct block_range {
+ blk64_t start;
+ blk64_t end;
+ struct block_range *next;
+};
+
+void add_blocks_to_range(struct block_range **head, struct block_range **tail,
+ blk64_t blk_start, blk64_t blk_end);
+void delete_block_ranges(struct block_range *head);
+int write_block_ranges(FILE *f, struct block_range *range, char *sep);
+
+#endif /* !BLOCK_RANGE_H */
--- /dev/null
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <ext2fs/ext2fs.h>
+
+#include "perms.h"
+#include "base_fs.h"
+#include "block_list.h"
+#include "basefs_allocator.h"
+#include "create_inode.h"
+
+static char *prog_name = "e2fsdroid";
+static char *in_file;
+static char *block_list;
+static char *basefs_out;
+static char *basefs_in;
+static char *mountpoint = "";
+static time_t fixed_time = -1;
+static char *fs_config_file;
+static struct selinux_opt seopt_file[8];
+static int max_nr_opt = (int)sizeof(seopt_file) / sizeof(seopt_file[0]);
+static char *product_out;
+static char *src_dir;
+static int android_configure;
+static int android_sparse_file = 1;
+
+static void usage(int ret)
+{
+ fprintf(stderr, "%s [-B block_list] [-D basefs_out] [-T timestamp]\n"
+ "\t[-C fs_config] [-S file_contexts] [-p product_out]\n"
+ "\t[-a mountpoint] [-d basefs_in] [-f src_dir] [-e] image\n",
+ prog_name);
+ exit(ret);
+}
+
+static char *absolute_path(const char *file)
+{
+ char *ret;
+ char cwd[PATH_MAX];
+
+ if (file[0] != '/') {
+ getcwd(cwd, PATH_MAX);
+ ret = malloc(strlen(cwd) + 1 + strlen(file) + 1);
+ if (ret)
+ sprintf(ret, "%s/%s", cwd, file);
+ } else
+ ret = strdup(file);
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int c;
+ char *p;
+ int flags = EXT2_FLAG_RW;
+ errcode_t retval;
+ io_manager io_mgr;
+ ext2_filsys fs = NULL;
+ struct fs_ops_callbacks fs_callbacks = { NULL, NULL };
+ char *token;
+ int nr_opt = 0;
+
+ add_error_table(&et_ext2_error_table);
+
+ while ((c = getopt (argc, argv, "T:C:S:p:a:D:d:B:f:e")) != EOF) {
+ switch (c) {
+ case 'T':
+ fixed_time = strtoul(optarg, &p, 0);
+ android_configure = 1;
+ break;
+ case 'C':
+ fs_config_file = absolute_path(optarg);
+ android_configure = 1;
+ break;
+ case 'S':
+ token = strtok(optarg, ",");
+ while (token) {
+ if (nr_opt == max_nr_opt) {
+ fprintf(stderr, "Expected at most %d selinux opts\n",
+ max_nr_opt);
+ exit(EXIT_FAILURE);
+ }
+ seopt_file[nr_opt].type = SELABEL_OPT_PATH;
+ seopt_file[nr_opt].value = absolute_path(token);
+ nr_opt++;
+ token = strtok(NULL, ",");
+ }
+ android_configure = 1;
+ break;
+ case 'p':
+ product_out = absolute_path(optarg);
+ break;
+ case 'a':
+ mountpoint = strdup(optarg);
+ break;
+ case 'D':
+ basefs_out = absolute_path(optarg);
+ break;
+ case 'd':
+ basefs_in = absolute_path(optarg);
+ break;
+ case 'B':
+ block_list = absolute_path(optarg);
+ break;
+ case 'f':
+ src_dir = absolute_path(optarg);
+ break;
+ case 'e':
+ android_sparse_file = 0;
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ }
+ }
+ if (optind >= argc) {
+ fprintf(stderr, "Expected filename after options\n");
+ exit(EXIT_FAILURE);
+ }
+ in_file = strdup(argv[optind]);
+
+ io_mgr = android_sparse_file ? sparse_io_manager: unix_io_manager;
+ retval = ext2fs_open(in_file, flags, 0, 0, io_mgr, &fs);
+ if (retval) {
+ com_err(prog_name, retval, "while opening file %s\n", in_file);
+ return retval;
+ }
+
+ if (src_dir) {
+ ext2fs_read_bitmaps(fs);
+ if (basefs_in) {
+ retval = base_fs_alloc_load(fs, basefs_in, mountpoint);
+ if (retval) {
+ com_err(prog_name, retval, "%s",
+ "while reading base_fs file");
+ exit(1);
+ }
+ fs_callbacks.create_new_inode =
+ base_fs_alloc_set_target;
+ fs_callbacks.end_create_new_inode =
+ base_fs_alloc_unset_target;
+ }
+ retval = populate_fs2(fs, EXT2_ROOT_INO, src_dir,
+ EXT2_ROOT_INO, &fs_callbacks);
+ if (retval) {
+ com_err(prog_name, retval, "%s",
+ "while populating file system");
+ exit(1);
+ }
+ if (basefs_in)
+ base_fs_alloc_cleanup(fs);
+ }
+
+ if (android_configure) {
+ retval = android_configure_fs(fs, src_dir, product_out, mountpoint,
+ seopt_file, nr_opt, fs_config_file, fixed_time);
+ if (retval) {
+ com_err(prog_name, retval, "%s",
+ "while configuring the file system");
+ exit(1);
+ }
+ }
+
+ if (block_list) {
+ retval = fsmap_iter_filsys(fs, &block_list_format, block_list,
+ mountpoint);
+ if (retval) {
+ com_err(prog_name, retval, "%s",
+ "while creating the block_list");
+ exit(1);
+ }
+ }
+
+ if (basefs_out) {
+ retval = fsmap_iter_filsys(fs, &base_fs_format,
+ basefs_out, mountpoint);
+ if (retval) {
+ com_err(prog_name, retval, "%s",
+ "while creating the basefs file");
+ exit(1);
+ }
+ }
+
+ retval = ext2fs_close_free(&fs);
+ if (retval) {
+ com_err(prog_name, retval, "%s",
+ "while writing superblocks");
+ exit(1);
+ }
+
+ remove_error_table(&et_ext2_error_table);
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libgen.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ext2fs/ext2fs.h>
+#include <et/com_err.h>
+#include <sparse/sparse.h>
+
+struct {
+ int crc;
+ int sparse;
+ int gzip;
+ char *in_file;
+ char *out_file;
+ bool overwrite_input;
+} params = {
+ .crc = 0,
+ .sparse = 1,
+ .gzip = 0,
+};
+
+#define ext2fs_fatal(Retval, Format, ...) \
+ do { \
+ com_err("error", Retval, Format, __VA_ARGS__); \
+ exit(EXIT_FAILURE); \
+ } while(0)
+
+#define sparse_fatal(Format) \
+ do { \
+ fprintf(stderr, "sparse: "Format); \
+ exit(EXIT_FAILURE); \
+ } while(0)
+
+static void usage(char *path)
+{
+ char *progname = basename(path);
+
+ fprintf(stderr, "%s [ options ] <image or block device> <output image>\n"
+ " -c include CRC block\n"
+ " -z gzip output\n"
+ " -S don't use sparse output format\n", progname);
+}
+
+static struct buf_item {
+ struct buf_item *next;
+ void *buf[0];
+} *buf_list;
+
+static void add_chunk(ext2_filsys fs, struct sparse_file *s, blk_t chunk_start, blk_t chunk_end)
+{
+ int retval;
+ unsigned int nb_blk = chunk_end - chunk_start;
+ size_t len = nb_blk * fs->blocksize;
+ int64_t offset = (int64_t)chunk_start * (int64_t)fs->blocksize;
+
+ if (params.overwrite_input == false) {
+ if (sparse_file_add_file(s, params.in_file, offset, len, chunk_start) < 0)
+ sparse_fatal("adding data to the sparse file");
+ } else {
+ /*
+ * The input file will be overwritten, make a copy of
+ * the blocks
+ */
+ struct buf_item *bi = calloc(1, sizeof(struct buf_item) + len);
+ if (buf_list == NULL)
+ buf_list = bi;
+ else {
+ bi->next = buf_list;
+ buf_list = bi;
+ }
+
+ retval = io_channel_read_blk64(fs->io, chunk_start, nb_blk, bi->buf);
+ if (retval < 0)
+ ext2fs_fatal(retval, "reading block %u - %u", chunk_start, chunk_end);
+
+ if (sparse_file_add_data(s, bi->buf, len, chunk_start) < 0)
+ sparse_fatal("adding data to the sparse file");
+ }
+}
+
+static void free_chunks(void)
+{
+ struct buf_item *bi;
+
+ while (buf_list) {
+ bi = buf_list->next;
+ free(buf_list);
+ buf_list = bi;
+ }
+}
+
+static struct sparse_file *ext_to_sparse(const char *in_file)
+{
+ errcode_t retval;
+ ext2_filsys fs;
+ struct sparse_file *s;
+ int64_t chunk_start = -1;
+ blk_t first_blk, last_blk, nb_blk, cur_blk;
+
+ retval = ext2fs_open(in_file, 0, 0, 0, unix_io_manager, &fs);
+ if (retval)
+ ext2fs_fatal(retval, "while reading %s", in_file);
+
+ retval = ext2fs_read_block_bitmap(fs);
+ if (retval)
+ ext2fs_fatal(retval, "while reading block bitmap of %s", in_file);
+
+ first_blk = ext2fs_get_block_bitmap_start2(fs->block_map);
+ last_blk = ext2fs_get_block_bitmap_end2(fs->block_map);
+ nb_blk = last_blk - first_blk + 1;
+
+ s = sparse_file_new(fs->blocksize, (uint64_t)fs->blocksize * (uint64_t)nb_blk);
+ if (!s)
+ sparse_fatal("creating sparse file");
+
+ /*
+ * The sparse format encodes the size of a chunk (and its header) in a
+ * 32-bit unsigned integer (UINT32_MAX)
+ * When writing the chunk, the library uses a single call to write().
+ * Linux's implementation of the 'write' syscall does not allow transfers
+ * larger than INT32_MAX (32-bit _and_ 64-bit systems).
+ * Make sure we do not create chunks larger than this limit.
+ */
+ int64_t max_blk_per_chunk = (INT32_MAX - 12) / fs->blocksize;
+
+ /* Iter on the blocks to merge contiguous chunk */
+ for (cur_blk = first_blk; cur_blk <= last_blk; ++cur_blk) {
+ if (ext2fs_test_block_bitmap2(fs->block_map, cur_blk)) {
+ if (chunk_start == -1) {
+ chunk_start = cur_blk;
+ } else if (cur_blk - chunk_start + 1 == max_blk_per_chunk) {
+ add_chunk(fs, s, chunk_start, cur_blk);
+ chunk_start = -1;
+ }
+ } else if (chunk_start != -1) {
+ add_chunk(fs, s, chunk_start, cur_blk);
+ chunk_start = -1;
+ }
+ }
+ if (chunk_start != -1)
+ add_chunk(fs, s, chunk_start, cur_blk - 1);
+
+ ext2fs_free(fs);
+ return s;
+}
+
+static bool same_file(const char *in, const char *out)
+{
+ struct stat st1, st2;
+
+ if (access(out, F_OK) == -1)
+ return false;
+
+ if (lstat(in, &st1) == -1)
+ ext2fs_fatal(errno, "stat %s\n", in);
+ if (lstat(out, &st2) == -1)
+ ext2fs_fatal(errno, "stat %s\n", out);
+ return st1.st_ino == st2.st_ino;
+}
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ int out_fd;
+ errcode_t retval;
+ struct sparse_file *s;
+
+ while ((opt = getopt(argc, argv, "czS")) != -1) {
+ switch(opt) {
+ case 'c':
+ params.crc = 1;
+ break;
+ case 'z':
+ params.gzip = 1;
+ break;
+ case 'S':
+ params.sparse = 0;
+ break;
+ default:
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (optind + 1 >= argc) {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ params.in_file = strdup(argv[optind++]);
+ params.out_file = strdup(argv[optind]);
+ params.overwrite_input = same_file(params.in_file, params.out_file);
+
+ s = ext_to_sparse(params.in_file);
+
+ out_fd = open(params.out_file, O_WRONLY | O_CREAT | O_TRUNC, 0664);
+ if (out_fd == -1)
+ ext2fs_fatal(errno, "opening %s\n", params.out_file);
+ if (sparse_file_write(s, out_fd, params.gzip, params.sparse, params.crc) < 0)
+ sparse_fatal("writing sparse file");
+
+ sparse_file_destroy(s);
+
+ free(params.in_file);
+ free(params.out_file);
+ free_chunks();
+ close(out_fd);
+
+ return 0;
+}
--- /dev/null
+#include "fsmap.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "support/nls-enable.h"
+
+struct walk_ext_priv_data {
+ char *path;
+ ext2_filsys fs;
+ struct fsmap_format *format;
+};
+
+static int walk_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk64_t *blocknr,
+ e2_blkcnt_t blockcnt,
+ blk64_t ref64_blk EXT2FS_ATTR((unused)),
+ int ref_offset EXT2FS_ATTR((unused)),
+ void *priv)
+{
+ struct walk_ext_priv_data *pdata = priv;
+ struct fsmap_format *format = pdata->format;
+
+ return format->add_block(fs, *blocknr, blockcnt < 0, format->private);
+}
+
+static errcode_t ino_iter_blocks(ext2_filsys fs, ext2_ino_t ino,
+ struct walk_ext_priv_data *pdata)
+{
+ errcode_t retval;
+ struct ext2_inode inode;
+ struct fsmap_format *format = pdata->format;
+
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ if (retval)
+ return retval;
+
+ if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
+ return format->inline_data(&(inode.i_block[0]),
+ format->private);
+
+ retval = ext2fs_block_iterate3(fs, ino, 0, NULL, walk_block, pdata);
+ if (retval)
+ com_err(__func__, retval, _("listing blocks of ino \"%u\""),
+ ino);
+ return retval;
+}
+
+static int is_dir(ext2_filsys fs, ext2_ino_t ino)
+{
+ struct ext2_inode inode;
+
+ if (ext2fs_read_inode(fs, ino, &inode))
+ return 0;
+ return S_ISDIR(inode.i_mode);
+}
+
+static int walk_ext_dir(ext2_ino_t dir EXT2FS_ATTR((unused)),
+ int flags EXT2FS_ATTR((unused)),
+ struct ext2_dir_entry *de,
+ int offset EXT2FS_ATTR((unused)),
+ int blocksize EXT2FS_ATTR((unused)),
+ char *buf EXT2FS_ATTR((unused)), void *priv_data)
+{
+ errcode_t retval;
+ struct ext2_inode inode;
+ char *filename, *cur_path, *name = de->name;
+ int name_len = de->name_len & 0xff;
+ struct walk_ext_priv_data *pdata = priv_data;
+ struct fsmap_format *format = pdata->format;
+
+ if (!strncmp(name, ".", name_len)
+ || !strncmp(name, "..", name_len)
+ || !strncmp(name, "lost+found", 10))
+ return 0;
+
+ if (asprintf(&filename, "%s/%.*s", pdata->path, name_len, name) < 0)
+ return -ENOMEM;
+
+ retval = ext2fs_read_inode(pdata->fs, de->inode, &inode);
+ if (retval) {
+ com_err(__func__, retval, _("reading ino \"%u\""), de->inode);
+ goto end;
+ }
+ format->start_new_file(filename, de->inode, &inode, format->private);
+ retval = ino_iter_blocks(pdata->fs, de->inode, pdata);
+ if (retval)
+ return retval;
+ format->end_new_file(format->private);
+
+ retval = 0;
+ if (is_dir(pdata->fs, de->inode)) {
+ cur_path = pdata->path;
+ pdata->path = filename;
+ retval = ext2fs_dir_iterate2(pdata->fs, de->inode, 0, NULL,
+ walk_ext_dir, pdata);
+ pdata->path = cur_path;
+ }
+
+end:
+ free(filename);
+ return retval;
+}
+
+errcode_t fsmap_iter_filsys(ext2_filsys fs, struct fsmap_format *format,
+ const char *file, const char *mountpoint)
+{
+ struct walk_ext_priv_data pdata;
+ errcode_t retval;
+
+ format->private = format->init(file, mountpoint);
+ pdata.fs = fs;
+ pdata.path = "";
+ pdata.format = format;
+
+ retval = ext2fs_dir_iterate2(fs, EXT2_ROOT_INO, 0, NULL, walk_ext_dir, &pdata);
+
+ format->cleanup(format->private);
+ return retval;
+}
--- /dev/null
+#ifndef FSMAP_H
+# define FSMAP_H
+
+# ifndef _GNU_SOURCE
+# define _GNU_SOURCE // asprintf
+# endif
+# include <stdio.h>
+# include <stdint.h>
+# include <stdbool.h>
+# include <sys/types.h>
+# include <ext2fs/ext2fs.h>
+
+struct fsmap_format {
+ void* (* init)(const char *file, const char *mountpoint);
+ int (* start_new_file)(char *path, ext2_ino_t ino,
+ struct ext2_inode *inode, void *data);
+ int (* add_block)(ext2_filsys fs, blk64_t blocknr, int metadata,
+ void *data);
+ int (* inline_data)(void *inline_data, void *data);
+ int (* end_new_file)(void *data);
+ int (* cleanup)(void *data);
+
+ void *private;
+};
+
+errcode_t fsmap_iter_filsys(ext2_filsys fs, struct fsmap_format *format,
+ const char *file, const char *mountpoint);
+
+#endif /* !FSMAP_H */
--- /dev/null
+#include "hashmap.h"
+#include <string.h>
+
+uint32_t djb2_hash(const void *str)
+{
+ int c;
+ const char *s = str;
+ uint32_t hash = 5381;
+
+ while ((c = *s++))
+ hash = ((hash << 5) + hash) + c;
+ return hash;
+}
+
+struct hashmap *hashmap_create(uint32_t(*hash_fct)(const void*),
+ void(*free_fct)(void*), size_t size)
+{
+ struct hashmap *h = calloc(sizeof(struct hashmap) +
+ sizeof(struct hashmap_entry) * size, 1);
+ h->size = size;
+ h->free = free_fct;
+ h->hash = hash_fct;
+ h->first = h->last = NULL;
+ return h;
+}
+
+void hashmap_add(struct hashmap *h, void *data, const void *key)
+{
+ uint32_t hash = h->hash(key) % h->size;
+ struct hashmap_entry *e = malloc(sizeof(*e));
+
+ e->data = data;
+ e->key = key;
+ e->next = h->entries[hash];
+ h->entries[hash] = e;
+
+ e->list_prev = NULL;
+ e->list_next = h->first;
+ if (h->first)
+ h->first->list_prev = e;
+ h->first = e;
+ if (!h->last)
+ h->last = e;
+}
+
+void *hashmap_lookup(struct hashmap *h, const void *key)
+{
+ struct hashmap_entry *iter;
+ uint32_t hash = h->hash(key) % h->size;
+
+ for (iter = h->entries[hash]; iter; iter = iter->next)
+ if (!strcmp(iter->key, key))
+ return iter->data;
+ return NULL;
+}
+
+void *hashmap_iter_in_order(struct hashmap *h, struct hashmap_entry **it)
+{
+ *it = *it ? (*it)->list_next : h->first;
+ return *it ? (*it)->data : NULL;
+}
+
+void hashmap_free(struct hashmap *h)
+{
+ for (size_t i = 0; i < h->size; ++i) {
+ struct hashmap_entry *it = h->entries[i];
+ while (it) {
+ struct hashmap_entry *tmp = it->next;
+ if (h->free)
+ h->free(it->data);
+ free(it);
+ it = tmp;
+ }
+ }
+ free(h);
+}
--- /dev/null
+#ifndef HASHMAP_H
+# define HASHMAP_H
+
+# include <stdlib.h>
+# include <stdint.h>
+
+struct hashmap {
+ uint32_t size;
+ uint32_t(*hash)(const void *key);
+ void(*free)(void*);
+ struct hashmap_entry *first;
+ struct hashmap_entry *last;
+ struct hashmap_entry {
+ void *data;
+ const void *key;
+ struct hashmap_entry *next;
+ struct hashmap_entry *list_next;
+ struct hashmap_entry *list_prev;
+ } *entries[0];
+};
+
+struct hashmap *hashmap_create(uint32_t(*hash_fct)(const void*),
+ void(*free_fct)(void*), size_t size);
+void hashmap_add(struct hashmap *h, void *data, const void *key);
+void *hashmap_lookup(struct hashmap *h, const void *key);
+void *hashmap_iter_in_order(struct hashmap *h, struct hashmap_entry **it);
+void hashmap_del(struct hashmap *h, struct hashmap_entry *e);
+void hashmap_free(struct hashmap *h);
+
+uint32_t djb2_hash(const void *str);
+
+#endif /* !HASHMAP_H */
--- /dev/null
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE //asprintf
+#endif
+#include "perms.h"
+#include "support/nls-enable.h"
+#include <time.h>
+#include <sys/stat.h>
+
+#ifndef XATTR_SELINUX_SUFFIX
+# define XATTR_SELINUX_SUFFIX "selinux"
+#endif
+#ifndef XATTR_CAPS_SUFFIX
+# define XATTR_CAPS_SUFFIX "capability"
+#endif
+
+struct inode_params {
+ ext2_filsys fs;
+ char *path;
+ char *filename;
+ char *src_dir;
+ char *target_out;
+ char *mountpoint;
+ fs_config_f fs_config_func;
+ struct selabel_handle *sehnd;
+ time_t fixed_time;
+};
+
+static errcode_t ino_add_xattr(ext2_filsys fs, ext2_ino_t ino, const char *name,
+ const void *value, int value_len)
+{
+ errcode_t retval, close_retval;
+ struct ext2_xattr_handle *xhandle;
+
+ retval = ext2fs_xattrs_open(fs, ino, &xhandle);
+ if (retval) {
+ com_err(__func__, retval, _("while opening inode %u"), ino);
+ return retval;
+ }
+ retval = ext2fs_xattrs_read(xhandle);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while reading xattrs of inode %u"), ino);
+ goto xattrs_close;
+ }
+ retval = ext2fs_xattr_set(xhandle, name, value, value_len);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while setting xattrs of inode %u"), ino);
+ goto xattrs_close;
+ }
+ retval = ext2fs_xattrs_write(xhandle);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while writting xattrs of inode %u"), ino);
+ goto xattrs_close;
+ }
+xattrs_close:
+ close_retval = ext2fs_xattrs_close(&xhandle);
+ if (close_retval) {
+ com_err(__func__, close_retval,
+ _("while closing xattrs of inode %u"), ino);
+ return retval ? retval : close_retval;
+ }
+ return retval;
+}
+
+static errcode_t set_selinux_xattr(ext2_filsys fs, ext2_ino_t ino,
+ struct inode_params *params)
+{
+ errcode_t retval;
+ char *secontext = NULL;
+ struct ext2_inode inode;
+
+ if (params->sehnd == NULL)
+ return 0;
+
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while reading inode %u"), ino);
+ return retval;
+ }
+
+ retval = selabel_lookup(params->sehnd, &secontext, params->filename,
+ inode.i_mode);
+ if (retval < 0) {
+ com_err(__func__, retval,
+ _("searching for label \"%s\""), params->filename);
+ exit(1);
+ }
+
+ retval = ino_add_xattr(fs, ino, "security." XATTR_SELINUX_SUFFIX,
+ secontext, strlen(secontext) + 1);
+
+ freecon(secontext);
+ return retval;
+}
+
+static errcode_t set_perms_and_caps(ext2_filsys fs, ext2_ino_t ino,
+ struct inode_params *params)
+{
+ errcode_t retval;
+ uint64_t capabilities = 0;
+ struct ext2_inode inode;
+ struct vfs_cap_data cap_data;
+ unsigned int uid = 0, gid = 0, imode = 0;
+
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ if (retval) {
+ com_err(__func__, retval, _("while reading inode %u"), ino);
+ return retval;
+ }
+
+ /* Permissions */
+ if (params->fs_config_func != NULL) {
+ params->fs_config_func(params->filename, S_ISDIR(inode.i_mode),
+ params->target_out, &uid, &gid, &imode,
+ &capabilities);
+ inode.i_uid = uid & 0xffff;
+ inode.i_gid = gid & 0xffff;
+ inode.i_mode = (inode.i_mode & S_IFMT) | (imode & 0xffff);
+ retval = ext2fs_write_inode(fs, ino, &inode);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while writting inode %u"), ino);
+ return retval;
+ }
+ }
+
+ /* Capabilities */
+ if (!capabilities)
+ return 0;
+ memset(&cap_data, 0, sizeof(cap_data));
+ cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
+ cap_data.data[0].permitted = (uint32_t) (capabilities & 0xffffffff);
+ cap_data.data[1].permitted = (uint32_t) (capabilities >> 32);
+ return ino_add_xattr(fs, ino, "security." XATTR_CAPS_SUFFIX,
+ &cap_data, sizeof(cap_data));
+}
+
+static errcode_t set_timestamp(ext2_filsys fs, ext2_ino_t ino,
+ struct inode_params *params)
+{
+ errcode_t retval;
+ struct ext2_inode inode;
+ struct stat stat;
+ char *src_filename = NULL;
+
+ retval = ext2fs_read_inode(fs, ino, &inode);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while reading inode %u"), ino);
+ return retval;
+ }
+
+ if (params->fixed_time == -1 && params->src_dir) {
+ /* replace mountpoint from filename with src_dir */
+ if (asprintf(&src_filename, "%s/%s", params->src_dir,
+ params->filename + strlen(params->mountpoint)) < 0) {
+ return -ENOMEM;
+ }
+ retval = lstat(src_filename, &stat);
+ if (retval < 0) {
+ com_err(__func__, retval,
+ _("while lstat file %s"), src_filename);
+ goto end;
+ }
+ inode.i_atime = inode.i_ctime = inode.i_mtime = stat.st_mtime;
+ } else {
+ inode.i_atime = inode.i_ctime = inode.i_mtime = params->fixed_time;
+ }
+
+ retval = ext2fs_write_inode(fs, ino, &inode);
+ if (retval) {
+ com_err(__func__, retval,
+ _("while writting inode %u"), ino);
+ goto end;
+ }
+
+end:
+ free(src_filename);
+ return retval;
+}
+
+static int is_dir(ext2_filsys fs, ext2_ino_t ino)
+{
+ struct ext2_inode inode;
+
+ if (ext2fs_read_inode(fs, ino, &inode))
+ return 0;
+ return S_ISDIR(inode.i_mode);
+}
+
+static errcode_t androidify_inode(ext2_filsys fs, ext2_ino_t ino,
+ struct inode_params *params)
+{
+ errcode_t retval;
+
+ retval = set_timestamp(fs, ino, params);
+ if (retval)
+ return retval;
+
+ retval = set_selinux_xattr(fs, ino, params);
+ if (retval)
+ return retval;
+
+ return set_perms_and_caps(fs, ino, params);
+}
+
+static int walk_dir(ext2_ino_t dir EXT2FS_ATTR((unused)),
+ int flags EXT2FS_ATTR((unused)),
+ struct ext2_dir_entry *de,
+ int offset EXT2FS_ATTR((unused)),
+ int blocksize EXT2FS_ATTR((unused)),
+ char *buf EXT2FS_ATTR((unused)), void *priv_data)
+{
+ __u16 name_len;
+ errcode_t retval;
+ struct inode_params *params = (struct inode_params *)priv_data;
+
+ name_len = de->name_len & 0xff;
+ if (!strncmp(de->name, ".", name_len)
+ || (!strncmp(de->name, "..", name_len)))
+ return 0;
+
+ if (asprintf(¶ms->filename, "%s/%.*s", params->path, name_len,
+ de->name) < 0)
+ return -ENOMEM;
+
+ if (!strncmp(de->name, "lost+found", 10)) {
+ retval = set_selinux_xattr(params->fs, de->inode, params);
+ if (retval)
+ goto end;
+ } else {
+ retval = androidify_inode(params->fs, de->inode, params);
+ if (retval)
+ goto end;
+ if (is_dir(params->fs, de->inode)) {
+ char *cur_path = params->path;
+ char *cur_filename = params->filename;
+ params->path = params->filename;
+ ext2fs_dir_iterate2(params->fs, de->inode, 0, NULL,
+ walk_dir, params);
+ params->path = cur_path;
+ params->filename = cur_filename;
+ }
+ }
+
+end:
+ free(params->filename);
+ return retval;
+}
+
+errcode_t __android_configure_fs(ext2_filsys fs, char *src_dir,
+ char *target_out,
+ char *mountpoint,
+ fs_config_f fs_config_func,
+ struct selabel_handle *sehnd,
+ time_t fixed_time)
+{
+ errcode_t retval;
+ struct inode_params params = {
+ .fs = fs,
+ .src_dir = src_dir,
+ .target_out = target_out,
+ .fs_config_func = fs_config_func,
+ .sehnd = sehnd,
+ .fixed_time = fixed_time,
+ .path = mountpoint,
+ .filename = mountpoint,
+ .mountpoint = mountpoint,
+ };
+
+ /* walk_dir will add the "/". Don't add it twice. */
+ if (strlen(mountpoint) == 1 && mountpoint[0] == '/')
+ params.path = "";
+
+ retval = set_selinux_xattr(fs, EXT2_ROOT_INO, ¶ms);
+ if (retval)
+ return retval;
+ retval = set_timestamp(fs, EXT2_ROOT_INO, ¶ms);
+ if (retval)
+ return retval;
+
+ return ext2fs_dir_iterate2(fs, EXT2_ROOT_INO, 0, NULL, walk_dir,
+ ¶ms);
+}
+
+errcode_t android_configure_fs(ext2_filsys fs, char *src_dir, char *target_out,
+ char *mountpoint,
+ struct selinux_opt *seopts,
+ unsigned int nopt,
+ char *fs_config_file, time_t fixed_time)
+{
+ errcode_t retval;
+ fs_config_f fs_config_func = NULL;
+ struct selabel_handle *sehnd = NULL;
+
+ /* Retrieve file contexts */
+ if (nopt > 0) {
+ sehnd = selabel_open(SELABEL_CTX_FILE, seopts, nopt);
+ if (!sehnd) {
+ com_err(__func__, -EINVAL,
+ _("while opening file contexts \"%s\""),
+ seopts[0].value);
+ return -EINVAL;
+ }
+ }
+
+ /* Load the FS config */
+ if (fs_config_file) {
+ retval = load_canned_fs_config(fs_config_file);
+ if (retval < 0) {
+ com_err(__func__, retval,
+ _("while loading fs_config \"%s\""),
+ fs_config_file);
+ return retval;
+ }
+ fs_config_func = canned_fs_config;
+ } else if (mountpoint)
+ fs_config_func = fs_config;
+
+ return __android_configure_fs(fs, src_dir, target_out, mountpoint,
+ fs_config_func, sehnd, fixed_time);
+}
--- /dev/null
+#ifndef ANDROID_PERMS_H
+# define ANDROID_PERMS_H
+
+# include "config.h"
+# include <ext2fs/ext2fs.h>
+
+typedef void (*fs_config_f)(const char *path, int dir,
+ const char *target_out_path,
+ unsigned *uid, unsigned *gid,
+ unsigned *mode, uint64_t *capabilities);
+
+# ifdef _WIN32
+struct selabel_handle;
+static inline errcode_t android_configure_fs(ext2_filsys fs,
+ char *src_dir,
+ char *target_out,
+ char *mountpoint,
+ void *seopts,
+ unsigned int nopt,
+ char *fs_config_file,
+ time_t fixed_time)
+{
+ return 0;
+}
+# else
+# include <selinux/selinux.h>
+# include <selinux/label.h>
+# if !defined(HOST)
+# include <selinux/android.h>
+# endif
+# include <private/android_filesystem_config.h>
+# include <private/canned_fs_config.h>
+
+errcode_t android_configure_fs(ext2_filsys fs, char *src_dir,
+ char *target_out,
+ char *mountpoint,
+ struct selinux_opt *seopts,
+ unsigned int nopt,
+ char *fs_config_file, time_t fixed_time);
+
+# endif
+#endif /* !ANDROID_PERMS_H */
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+//########################
+// Build the debugfs binary
+
+cc_defaults {
+ name: "debugfs-defaults",
+ srcs: [
+ "debug_cmds.c",
+ "debugfs.c",
+ "util.c",
+ "ncheck.c",
+ "icheck.c",
+ "ls.c",
+ "lsdel.c",
+ "dump.c",
+ "set_fields.c",
+ "logdump.c",
+ "htree.c",
+ "unused.c",
+ "e2freefrag.c",
+ "filefrag.c",
+ "extent_cmds.c",
+ "extent_inode.c",
+ "zap.c",
+ "quota.c",
+ "xattrs.c",
+ "journal.c",
+ "revoke.c",
+ "recovery.c",
+ "do_journal.c",
+ ],
+ cflags: [
+ "-W",
+ "-Wall",
+ "-Wno-macro-redefined",
+ "-fno-strict-aliasing",
+ "-DDEBUGFS",
+ ],
+ include_dirs: [
+ "external/e2fsprogs/misc",
+ "external/e2fsprogs/e2fsck"
+ ],
+}
+
+debugfs_libs = [
+ "libext2_misc",
+ "libext2fs",
+ "libext2_blkid",
+ "libext2_uuid",
+ "libext2_ss",
+ "libext2_quota",
+ "libext2_com_err",
+ "libext2_e2p",
+]
+
+cc_binary {
+ name: "debugfs",
+ host_supported: true,
+ defaults: ["debugfs-defaults"],
+
+ shared_libs: debugfs_libs,
+ system_shared_libs: ["libc"],
+}
+
+cc_binary {
+ name: "debugfs_static",
+ static_executable: true,
+ defaults: ["debugfs-defaults"],
+
+ static_libs: debugfs_libs + ["libc"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-#########################
-# Build the debugfs binary
-
-debugfs_src_files := \
- debug_cmds.c \
- debugfs.c \
- util.c \
- ncheck.c\
- icheck.c \
- ls.c \
- lsdel.c \
- dump.c \
- set_fields.c \
- logdump.c \
- htree.c \
- unused.c \
- e2freefrag.c \
- filefrag.c \
- extent_cmds.c \
- extent_inode.c \
- zap.c \
- create_inode.c \
- quota.c \
- xattrs.c \
- journal.c \
- revoke.c \
- recovery.c \
- do_journal.c
-
-debugfs_shared_libraries := \
- libext2fs \
- libext2_blkid \
- libext2_uuid \
- libext2_ss \
- libext2_quota \
- libext2_com_err \
- libext2_e2p
-
-debugfs_system_shared_libraries := libc
-
-debugfs_static_libraries := \
- libext2fs \
- libext2_blkid \
- libext2_uuid_static \
- libext2_ss \
- libext2_quota \
- libext2_com_err \
- libext2_e2p
-
-debugfs_system_static_libraries := libc
-
-debugfs_c_includes := \
- external/e2fsprogs/e2fsck \
- external/e2fsprogs/misc \
- external/e2fsprogs/lib
-
-debugfs_cflags := -O2 -g -W -Wall -fno-strict-aliasing -DDEBUGFS
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(debugfs_src_files)
-LOCAL_C_INCLUDES := $(debugfs_c_includes)
-LOCAL_CFLAGS := $(debugfs_cflags)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(debugfs_system_shared_libraries)
-LOCAL_SHARED_LIBRARIES := $(debugfs_shared_libraries)
-LOCAL_MODULE := debugfs
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(debugfs_src_files)
-LOCAL_C_INCLUDES := $(debugfs_c_includes)
-LOCAL_CFLAGS := $(debugfs_cflags)
-LOCAL_STATIC_LIBRARIES := $(debugfs_static_libraries) $(debugfs_system_static_libraries)
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE := debugfs_static
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(debugfs_src_files)
-LOCAL_C_INCLUDES := $(debugfs_c_includes)
-LOCAL_CFLAGS := $(debugfs_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(debugfs_shared_libraries))
-LOCAL_MODULE := debugfs_host
-LOCAL_MODULE_STEM := debugfs
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
$(Q) $(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(SYSLIBS) -DUNITTEST \
-o tst_set_fields $(srcdir)/set_fields.c $(srcdir)/util.c $(LIBS)
-check:: tst_set_fields
+fullcheck check:: tst_set_fields
$(TESTENV) ./tst_set_fields
# +++ Dependency line eater +++
fprintf(out, "%d\n", inode->i_size);
if (os == EXT2_OS_HURD)
fprintf(out,
- "%sFile ACL: %d Directory ACL: %d Translator: %d\n",
+ "%sFile ACL: %d Translator: %d\n",
prefix,
- inode->i_file_acl, LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0,
+ inode->i_file_acl,
inode->osd1.hurd1.h_i_translator);
else
- fprintf(out, "%sFile ACL: %llu Directory ACL: %d\n",
+ fprintf(out, "%sFile ACL: %llu\n",
prefix,
inode->i_file_acl | ((long long)
- (inode->osd2.linux2.l_i_file_acl_high) << 32),
- LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0);
+ (inode->osd2.linux2.l_i_file_acl_high) << 32));
if (os != EXT2_OS_HURD)
fprintf(out, "%sLinks: %d Blockcount: %llu\n",
prefix, inode->i_links_count,
modify_u32(argv[0], "Reserved1", decimal_format, &inode.i_reserved1);
#endif
modify_u32(argv[0], "File acl", decimal_format, &inode.i_file_acl);
- if (LINUX_S_ISDIR(inode.i_mode))
- modify_u32(argv[0], "Directory acl", decimal_format, &inode.i_dir_acl);
- else
- modify_u32(argv[0], "High 32bits of size", decimal_format, &inode.i_size_high);
+
+ modify_u32(argv[0], "High 32bits of size", decimal_format,
+ &inode.i_size_high);
if (os == EXT2_OS_HURD)
modify_u32(argv[0], "Translator Block",
fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels);
fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags);
- ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length);
+ ent = (struct ext2_dx_entry *)
+ ((char *)rootnode + rootnode->info_length);
htree_dump_int_node(current_fs, ino, &inode, rootnode, ent,
buf + current_fs->blocksize,
/* Special case: i_file_acl_high is 2 bytes */
{ "file_acl", &set_inode.i_file_acl,
&set_inode.osd2.linux2.l_i_file_acl_high, 6, parse_uint },
- { "dir_acl", &set_inode.i_dir_acl, NULL, 4, parse_uint, FLAG_ALIAS },
{ "faddr", &set_inode.i_faddr, NULL, 4, parse_uint },
{ "frag", &set_inode.osd2.hurd2.h_i_frag, NULL, 1, parse_uint, FLAG_ALIAS },
{ "fsize", &set_inode.osd2.hurd2.h_i_fsize, NULL, 1, parse_uint },
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+//########################
+// Build the e2fsck binary
+
+cc_defaults {
+ name: "e2fsck-defaults",
+ srcs: [
+ "e2fsck.c",
+ "super.c",
+ "pass1.c",
+ "pass1b.c",
+ "pass2.c",
+ "pass3.c",
+ "pass4.c",
+ "pass5.c",
+ "logfile.c",
+ "journal.c",
+ "recovery.c",
+ "revoke.c",
+ "badblocks.c",
+ "util.c",
+ "unix.c",
+ "dirinfo.c",
+ "dx_dirinfo.c",
+ "ehandler.c",
+ "problem.c",
+ "message.c",
+ "ea_refcount.c",
+ "quota.c",
+ "rehash.c",
+ "region.c",
+ "sigcatcher.c",
+ "readahead.c",
+ "extents.c",
+ ],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined", "-fno-strict-aliasing"],
+}
+
+e2fsck_libs = [
+ "libext2fs",
+ "libext2_blkid",
+ "libext2_uuid",
+ "libext2_quota",
+ "libext2_com_err",
+ "libext2_e2p",
+]
+
+cc_binary {
+ name: "e2fsck",
+ host_supported: true,
+ defaults: ["e2fsck-defaults"],
+
+ shared_libs: e2fsck_libs,
+ system_shared_libs: ["libc"],
+}
+
+cc_binary {
+ name: "e2fsck_static",
+ static_executable: true,
+ defaults: ["e2fsck-defaults"],
+
+ static_libs: e2fsck_libs + ["libc"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-#########################
-# Build the e2fsck binary
-
-e2fsck_src_files := \
- e2fsck.c \
- super.c \
- pass1.c \
- pass1b.c \
- pass2.c \
- pass3.c \
- pass4.c \
- pass5.c \
- logfile.c \
- journal.c \
- recovery.c \
- revoke.c \
- badblocks.c \
- util.c \
- unix.c \
- dirinfo.c \
- dx_dirinfo.c \
- ehandler.c \
- problem.c \
- message.c \
- ea_refcount.c \
- quota.c \
- rehash.c \
- region.c \
- sigcatcher.c \
- readahead.c \
- extents.c
-
-e2fsck_shared_libraries := \
- libext2fs \
- libext2_blkid \
- libext2_uuid \
- libext2_quota \
- libext2_com_err \
- libext2_e2p
-
-e2fsck_system_shared_libraries := libc
-
-e2fsck_static_libraries := \
- libext2fs \
- libext2_blkid \
- libext2_uuid_static \
- libext2_quota \
- libext2_com_err \
- libext2_e2p
-
-e2fsck_system_static_libraries := libc
-
-e2fsck_c_includes :=
-
-e2fsck_cflags := -O2 -g -W -Wall -fno-strict-aliasing
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(e2fsck_src_files)
-LOCAL_C_INCLUDES := $(e2fsck_c_includes)
-LOCAL_CFLAGS := $(e2fsck_cflags)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(e2fsck_system_shared_libraries)
-LOCAL_SHARED_LIBRARIES := $(e2fsck_shared_libraries)
-LOCAL_MODULE := e2fsck
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(e2fsck_src_files)
-LOCAL_C_INCLUDES := $(e2fsck_c_includes)
-LOCAL_CFLAGS := $(e2fsck_cflags)
-LOCAL_STATIC_LIBRARIES := $(e2fsck_static_libraries) $(e2fsck_system_static_libraries)
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE := e2fsck_static
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(e2fsck_src_files)
-LOCAL_C_INCLUDES := $(e2fsck_c_includes)
-LOCAL_CFLAGS := $(e2fsck_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(e2fsck_shared_libraries))
-LOCAL_MODULE := e2fsck_host
-LOCAL_MODULE_STEM := e2fsck
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
$(ALL_CFLAGS) $(ALL_LDFLAGS) -DTEST_PROGRAM \
$(LIBCOM_ERR) $(SYSLIBS)
-check:: tst_refcount tst_region tst_problem
+fullcheck check:: tst_refcount tst_region tst_problem
$(TESTENV) ./tst_refcount
$(TESTENV) ./tst_region
$(TESTENV) ./tst_problem
blk64_t phys;
int flags;
blk64_t parent;
+ blk64_t previous;
ext2_dirhash_t min_hash;
ext2_dirhash_t max_hash;
ext2_dirhash_t node_min_hash;
extern void e2fsck_clear_progbar(e2fsck_t ctx);
extern int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
float percent, unsigned int dpynum);
+
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+
#endif /* _E2FSCK_H */
* %IM <inode> -> i_mtime
* %IF <inode> -> i_faddr
* %If <inode> -> i_file_acl
- * %Id <inode> -> i_dir_acl
+ * %Id <inode> -> i_size_high
* %Iu <inode> -> i_uid
* %Ig <inode> -> i_gid
* %It <inode type>
break;
case 'd':
fprintf(f, "%u", (LINUX_S_ISDIR(inode->i_mode) ?
- inode->i_dir_acl : 0));
+ inode->i_size_high : 0));
break;
case 'u':
fprintf(f, "%d", inode_uid(*inode));
}
if (inode->i_faddr || frag || fsize ||
- (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
+ (!ext2fs_has_feature_largedir(fs->super) &&
+ (LINUX_S_ISDIR(inode->i_mode) && inode->i_size_high)))
mark_inode_bad(ctx, ino);
if ((fs->super->s_creator_os != EXT2_OS_HURD) &&
!ext2fs_has_feature_64bit(fs->super) &&
}
}
+/*
+ * When cluster size is greater than one block, it is caller's responsibility
+ * to make sure block parameter starts at a cluster boundary.
+ */
static _INLINE_ void mark_blocks_used(e2fsck_t ctx, blk64_t block,
unsigned int num)
{
if (ext2fs_test_block_bitmap_range2(ctx->block_found_map, block, num))
ext2fs_mark_block_bitmap_range2(ctx->block_found_map, block, num);
- else
- while (num--)
- mark_block_used(ctx, block++);
+ else {
+ int i;
+ for (i = 0; i < num; i += EXT2FS_CLUSTER_RATIO(ctx->fs))
+ mark_block_used(ctx, block + i);
+ }
}
/*
return 1;
pctx->num = root->indirect_levels;
- if ((root->indirect_levels > 1) &&
+ if ((root->indirect_levels > ext2_dir_htree_level(fs)) &&
fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
return 1;
{
struct ext2fs_extent extent;
blk64_t blk, last_lblk;
- e2_blkcnt_t blockcnt;
- unsigned int i;
+ unsigned int i, n;
int is_dir, is_leaf;
problem_t problem;
struct ext2_extent_info info;
}
}
alloc_later:
- while (is_dir && (++pb->last_db_block <
- (e2_blkcnt_t) extent.e_lblk)) {
- pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist,
- pb->ino, 0,
- pb->last_db_block);
- if (pctx->errcode) {
- pctx->blk = 0;
- pctx->num = pb->last_db_block;
- goto failed_add_dir_block;
- }
- }
- if (!ctx->fs->cluster_ratio_bits) {
- mark_blocks_used(ctx, extent.e_pblk, extent.e_len);
- pb->num_blocks += extent.e_len;
- }
- for (blk = extent.e_pblk, blockcnt = extent.e_lblk, i = 0;
- i < extent.e_len;
- blk++, blockcnt++, i++) {
- if (ctx->fs->cluster_ratio_bits &&
- !(pb->previous_block &&
- (EXT2FS_B2C(ctx->fs, blk) ==
- EXT2FS_B2C(ctx->fs, pb->previous_block)) &&
- (blk & EXT2FS_CLUSTER_MASK(ctx->fs)) ==
- ((unsigned) blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) {
- mark_block_used(ctx, blk);
- pb->num_blocks++;
- }
- if (has_unaligned_cluster_map(ctx, pb->previous_block,
- pb->last_block, blk,
- blockcnt)) {
- pctx->blk = blockcnt;
- pctx->blk2 = blk;
- fix_problem(ctx, PR_1_MISALIGNED_CLUSTER, pctx);
- mark_block_used(ctx, blk);
- mark_block_used(ctx, blk);
+ if (is_dir) {
+ while (++pb->last_db_block <
+ (e2_blkcnt_t) extent.e_lblk) {
+ pctx->errcode = ext2fs_add_dir_block2(
+ ctx->fs->dblist,
+ pb->ino, 0,
+ pb->last_db_block);
+ if (pctx->errcode) {
+ pctx->blk = 0;
+ pctx->num = pb->last_db_block;
+ goto failed_add_dir_block;
+ }
}
- pb->last_block = blockcnt;
- pb->previous_block = blk;
- if (is_dir) {
- pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist, pctx->ino, blk, blockcnt);
+ for (i = 0; i < extent.e_len; i++) {
+ pctx->errcode = ext2fs_add_dir_block2(
+ ctx->fs->dblist,
+ pctx->ino,
+ extent.e_pblk + i,
+ extent.e_lblk + i);
if (pctx->errcode) {
- pctx->blk = blk;
- pctx->num = blockcnt;
+ pctx->blk = extent.e_pblk + i;
+ pctx->num = extent.e_lblk + i;
failed_add_dir_block:
fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
/* Should never get here */
return;
}
}
+ if (extent.e_len > 0)
+ pb->last_db_block = extent.e_lblk + extent.e_len - 1;
+ }
+ if (has_unaligned_cluster_map(ctx, pb->previous_block,
+ pb->last_block,
+ extent.e_pblk,
+ extent.e_lblk)) {
+ for (i = 0; i < extent.e_len; i++) {
+ pctx->blk = extent.e_lblk + i;
+ pctx->blk2 = extent.e_pblk + i;
+ fix_problem(ctx, PR_1_MISALIGNED_CLUSTER, pctx);
+ mark_block_used(ctx, extent.e_pblk + i);
+ mark_block_used(ctx, extent.e_pblk + i);
+ }
+ }
+
+ /*
+ * Check whether first cluster got marked in previous iteration.
+ */
+ if (ctx->fs->cluster_ratio_bits &&
+ pb->previous_block &&
+ (EXT2FS_B2C(ctx->fs, extent.e_pblk) ==
+ EXT2FS_B2C(ctx->fs, pb->previous_block)))
+ /* Set blk to the beginning of next cluster. */
+ blk = EXT2FS_C2B(
+ ctx->fs,
+ EXT2FS_B2C(ctx->fs, extent.e_pblk) + 1);
+ else
+ /* Set blk to the beginning of current cluster. */
+ blk = EXT2FS_C2B(ctx->fs,
+ EXT2FS_B2C(ctx->fs, extent.e_pblk));
+
+ if (blk < extent.e_pblk + extent.e_len) {
+ mark_blocks_used(ctx, blk,
+ extent.e_pblk + extent.e_len - blk);
+ n = DIV_ROUND_UP(extent.e_pblk + extent.e_len - blk,
+ EXT2FS_CLUSTER_RATIO(ctx->fs));
+ pb->num_blocks += n;
}
- if (is_dir && extent.e_len > 0)
- pb->last_db_block = blockcnt - 1;
+ pb->last_block = extent.e_lblk + extent.e_len - 1;
pb->previous_block = extent.e_pblk + extent.e_len - 1;
start_block = pb->last_block = last_lblk;
if (is_leaf && !is_dir &&
unsigned long long next_ra_off;
};
+static void update_parents(struct dx_dir_info *dx_dir, int type)
+{
+ struct dx_dirblock_info *dx_db, *dx_parent, *dx_previous;
+ int b;
+
+ for (b = 0, dx_db = dx_dir->dx_block;
+ b < dx_dir->numblocks;
+ b++, dx_db++) {
+ dx_parent = &dx_dir->dx_block[dx_db->parent];
+ if (dx_db->type != type)
+ continue;
+
+ /*
+ * XXX Make sure dx_parent->min_hash > dx_db->min_hash
+ */
+ if (dx_db->flags & DX_FLAG_FIRST) {
+ dx_parent->min_hash = dx_db->min_hash;
+ if (dx_parent->previous) {
+ dx_previous =
+ &dx_dir->dx_block[dx_parent->previous];
+ dx_previous->node_max_hash =
+ dx_parent->min_hash;
+ }
+ }
+ /*
+ * XXX Make sure dx_parent->max_hash < dx_db->max_hash
+ */
+ if (dx_db->flags & DX_FLAG_LAST) {
+ dx_parent->max_hash = dx_db->max_hash;
+ }
+ }
+}
+
void e2fsck_pass2(e2fsck_t ctx)
{
struct ext2_super_block *sb = ctx->fs->super;
* Find all of the first and last leaf blocks, and
* update their parent's min and max hash values
*/
- for (b=0, dx_db = dx_dir->dx_block;
- b < dx_dir->numblocks;
- b++, dx_db++) {
- if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
- !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
- continue;
- dx_parent = &dx_dir->dx_block[dx_db->parent];
- /*
- * XXX Make sure dx_parent->min_hash > dx_db->min_hash
- */
- if (dx_db->flags & DX_FLAG_FIRST)
- dx_parent->min_hash = dx_db->min_hash;
- /*
- * XXX Make sure dx_parent->max_hash < dx_db->max_hash
- */
- if (dx_db->flags & DX_FLAG_LAST)
- dx_parent->max_hash = dx_db->max_hash;
- }
+ update_parents(dx_dir, DX_DIRBLOCK_LEAF);
+
+ /* for 3 level htree: update 2 level parent's min
+ * and max hash values */
+ update_parents(dx_dir, DX_DIRBLOCK_NODE);
for (b=0, dx_db = dx_dir->dx_block;
b < dx_dir->numblocks;
dx_db->flags |= DX_FLAG_REFERENCED;
dx_db->parent = db->blockcnt;
}
+
+ dx_db->previous =
+ i ? ext2fs_le32_to_cpu(ent[i-1].block & 0x0ffffff) : 0;
+
if (hash < min_hash)
min_hash = hash;
if (hash > max_hash)
return DIRENT_ABORT;
}
+ /* This will allow (at some point in the future) to punch out empty
+ * directory blocks and reduce the space used by a directory that grows
+ * very large and then the files are deleted. For now, all that is
+ * needed is to avoid e2fsck filling in these holes as part of
+ * feature flag. */
+ if (db->blk == 0 && ext2fs_has_feature_largedir(fs->super))
+ return 0;
+
if (db->blk == 0 && !inline_data_size) {
if (allocate_dir_block(ctx, db, buf, &cd->pctx))
return 0;
dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
if ((root->reserved_zero ||
root->info_length < 8 ||
- root->indirect_levels > 1) &&
+ root->indirect_levels >=
+ ext2_dir_htree_level(fs)) &&
fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
clear_htree(ctx, ino);
dx_dir->numblocks = 0;
} else
not_fixed++;
}
- if (inode.i_dir_acl &&
+ if (inode.i_size_high && !ext2fs_has_feature_largedir(fs->super) &&
LINUX_S_ISDIR(inode.i_mode)) {
- if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
- inode.i_dir_acl = 0;
+ if (fix_problem(ctx, PR_2_DIR_SIZE_HIGH_ZERO, &pctx)) {
+ inode.i_size_high = 0;
inode_modified++;
} else
not_fixed++;
#include "e2fsck.h"
#include "problem.h"
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
-
static void check_block_bitmaps(e2fsck_t ctx);
static void check_inode_bitmaps(e2fsck_t ctx);
static void check_inode_end(e2fsck_t ctx);
N_("i_file_acl @F %If, @s zero.\n"),
PROMPT_CLEAR, 0 },
- /* i_dir_acl should be zero */
- { PR_2_DIR_ACL_ZERO,
- N_("i_dir_acl @F %Id, @s zero.\n"),
+ /* i_size_high should be zero */
+ { PR_2_DIR_SIZE_HIGH_ZERO,
+ N_("i_size_high @F %Id, @s zero.\n"),
PROMPT_CLEAR, 0 },
/* i_frag should be zero */
/* i_file_acl should be zero */
#define PR_2_FILE_ACL_ZERO 0x02000E
-/* i_dir_acl should be zero */
-#define PR_2_DIR_ACL_ZERO 0x02000F
+/* i_size_high should be zero */
+#define PR_2_DIR_SIZE_HIGH_ZERO 0x02000F
/* i_frag should be zero */
#define PR_2_FRAG_ZERO 0x020010
return (struct ext2_dx_entry *) limits;
}
+static int alloc_blocks(ext2_filsys fs,
+ struct ext2_dx_countlimit **limit,
+ struct ext2_dx_entry **prev_ent,
+ struct ext2_dx_entry **next_ent,
+ int *prev_offset, int *next_offset,
+ struct out_dir *outdir, int i,
+ int *prev_count, int *next_count)
+{
+ errcode_t retval;
+ char *block_start;
+
+ if (*limit)
+ (*limit)->limit = (*limit)->count =
+ ext2fs_cpu_to_le16((*limit)->limit);
+ *prev_ent = (struct ext2_dx_entry *) (outdir->buf + *prev_offset);
+ (*prev_ent)->block = ext2fs_cpu_to_le32(outdir->num);
+
+ if (i != 1)
+ (*prev_ent)->hash =
+ ext2fs_cpu_to_le32(outdir->hashes[i]);
+
+ retval = get_next_block(fs, outdir, &block_start);
+ if (retval)
+ return retval;
+
+ *next_ent = set_int_node(fs, block_start);
+ *limit = (struct ext2_dx_countlimit *)(*next_ent);
+ if (next_offset)
+ *next_offset = ((char *) *next_ent - outdir->buf);
+
+ *next_count = (*limit)->limit;
+ (*prev_offset) += sizeof(struct ext2_dx_entry);
+ (*prev_count)--;
+
+ return 0;
+}
+
/*
* This function takes the leaf nodes which have been written in
* outdir, and populates the root node and any necessary interior nodes.
ext2_ino_t ino,
ext2_ino_t parent)
{
- struct ext2_dx_root_info *root_info;
- struct ext2_dx_entry *root, *dx_ent = 0;
- struct ext2_dx_countlimit *root_limit, *limit;
+ struct ext2_dx_root_info *root_info;
+ struct ext2_dx_entry *root, *int_ent, *dx_ent = 0;
+ struct ext2_dx_countlimit *root_limit, *int_limit, *limit;
errcode_t retval;
char * block_start;
- int i, c1, c2, nblks;
- int limit_offset, root_offset;
+ int i, c1, c2, c3, nblks;
+ int limit_offset, int_offset, root_offset;
root_info = set_root_node(fs, outdir->buf, ino, parent);
root_offset = limit_offset = ((char *) root_info - outdir->buf) +
nblks = outdir->num;
/* Write out the pointer blocks */
- if (nblks-1 <= c1) {
+ if (nblks - 1 <= c1) {
/* Just write out the root block, and we're done */
root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
for (i=1; i < nblks; i++) {
root++;
c1--;
}
- } else {
+ } else if (nblks - 1 <= ext2fs_htree_intnode_maxrecs(fs, c1)) {
c2 = 0;
- limit = 0;
+ limit = NULL;
root_info->indirect_levels = 1;
for (i=1; i < nblks; i++) {
- if (c1 == 0)
+ if (c2 == 0 && c1 == 0)
return ENOSPC;
if (c2 == 0) {
- if (limit)
- limit->limit = limit->count =
- ext2fs_cpu_to_le16(limit->limit);
- root = (struct ext2_dx_entry *)
- (outdir->buf + root_offset);
- root->block = ext2fs_cpu_to_le32(outdir->num);
- if (i != 1)
- root->hash =
- ext2fs_cpu_to_le32(outdir->hashes[i]);
- if ((retval = get_next_block(fs, outdir,
- &block_start)))
+ retval = alloc_blocks(fs, &limit, &root,
+ &dx_ent, &root_offset,
+ NULL, outdir, i, &c1,
+ &c2);
+ if (retval)
return retval;
- dx_ent = set_int_node(fs, block_start);
- limit = (struct ext2_dx_countlimit *) dx_ent;
- c2 = limit->limit;
- root_offset += sizeof(struct ext2_dx_entry);
- c1--;
}
dx_ent->block = ext2fs_cpu_to_le32(i);
if (c2 != limit->limit)
}
limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
limit->limit = ext2fs_cpu_to_le16(limit->limit);
+ } else {
+ c2 = 0;
+ c3 = 0;
+ limit = NULL;
+ int_limit = 0;
+ root_info->indirect_levels = 2;
+ for (i = 1; i < nblks; i++) {
+ if (c3 == 0 && c2 == 0 && c1 == 0)
+ return ENOSPC;
+ if (c3 == 0 && c2 == 0) {
+ retval = alloc_blocks(fs, &int_limit, &root,
+ &int_ent, &root_offset,
+ &int_offset, outdir, i,
+ &c1, &c2);
+ if (retval)
+ return retval;
+ }
+ if (c3 == 0) {
+ retval = alloc_blocks(fs, &limit, &int_ent,
+ &dx_ent, &int_offset,
+ NULL, outdir, i, &c2,
+ &c3);
+ if (retval)
+ return retval;
+
+ }
+ dx_ent->block = ext2fs_cpu_to_le32(i);
+ if (c3 != limit->limit)
+ dx_ent->hash =
+ ext2fs_cpu_to_le32(outdir->hashes[i]);
+ dx_ent++;
+ c3--;
+ }
+ int_limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
+ int_limit->limit = ext2fs_cpu_to_le16(limit->limit);
+
+ limit->count = ext2fs_cpu_to_le16(limit->limit - c3);
+ limit->limit = ext2fs_cpu_to_le16(limit->limit);
+
}
root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
__u32 i_block[EXT2_N_BLOCKS]; /* Pointers to blocks */
__u32 i_version; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
- __u32 i_dir_acl; /* Directory ACL */
+ __u32 i_size_high; /* High 32bits of size */
__u32 i_faddr; /* Fragment address */
union {
struct {
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_version; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
- __u32 i_dir_acl; /* Directory ACL */
+ __u32 i_size_high; /* High 32bits of size */
__u32 i_faddr; /* Fragment address */
union {
struct {
__u32 i_block[14]; /* Pointers to blocks */
__u32 i_version; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
- __u32 i_dir_acl; /* Directory ACL */
+ __u32 i_size_high; /* High 32bits of size */
__u32 i_faddr; /* Fragment address */
__u8 l_i_frag; /* Fragment number */
__u8 l_i_fsize; /* Fragment size */
#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H
-#ifndef _MSC_VER
-#error _MSC_VER not defined
-#endif
+//#ifndef _MSC_VER
+//#error _MSC_VER not defined
+//#endif
+#include <sys/types.h>
typedef unsigned __int8 __u8;
typedef signed __int8 __s8;
typedef unsigned __int64 __u64;
-typedef __u32 ino_t;
+//typedef __u32 ino_t;
+typedef __u32 dev_t;
+typedef __u32 uid_t;
+typedef __u32 gid_t;
+#include <stdint.h>
#endif /* LINUX_TYPES_H */
$(Q) $(SHELL) $(srcdir)/config.charset '@host@' > t-$@
$(Q) mv t-$@ $@
-check: all
+fullcheck check: all
# We must not install the libintl.h/libintl.a files if we are on a
# system which has the GNU gettext() function in its C library or in a
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+// All the libraries under this directory export their headers as relative
+// paths to this directory (external/e2fsprogs/lib). This is a helper headers
+// only library to allow exporting
+cc_library_headers {
+ name: "libext2-headers",
+ host_supported: true,
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+ export_include_dirs: ["."],
+}
+
+
+subdirs = [
+ "*",
+]
+++ /dev/null
-include $(call all-subdir-makefiles)
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+cc_library {
+ name: "libext2_blkid",
+ host_supported: true,
+ unique_host_soname: true,
+ srcs: [
+ "cache.c",
+ "dev.c",
+ "devname.c",
+ "devno.c",
+ "getsize.c",
+ "llseek.c",
+ "probe.c",
+ "read.c",
+ "resolve.c",
+ "save.c",
+ "tag.c",
+ "version.c",
+ ],
+ shared_libs: ["libext2_uuid"],
+
+ cflags: [
+ "-W",
+ "-Wall",
+ "-fno-strict-aliasing",
+ "-Wno-macro-redefined",
+ ],
+
+ header_libs: ["libext2-headers"],
+ export_include_dirs: ["."],
+ export_header_lib_headers: ["libext2-headers"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-libext2_blkid_src_files := \
- cache.c \
- dev.c \
- devname.c \
- devno.c \
- getsize.c \
- llseek.c \
- probe.c \
- read.c \
- resolve.c \
- save.c \
- tag.c \
- version.c \
-
-
-libext2_blkid_shared_libraries := libext2_uuid
-
-libext2_blkid_system_shared_libraries := libc
-
-libext2_blkid_static_libraries := libext2_uuid_static
-
-libext2_blkid_system_static_libraries := libc
-
-libext2_blkid_c_includes := external/e2fsprogs/lib
-
-libext2_blkid_cflags := -O2 -g -W -Wall -fno-strict-aliasing
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_blkid_src_files)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(libext2_blkid_system_shared_libraries)
-LOCAL_SHARED_LIBRARIES := $(libext2_blkid_shared_libraries)
-LOCAL_C_INCLUDES := $(libext2_blkid_c_includes)
-LOCAL_CFLAGS := $(libext2_blkid_cflags)
-LOCAL_MODULE := libext2_blkid
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_blkid_src_files)
-LOCAL_STATIC_LIBRARIES := $(libext2_blkid_static_libraries) $(libext2_blkid_system_static_libraries)
-LOCAL_C_INCLUDES := $(libext2_blkid_c_includes)
-LOCAL_CFLAGS := $(libext2_blkid_cflags) $(libext2_blkid_cflags_linux) -fno-strict-aliasing
-LOCAL_MODULE := libext2_blkid
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_blkid_src_files)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(libext2_blkid_shared_libraries))
-LOCAL_C_INCLUDES := $(libext2_blkid_c_includes)
-LOCAL_CFLAGS := $(libext2_blkid_cflags)
-LOCAL_MODULE := libext2_blkid-host
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_SHARED_LIBRARY)
$(Q) cat $(srcdir)/test_probe.in >> test_probe
$(Q) chmod +x test_probe
-check:: all tst_cache tst_dev tst_devname tst_devno tst_getsize tst_probe \
- tst_read tst_resolve tst_save tst_tag test_probe tst_types
+fullcheck check:: all tst_cache tst_dev tst_devname tst_devno \
+ tst_getsize tst_probe tst_read tst_resolve tst_save tst_tag \
+ test_probe tst_types
./test_probe
./tst_types
{
FILE *proc;
char line[1024];
- char ptname0[128], ptname1[128], *ptname = 0;
+ char ptname0[129], ptname1[129], *ptname = 0;
char *ptnames[2];
dev_t devs[2];
int ma, mi;
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+cc_library {
+ name: "libext2_e2p",
+ host_supported: true,
+ unique_host_soname: true,
+ srcs: [
+ "feature.c",
+ "fgetflags.c",
+ "fsetflags.c",
+ "fgetproject.c",
+ "fsetproject.c",
+ "fgetversion.c",
+ "fsetversion.c",
+ "getflags.c",
+ "getversion.c",
+ "hashstr.c",
+ "iod.c",
+ "ls.c",
+ "mntopts.c",
+ "parse_num.c",
+ "pe.c",
+ "pf.c",
+ "ps.c",
+ "setflags.c",
+ "setversion.c",
+ "uuid.c",
+ "ostype.c",
+ "percent.c",
+ ],
+
+ cflags: [
+ "-W",
+ "-Wall",
+ "-Wno-macro-redefined",
+ ],
+
+ header_libs: ["libext2-headers"],
+ export_include_dirs: ["."],
+ export_header_lib_headers: ["libext2-headers"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-libext2_e2p_src_files := \
- feature.c \
- fgetflags.c \
- fsetflags.c \
- fgetproject.c \
- fsetproject.c \
- fgetversion.c \
- fsetversion.c \
- getflags.c \
- getversion.c \
- hashstr.c \
- iod.c \
- ls.c \
- mntopts.c \
- parse_num.c \
- pe.c \
- pf.c \
- ps.c \
- setflags.c \
- setversion.c \
- uuid.c \
- ostype.c \
- percent.c
-
-libext2_e2p_c_includes := external/e2fsprogs/lib
-
-libext2_e2p_cflags := -O2 -g -W -Wall
-
-libext2_e2p_system_shared_libraries := libc
-
-libext2_e2p_system_static_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_e2p_src_files)
-LOCAL_C_INCLUDES := $(libext2_e2p_c_includes)
-LOCAL_CFLAGS := $(libext2_e2p_cflags)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(libext2_e2p_system_shared_libraries)
-LOCAL_MODULE := libext2_e2p
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_e2p_src_files)
-LOCAL_C_INCLUDES := $(libext2_e2p_c_includes)
-LOCAL_CFLAGS := $(libext2_e2p_cflags)
-LOCAL_STATIC_LIBRARIES := $(libext2_e2p_system_static_libraries)
-LOCAL_MODULE := libext2_e2p
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_e2p_src_files)
-LOCAL_C_INCLUDES := $(libext2_e2p_c_includes)
-LOCAL_CFLAGS := $(libext2_e2p_cflags)
-LOCAL_MODULE := libext2_e2p-host
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_SHARED_LIBRARY)
$(Q) $(CC) -DTEST_PROGRAM -I$(top_srcdir)/lib -o tst_feature \
$(srcdir)/feature.c $(ALL_CFLAGS) $(ALL_LDFLAGS)
-check:: tst_ostype tst_feature
+fullcheck check:: tst_ostype tst_feature
./tst_ostype
./tst_feature
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+cc_library {
+ name: "libext2_com_err",
+ host_supported: true,
+ unique_host_soname: true,
+ srcs: [
+ "error_message.c",
+ "et_name.c",
+ "init_et.c",
+ "com_err.c",
+ "com_right.c",
+ ],
+
+ cflags: [
+ "-W",
+ "-Wall",
+ ],
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+
+ header_libs: ["libext2-headers"],
+ export_include_dirs: ["."],
+ export_header_lib_headers: ["libext2-headers"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-libext2_com_err_src_files := \
- error_message.c \
- et_name.c \
- init_et.c \
- com_err.c \
- com_right.c
-
-libext2_com_err_c_includes := external/e2fsprogs/lib
-
-libext2_com_err_cflags := -O2 -g -W -Wall
-
-libext2_com_err_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_com_err_src_files)
-LOCAL_C_INCLUDES := $(libext2_com_err_c_includes)
-LOCAL_CFLAGS := $(libext2_com_err_cflags)
-LOCAL_SYSTEM_SHARED_LIBRARIES := libc
-LOCAL_MODULE := libext2_com_err
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_com_err_src_files)
-LOCAL_C_INCLUDES := $(libext2_com_err_c_includes)
-LOCAL_CFLAGS := $(libext2_com_err_cflags)
-LOCAL_STATIC_LIBRARIES := libc
-LOCAL_MODULE := libext2_com_err
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_com_err_src_files)
-LOCAL_C_INCLUDES := $(libext2_com_err_c_includes)
-LOCAL_CFLAGS := $(libext2_com_err_cflags)
-LOCAL_MODULE := libext2_com_err-host
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_SHARED_LIBRARY)
$(DESTDIR)$(pkgconfigdir)/com_err.pc
$(RM) -rf $(DESTDIR)$(includedir)/et $(DESTDIR)$(datadir)/et
-check:: compile_et
+fullcheck check:: compile_et
for i in $(srcdir)/test_cases/*.et ; do \
t=`basename $$i | sed -e 's/.et//'`; \
_ET_DIR_OVERRIDE=$(srcdir) ./compile_et $$i ; \
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
+#if HAVE_FCNTL
#include <fcntl.h>
+#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
*/
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;
debug_f = fopen("/dev/tty", "a");
if (debug_f) {
fd = fileno(debug_f);
+#if defined(HAVE_FCNTL)
if (fd >= 0) {
flags = fcntl(fd, F_GETFD);
if (flags >= 0)
fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
}
+#endif
} else
debug_mask = DEBUG_INIT;
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+cc_library {
+ name: "libext2fs",
+ host_supported: true,
+ unique_host_soname: true,
+ srcs: [
+ "ext2_err.c",
+ "alloc.c",
+ "alloc_sb.c",
+ "alloc_stats.c",
+ "alloc_tables.c",
+ "atexit.c",
+ "badblocks.c",
+ "bb_inode.c",
+ "bitmaps.c",
+ "bitops.c",
+ "blkmap64_ba.c",
+ "blkmap64_rb.c",
+ "blknum.c",
+ "block.c",
+ "bmap.c",
+ "check_desc.c",
+ "crc16.c",
+ "crc32c.c",
+ "csum.c",
+ "closefs.c",
+ "dblist.c",
+ "dblist_dir.c",
+ "digest_encode.c",
+ "dirblock.c",
+ "dirhash.c",
+ "dir_iterate.c",
+ "dupfs.c",
+ "expanddir.c",
+ "ext_attr.c",
+ "extent.c",
+ "fallocate.c",
+ "fileio.c",
+ "finddev.c",
+ "flushb.c",
+ "freefs.c",
+ "gen_bitmap.c",
+ "gen_bitmap64.c",
+ "get_num_dirs.c",
+ "get_pathname.c",
+ "getsize.c",
+ "getsectsize.c",
+ "i_block.c",
+ "icount.c",
+ "imager.c",
+ "ind_block.c",
+ "initialize.c",
+ "inline.c",
+ "inline_data.c",
+ "inode.c",
+ "io_manager.c",
+ "ismounted.c",
+ "link.c",
+ "llseek.c",
+ "lookup.c",
+ "mmp.c",
+ "mkdir.c",
+ "mkjournal.c",
+ "namei.c",
+ "native.c",
+ "newdir.c",
+ "openfs.c",
+ "progress.c",
+ "punch.c",
+ "qcow2.c",
+ "rbtree.c",
+ "read_bb.c",
+ "read_bb_file.c",
+ "res_gdt.c",
+ "rw_bitmaps.c",
+ "sha256.c",
+ "sha512.c",
+ "swapfs.c",
+ "symlink.c",
+ "undo_io.c",
+ "unix_io.c",
+ "sparse_io.c",
+ "unlink.c",
+ "valid_blk.c",
+ "version.c",
+ // get rid of this?!
+ "test_io.c",
+ ],
+ shared_libs: [
+ "libsparse",
+ ],
+ whole_static_libs: [
+ "libext2_com_err"
+ ],
+ cflags: [
+ "-W",
+ "-Wall",
+ "-Wno-unused-parameter",
+ "-Wno-macro-redefined",
+ ],
+ target: {
+ host: {
+ shared_libs: ["libz-host"],
+ // Consider removing this library as a whole for the host. It is not
+ // in the android side.
+ whole_static_libs: ["libext2_com_err"],
+ },
+ android: {
+ shared_libs: [
+ "libext2_com_err",
+ "libext2_uuid",
+ "libz"
+ ],
+ },
+ windows: {
+ // include/nonunix is used as an overlay on top of the system
+ // include directory. Some empty header files in include/nonunix
+ // hide the ones in the system include path. This setup doesn't work
+ // unless we pass the include/nonunix as an -isystem flag.
+ // TODO(deymo): Enable windows
+ enabled: false,
+ cflags: [
+ "-Wno-format",
+ // "-isystem external/e2fsprogs/include/nonunix",
+ ],
+ host_ldlibs: ["-lws2_32"],
+ },
+ },
+
+ header_libs: ["libext2-headers"],
+ export_include_dirs: ["."],
+ export_header_lib_headers: ["libext2-headers"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-libext2fs_src_files := \
- ext2_err.c \
- alloc.c \
- alloc_sb.c \
- alloc_stats.c \
- alloc_tables.c \
- atexit.c \
- badblocks.c \
- bb_inode.c \
- bitmaps.c \
- bitops.c \
- blkmap64_ba.c \
- blkmap64_rb.c \
- blknum.c \
- block.c \
- bmap.c \
- check_desc.c \
- crc16.c \
- crc32c.c \
- csum.c \
- closefs.c \
- dblist.c \
- dblist_dir.c \
- digest_encode.c \
- dirblock.c \
- dirhash.c \
- dir_iterate.c \
- dupfs.c \
- expanddir.c \
- ext_attr.c \
- extent.c \
- fallocate.c \
- fileio.c \
- finddev.c \
- flushb.c \
- freefs.c \
- gen_bitmap.c \
- gen_bitmap64.c \
- get_num_dirs.c \
- get_pathname.c \
- getsize.c \
- getsectsize.c \
- i_block.c \
- icount.c \
- imager.c \
- ind_block.c \
- initialize.c \
- inline.c \
- inline_data.c \
- inode.c \
- io_manager.c \
- ismounted.c \
- link.c \
- llseek.c \
- lookup.c \
- mmp.c \
- mkdir.c \
- mkjournal.c \
- namei.c \
- native.c \
- newdir.c \
- openfs.c \
- progress.c \
- punch.c \
- qcow2.c \
- rbtree.c \
- read_bb.c \
- read_bb_file.c \
- res_gdt.c \
- rw_bitmaps.c \
- sha256.c \
- sha512.c \
- swapfs.c \
- symlink.c \
- undo_io.c \
- unix_io.c \
- unlink.c \
- valid_blk.c \
- version.c
-
-# get rid of this?!
-libext2fs_src_files += test_io.c
-
-libext2fs_shared_libraries := \
- libext2_com_err \
- libext2_uuid \
- libext2_blkid \
- libext2_e2p
-
-libext2fs_system_shared_libraries := libc
-
-libext2fs_static_libraries := \
- libext2_com_err \
- libext2_uuid_static \
- libext2_blkid \
- libext2_e2p
-
-libext2fs_system_static_libraries := libc
-
-libext2fs_c_includes := external/e2fsprogs/lib
-
-libext2fs_cflags := -O2 -g -W -Wall
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2fs_src_files)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(libext2fs_system_shared_libraries)
-LOCAL_SHARED_LIBRARIES := $(libext2fs_shared_libraries)
-LOCAL_C_INCLUDES := $(libext2fs_c_includes)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(libext2fs_c_includes)
-LOCAL_CFLAGS := $(libext2fs_cflags)
-LOCAL_MODULE := libext2fs
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2fs_src_files)
-LOCAL_STATIC_LIBRARIES := $(libext2fs_static_libraries) $(libext2fs_system_static_libraries)
-LOCAL_C_INCLUDES := $(libext2fs_c_includes)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(libext2fs_c_includes)
-LOCAL_CFLAGS := $(libext2fs_cflags) $(libext2fs_cflags_linux)
-LOCAL_MODULE := libext2fs
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2fs_src_files)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(libext2fs_shared_libraries))
-LOCAL_C_INCLUDES := $(libext2fs_c_includes)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(libext2fs_c_includes)
-LOCAL_CFLAGS := $(libext2fs_cflags)
-LOCAL_MODULE := libext2fs-host
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_SHARED_LIBRARY)
$(TDB_OBJ) \
undo_io.o \
unix_io.o \
+ sparse_io.o \
unlink.o \
valid_blk.o \
version.o \
$(srcdir)/tst_iscan.c \
$(srcdir)/undo_io.c \
$(srcdir)/unix_io.c \
+ $(srcdir)/sparse_io.c \
$(srcdir)/unlink.c \
$(srcdir)/valid_blk.c \
$(srcdir)/version.c \
$(Q) $(CC) -o mkjournal $(srcdir)/mkjournal.c -DDEBUG \
$(STATIC_LIBEXT2FS) $(LIBCOM_ERR) $(ALL_CFLAGS) $(SYSLIBS)
-check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount \
+fullcheck check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount \
tst_super_size tst_types tst_inode_size tst_csum tst_crc32c tst_bitmaps \
tst_inline tst_inline_data tst_libext2fs tst_sha256 tst_sha512 \
tst_digest_encode tst_getsize tst_getsectsize
$(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)/bitops.h
+sparse_io.o: $(srcdir)/sparse_io.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)/bitops.h
unlink.o: $(srcdir)/unlink.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 \
* Stupid algorithm --- we now just search forward starting from the
* goal. Should put in a smarter one someday....
*/
-errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
- ext2fs_block_bitmap map, blk64_t *ret)
+errcode_t ext2fs_new_block3(ext2_filsys fs, blk64_t goal,
+ ext2fs_block_bitmap map, blk64_t *ret,
+ struct blk_alloc_ctx *ctx)
{
errcode_t retval;
blk64_t b = 0;
errcode_t (*gab)(ext2_filsys fs, blk64_t goal, blk64_t *ret);
+ errcode_t (*gab2)(ext2_filsys, blk64_t, blk64_t *,
+ struct blk_alloc_ctx *);
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
- if (!map && fs->get_alloc_block) {
+ if (!map) {
/*
* In case there are clients out there whose get_alloc_block
* handlers call ext2fs_new_block2 with a NULL block map,
* temporarily swap out the function pointer so that we don't
* end up in an infinite loop.
*/
- gab = fs->get_alloc_block;
- fs->get_alloc_block = NULL;
- retval = gab(fs, goal, &b);
- fs->get_alloc_block = gab;
- goto allocated;
+ if (fs->get_alloc_block2) {
+ gab2 = fs->get_alloc_block2;
+ fs->get_alloc_block2 = NULL;
+ retval = gab2(fs, goal, &b, ctx);
+ fs->get_alloc_block2 = gab2;
+ goto allocated;
+ } else if (fs->get_alloc_block) {
+ gab = fs->get_alloc_block;
+ fs->get_alloc_block = NULL;
+ retval = gab(fs, goal, &b);
+ fs->get_alloc_block = gab;
+ goto allocated;
+ }
}
if (!map)
map = fs->block_map;
return 0;
}
+errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
+ ext2fs_block_bitmap map, blk64_t *ret)
+{
+ return ext2fs_new_block3(fs, goal, map, ret, NULL);
+}
+
errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
ext2fs_block_bitmap map, blk_t *ret)
{
* This function zeros out the allocated block, and updates all of the
* appropriate filesystem records.
*/
-errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal,
- char *block_buf, blk64_t *ret)
+errcode_t ext2fs_alloc_block3(ext2_filsys fs, blk64_t goal, char *block_buf,
+ blk64_t *ret, struct blk_alloc_ctx *ctx)
{
errcode_t retval;
blk64_t block;
- if (fs->get_alloc_block) {
+ if (fs->get_alloc_block2) {
+ retval = (fs->get_alloc_block2)(fs, goal, &block, ctx);
+ if (retval)
+ goto fail;
+ } else if (fs->get_alloc_block) {
retval = (fs->get_alloc_block)(fs, goal, &block);
if (retval)
goto fail;
goto fail;
}
- retval = ext2fs_new_block2(fs, goal, 0, &block);
+ retval = ext2fs_new_block3(fs, goal, 0, &block, ctx);
if (retval)
goto fail;
}
return retval;
}
+errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal,
+ char *block_buf, blk64_t *ret)
+{
+ return ext2fs_alloc_block3(fs, goal, block_buf, ret, NULL);
+}
+
errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
char *block_buf, blk_t *ret)
{
errcode_t retval;
- blk64_t val;
- retval = ext2fs_alloc_block2(fs, goal, block_buf, &val);
+ blk64_t ret64, goal64 = goal;
+ retval = ext2fs_alloc_block3(fs, goal64, block_buf, &ret64, NULL);
if (!retval)
- *ret = (blk_t) val;
- return retval;
+ *ret = (blk_t)ret64;
+ return retval;
}
errcode_t ext2fs_get_free_blocks2(ext2_filsys fs, blk64_t start, blk64_t finish,
extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
- ino_t inode, int num);
+ ext2_ino_t inode, int num);
extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
__u32 bitno);
extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
* %End-Header%
*/
+#include "config.h"
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
+#if HAVE_LINUX_TYPES_H
+#include <linux/types.h>
+#endif
#include "ext2_fs.h"
#include "ext2fsP.h"
int *ret_flags, int *blocks_alloc,
blk64_t *phys_blk)
{
+ struct blk_alloc_ctx alloc_ctx;
struct ext2fs_extent extent;
unsigned int offset;
errcode_t retval = 0;
0, block-1, 0, blocks_alloc, &blk64);
if (retval)
blk64 = ext2fs_find_inode_goal(fs, ino, inode, block);
- retval = ext2fs_alloc_block2(fs, blk64, block_buf,
- &blk64);
+ alloc_ctx.ino = ino;
+ alloc_ctx.inode = inode;
+ alloc_ctx.lblk = extent.e_lblk;
+ alloc_ctx.flags = BLOCK_ALLOC_DATA;
+ retval = ext2fs_alloc_block3(fs, blk64, block_buf, &blk64,
+ &alloc_ctx);
if (retval)
return retval;
blk64 &= ~EXT2FS_CLUSTER_MASK(fs);
ext2_extent_handle_t handle = 0;
blk_t addr_per_block;
blk_t b, blk32;
+ blk64_t b64;
char *buf = 0;
errcode_t retval = 0;
int blocks_alloc = 0, inode_dirty = 0;
+ struct blk_alloc_ctx alloc_ctx = {
+ .ino = ino,
+ .inode = inode,
+ .lblk = 0,
+ .flags = BLOCK_ALLOC_DATA,
+ };
if (!(bmap_flags & BMAP_SET))
*phys_blk = 0;
ext2fs_find_inode_goal(fs, ino, inode, block);
if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) {
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+ b64 = b;
+ retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
+ &alloc_ctx);
+ b = b64;
if (retval)
goto done;
inode_bmap(inode, block) = b;
}
b = inode_bmap(inode, EXT2_IND_BLOCK-1);
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+ b64 = b;
+ retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
+ &alloc_ctx);
+ b = b64;
if (retval)
goto done;
inode_bmap(inode, EXT2_IND_BLOCK) = b;
}
b = inode_bmap(inode, EXT2_IND_BLOCK);
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+ b64 = b;
+ retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
+ &alloc_ctx);
+ b = b64;
if (retval)
goto done;
inode_bmap(inode, EXT2_DIND_BLOCK) = b;
}
b = inode_bmap(inode, EXT2_DIND_BLOCK);
- retval = ext2fs_alloc_block(fs, b, block_buf, &b);
+ b64 = b;
+ retval = ext2fs_alloc_block3(fs, b64, block_buf, &b64,
+ &alloc_ctx);
+ b = b64;
if (retval)
goto done;
inode_bmap(inode, EXT2_TIND_BLOCK) = b;
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
- __u32 i_size_high; /* Formerly i_dir_acl, directory ACL */
+ __u32 i_size_high;
__u32 i_faddr; /* Fragment address */
union {
struct {
__u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
__u32 i_generation; /* File version (for NFS) */
__u32 i_file_acl; /* File ACL */
- __u32 i_size_high; /* Formerly i_dir_acl, directory ACL */
+ __u32 i_size_high;
__u32 i_faddr; /* Fragment address */
union {
struct {
#define EXT4_EPOCH_BITS 2
#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
-#define i_dir_acl i_size_high
-
#define i_checksum_lo osd2.linux2.l_i_checksum_lo
#define inode_includes(size, field) \
#define EXT2_FEATURE_COMPAT_SUPP 0
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
- EXT4_FEATURE_INCOMPAT_MMP)
+ EXT4_FEATURE_INCOMPAT_MMP| \
+ EXT4_FEATURE_INCOMPAT_LARGEDIR)
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
#ifndef _EXT2FS_EXT2_IO_H
#define _EXT2FS_EXT2_IO_H
+#include <ext2fs/ext2_types.h>
+
/*
* ext2_loff_t is defined here since unix_io.c needs it.
*/
extern io_manager unix_io_manager;
extern io_manager unixfd_io_manager;
+/* sparse_io.c */
+extern io_manager sparse_io_manager;
+extern io_manager sparsefd_io_manager;
+
/* undo_io.c */
extern io_manager undo_io_manager;
extern errcode_t set_undo_io_backing_manager(io_manager manager);
#define EXT2_MKJOURNAL_LAZYINIT 0x0000002 /* don't zero journal inode before use*/
#define EXT2_MKJOURNAL_NO_MNT_CHECK 0x0000004 /* don't check mount status */
+struct blk_alloc_ctx;
struct opaque_ext2_group_desc;
struct struct_ext2_filsys {
*/
errcode_t (*get_alloc_block)(ext2_filsys fs, blk64_t goal,
blk64_t *ret);
+ errcode_t (*get_alloc_block2)(ext2_filsys fs, blk64_t goal,
+ blk64_t *ret, struct blk_alloc_ctx *ctx);
void (*block_alloc_stats)(ext2_filsys fs, blk64_t blk, int inuse);
/*
#define BLOCK_COUNT_TIND (-3)
#define BLOCK_COUNT_TRANSLATOR (-4)
+#define BLOCK_ALLOC_UNKNOWN 0
+#define BLOCK_ALLOC_DATA 1
+#define BLOCK_ALLOC_METADATA 2
+
+struct blk_alloc_ctx {
+ ext2_ino_t ino;
+ struct ext2_inode *inode;
+ blk64_t lblk;
+ int flags;
+};
+
#if 0
/*
* Flags for ext2fs_move_blocks
EXT4_FEATURE_INCOMPAT_64BIT|\
EXT4_FEATURE_INCOMPAT_INLINE_DATA|\
EXT4_FEATURE_INCOMPAT_ENCRYPT|\
- EXT4_FEATURE_INCOMPAT_CSUM_SEED)
+ EXT4_FEATURE_INCOMPAT_CSUM_SEED|\
+ EXT4_FEATURE_INCOMPAT_LARGEDIR)
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
ext2fs_block_bitmap map, blk_t *ret);
extern errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
ext2fs_block_bitmap map, blk64_t *ret);
+extern errcode_t ext2fs_new_block3(ext2_filsys fs, blk64_t goal,
+ ext2fs_block_bitmap map, blk64_t *ret,
+ struct blk_alloc_ctx *ctx);
extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
blk_t finish, int num,
ext2fs_block_bitmap map,
char *block_buf, blk_t *ret);
extern errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal,
char *block_buf, blk64_t *ret);
+extern errcode_t ext2fs_alloc_block3(ext2_filsys fs, blk64_t goal,
+ char *block_buf, blk64_t *ret,
+ struct blk_alloc_ctx *ctx);
+
extern void ext2fs_set_alloc_block_callback(ext2_filsys fs,
errcode_t (*func)(ext2_filsys fs,
blk64_t goal,
return (blk_t) ext2fs_inode_data_blocks2(fs, inode);
}
+/* htree levels for ext4 */
+#define EXT4_HTREE_LEVEL_COMPAT 2
+#define EXT4_HTREE_LEVEL 3
+
+static inline unsigned int ext2_dir_htree_level(ext2_filsys fs)
+{
+ if (ext2fs_has_feature_largedir(fs->super))
+ return EXT4_HTREE_LEVEL;
+
+ return EXT4_HTREE_LEVEL_COMPAT;
+}
+
+_INLINE_ int ext2fs_htree_intnode_maxrecs(ext2_filsys fs, int blocks)
+{
+ return blocks * ((fs->blocksize - 8) / sizeof(struct ext2_dx_entry));
+}
+
/*
* This is an efficient, overflow safe way of calculating ceil((1.0 * a) / b)
*/
* still is a race condition for those kernels, but this
* reduces it greatly.)
*/
+#if defined(HAVE_FSYNC)
if (fsync (fd) == -1)
return errno;
+#endif
if (flushb) {
}
int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap,
- ino_t inode, int num)
+ ext2_ino_t inode, int num)
{
EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP);
if ((inode < bitmap->start) || (inode+num-1 > bitmap->real_end)) {
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
+#ifdef HAVE_WINSOCK_H
+#include <winsock.h>
+#else
#include <arpa/inet.h>
+#endif
#define printk printf
#define KERN_ERR ""
--- /dev/null
+#include "config.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdint.h>
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#if !defined(ENABLE_LIBSPARSE)
+static errcode_t sparse_open(const char *name EXT2FS_ATTR((unused)),
+ int flags EXT2FS_ATTR((unused)),
+ io_channel *channel EXT2FS_ATTR((unused)))
+{
+ return EXT2_ET_UNIMPLEMENTED;
+}
+static errcode_t sparse_close(io_channel channel EXT2FS_ATTR((unused)))
+{
+ return EXT2_ET_UNIMPLEMENTED;
+}
+static struct struct_io_manager struct_sparse_manager = {
+ .magic = EXT2_ET_MAGIC_IO_MANAGER,
+ .name = "Android sparse I/O Manager",
+ .open = sparse_open,
+ .close = sparse_close,
+};
+static struct struct_io_manager struct_sparsefd_manager = {
+ .magic = EXT2_ET_MAGIC_IO_MANAGER,
+ .name = "Android sparse fd I/O Manager",
+ .open = sparse_open,
+ .close = sparse_close,
+};
+#else
+#include <sparse/sparse.h>
+
+struct sparse_map {
+ int fd;
+ char **blocks;
+ int block_size;
+ uint64_t blocks_count;
+ char *file;
+ struct sparse_file *sparse_file;
+ io_channel channel;
+};
+
+struct sparse_io_params {
+ int fd;
+ char *file;
+ uint64_t blocks_count;
+ unsigned int block_size;
+};
+
+static errcode_t sparse_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf);
+
+static void free_sparse_blocks(struct sparse_map *sm)
+{
+ uint64_t i;
+
+ for (i = 0; i < sm->blocks_count; ++i)
+ free(sm->blocks[i]);
+ free(sm->blocks);
+ sm->blocks = NULL;
+}
+
+static int sparse_import_segment(void *priv, const void *data, int len,
+ unsigned int block, unsigned int nr_blocks)
+{
+ struct sparse_map *sm = priv;
+
+ /* Ignore chunk headers, only write the data */
+ if (!nr_blocks || len % sm->block_size)
+ return 0;
+
+ return sparse_write_blk(sm->channel, block, nr_blocks, data);
+}
+
+static errcode_t io_manager_import_sparse(struct sparse_io_params *params,
+ struct sparse_map *sm, io_channel io)
+{
+ int fd;
+ errcode_t retval;
+ struct sparse_file *sparse_file;
+
+ if (params->fd < 0) {
+ fd = open(params->file, O_RDONLY);
+ if (fd < 0) {
+ retval = -1;
+ goto err_open;
+ }
+ } else
+ fd = params->fd;
+ sparse_file = sparse_file_import(fd, false, false);
+ if (!sparse_file) {
+ retval = -1;
+ goto err_sparse;
+ }
+
+ sm->block_size = sparse_file_block_size(sparse_file);
+ sm->blocks_count = (sparse_file_len(sparse_file, 0, 0) - 1)
+ / sm->block_size + 1;
+ sm->blocks = calloc(sm->blocks_count, sizeof(char*));
+ if (!sm->blocks) {
+ retval = -1;
+ goto err_alloc;
+ }
+ io->block_size = sm->block_size;
+
+ retval = sparse_file_foreach_chunk(sparse_file, true, false,
+ sparse_import_segment, sm);
+
+ if (retval)
+ free_sparse_blocks(sm);
+err_alloc:
+ sparse_file_destroy(sparse_file);
+err_sparse:
+ close(fd);
+err_open:
+ return retval;
+}
+
+static errcode_t io_manager_configure(struct sparse_io_params *params,
+ int flags, io_channel io)
+{
+ errcode_t retval;
+ uint64_t img_size;
+ struct sparse_map *sm = calloc(1, sizeof(*sm));
+ if (!sm)
+ return EXT2_ET_NO_MEMORY;
+
+ sm->file = params->file;
+ sm->channel = io;
+ io->private_data = sm;
+ retval = io_manager_import_sparse(params, sm, io);
+ if (retval) {
+ if (!params->block_size || !params->blocks_count) {
+ retval = -EINVAL;
+ goto err_params;
+ }
+ sm->block_size = params->block_size;
+ sm->blocks_count = params->blocks_count;
+ sm->blocks = calloc(params->blocks_count, sizeof(void*));
+ if (!sm->blocks) {
+ retval = EXT2_ET_NO_MEMORY;
+ goto err_alloc;
+ }
+ }
+ io->block_size = sm->block_size;
+ img_size = (uint64_t)sm->block_size * sm->blocks_count;
+
+ if (flags & IO_FLAG_RW) {
+ sm->sparse_file = sparse_file_new(sm->block_size, img_size);
+ if (!sm->sparse_file) {
+ retval = EXT2_ET_NO_MEMORY;
+ goto err_alloc;
+ }
+ if (params->fd < 0) {
+ sm->fd = open(params->file, O_CREAT | O_RDWR | O_TRUNC,
+ 0644);
+ if (sm->fd < 0) {
+ retval = errno;
+ goto err_open;
+ }
+ } else
+ sm->fd = params->fd;
+ } else {
+ sm->fd = -1;
+ sm->sparse_file = NULL;
+ }
+ return 0;
+
+err_open:
+ sparse_file_destroy(sm->sparse_file);
+err_alloc:
+ free_sparse_blocks(sm);
+err_params:
+ free(sm);
+ return retval;
+}
+
+static errcode_t sparse_open_channel(struct sparse_io_params *sparse_params,
+ int flags, io_channel *channel)
+{
+ io_channel io;
+
+ io = calloc(1, sizeof(struct struct_io_channel));
+ io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+ io->block_size = 0;
+ io->refcount = 1;
+ *channel = io;
+ return io_manager_configure(sparse_params, flags, io);
+}
+
+static errcode_t read_sparse_argv(const char *name, bool is_fd,
+ struct sparse_io_params *sparse_params)
+{
+ int ret;
+ sparse_params->fd = -1;
+ sparse_params->block_size = 0;
+ sparse_params->blocks_count = 0;
+
+ sparse_params->file = malloc(strlen(name) + 1);
+ if (!sparse_params->file) {
+ fprintf(stderr, "failed to alloc %zu\n", strlen(name) + 1);
+ return EXT2_ET_NO_MEMORY;
+ }
+
+ if (is_fd) {
+ ret = sscanf(name, "%d:%llu:%u", &sparse_params->fd,
+ (unsigned long long *)&sparse_params->blocks_count,
+ &sparse_params->block_size);
+ } else {
+ ret = sscanf(name, "%[^:]%*[:]%llu%*[:]%u", sparse_params->file,
+ (unsigned long long *)&sparse_params->blocks_count,
+ &sparse_params->block_size);
+ }
+
+ if (ret < 1) {
+ free(sparse_params->file);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static errcode_t sparse_open(const char *name, int flags, io_channel *channel)
+{
+ errcode_t retval;
+ struct sparse_io_params sparse_params;
+
+ retval = read_sparse_argv(name, false, &sparse_params);
+ if (retval)
+ return EXT2_ET_BAD_DEVICE_NAME;
+
+ retval = sparse_open_channel(&sparse_params, flags, channel);
+ if (retval)
+ return retval;
+ (*channel)->manager = sparse_io_manager;
+
+ return retval;
+}
+
+static errcode_t sparsefd_open(const char *name, int flags, io_channel *channel)
+{
+ errcode_t retval;
+ struct sparse_io_params sparse_params;
+
+ retval = read_sparse_argv(name, true, &sparse_params);
+ if (retval)
+ return EXT2_ET_BAD_DEVICE_NAME;
+
+ retval = sparse_open_channel(&sparse_params, flags, channel);
+ if (retval)
+ return retval;
+ (*channel)->manager = sparsefd_io_manager;
+
+ return retval;
+}
+
+static errcode_t sparse_merge_blocks(struct sparse_map *sm, uint64_t start,
+ uint64_t num)
+{
+ char *buf;
+ uint64_t i;
+ unsigned int block_size = sm->block_size;
+ errcode_t retval = 0;
+
+ buf = calloc(num, block_size);
+ if (!buf) {
+ fprintf(stderr, "failed to alloc %lu\n", num * block_size);
+ return EXT2_ET_NO_MEMORY;
+ }
+
+ for (i = 0; i < num; i++) {
+ memcpy(buf + i * block_size, sm->blocks[start + i] , block_size);
+ free(sm->blocks[start + i]);
+ sm->blocks[start + i] = NULL;
+ }
+
+ /* free_sparse_blocks will release this buf. */
+ sm->blocks[start] = buf;
+
+ retval = sparse_file_add_data(sm->sparse_file, sm->blocks[start],
+ block_size * num, start);
+
+ return retval;
+}
+
+static errcode_t sparse_close_channel(io_channel channel)
+{
+ uint64_t i;
+ errcode_t retval = 0;
+ struct sparse_map *sm = channel->private_data;
+
+ if (sm->sparse_file) {
+ int64_t chunk_start = (sm->blocks[0] == NULL) ? -1 : 0;
+ for (i = 0; i < sm->blocks_count; ++i) {
+ if (!sm->blocks[i] && chunk_start != -1) {
+ retval = sparse_merge_blocks(sm, chunk_start, i - chunk_start);
+ chunk_start = -1;
+ } else if (sm->blocks[i] && chunk_start == -1) {
+ chunk_start = i;
+ }
+ if (retval)
+ goto ret;
+ }
+ if (chunk_start != -1) {
+ retval = sparse_merge_blocks(sm, chunk_start,
+ sm->blocks_count - chunk_start);
+ if (retval)
+ goto ret;
+ }
+ retval = sparse_file_write(sm->sparse_file, sm->fd,
+ /*gzip*/0, /*sparse*/1, /*crc*/0);
+ }
+
+ret:
+ if (sm->sparse_file)
+ sparse_file_destroy(sm->sparse_file);
+ free_sparse_blocks(sm);
+ free(sm->file);
+ free(sm);
+ free(channel);
+ return retval;
+}
+
+static errcode_t sparse_close(io_channel channel)
+{
+ errcode_t retval;
+ struct sparse_map *sm = channel->private_data;
+ int fd = sm->fd;
+
+ retval = sparse_close_channel(channel);
+ if (fd >= 0)
+ close(fd);
+
+ return retval;
+}
+
+static errcode_t sparse_set_blksize(io_channel channel, int blksize)
+{
+ channel->block_size = blksize;
+ return 0;
+}
+
+static blk64_t block_to_sparse_block(blk64_t block, blk64_t *offset,
+ io_channel channel, struct sparse_map *sm)
+{
+ int ratio;
+ blk64_t ret = block;
+
+ ratio = sm->block_size / channel->block_size;
+ ret /= ratio;
+ *offset = (block % ratio) * channel->block_size;
+
+ return ret;
+}
+
+static errcode_t check_block_size(io_channel channel, struct sparse_map *sm)
+{
+ if (sm->block_size >= channel->block_size)
+ return 0;
+ return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
+}
+
+static errcode_t sparse_read_blk64(io_channel channel, blk64_t block,
+ int count, void *buf)
+{
+ int i;
+ char *out = buf;
+ blk64_t offset = 0, cur_block;
+ struct sparse_map *sm = channel->private_data;
+
+ if (check_block_size(channel, sm))
+ return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
+
+ if (count < 0) { //partial read
+ count = -count;
+ cur_block = block_to_sparse_block(block, &offset, channel, sm);
+ if (sm->blocks[cur_block])
+ memcpy(out, (sm->blocks[cur_block]) + offset, count);
+ else
+ memset(out, 0, count);
+ } else {
+ for (i = 0; i < count; ++i) {
+ cur_block = block_to_sparse_block(block + i, &offset,
+ channel, sm);
+ if (sm->blocks[cur_block])
+ memcpy(out + (i * channel->block_size),
+ sm->blocks[cur_block] + offset,
+ channel->block_size);
+ else if (sm->blocks)
+ memset(out + (i * channel->block_size), 0,
+ channel->block_size);
+ }
+ }
+ return 0;
+}
+
+static errcode_t sparse_read_blk(io_channel channel, unsigned long block,
+ int count, void *buf)
+{
+ return sparse_read_blk64(channel, block, count, buf);
+}
+
+static errcode_t sparse_write_blk64(io_channel channel, blk64_t block,
+ int count, const void *buf)
+{
+ int i;
+ blk64_t offset = 0, cur_block;
+ const char *in = buf;
+ struct sparse_map *sm = channel->private_data;
+
+ if (check_block_size(channel, sm))
+ return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
+
+ if (count < 0) { //partial write
+ count = -count;
+ cur_block = block_to_sparse_block(block, &offset, channel,
+ sm);
+ if (!sm->blocks[cur_block]) {
+ sm->blocks[cur_block] = calloc(1, sm->block_size);
+ if (!sm->blocks[cur_block])
+ return EXT2_ET_NO_MEMORY;
+ }
+ memcpy(sm->blocks[cur_block] + offset, in, count);
+ } else {
+ for (i = 0; i < count; ++i) {
+ if (block + i >= sm->blocks_count)
+ return 0;
+ cur_block = block_to_sparse_block(block + i, &offset,
+ channel, sm);
+ if (!sm->blocks[cur_block]) {
+ sm->blocks[cur_block] =
+ calloc(1, sm->block_size);
+ if (!sm->blocks[cur_block])
+ return EXT2_ET_NO_MEMORY;
+ }
+ memcpy(sm->blocks[cur_block] + offset,
+ in + (i * channel->block_size),
+ channel->block_size);
+ }
+ }
+ return 0;
+}
+
+static errcode_t sparse_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf)
+{
+ return sparse_write_blk64(channel, block, count, buf);
+}
+
+static errcode_t sparse_discard(io_channel channel __attribute__((unused)),
+ blk64_t blk, unsigned long long count)
+{
+ blk64_t cur_block, offset;
+ struct sparse_map *sm = channel->private_data;
+
+ if (check_block_size(channel, sm))
+ return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
+
+ for (unsigned long long i = 0; i < count; ++i) {
+ if (blk + i >= sm->blocks_count)
+ return 0;
+ cur_block = block_to_sparse_block(blk + i, &offset, channel,
+ sm);
+ if (!sm->blocks[cur_block])
+ continue;
+ free(sm->blocks[cur_block]);
+ sm->blocks[cur_block] = NULL;
+ }
+ return 0;
+}
+
+static errcode_t sparse_zeroout(io_channel channel, blk64_t blk,
+ unsigned long long count)
+{
+ return sparse_discard(channel, blk, count);
+}
+
+static errcode_t sparse_flush(io_channel channel __attribute__((unused)))
+{
+ return 0;
+}
+
+static errcode_t sparse_set_option(io_channel channel __attribute__((unused)),
+ const char *option __attribute__((unused)),
+ const char *arg __attribute__((unused)))
+{
+ return 0;
+}
+
+static errcode_t sparse_cache_readahead(
+ io_channel channel __attribute__((unused)),
+ blk64_t blk __attribute__((unused)),
+ unsigned long long count __attribute__((unused)))
+{
+ return 0;
+}
+
+static struct struct_io_manager struct_sparse_manager = {
+ .magic = EXT2_ET_MAGIC_IO_MANAGER,
+ .name = "Android sparse I/O Manager",
+ .open = sparse_open,
+ .close = sparse_close,
+ .set_blksize = sparse_set_blksize,
+ .read_blk = sparse_read_blk,
+ .write_blk = sparse_write_blk,
+ .flush = sparse_flush,
+ .write_byte = NULL,
+ .set_option = sparse_set_option,
+ .get_stats = NULL,
+ .read_blk64 = sparse_read_blk64,
+ .write_blk64 = sparse_write_blk64,
+ .discard = sparse_discard,
+ .cache_readahead = sparse_cache_readahead,
+ .zeroout = sparse_zeroout,
+};
+
+static struct struct_io_manager struct_sparsefd_manager = {
+ .magic = EXT2_ET_MAGIC_IO_MANAGER,
+ .name = "Android sparse fd I/O Manager",
+ .open = sparsefd_open,
+ .close = sparse_close,
+ .set_blksize = sparse_set_blksize,
+ .read_blk = sparse_read_blk,
+ .write_blk = sparse_write_blk,
+ .flush = sparse_flush,
+ .write_byte = NULL,
+ .set_option = sparse_set_option,
+ .get_stats = NULL,
+ .read_blk64 = sparse_read_blk64,
+ .write_blk64 = sparse_write_blk64,
+ .discard = sparse_discard,
+ .cache_readahead = sparse_cache_readahead,
+ .zeroout = sparse_zeroout,
+};
+
+#endif
+
+io_manager sparse_io_manager = &struct_sparse_manager;
+io_manager sparsefd_io_manager = &struct_sparsefd_manager;
has_extents = 1;
if (!hostorder && (t->i_flags & EXT4_INLINE_DATA_FL))
has_inline_data = 1;
- t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
+ t->i_size_high = ext2fs_swab32(f->i_size_high);
/*
* Extent data and inline data are swapped on access, not here
*/
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;
int fd_flags;
fd = atoi(str_fd);
+#if defined(HAVE_FCNTL)
fd_flags = fcntl(fd, F_GETFD);
if (fd_flags == -1)
return -EBADF;
if (fd_flags & O_DIRECT)
flags |= IO_FLAG_DIRECT_IO;
#endif
+#endif /* HAVE_FCNTL */
return unix_open_channel(str_fd, fd, flags, channel, unixfd_io_manager);
}
#ifndef NO_IO_CACHE
retval = flush_cached_blocks(channel, data, 0);
#endif
+#ifdef HAVE_FSYNC
if (!retval && fsync(data->dev) != 0)
return errno;
+#endif
return retval;
}
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+cc_library {
+ name: "libext2_ss",
+ host_supported: true,
+ unique_host_soname: true,
+ srcs: [
+ "ss_err.c",
+ "std_rqs.c",
+ "invocation.c",
+ "help.c",
+ "execute_cmd.c",
+ "listen.c",
+ "parse.c",
+ "error.c",
+ "prompt.c",
+ "request_tbl.c",
+ "list_rqs.c",
+ "pager.c",
+ "requests.c",
+ "data.c",
+ "get_readline.c",
+ ],
+ shared_libs: ["libext2_com_err"],
+ cflags: [
+ "-W",
+ "-Wall",
+ ],
+
+ header_libs: ["libext2-headers"],
+ export_include_dirs: ["."],
+ export_header_lib_headers: ["libext2-headers"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-libext2_ss_src_files := \
- ss_err.c \
- std_rqs.c \
- invocation.c help.c \
- execute_cmd.c \
- listen.c \
- parse.c \
- error.c \
- prompt.c \
- request_tbl.c \
- list_rqs.c \
- pager.c \
- requests.c \
- data.c \
- get_readline.c
-
-libext2_ss_c_includes := external/e2fsprogs/lib
-
-libext2_ss_cflags := -O2 -g -W -Wall
-
-libext2_ss_shared_libraries := \
- libext2_com_err
-
-libext2_ss_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_ss_src_files)
-LOCAL_C_INCLUDES := $(libext2_ss_c_includes)
-LOCAL_CFLAGS := $(libext2_ss_cflags)
-LOCAL_SHARED_LIBRARIES := $(libext2_ss_shared_libraries)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(libext2_ss_system_shared_libraries)
-LOCAL_MODULE := libext2_ss
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_ss_src_files)
-LOCAL_C_INCLUDES := $(libext2_ss_c_includes)
-LOCAL_CFLAGS := $(libext2_ss_cflags)
-LOCAL_STATIC_LIBRARIES := libc
-LOCAL_MODULE := libext2_ss
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_ss_src_files)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(libext2_ss_shared_libraries))
-LOCAL_C_INCLUDES := $(libext2_ss_c_includes)
-LOCAL_CFLAGS := $(libext2_ss_cflags)
-LOCAL_MODULE := libext2_ss-host
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_SHARED_LIBRARY)
$(Q) $(CC) -o $@ test_ss.o test_cmd.o $(ALL_CFLAGS) $(ALL_LDFLAGS) \
$(LIBSS) $(LIBCOM_ERR) $(SYSLIBS)
-check:: all test_ss
+fullcheck check:: all test_ss
$(E) " RUN TEST test_ss"
-@($(TESTENV) ./test_ss -f $(srcdir)/test_script > test_out 2>&1; exit 0)
$(Q) if diff test_out $(srcdir)/test_script_expected > test.diff; then \
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+cc_library {
+ name: "libext2_quota",
+ host_supported: true,
+ unique_host_soname: true,
+ srcs: [
+ "dict.c",
+ "mkquota.c",
+ "parse_qtype.c",
+ "plausible.c",
+ "profile.c",
+ "profile_helpers.c",
+ "prof_err.c",
+ "quotaio.c",
+ "quotaio_tree.c",
+ "quotaio_v2.c",
+ ],
+ shared_libs: [
+ "libext2fs",
+ "libext2_com_err",
+ "libext2_blkid",
+ ],
+
+ cflags: [
+ "-W",
+ "-Wall",
+ "-Wno-macro-redefined",
+ ],
+
+ header_libs: ["libext2-headers"],
+ export_include_dirs: ["."],
+ export_header_lib_headers: ["libext2-headers"],
+}
+
+cc_library_shared {
+ name: "libext2_profile",
+ host_supported: true,
+ unique_host_soname: true,
+
+ srcs: [
+ "prof_err.c",
+ "profile.c",
+ ],
+ cflags = [
+ "-W",
+ "-Wall",
+ ],
+ shared_libs: ["libext2_com_err"],
+
+ header_libs: ["libext2-headers"],
+ export_include_dirs: ["."],
+ export_header_lib_headers: ["libext2-headers"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-libext2_quota_src_files := \
- dict.c \
- mkquota.c \
- parse_qtype.c \
- plausible.c \
- profile.c \
- profile_helpers.c \
- prof_err.c \
- quotaio.c \
- quotaio_tree.c \
- quotaio_v2.c
-
-libext2_quota_c_includes := external/e2fsprogs/lib
-
-libext2_quota_cflags := -O2 -g -W -Wall
-
-libext2_quota_shared_libraries := libext2fs libext2_com_err libext2_blkid
-
-libext2_quota_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_quota_src_files)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(libext2_quota_system_shared_libraries)
-LOCAL_C_INCLUDES := $(libext2_quota_c_includes)
-LOCAL_CFLAGS := $(libext2_quota_cflags)
-LOCAL_SYSTEM_SHARED_LIBRARIES := libc $(libext2_quota_shared_libraries)
-LOCAL_MODULE := libext2_quota
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-libext2_quota_static_libraries := libext2fs libext2_com_err
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_quota_src_files)
-LOCAL_C_INCLUDES := $(libext2_quota_c_includes)
-LOCAL_CFLAGS := $(libext2_quota_cflags)
-LOCAL_STATIC_LIBRARIES := libc $(libext2_quota_static_libraries)
-LOCAL_MODULE := libext2_quota
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_quota_src_files)
-LOCAL_C_INCLUDES := $(libext2_quota_c_includes)
-LOCAL_CFLAGS := $(libext2_quota_cflags)
-LOCAL_MODULE := libext2_quota-host
-LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(libext2_quota_shared_libraries))
-
-include $(BUILD_HOST_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-libext2_profile_src_files := \
- prof_err.c \
- profile.c
-
-libext2_profile_shared_libraries := \
- libext2_com_err
-
-libext2_profile_system_shared_libraries := libc
-
-libext2_profile_c_includes := external/e2fsprogs/lib
-
-libext2_profile_cflags := -O2 -g -W -Wall
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_profile_src_files)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(libext2_profile_system_shared_libraries)
-LOCAL_SHARED_LIBRARIES := $(libext2_profile_shared_libraries)
-LOCAL_C_INCLUDES := $(libext2_profile_c_includes)
-LOCAL_CFLAGS := $(libext2_profile_cflags)
-LOCAL_MODULE := libext2_profile
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_profile_src_files)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(libext2_profile_shared_libraries))
-LOCAL_C_INCLUDES := $(libext2_profile_c_includes)
-LOCAL_CFLAGS := $(libext2_profile_cflags)
-LOCAL_MODULE := libext2_profile-host
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_SHARED_LIBRARY)
../libsupport.a ../libsupport_p.a $(SMANPAGES) \
prof_err.c prof_err.h test_profile test_cstring
-#check:: tst_uuid
+#fullcheck check:: tst_uuid
# LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_uuid
mostlyclean:: clean
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+cc_library {
+ name: "libext2_uuid",
+ host_supported: true,
+ unique_host_soname: true,
+ srcs: [
+ "clear.c",
+ "compare.c",
+ "copy.c",
+ "gen_uuid.c",
+ "isnull.c",
+ "pack.c",
+ "parse.c",
+ "unpack.c",
+ "unparse.c",
+ "uuid_time.c",
+ ],
+ cflags: [
+ "-W",
+ "-Wall",
+ "-Wno-unused-function",
+ "-Wno-unused-parameter",
+ ],
+
+ header_libs: ["libext2-headers"],
+ export_include_dirs: ["."],
+ export_header_lib_headers: ["libext2-headers"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-libext2_uuid_src_files := \
- clear.c \
- compare.c \
- copy.c \
- gen_uuid.c \
- isnull.c \
- pack.c \
- parse.c \
- unpack.c \
- unparse.c \
- uuid_time.c
-
-
-libext2_uuid_c_includes := external/e2fsprogs/lib
-
-libext2_uuid_cflags := -O2 -g -W -Wall \
- -Wno-unused-function \
- -Wno-unused-parameter
-
-libext2_uuid_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_uuid_src_files)
-LOCAL_C_INCLUDES := $(libext2_uuid_c_includes)
-LOCAL_CFLAGS := $(libext2_uuid_cflags)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) $(LOCAL_PATH)/..
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(libext2_uuid_system_shared_libraries)
-LOCAL_MODULE := libext2_uuid
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_uuid_src_files)
-LOCAL_C_INCLUDES := $(libext2_uuid_c_includes)
-LOCAL_CFLAGS := $(libext2_uuid_cflags)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_MODULE := libext2_uuid-host
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_SHARED_LIBRARY)
-
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_uuid_src_files)
-LOCAL_C_INCLUDES := $(libext2_uuid_c_includes)
-LOCAL_CFLAGS := $(libext2_uuid_cflags)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_STATIC_LIBRARIES := libc
-LOCAL_MODULE := libext2_uuid_static
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(libext2_uuid_src_files)
-LOCAL_C_INCLUDES := $(libext2_uuid_c_includes)
-LOCAL_CFLAGS := $(libext2_uuid_cflags)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_MODULE := libext2_uuid-host
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_STATIC_LIBRARY)
../libuuid.a ../libuuid_p.a tst_uuid uuid_time \
uuid.pc uuid_types.h $(SMANPAGES)
-check:: tst_uuid
+fullcheck check:: tst_uuid
LD_LIBRARY_PATH=$(LIB) DYLD_LIBRARY_PATH=$(LIB) ./tst_uuid
mostlyclean:: clean
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+// Library used to export files from this directory to other programs in this
+// project.
+cc_library {
+ name: "libext2_misc",
+ host_supported: true,
+
+ srcs: [
+ "create_inode.c",
+ ],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+ shared_libs: [
+ "libext2_quota",
+ "libext2fs",
+ ],
+ system_shared_libs: ["libc"],
+ export_include_dirs: ["."],
+}
+
+//########################################################################
+// Build mke2fs
+
+cc_binary {
+ name: "mke2fs",
+ host_supported: true,
+
+ srcs: [
+ "mke2fs.c",
+ "util.c",
+ "mk_hugefiles.c",
+ "default_profile.c",
+ ],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+ shared_libs: [
+ "libext2fs",
+ "libext2_blkid",
+ "libext2_misc",
+ "libext2_uuid",
+ "libext2_quota",
+ "libext2_com_err",
+ "libext2_e2p",
+ ],
+ system_shared_libs: ["libc"],
+ include_dirs: ["external/e2fsprogs/e2fsck"],
+}
+
+//##########################################################################
+// Build tune2fs
+
+cc_defaults {
+ name: "tune2fs-defaults",
+ srcs: [
+ "tune2fs.c",
+ "util.c",
+ ],
+ cflags: [
+ "-W",
+ "-Wall",
+ "-DNO_RECOVERY",
+ "-Wno-macro-redefined",
+ ],
+ include_dirs: ["external/e2fsprogs/e2fsck"],
+}
+
+tune2fs_libs = [
+ "libext2_com_err",
+ "libext2_blkid",
+ "libext2_quota",
+ "libext2_uuid",
+ "libext2_e2p",
+ "libext2fs",
+]
+
+cc_binary {
+ name: "tune2fs",
+ host_supported: true,
+ defaults: ["tune2fs-defaults"],
+
+ shared_libs: tune2fs_libs,
+ system_shared_libs: ["libc"],
+}
+
+cc_binary {
+ name: "tune2fs_static",
+ static_executable: true,
+ defaults: ["tune2fs-defaults"],
+
+ static_libs: tune2fs_libs + ["libc"],
+}
+
+cc_library_static {
+ name: "libtune2fs",
+ defaults: ["tune2fs-defaults"],
+
+ cflags: ["-DBUILD_AS_LIB"],
+ static_libs: tune2fs_libs,
+}
+
+//########################################################################
+// Build badblocks
+
+cc_binary {
+ name: "badblocks",
+ host_supported: true,
+
+ srcs: ["badblocks.c"],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+ shared_libs: [
+ "libext2fs",
+ "libext2_com_err",
+ "libext2_uuid",
+ "libext2_blkid",
+ "libext2_e2p",
+ ],
+ system_shared_libs: ["libc"],
+}
+
+//########################################################################
+// Build chattr
+
+cc_binary {
+ name: "chattr",
+ host_supported: true,
+
+ srcs: ["chattr.c"],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+ shared_libs: [
+ "libext2_com_err",
+ "libext2_e2p",
+ ],
+ system_shared_libs: ["libc"],
+}
+
+//########################################################################
+// Build lsattr
+
+cc_defaults {
+ name: "lsattr-defaults",
+ srcs: ["lsattr.c"],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+}
+
+lsattr_libs = [
+ "libext2_com_err",
+ "libext2_e2p",
+]
+
+cc_binary {
+ name: "lsattr",
+ host_supported: true,
+ defaults: ["lsattr-defaults"],
+
+ shared_libs: lsattr_libs,
+ system_shared_libs: ["libc"],
+}
+
+cc_binary {
+ name: "lsattr_static",
+ static_executable: true,
+ defaults: ["lsattr-defaults"],
+
+ static_libs: lsattr_libs + ["libc"],
+}
+
+//########################################################################
+// Build blkid
+
+cc_binary {
+ name: "blkid",
+
+ srcs: ["blkid.c"],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+ shared_libs: [
+ "libext2fs",
+ "libext2_blkid",
+ "libext2_com_err",
+ "libext2_e2p",
+ ],
+ system_shared_libs: ["libc"],
+}
+
+//########################################################################
+// Build e4crypt
+
+cc_binary {
+ name: "e4crypt",
+ host_supported: true,
+
+ srcs: ["e4crypt.c"],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+ shared_libs: [
+ "libext2fs",
+ "libext2_uuid",
+ ],
+ system_shared_libs: ["libc"],
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+//##########################################################################
+// Build e2image
+
+cc_binary {
+ name: "e2image",
+ host_supported: true,
+
+ srcs: ["e2image.c"],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+ shared_libs: [
+ "libext2fs",
+ "libext2_blkid",
+ "libext2_com_err",
+ "libext2_quota",
+ ],
+ system_shared_libs: ["libc"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-#########################################################################
-# Build mke2fs
-mke2fs_src_files := \
- mke2fs.c \
- util.c \
- mk_hugefiles.c \
- default_profile.c \
- create_inode.c
-
-mke2fs_c_includes := \
- external/e2fsprogs/e2fsck
-
-mke2fs_cflags := -O2 -g -W -Wall
-
-mke2fs_shared_libraries := \
- libext2fs \
- libext2_blkid \
- libext2_uuid \
- libext2_quota \
- libext2_com_err \
- libext2_e2p
-
-mke2fs_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(mke2fs_src_files)
-LOCAL_C_INCLUDES := $(mke2fs_c_includes)
-LOCAL_CFLAGS := $(mke2fs_cflags)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(mke2fs_system_shared_libraries)
-LOCAL_SHARED_LIBRARIES := $(mke2fs_shared_libraries)
-LOCAL_MODULE := mke2fs
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(mke2fs_src_files)
-LOCAL_C_INCLUDES := $(mke2fs_c_includes)
-LOCAL_CFLAGS := $(mke2fs_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(mke2fs_shared_libraries))
-LOCAL_MODULE := mke2fs_host
-LOCAL_MODULE_STEM := mke2fs
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
-
-###########################################################################
-# Build tune2fs
-#
-tune2fs_src_files := \
- tune2fs.c \
- util.c
-
-tune2fs_c_includes := \
- external/e2fsprogs/e2fsck
-
-tune2fs_cflags := -O2 -g -W -Wall -DNO_RECOVERY
-
-tune2fs_shared_libraries := \
- libext2fs \
- libext2_com_err \
- libext2_blkid \
- libext2_quota \
- libext2_uuid \
- libext2_e2p
-
-tune2fs_system_shared_libraries := libc
-
-
-tune2fs_static_libraries := \
- libext2_com_err \
- libext2_blkid \
- libext2_quota \
- libext2_uuid_static \
- libext2_e2p \
- libext2fs
-
-tune2fs_system_static_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(tune2fs_src_files)
-LOCAL_C_INCLUDES := $(tune2fs_c_includes)
-LOCAL_CFLAGS := $(tune2fs_cflags)
-LOCAL_SHARED_LIBRARIES := $(tune2fs_shared_libraries)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(tune2fs_system_shared_libraries)
-LOCAL_MODULE := tune2fs
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(tune2fs_src_files)
-LOCAL_C_INCLUDES := $(tune2fs_c_includes)
-LOCAL_CFLAGS := $(tune2fs_cflags)
-LOCAL_STATIC_LIBRARIES := $(tune2fs_static_libraries) $(tune2fs_system_static_libraries)
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE := tune2fs_static
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(tune2fs_src_files)
-LOCAL_C_INCLUDES := $(tune2fs_c_includes)
-LOCAL_CFLAGS := $(tune2fs_cflags) -DBUILD_AS_LIB
-LOCAL_STATIC_LIBRARIES := $(tune2fs_static_libraries) $(tune2fs_system_static_libraries)
-LOCAL_MODULE := libtune2fs
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(tune2fs_src_files)
-LOCAL_C_INCLUDES := $(tune2fs_c_includes)
-LOCAL_CFLAGS := $(tune2fs_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(tune2fs_shared_libraries))
-LOCAL_MODULE := tune2fs_host
-LOCAL_MODULE_STEM := tune2fs
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
-
-#########################################################################
-# Build badblocks
-#
-include $(CLEAR_VARS)
-
-badblocks_src_files := \
- badblocks.c
-
-badblocks_c_includes :=
-
-badblocks_cflags := -O2 -g -W -Wall
-
-badblocks_shared_libraries := \
- libext2fs \
- libext2_com_err \
- libext2_uuid \
- libext2_blkid \
- libext2_e2p
-
-badblocks_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(badblocks_src_files)
-LOCAL_C_INCLUDES := $(badblocks_c_includes)
-LOCAL_CFLAGS := $(badblocks_cflags)
-LOCAL_SHARED_LIBRARIES := $(badblocks_shared_libraries)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(badblocks_system_shared_libraries)
-LOCAL_MODULE := badblocks
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(badblocks_src_files)
-LOCAL_C_INCLUDES := $(badblocks_c_includes)
-LOCAL_CFLAGS := $(badblocks_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(badblocks_shared_libraries))
-LOCAL_MODULE := badblocks_host
-LOCAL_MODULE_STEM := badblocks
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
-
-#########################################################################
-# Build chattr
-#
-include $(CLEAR_VARS)
-
-chattr_src_files := \
- chattr.c
-
-chattr_c_includes := \
- external/e2fsprogs/lib
-
-chattr_cflags := -O2 -g -W -Wall
-
-chattr_shared_libraries := \
- libext2_com_err \
- libext2_e2p
-
-chattr_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(chattr_src_files)
-LOCAL_C_INCLUDES := $(chattr_c_includes)
-LOCAL_CFLAGS := $(chattr_cflags)
-LOCAL_SHARED_LIBRARIES := $(chattr_shared_libraries)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(chattr_system_shared_libraries)
-LOCAL_MODULE := chattr
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(chattr_src_files)
-LOCAL_C_INCLUDES := $(chattr_c_includes)
-LOCAL_CFLAGS := $(chattr_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(chattr_shared_libraries))
-LOCAL_MODULE := chattr_host
-LOCAL_MODULE_STEM := chattr
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
-
-#########################################################################
-# Build lsattr
-#
-include $(CLEAR_VARS)
-
-lsattr_src_files := \
- lsattr.c
-
-lsattr_c_includes := \
- external/e2fsprogs/lib
-
-lsattr_cflags := -O2 -g -W -Wall
-
-lsattr_shared_libraries := \
- libext2_com_err \
- libext2_e2p
-
-lsattr_system_shared_libraries := libc
-
-lsattr_static_libraries := \
- libext2_com_err \
- libext2_e2p
-
-lsattr_system_static_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(lsattr_src_files)
-LOCAL_C_INCLUDES := $(lsattr_c_includes)
-LOCAL_CFLAGS := $(lsattr_cflags)
-LOCAL_SHARED_LIBRARIES := $(lsattr_shared_libraries)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(lsattr_system_shared_libraries)
-LOCAL_MODULE := lsattr
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(lsattr_src_files)
-LOCAL_C_INCLUDES := $(lsattr_c_includes)
-LOCAL_CFLAGS := $(lsattr_cflags)
-LOCAL_STATIC_LIBRARIES := $(lsattr_static_libraries) $(lsattr_system_static_libraries)
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE := lsattr_static
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(lsattr_src_files)
-LOCAL_C_INCLUDES := $(lsattr_c_includes)
-LOCAL_CFLAGS := $(lsattr_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(lsattr_shared_libraries))
-LOCAL_MODULE := lsattr_host
-LOCAL_MODULE_STEM := lsattr
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
-
-#########################################################################
-# Build blkid
-#
-include $(CLEAR_VARS)
-
-blkid_src_files := \
- blkid.c
-
-blkid_c_includes :=
-
-blkid_cflags := -O2 -g -W -Wall
-
-blkid_shared_libraries := \
- libext2fs \
- libext2_blkid \
- libext2_com_err \
- libext2_e2p
-
-blkid_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(blkid_src_files)
-LOCAL_C_INCLUDES := $(blkid_c_includes)
-LOCAL_CFLAGS := $(blkid_cflags)
-LOCAL_SHARED_LIBRARIES := $(blkid_shared_libraries)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(blkid_system_shared_libraries)
-LOCAL_MODULE := blkid
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-#########################################################################
-# Build e4crypt
-e4crypt_src_files := e4crypt.c
-
-e4crypt_c_includes := \
- external/e2fsprogs/lib
-
-e4crypt_cflags := -O2 -g -W -Wall
-
-e4crypt_shared_libraries := libext2fs libext2_uuid
-
-e4crypt_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(e4crypt_src_files)
-LOCAL_C_INCLUDES := $(e4crypt_c_includes)
-LOCAL_CFLAGS := $(e4crypt_cflags)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(e4crypt_system_shared_libraries)
-LOCAL_SHARED_LIBRARIES := $(e4crypt_shared_libraries)
-LOCAL_MODULE := e4crypt
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(e4crypt_src_files)
-LOCAL_C_INCLUDES := $(e4crypt_c_includes)
-LOCAL_CFLAGS := $(e4crypt_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(e4crypt_shared_libraries))
-LOCAL_MODULE := e4crypt_host
-LOCAL_MODULE_STEM := e4crypt
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_HOST_OS := linux
-
-include $(BUILD_HOST_EXECUTABLE)
-
-###########################################################################
-# Build e2image
-#
-e2image_src_files := \
- e2image.c
-
-e2image_c_includes := \
- external/e2fsprogs/lib
-
-e2image_cflags := -O2 -g -W -Wall
-
-e2image_shared_libraries := \
- libext2fs \
- libext2_blkid \
- libext2_com_err \
- libext2_quota
-
-e2image_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(e2image_src_files)
-LOCAL_C_INCLUDES := $(e2image_c_includes)
-mke2fs_c_includesLOCAL_CFLAGS := $(e2image_cflags)
-LOCAL_SHARED_LIBRARIES := $(e2image_shared_libraries)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(e2image_system_shared_libraries)
-LOCAL_MODULE := e2image
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(e2image_src_files)
-LOCAL_C_INCLUDES := $(e2image_c_includes)
-LOCAL_CFLAGS := $(e2image_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(e2image_shared_libraries))
-LOCAL_MODULE := e2image_host
-LOCAL_MODULE_STEM := e2image
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
-
$(Q) $(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(srcdir)/base_device.c \
-DDEBUG -o base_device $(SYSLIBS)
-check:: base_device
+fullcheck check:: base_device
./base_device < $(srcdir)/base_device.tst > base_device.out
cmp $(srcdir)/base_device.tst base_device.out
return retval;
}
+struct file_info {
+ char *path;
+ size_t path_len;
+ size_t path_max_len;
+};
+
+static errcode_t path_append(struct file_info *target, const char *file)
+{
+ if (strlen(file) + target->path_len + 1 > target->path_max_len) {
+ target->path_max_len *= 2;
+ target->path = realloc(target->path, target->path_max_len);
+ if (!target->path)
+ return EXT2_ET_NO_MEMORY;
+ }
+ target->path_len += sprintf(target->path + target->path_len, "/%s",
+ file);
+ return 0;
+}
+
/* Copy files from source_dir to fs */
static errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
const char *source_dir, ext2_ino_t root,
- struct hdlinks_s *hdlinks)
+ struct hdlinks_s *hdlinks,
+ struct file_info *target,
+ struct fs_ops_callbacks *fs_callbacks)
{
const char *name;
DIR *dh;
errcode_t retval = 0;
int read_cnt;
int hdlink;
+ size_t cur_dir_path_len;
if (chdir(source_dir) < 0) {
retval = errno;
save_inode = 1;
}
+ cur_dir_path_len = target->path_len;
+ retval = path_append(target, name);
+ if (retval)
+ return retval;
+
+ if (fs_callbacks && fs_callbacks->create_new_inode) {
+ retval = fs_callbacks->create_new_inode(fs,
+ target->path, name, parent_ino, root,
+ st.st_mode & S_IFMT);
+ if (retval)
+ goto out;
+ }
+
switch(st.st_mode & S_IFMT) {
case S_IFCHR:
case S_IFBLK:
goto out;
}
/* Populate the dir recursively*/
- retval = __populate_fs(fs, ino, name, root, hdlinks);
+ retval = __populate_fs(fs, ino, name, root, hdlinks,
+ target, fs_callbacks);
if (retval)
goto out;
if (chdir("..")) {
goto out;
}
+ if (fs_callbacks && fs_callbacks->end_create_new_inode) {
+ retval = fs_callbacks->end_create_new_inode(fs,
+ target->path, name, parent_ino, root,
+ st.st_mode & S_IFMT);
+ if (retval)
+ goto out;
+ }
+
/* Save the hardlink ino */
if (save_inode) {
/*
hdlinks->hdl[hdlinks->count].dst_ino = ino;
hdlinks->count++;
}
+ target->path_len = cur_dir_path_len;
+ target->path[target->path_len] = 0;
}
out:
return retval;
}
-errcode_t populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
- const char *source_dir, ext2_ino_t root)
+errcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino,
+ const char *source_dir, ext2_ino_t root,
+ struct fs_ops_callbacks *fs_callbacks)
{
+ struct file_info file_info;
struct hdlinks_s hdlinks;
errcode_t retval;
return retval;
}
- retval = __populate_fs(fs, parent_ino, source_dir, root, &hdlinks);
+ file_info.path_len = 0;
+ file_info.path_max_len = 255;
+ file_info.path = calloc(file_info.path_max_len, 1);
+ retval = __populate_fs(fs, parent_ino, source_dir, root, &hdlinks,
+ &file_info, fs_callbacks);
+
+ free(file_info.path);
free(hdlinks.hdl);
return retval;
}
+
+errcode_t populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
+ const char *source_dir, ext2_ino_t root)
+{
+ return populate_fs2(fs, parent_ino, source_dir, root, NULL);
+}
#define HDLINK_CNT (4)
+struct fs_ops_callbacks {
+ errcode_t (* create_new_inode)(ext2_filsys fs, const char *target_path,
+ const char *name, ext2_ino_t parent_ino, ext2_ino_t root,
+ mode_t mode);
+ errcode_t (* end_create_new_inode)(ext2_filsys fs,
+ const char *target_path, const char *name,
+ ext2_ino_t parent_ino, ext2_ino_t root, mode_t mode);
+};
+
/* For populating the filesystem */
extern errcode_t populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
const char *source_dir, ext2_ino_t root);
+extern errcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino,
+ const char *source_dir, ext2_ino_t root,
+ struct fs_ops_callbacks *fs_callbacks);
extern errcode_t do_mknod_internal(ext2_filsys fs, ext2_ino_t cwd,
const char *name, struct stat *st);
extern errcode_t do_symlink_internal(ext2_filsys fs, ext2_ino_t cwd,
const char *src_root_dir; /* Copy files from the specified directory */
static char *undo_file;
+static int android_sparse_file; /* -E android_sparse */
+static char *android_sparse_params;
+
static profile_t profile;
static int sys_page_size = 4096;
int retval;
unsigned int *magic;
- buf = malloc(512*nsect);
+ buf = calloc(512, nsect);
if (!buf) {
printf(_("Out of memory erasing sectors %d-%d\n"),
sect, sect + nsect - 1);
badopt = token;
continue;
}
+ } else if (!strcmp(token, "android_sparse")) {
+ android_sparse_file = 1;
} else {
r_usage++;
badopt = token;
EXT4_FEATURE_INCOMPAT_64BIT|
EXT4_FEATURE_INCOMPAT_INLINE_DATA|
EXT4_FEATURE_INCOMPAT_ENCRYPT |
- EXT4_FEATURE_INCOMPAT_CSUM_SEED,
+ EXT4_FEATURE_INCOMPAT_CSUM_SEED |
+ EXT4_FEATURE_INCOMPAT_LARGEDIR,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
*/
if (!quiet)
flags |= EXT2_FLAG_PRINT_PROGRESS;
- retval = ext2fs_initialize(device_name, flags, &fs_param, io_ptr, &fs);
+ if (android_sparse_file) {
+ android_sparse_params = malloc(PATH_MAX + 32);
+ if (!android_sparse_params) {
+ com_err(program_name, ENOMEM, "%s",
+ _("in malloc for android_sparse_params"));
+ exit(1);
+ }
+ snprintf(android_sparse_params, PATH_MAX + 32, "%s:%u:%u",
+ device_name, fs_param.s_blocks_count,
+ 1024 << fs_param.s_log_block_size);
+ retval = ext2fs_initialize(android_sparse_params, flags,
+ &fs_param, sparse_io_manager, &fs);
+ } else
+ retval = ext2fs_initialize(device_name, flags, &fs_param,
+ io_ptr, &fs);
if (retval) {
com_err(device_name, retval, "%s",
_("while setting up superblock"));
EXT4_FEATURE_INCOMPAT_MMP |
EXT4_FEATURE_INCOMPAT_64BIT |
EXT4_FEATURE_INCOMPAT_ENCRYPT |
- EXT4_FEATURE_INCOMPAT_CSUM_SEED,
+ EXT4_FEATURE_INCOMPAT_CSUM_SEED |
+ EXT4_FEATURE_INCOMPAT_LARGEDIR,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
done; \
done
-check: all
+fullcheck check: all
info dvi ps pdf html tags TAGS ctags CTAGS ID:
"#. %IM <inode> -> i_mtime\n",
"#. %IF <inode> -> i_faddr\n",
"#. %If <inode> -> i_file_acl\n",
- "#. %Id <inode> -> i_dir_acl\n",
+ "#. %Id <inode> -> i_size_high\n",
"#. %Iu <inode> -> i_uid\n",
"#. %Ig <inode> -> i_gid\n",
"#. %It <str> file type\n",
--- /dev/null
+// Copyright 2017 The Android Open Source Project
+
+cc_binary {
+ name: "resize2fs",
+ host_supported: true,
+
+ srcs: [
+ "extent.c",
+ "resize2fs.c",
+ "main.c",
+ "online.c",
+ "sim_progress.c",
+ "resource_track.c",
+ ],
+ cflags: ["-W", "-Wall", "-Wno-macro-redefined"],
+ shared_libs: [
+ "libext2fs",
+ "libext2_com_err",
+ "libext2_e2p",
+ "libext2_uuid",
+ "libext2_blkid",
+ ],
+ system_shared_libs: ["libc"],
+}
+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-
-resize2fs_src_files := \
- extent.c \
- resize2fs.c \
- main.c \
- online.c \
- sim_progress.c \
- resource_track.c
-
-resize2fs_c_includes := external/e2fsprogs/lib
-
-resize2fs_cflags := -O2 -g -W -Wall
-
-resize2fs_shared_libraries := \
- libext2fs \
- libext2_com_err \
- libext2_e2p \
- libext2_uuid \
- libext2_blkid
-
-resize2fs_system_shared_libraries := libc
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(resize2fs_src_files)
-LOCAL_C_INCLUDES := $(resize2fs_c_includes)
-LOCAL_CFLAGS := $(resize2fs_cflags)
-LOCAL_SHARED_LIBRARIES := $(resize2fs_shared_libraries)
-LOCAL_SYSTEM_SHARED_LIBRARIES := $(resize2fs_system_shared_libraries)
-LOCAL_MODULE := resize2fs
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(resize2fs_src_files)
-LOCAL_C_INCLUDES := $(resize2fs_c_includes)
-LOCAL_CFLAGS := $(resize2fs_cflags)
-LOCAL_SHARED_LIBRARIES := $(addsuffix -host, $(resize2fs_shared_libraries))
-LOCAL_MODULE := resize2fs_host
-LOCAL_MODULE_STEM := resize2fs
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_HOST_EXECUTABLE)
test_extent.out: test_extent $(srcdir)/test_extent.in
$(TESTENV) ./test_extent < $(srcdir)/test_extent.in > test_extent.out
-check:: test_extent.out
+fullcheck check:: test_extent.out
$(Q) if cmp -s test_extent.out $(srcdir)/test_extent.in ; then \
echo "Test succeeded." ; \
else \
@ifGNUmake@TESTS=$(wildcard $(srcdir)/[a-z]_*)
@ifNotGNUmake@TESTS != echo $(srcdir)/[a-z]_*
+SKIP_SLOW_TESTS=--skip-slow-tests
+
$(TESTS):: test_one always_run
- @./test_one $@
+ @./test_one $(SKIP_SLOW_TESTS) $@
foo:
echo $(TESTS)
check:: test_pre test_post test_script
+fullcheck::
+ $(MAKE) SKIP_SLOW_TESTS= check
+
check-failed: $(basename $(wildcard *.failed))
@$(srcdir)/test_post
Inode: 12 Type: regular Mode: 0666 Flags: 0x0
Generation: 0 Version: 0x00000000:00000000
User: 0 Group: 0 Project: 0 Size: 40960
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 82
Fragment: Address: 0 Number: 0 Size: 0
Size of extra inode fields: 32
Inode: 13 Type: regular Mode: 0666 Flags: 0x0
Generation: 0 Version: 0x00000000:00000000
User: 0 Group: 0 Project: 0 Size: 10240000
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 20082
Fragment: Address: 0 Number: 0 Size: 0
Size of extra inode fields: 32
Inode: 13 Type: regular Mode: 0644 Flags: 0x10000000
Generation: 3289262644 Version: 0x00000000:00000001
User: 0 Group: 0 Size: 80
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x53cec6b4:c72e3c00 -- Tue Jul 22 20:16:52 2014
Inode: 18 Type: regular Mode: 0644 Flags: 0x10000000
Generation: 3842229473 Version: 0x00000000:00000001
User: 0 Group: 0 Size: 20
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x53cec6b4:cafecc00 -- Tue Jul 22 20:16:52 2014
Inode: 16 Type: directory Mode: 0755 Flags: 0x10000000
Generation: 3842229469 Version: 0x00000000:00000004
User: 0 Group: 0 Size: 132
-File ACL: 7 Directory ACL: 0
+File ACL: 7
Links: 2 Blockcount: 8
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x53cec6e3:27eac000 -- Tue Jul 22 20:17:39 2014
Inode: 20 Type: directory Mode: 0755 Flags: 0x10000000
Generation: 3710818931 Version: 0x00000000:00000001
User: 0 Group: 0 Size: 60
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 2 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x53cec6b4:ca0aa800 -- Tue Jul 22 20:16:52 2014
Inode: 12 Type: symlink Mode: 0777 Flags: 0x10000000
Generation: 3289262643 Version: 0x00000000:00000001
User: 0 Group: 0 Size: 80
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x53cec47f:724db800 -- Tue Jul 22 20:07:27 2014
Inode: 19 Type: symlink Mode: 0777 Flags: 0x0
Generation: 3842229474 Version: 0x00000000:00000001
User: 0 Group: 0 Size: 20
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x53cec44c:a1fcc000 -- Tue Jul 22 20:06:36 2014
Inode: 12 Type: symlink Mode: 0777 Flags: 0x0
Generation: 0 Version: 0x00000000
User: 0 Group: 0 Size: 3
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
Inode: 13 Type: symlink Mode: 0777 Flags: 0x0
Generation: 0 Version: 0x00000000
User: 0 Group: 0 Size: 80
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 2
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
Inode: 14 Type: FIFO Mode: 0000 Flags: 0x0
Generation: 0 Version: 0x00000000
User: 0 Group: 0 Size: 0
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
Inode: 15 Type: block special Mode: 0000 Flags: 0x0
Generation: 0 Version: 0x00000000
User: 0 Group: 0 Size: 0
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
Inode: 16 Type: character special Mode: 0000 Flags: 0x0
Generation: 0 Version: 0x00000000
User: 0 Group: 0 Size: 0
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
Will fix in pass 1B.
Inode 17 logical block 2 (physical block 1184) violates cluster allocation rules.
Will fix in pass 1B.
-Inode 17, i_blocks is 32, should be 64. Fix? yes
-
Inode 18 logical block 3 (physical block 1201) violates cluster allocation rules.
Will fix in pass 1B.
Inode 18, i_blocks is 32, should be 64. Fix? yes
Inode 16, i_blocks is 64, should be 32. Fix? yes
-Inode 17, i_blocks is 64, should be 32. Fix? yes
-
Inode 18, i_blocks is 64, should be 32. Fix? yes
Pass 2: Checking directory structure
Inode: 12 Type: regular Mode: 0644 Flags: 0x80000
Generation: 1117152157 Version: 0x00000001
User: 0 Group: 0 Size: 3072
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 32
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
Inode: 13 Type: regular Mode: 0644 Flags: 0x80000
Generation: 1117152158 Version: 0x00000001
User: 0 Group: 0 Size: 3072
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 32
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
Inode: 14 Type: regular Mode: 0644 Flags: 0x80000
Generation: 1117152159 Version: 0x00000001
User: 0 Group: 0 Size: 3072
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 32
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
Inode: 15 Type: regular Mode: 0644 Flags: 0x80000
Generation: 1117152160 Version: 0x00000001
User: 0 Group: 0 Size: 3072
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
Inode: 16 Type: regular Mode: 0644 Flags: 0x80000
Generation: 1117152161 Version: 0x00000001
User: 0 Group: 0 Size: 6144
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 32
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
Inode: 17 Type: regular Mode: 0644 Flags: 0x80000
Generation: 1117152162 Version: 0x00000001
User: 0 Group: 0 Size: 3072
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 32
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
Inode: 18 Type: regular Mode: 0644 Flags: 0x80000
Generation: 1117152163 Version: 0x00000001
User: 0 Group: 0 Size: 3072
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 32
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
Inode: 12 Type: regular Mode: 0644 Flags: 0x0
Generation: 1573716129 Version: 0x00000000:00000001
User: 0 Group: 0 Size: 524288
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 1030
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x5457f87a:62ae2980 -- Mon Nov 3 21:49:46 2014
Inode: 12 Type: regular Mode: 0644 Flags: 0x0
Generation: 1573716129 Version: 0x00000000:00000001
User: 0 Group: 0 Size: 524288
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 1030
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x5457f87a:62ae2980 -- Mon Nov 3 21:49:46 2014
Inode: 12 Type: regular Mode: 0775 Flags: 0x0
Generation: 2022334337 Version: 0x00000001
User: 1000 Group: 1000 Size: 21080
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 16
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x5924849d -- Tue May 23 18:51:09 2017
Inode: 12 Type: symlink Mode: 0777 Flags: 0x0
Generation: 0 Version: 0x00000000:00000000
User: 0 Group: 0 Project: 0 Size: 31
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
Size of extra inode fields: 32
Inode: 13 Type: symlink Mode: 0777 Flags: 0x10000000
Generation: 0 Version: 0x00000000:00000000
User: 0 Group: 0 Project: 0 Size: 71
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
Size of extra inode fields: 32
Inode: 14 Type: symlink Mode: 0777 Flags: 0x80000
Generation: 0 Version: 0x00000000:00000000
User: 0 Group: 0 Project: 0 Size: 501
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 2
Fragment: Address: 0 Number: 0 Size: 0
Size of extra inode fields: 32
Inode: 15 Type: symlink Mode: 0777 Flags: 0x80000
Generation: 0 Version: 0x00000000:00000000
User: 0 Group: 0 Project: 0 Size: 1024
-File ACL: 0 Directory ACL: 0
+File ACL: 0
Links: 1 Blockcount: 2
Fragment: Address: 0 Number: 0 Size: 0
Size of extra inode fields: 32
--- /dev/null
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 3A: Optimizing directories
+Pass 4: Checking reference counts
+Inode 13 ref count is 1, should be 47245. Fix? yes
+
+Pass 5: Checking group summary information
+
+test.img: ***** FILE SYSTEM WAS MODIFIED *****
+test.img: 13/115368 files (0.0% non-contiguous), 32817/460800 blocks
+Exit status is 1
--- /dev/null
+optimize 3 level htree directories
--- /dev/null
+OUT=$test_name.log
+EXP=$test_dir/expect
+E2FSCK=../e2fsck/e2fsck
+
+NAMELEN=255
+DIRENT_SZ=8
+BLOCKSZ=1024
+DIRENT_PER_LEAF=$((BLOCKSZ / (NAMELEN + DIRENT_SZ)))
+HEADER=32
+INDEX_SZ=8
+INDEX_L1=$(((BLOCKSZ - HEADER) / INDEX_SZ))
+INDEX_L2=$(((BLOCKSZ - DIRENT_SZ) / INDEX_SZ))
+ENTRIES=$((INDEX_L1 * INDEX_L2 * DIRENT_PER_LEAF))
+
+cp /dev/null $OUT
+$MKE2FS -b 1024 -O large_dir,uninit_bg,dir_nlink -F $TMPFILE 460800 \
+ > /dev/null 2>&1
+{
+ echo "feature large_dir"
+ echo "mkdir /foo"
+ echo "cd /foo"
+ touch foofile
+ echo "write foofile foofile"
+ i=0
+ while test $i -lt $ENTRIES ; do
+ if test $(( i % DIRENT_PER_LEAF )) -eq 0 ; then
+ echo "expand ./"
+ fi
+ if test $(( i % 5000 )) -eq 0 -a $i -gt 0 ; then
+ >&2 echo "$test_name: $i processed"
+ fi
+ printf "ln foofile %0255X\n" $i
+ i=$(($i + 1))
+ done
+} | $DEBUGFS -w -f /dev/stdin $TMPFILE > /dev/null 2>&1
+
+$E2FSCK -yfD $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+cmp -s $OUT $EXP
+RC=$?
+if [ $RC -eq 0 ]; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff -u $EXP $OUT > $test_name.failed
+fi
i_faddr for inode 15 (/test/quux) is 23, should be zero.
Clear? yes
-i_dir_acl for inode 15 (/test/quux) is 12, should be zero.
+i_size_high for inode 15 (/test/quux) is 12, should be zero.
Clear? yes
i_file_acl for inode 13 (/test/???) is 12, should be zero.
export USE_VALGRIND="valgrind --sim-hints=lax-ioctls --leak-check=full --show-reachable=yes --log-file=/tmp/valgrind-%p.log"
shift;
;;
+ --skip-slow-tests)
+ SKIP_SLOW_TESTS=yes
+ shift;
+ ;;
esac
case "$1" in
test_description=
fi
+if [ -n "$SKIP_SLOW_TESTS" -a -f $test_dir/is_slow_test ]; then
+ echo "$test_name: $test_description: skipped (slow test)"
+ exit 0
+fi
+
rm -f $test_name.ok $test_name.failed
#echo -e -n "$test_name: $test_description:\r"
-/* work around bug in AndroidConfig.h */
-#ifdef HAVE_MALLOC_H
-#undef HAVE_MALLOC_H
+#ifndef __APPLE__
#define HAVE_MALLOC_H 1
#endif
#define ROOT_SYSCONFDIR "/etc"
+#define ENABLE_LIBSPARSE 1
+
#define DISABLE_BACKTRACE 1
#define HAVE_DIRENT_H 1
#define HAVE_ERRNO_H 1
-#define HAVE_EXT2_IOCTLS 1
-#define HAVE_FALLOCATE 1
#define HAVE_GETOPT_H 1
-#define HAVE_GETPAGESIZE 1
#define HAVE_GETPWUID_R 1
#define HAVE_INTPTR_T 1
#define HAVE_INTTYPES_H 1
-#define HAVE_LINUX_FD_H 1
-#define HAVE_LSEEK64 1
-#define HAVE_LSEEK64_PROTOTYPE 1
#define HAVE_MMAP 1
-#define HAVE_NETINET_IN_H 1
-#define HAVE_NET_IF_H 1
-#define HAVE_POSIX_MEMALIGN 1
-#define HAVE_PREAD 1
-#define HAVE_PREAD64 1
-#define HAVE_PWRITE 1
-#define HAVE_PWRITE64 1
#define HAVE_SETJMP_H 1
+#ifdef __linux__
+#define HAVE_SETMNTENT 1
+#endif
#define HAVE_SNPRINTF 1
#define HAVE_STDLIB_H 1
#define HAVE_STRCASECMP 1
#define HAVE_STRNLEN 1
#define HAVE_STRPTIME 1
#define HAVE_SYSCONF 1
-#define HAVE_SYS_IOCTL_H 1
-#define HAVE_SYS_MMAN_H 1
-#define HAVE_SYS_MOUNT_H 1
-#define HAVE_SYS_PARAM_H 1
-#define HAVE_SYS_PRCTL_H 1
-#define HAVE_SYS_RESOURCE_H 1
-#define HAVE_SYS_SELECT_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_SYS_TIME_H 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_SYS_WAIT_H 1
#define HAVE_TYPE_SSIZE_T 1
#define HAVE_UNISTD_H 1
#define HAVE_UTIME_H 1
+
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TYPES_H 1
+
+#if defined(_WIN32)
+# define HAVE_LINUX_TYPES_H 1
+# define HAVE_WINSOCK_H 1
+#endif
+#if defined(__APPLE__) || defined(__linux__)
+# define HAVE_FCNTL 1
+# define HAVE_FSYNC 1
+# define HAVE_GETPAGESIZE 1
+# define HAVE_NET_IF_H 1
+# define HAVE_NETINET_IN_H 1
+# define HAVE_PREAD 1
+# define HAVE_PWRITE 1
+# define HAVE_POSIX_MEMALIGN 1
+# define HAVE_SYS_IOCTL_H 1
+# define HAVE_SYS_MMAN_H 1
+# define HAVE_SYS_MOUNT_H 1
+# define HAVE_SYS_PARAM_H 1
+# define HAVE_SYS_RESOURCE_H 1
+# define HAVE_SYS_SELECT_H 1
+# define HAVE_SYS_WAIT_H 1
+#endif
+#if defined(__linux__)
+# define HAVE_EXT2_IOCTLS 1
+# define HAVE_FALLOCATE 1
+# define HAVE_LINUX_FD_H 1
+# define HAVE_LINUX_TYPES_H 1
+# define HAVE_LSEEK64 1
+# define HAVE_LSEEK64_PROTOTYPE 1
+# define HAVE_PREAD64 1
+# define HAVE_PWRITE64 1
+# define HAVE_SYS_PRCTL_H 1
+# define HAVE_SYS_SYSMACROS_H 1
+#endif
lib/ext2fs/ext2_types.h lib/config.h lib/blkid/blkid.h \
lib/uuid/uuid.h lib/ext2fs/crc32c_table.h misc/default_profile.c \
lib/ss/std_rqs.c debugfs/debug_cmds.c debugfs/ro_debug_cmds.c \
- debugfs/extent_cmds.c debugfs/e2freefrag.c debugfs/create_inode.c \
+ debugfs/extent_cmds.c debugfs/e2freefrag.c \
debugfs/recovery.c debugfs/revoke.c \
MODULE_LICENSE_GPL README.version"
cp util/android_types.h lib/blkid/blkid_types.h
cp util/android_types.h lib/uuid/uuid_types.h
cp util/android_config.h lib/config.h
-cp misc/e2freefrag.c misc/create_inode.c debugfs/
+cp misc/e2freefrag.c debugfs/
cp e2fsck/recovery.c e2fsck/revoke.c debugfs/
gcc -o gen_crc32ctable lib/ext2fs/gen_crc32ctable.c