/*
 * 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.
 */

#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCE 1

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <libgen.h>
#include <unistd.h>

#include <sparse/sparse.h>

#include "ext4_utils.h"
#include "make_ext4fs.h"
#include "allocate.h"

#if defined(__APPLE__) && defined(__MACH__)
#define off64_t off_t
#endif

#ifndef USE_MINGW /* O_BINARY is windows-specific flag */
#define O_BINARY 0
#endif

extern struct fs_info info;

static int verbose = 0;

static void usage(char *path)
{
	fprintf(stderr, "%s [ options ] <image or block device> <output image>\n", path);
	fprintf(stderr, "\n");
	fprintf(stderr, "  -c include CRC block\n");
	fprintf(stderr, "  -v verbose output\n");
	fprintf(stderr, "  -z gzip output\n");
	fprintf(stderr, "  -S don't use sparse output format\n");
}

static int build_sparse_ext(int fd, const char *filename)
{
	unsigned int i;
	unsigned int block;
	int start_contiguous_block;
	u8 *block_bitmap;
	off64_t ret;

	block_bitmap = malloc(info.block_size);
	if (!block_bitmap)
		critical_error("failed to allocate block bitmap");

	if (aux_info.first_data_block > 0)
		sparse_file_add_file(ext4_sparse_file, filename, 0,
				info.block_size * aux_info.first_data_block, 0);

	for (i = 0; i < aux_info.groups; i++) {
		u32 first_block = aux_info.first_data_block + i * info.blocks_per_group;
		u32 last_block = min(info.blocks_per_group, aux_info.len_blocks - first_block);

		ret = lseek64(fd, (u64)info.block_size * aux_info.bg_desc[i].bg_block_bitmap,
				SEEK_SET);
		if (ret < 0)
			critical_error_errno("failed to seek to block group bitmap %d", i);

		ret = read(fd, block_bitmap, info.block_size);
		if (ret < 0)
			critical_error_errno("failed to read block group bitmap %d", i);
		if (ret != (int)info.block_size)
			critical_error("failed to read all of block group bitmap %d", i);

		start_contiguous_block = -1;
		for (block = 0; block < last_block; block++) {
			if (start_contiguous_block >= 0) {
				if (!bitmap_get_bit(block_bitmap, block)) {
					u32 start_block = first_block + start_contiguous_block;
					u32 len_blocks = block - start_contiguous_block;

					sparse_file_add_file(ext4_sparse_file, filename,
							(u64)info.block_size * start_block,
							info.block_size * len_blocks, start_block);
					start_contiguous_block = -1;
				}
			} else {
				if (bitmap_get_bit(block_bitmap, block))
					start_contiguous_block = block;
			}
		}

		if (start_contiguous_block >= 0) {
			u32 start_block = first_block + start_contiguous_block;
			u32 len_blocks = last_block - start_contiguous_block;
			sparse_file_add_file(ext4_sparse_file, filename,
					(u64)info.block_size * start_block,
					info.block_size * len_blocks, start_block);
		}
	}

	return 0;
}

int main(int argc, char **argv)
{
	int opt;
	const char *in = NULL;
	const char *out = NULL;
	int gzip = 0;
	int sparse = 1;
	int infd, outfd;
	int crc = 0;

	while ((opt = getopt(argc, argv, "cvzS")) != -1) {
		switch (opt) {
		case 'c':
			crc = 1;
			break;
		case 'v':
			verbose = 1;
			break;
		case 'z':
			gzip = 1;
			break;
		case 'S':
			sparse = 0;
			break;
		}
	}

	if (optind >= argc) {
		fprintf(stderr, "Expected image or block device after options\n");
		usage(argv[0]);
		exit(EXIT_FAILURE);
	}

	in = argv[optind++];

	if (optind >= argc) {
		fprintf(stderr, "Expected output image after input image\n");
		usage(argv[0]);
		exit(EXIT_FAILURE);
	}

	out = argv[optind++];

	if (optind < argc) {
		fprintf(stderr, "Unexpected argument: %s\n", argv[optind]);
		usage(argv[0]);
		exit(EXIT_FAILURE);
	}

	infd = open(in, O_RDONLY);

	if (infd < 0)
		critical_error_errno("failed to open input image");

	read_ext(infd, verbose);

	ext4_sparse_file = sparse_file_new(info.block_size, info.len);

	build_sparse_ext(infd, in);

	close(infd);

	if (strcmp(out, "-")) {
		outfd = open(out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
		if (outfd < 0) {
			error_errno("open");
			return EXIT_FAILURE;
		}
	} else {
		outfd = STDOUT_FILENO;
	}

	write_ext4_image(outfd, gzip, sparse, crc);
	close(outfd);

	sparse_file_destroy(ext4_sparse_file);

	return 0;
}
