f2fs_utils: provide sparse io and dynamic load.
This uses
external/f2fs-tools LGPL v2.1
It provides low-level IO functions that f2fs-tools/mkfs expects
for writing to the media. In this case we use the sparse lib.
Change-Id: I8d141a0d4d14df9fe84d3b131484e9696fcd8870
Signed-off-by: JP Abgrall <jpa@google.com>
diff --git a/f2fs_utils/f2fs_ioutils.c b/f2fs_utils/f2fs_ioutils.c
new file mode 100644
index 0000000..a211b05
--- /dev/null
+++ b/f2fs_utils/f2fs_ioutils.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define _LARGEFILE64_SOURCE
+
+#include <asm/types.h>
+#include <errno.h>
+#include <linux/fs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* memset() */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+
+#include <assert.h>
+
+#include <f2fs_fs.h>
+#include <f2fs_format_utils.h>
+
+#include <sparse/sparse.h>
+
+struct selabel_handle;
+
+#include "make_f2fs.h"
+
+#ifdef USE_MINGW
+
+#include <winsock2.h>
+
+/* These match the Linux definitions of these flags.
+ L_xx is defined to avoid conflicting with the win32 versions.
+*/
+#define L_S_IRUSR 00400
+#define L_S_IWUSR 00200
+#define L_S_IXUSR 00100
+#define S_IRWXU (L_S_IRUSR | L_S_IWUSR | L_S_IXUSR)
+#define S_IRGRP 00040
+#define S_IWGRP 00020
+#define S_IXGRP 00010
+#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+#define S_IROTH 00004
+#define S_IWOTH 00002
+#define S_IXOTH 00001
+#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+#define S_ISUID 0004000
+#define S_ISGID 0002000
+#define S_ISVTX 0001000
+
+#else
+
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#include <selinux/android.h>
+
+#define O_BINARY 0
+
+#endif
+
+struct f2fs_configuration config;
+struct sparse_file *f2fs_sparse_file;
+
+struct buf_item {
+ void *buf;
+ size_t len;
+ struct buf_item *next;
+};
+
+struct buf_item *buf_list;
+
+static int dev_write_fd(void *buf, __u64 offset, size_t len)
+{
+ if (lseek64(config.fd, (off64_t)offset, SEEK_SET) < 0)
+ return -1;
+ if (write(config.fd, buf, len) != len)
+ return -1;
+ return 0;
+}
+
+void flush_sparse_buffs()
+{
+ while (buf_list) {
+ struct buf_item *bi = buf_list;
+ buf_list = buf_list->next;
+ free(bi->buf);
+ free(bi);
+ }
+}
+
+static int dev_write_sparse(void *buf, __u64 byte_offset, size_t byte_len)
+{
+ struct buf_item *bi = calloc(1, sizeof(struct buf_item));
+
+ if (bi == NULL) {
+ return -ENOMEM;
+ }
+ bi->buf = malloc(byte_len);
+ if (bi->buf == NULL) {
+ free(bi);
+ return -ENOMEM;
+ }
+
+ bi->len = byte_len;
+ memcpy(bi->buf, buf, byte_len);
+ bi->next = buf_list;
+ buf_list = bi;
+
+ sparse_file_add_data(f2fs_sparse_file, bi->buf, byte_len, byte_offset/F2FS_BLKSIZE);
+ return 0;
+}
+
+void f2fs_finalize_device()
+{
+}
+
+int f2fs_trim_device()
+{
+ return 0;
+}
+
+/*
+ * IO interfaces
+ */
+int dev_read(void *buf, __u64 offset, size_t len)
+{
+ return 0;
+}
+
+int dev_write(void *buf, __u64 offset, size_t len)
+{
+ if (config.fd >= 0) {
+ return dev_write_fd(buf, offset, len);
+ } else {
+ return dev_write_sparse(buf, offset, len);
+ }
+}
+
+
+int dev_fill(void *buf, __u64 offset, size_t len)
+{
+ int ret;
+ if (config.fd >= 0) {
+ return dev_write_fd(buf, offset, len);
+ }
+ // sparse file fills with zero by default.
+ // return sparse_file_add_fill(f2fs_sparse_file, ((__u8*)(bi->buf))[0], byte_len, byte_offset/F2FS_BLKSIZE);
+ return 0;
+}
+
+int dev_read_block(void *buf, __u64 blk_addr)
+{
+ assert(false); // Must not be invoked.
+ return 0;
+}
+
+int dev_read_blocks(void *buf, __u64 addr, __u32 nr_blks)
+{
+ assert(false); // Must not be invoked.
+ return 0;
+}
+