add make_ext4fs to the libext4_utils
Move the bulk of make_ext4fs into libext4_utils, leaving a main() that
does only option parsing. Add reset functionality so that
make_ext4fs() can be called multiple times within a process.
Change-Id: Ia09a2385eab32bf3ca9eb9257c4f9df2c85e55be
diff --git a/ext4_utils/Android.mk b/ext4_utils/Android.mk
index 5e0a73f..d8a20f9 100644
--- a/ext4_utils/Android.mk
+++ b/ext4_utils/Android.mk
@@ -4,6 +4,7 @@
include $(CLEAR_VARS)
libext4_utils_src_files := \
+ make_ext4fs.c \
ext4_utils.c \
allocate.c \
backed_block.c \
@@ -45,7 +46,7 @@
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := make_ext4fs.c
+LOCAL_SRC_FILES := make_ext4fs_main.c
LOCAL_MODULE := make_ext4fs
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES += libext4_utils libz
@@ -54,7 +55,7 @@
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := make_ext4fs.c
+LOCAL_SRC_FILES := make_ext4fs_main.c
LOCAL_MODULE := make_ext4fs
LOCAL_STATIC_LIBRARIES += libext4_utils libz
diff --git a/ext4_utils/backed_block.c b/ext4_utils/backed_block.c
index 6fb4870..5fa6943 100644
--- a/ext4_utils/backed_block.c
+++ b/ext4_utils/backed_block.c
@@ -122,12 +122,23 @@
/* Frees the memory used by the linked list of data blocks */
void free_data_blocks()
{
+ if (!data_blocks) return;
struct data_block *db = data_blocks;
while (db) {
struct data_block *next = db->next;
free((void*)db->filename);
- free((void*)db->data);
+
+ // There used to be a free() of db->data here, but it
+ // made the function crash since queue_data_block() is
+ // sometimes passed pointers it can't take ownership of
+ // (like a pointer into the middle of an allocated
+ // block). It's not clear what the queue_data_block
+ // contract is supposed to be, but we'd rather leak
+ // memory than crash.
+
free(db);
db = next;
}
+ data_blocks = NULL;
+ last_used = NULL;
}
diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c
index 347943b..4840917 100644
--- a/ext4_utils/make_ext4fs.c
+++ b/ext4_utils/make_ext4fs.c
@@ -203,88 +203,26 @@
return DIV_ROUND_UP(info.inodes, block_groups);
}
-static void usage(char *path)
-{
- fprintf(stderr, "%s [ -l <len> ] [ -j <journal size> ] [ -b <block_size> ]\n", basename(path));
- fprintf(stderr, " [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n");
- fprintf(stderr, " [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n");
- fprintf(stderr, " <filename> [<directory>]\n");
+void reset_ext4fs_info() {
+ // Reset all the global data structures used by make_ext4fs so it
+ // can be called again.
+ memset(&info, 0, sizeof(info));
+ memset(&aux_info, 0, sizeof(aux_info));
+ free_data_blocks();
}
-int main(int argc, char **argv)
+int make_ext4fs(const char *filename, const char *directory,
+ char *mountpoint, int android, int gzip)
{
- int opt;
- const char *filename = NULL;
- const char *directory = NULL;
- char *mountpoint = "";
- int android = 0;
- int gzip = 0;
- u32 root_inode_num;
- u16 root_mode;
-
- while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fz")) != -1) {
- switch (opt) {
- case 'l':
- info.len = parse_num(optarg);
- break;
- case 'j':
- info.journal_blocks = parse_num(optarg);
- break;
- case 'b':
- info.block_size = parse_num(optarg);
- break;
- case 'g':
- info.blocks_per_group = parse_num(optarg);
- break;
- case 'i':
- info.inodes = parse_num(optarg);
- break;
- case 'I':
- info.inode_size = parse_num(optarg);
- break;
- case 'L':
- info.label = optarg;
- break;
- case 'f':
- force = 1;
- break;
- case 'a':
- android = 1;
- mountpoint = optarg;
- break;
- case 'z':
- gzip = 1;
- break;
- default: /* '?' */
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- }
-
- if (optind >= argc) {
- fprintf(stderr, "Expected filename after options\n");
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
-
- filename = argv[optind++];
-
- if (optind < argc)
- directory = argv[optind++];
-
- if (optind < argc) {
- fprintf(stderr, "Unexpected argument: %s\n", argv[optind]);
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
+ u32 root_inode_num;
+ u16 root_mode;
if (info.len == 0)
info.len = get_file_size(filename);
if (info.len <= 0) {
fprintf(stderr, "Need size of filesystem\n");
- usage(argv[0]);
- exit(EXIT_FAILURE);
+ return EXIT_FAILURE;
}
if (info.journal_blocks > 0)
@@ -350,7 +288,7 @@
root_inode_num = build_directory_structure(directory, mountpoint, 0, android);
else
root_inode_num = build_default_directory_structure();
-
+
root_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
inode_set_permissions(root_inode_num, root_mode, 0, 0);
diff --git a/ext4_utils/make_ext4fs.h b/ext4_utils/make_ext4fs.h
index 11fdf77..4045e6a 100644
--- a/ext4_utils/make_ext4fs.h
+++ b/ext4_utils/make_ext4fs.h
@@ -20,4 +20,8 @@
#include "ext4_utils.h"
#include "ext4.h"
+void reset_ext4fs_info();
+int make_ext4fs(const char *filename, const char *directory,
+ char *mountpoint, int android, int gzip);
+
#endif
diff --git a/ext4_utils/make_ext4fs_main.c b/ext4_utils/make_ext4fs_main.c
new file mode 100644
index 0000000..b11d9fe
--- /dev/null
+++ b/ext4_utils/make_ext4fs_main.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 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 <unistd.h>
+#include <libgen.h>
+
+#if defined(__linux__)
+#include <linux/fs.h>
+#elif defined(__APPLE__) && defined(__MACH__)
+#include <sys/disk.h>
+#endif
+
+#include "make_ext4fs.h"
+
+extern struct fs_info info;
+
+
+static void usage(char *path)
+{
+ fprintf(stderr, "%s [ -l <len> ] [ -j <journal size> ] [ -b <block_size> ]\n", basename(path));
+ fprintf(stderr, " [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n");
+ fprintf(stderr, " [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n");
+ fprintf(stderr, " <filename> [<directory>]\n");
+}
+
+int main(int argc, char **argv)
+{
+ int opt;
+ const char *filename = NULL;
+ const char *directory = NULL;
+ char *mountpoint = "";
+ int android = 0;
+ int gzip = 0;
+
+ while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fz")) != -1) {
+ switch (opt) {
+ case 'l':
+ info.len = parse_num(optarg);
+ break;
+ case 'j':
+ info.journal_blocks = parse_num(optarg);
+ break;
+ case 'b':
+ info.block_size = parse_num(optarg);
+ break;
+ case 'g':
+ info.blocks_per_group = parse_num(optarg);
+ break;
+ case 'i':
+ info.inodes = parse_num(optarg);
+ break;
+ case 'I':
+ info.inode_size = parse_num(optarg);
+ break;
+ case 'L':
+ info.label = optarg;
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'a':
+ android = 1;
+ mountpoint = optarg;
+ break;
+ case 'z':
+ gzip = 1;
+ break;
+ default: /* '?' */
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "Expected filename after options\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ filename = argv[optind++];
+
+ if (optind < argc)
+ directory = argv[optind++];
+
+ if (optind < argc) {
+ fprintf(stderr, "Unexpected argument: %s\n", argv[optind]);
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ return make_ext4fs(filename, directory, mountpoint, android, gzip);
+}