Add support for writing a gzip compressed image
Change-Id: Ica2ff90060f6a4ced2c671084205b58eede66cdf
diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c
index c96048b..5b0a3af 100644
--- a/ext4_utils/make_ext4fs.c
+++ b/ext4_utils/make_ext4fs.c
@@ -19,11 +19,10 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
-#include <sys/mman.h>
+#include <sys/ioctl.h>
#include <limits.h>
#include <arpa/inet.h>
#include <fcntl.h>
-#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
@@ -38,6 +37,7 @@
#endif
#include "make_ext4fs.h"
+#include "output_file.h"
#include "ext4_utils.h"
#include "allocate.h"
#include "ext_utils.h"
@@ -57,8 +57,7 @@
/* TODO: Not implemented:
Allocating blocks in the same block group as the file inode
Hash or binary tree directories
- Non-extent inodes
- Special files: symbolic links, sockets, devices, fifos
+ Special files: sockets, devices, fifos
*/
int force = 0;
@@ -66,132 +65,27 @@
struct fs_info info;
struct fs_aux_info aux_info;
-/* Write a contiguous region of data blocks from a memory buffer */
-static void write_data_block(void *priv, u32 block, u8 *data, int len)
-{
- int fd = *(int*)priv;
- off_t off;
- int ret;
-
- if (block * info.block_size + len >= info.len) {
- error("attempted to write block %llu past end of filesystem",
- block * info.block_size + len - info.len);
- return;
- }
-
- off = (off_t)block * info.block_size;
- off = lseek(fd, off, SEEK_SET);
- if (off < 0) {
- error_errno("lseek");
- return;
- }
-
- ret = write(fd, data, len);
- if (ret < 0)
- error_errno("write");
- else if (ret < len)
- error("incomplete write");
-}
-
-/* Write a contiguous region of data blocks from a file */
-static void write_data_file(void *priv, u32 block, const char *file,
- off_t offset, int len)
-{
- int fd = *(int*)priv;
- off_t off;
- int ret;
-
- if (block * info.block_size + len >= info.len) {
- error("attempted to write block %llu past end of filesystem",
- block * info.block_size + len - info.len);
- return;
- }
-
- int file_fd = open(file, O_RDONLY);
- if (file_fd < 0) {
- error_errno("open");
- return;
- }
-
- u8 *data = mmap(NULL, len, PROT_READ, MAP_SHARED, file_fd, offset);
- if (data == MAP_FAILED) {
- error_errno("mmap");
- close(fd);
- return;
- }
-
- off = (off_t)block * info.block_size;
- off = lseek(fd, off, SEEK_SET);
- if (off < 0) {
- error_errno("lseek");
- return;
- }
-
- ret = write(fd, data, len);
- if (ret < 0)
- error_errno("write");
- else if (ret < len)
- error("incomplete write");
-
- munmap(data, len);
-
- close(file_fd);
-}
-
/* Write the filesystem image to a file */
-static void write_ext4_image(const char *filename)
+static void write_ext4_image(const char *filename, int gz)
{
int ret = 0;
- int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ struct output_file *out = open_output_file(filename, gz);
off_t off;
- if (fd < 0) {
- error_errno("open");
+ if (!out)
return;
- }
- off = lseek(fd, 1024, SEEK_SET);
- if (off < 0) {
- error_errno("lseek");
- return;
- }
+ write_data_block(out, 1024, (u8*)aux_info.sb, 1024);
- ret = write(fd, aux_info.sb, 1024);
- if (ret < 0)
- error_errno("write");
- else if (ret < 1024)
- error("incomplete write");
+ write_data_block(out, (aux_info.first_data_block + 1) * info.block_size,
+ (u8*)aux_info.bg_desc,
+ aux_info.bg_desc_blocks * info.block_size);
- off = (aux_info.first_data_block + 1) * info.block_size;
- off = lseek(fd, off, SEEK_SET);
- if (off < 0) {
- error_errno("lseek");
- return;
- }
+ for_each_data_block(write_data_block, write_data_file, out);
- ret = write(fd, aux_info.bg_desc,
- aux_info.bg_desc_blocks * info.block_size);
- if (ret < 0)
- error_errno("write");
- else if (ret < (int)(aux_info.bg_desc_blocks * info.block_size))
- error("incomplete write");
+ write_data_block(out, info.len - 1, (u8*)"", 1);
- for_each_data_block(write_data_block, write_data_file, &fd);
-
- off = info.len - 1;
- off = lseek(fd, off, SEEK_SET);
- if (off < 0) {
- error_errno("lseek");
- return;
- }
-
- ret = write(fd, "\0", 1);
- if (ret < 0)
- error_errno("write");
- else if (ret < 1)
- error("incomplete write");
-
- close(fd);
+ close_output_file(out);
}
/* Compute the rest of the parameters of the filesystem from the basic info */
@@ -664,10 +558,11 @@
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:f")) != -1) {
+ while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fz")) != -1) {
switch (opt) {
case 'l':
info.len = parse_num(optarg);
@@ -697,6 +592,9 @@
android = 1;
mountpoint = optarg;
break;
+ case 'z':
+ gzip = 1;
+ break;
default: /* '?' */
usage(argv[0]);
exit(EXIT_FAILURE);
@@ -804,7 +702,7 @@
aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo,
aux_info.sb->s_blocks_count_lo);
- write_ext4_image(filename);
+ write_ext4_image(filename, gzip);
return 0;
}