output_file.c revision 28fa5bc347390480fe190294c6c385b6a9f0d68b
128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/*
228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Copyright (C) 2010 The Android Open Source Project
328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross *
428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Licensed under the Apache License, Version 2.0 (the "License");
528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * you may not use this file except in compliance with the License.
628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * You may obtain a copy of the License at
728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross *
828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross *      http://www.apache.org/licenses/LICENSE-2.0
928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross *
1028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * Unless required by applicable law or agreed to in writing, software
1128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * distributed under the License is distributed on an "AS IS" BASIS,
1228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * See the License for the specific language governing permissions and
1428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross * limitations under the License.
1528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross */
1628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
1728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define _FILE_OFFSET_BITS 64
1828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define _LARGEFILE64_SOURCE 1
1928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
2028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <fcntl.h>
2128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdbool.h>
2228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <stdlib.h>
2328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <string.h>
2428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/stat.h>
2528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/types.h>
2628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <unistd.h>
2728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <zlib.h>
2828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
2928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "output_file.h"
3028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_format.h"
3128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include "sparse_crc32.h"
3228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
3328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW
3428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#include <sys/mman.h>
3528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define O_BINARY 0
3628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif
3728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
3828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#if defined(__APPLE__) && defined(__MACH__)
3928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define lseek64 lseek
4028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define ftruncate64 ftruncate
4128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define mmap64 mmap
4228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define off64_t off_t
4328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif
4428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
4528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifdef __BIONIC__
4628fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossextern void*  __mmap2(void *, size_t, int, int, int, off_t);
4728fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic inline void *mmap64(void *addr, size_t length, int prot, int flags,
4828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross        int fd, off64_t offset)
4928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
5028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross    return __mmap2(addr, length, prot, flags, fd, offset >> 12);
5128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
5228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif
5328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
5428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_MAJOR_VER 1
5528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_MINOR_VER 0
5628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define SPARSE_HEADER_LEN       (sizeof(sparse_header_t))
5728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#define CHUNK_HEADER_LEN (sizeof(chunk_header_t))
5828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
5928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file_ops {
6028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int (*seek)(struct output_file *, int64_t);
6128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int (*write)(struct output_file *, u8 *, int);
6228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	void (*close)(struct output_file *);
6328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross};
6428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
6528fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file {
6628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int fd;
6728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	gzFile gz_fd;
6828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	bool close_fd;
6928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int sparse;
7028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int64_t cur_out_ptr;
7128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	u32 chunk_cnt;
7228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	u32 crc32;
7328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	struct output_file_ops *ops;
7428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int use_crc;
7528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	unsigned int block_size;
7628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int64_t len;
7728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross};
7828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
7928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic int file_seek(struct output_file *out, int64_t off)
8028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
8128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	off64_t ret;
8228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
8328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	ret = lseek64(out->fd, off, SEEK_SET);
8428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (ret < 0) {
8528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error_errno("lseek64");
8628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
8728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
8828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return 0;
8928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
9028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
9128fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic int file_write(struct output_file *out, u8 *data, int len)
9228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
9328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret;
9428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	ret = write(out->fd, data, len);
9528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (ret < 0) {
9628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error_errno("write");
9728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
9828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	} else if (ret < len) {
9928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("incomplete write");
10028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
10128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
10228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
10328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return 0;
10428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
10528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
10628fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void file_close(struct output_file *out)
10728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
10828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (out->close_fd) {
10928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		close(out->fd);
11028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
11128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
11228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
11328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
11428fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic struct output_file_ops file_ops = {
11528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.seek = file_seek,
11628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.write = file_write,
11728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.close = file_close,
11828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross};
11928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
12028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic int gz_file_seek(struct output_file *out, int64_t off)
12128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
12228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	off64_t ret;
12328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
12428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	ret = gzseek(out->gz_fd, off, SEEK_SET);
12528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (ret < 0) {
12628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error_errno("gzseek");
12728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
12828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
12928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return 0;
13028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
13128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
13228fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic int gz_file_write(struct output_file *out, u8 *data, int len)
13328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
13428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret;
13528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	ret = gzwrite(out->gz_fd, data, len);
13628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (ret < 0) {
13728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error_errno("gzwrite");
13828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
13928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	} else if (ret < len) {
14028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("incomplete gzwrite");
14128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
14228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
14328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
14428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return 0;
14528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
14628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
14728fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic void gz_file_close(struct output_file *out)
14828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
14928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	gzclose(out->gz_fd);
15028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
15128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
15228fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic struct output_file_ops gz_file_ops = {
15328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.seek = gz_file_seek,
15428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.write = gz_file_write,
15528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.close = gz_file_close,
15628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross};
15728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
15828fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic sparse_header_t sparse_header = {
15928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.magic = SPARSE_HEADER_MAGIC,
16028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.major_version = SPARSE_HEADER_MAJOR_VER,
16128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.minor_version = SPARSE_HEADER_MINOR_VER,
16228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.file_hdr_sz = SPARSE_HEADER_LEN,
16328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.chunk_hdr_sz = CHUNK_HEADER_LEN,
16428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.blk_sz = 0,
16528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.total_blks = 0,
16628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.total_chunks = 0,
16728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	.image_checksum = 0
16828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross};
16928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
17028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic u8 *zero_buf;
17128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
17228fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic int emit_skip_chunk(struct output_file *out, u64 skip_len)
17328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
17428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header_t chunk_header;
17528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret, chunk;
17628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
17728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	//DBG printf("skip chunk: 0x%llx bytes\n", skip_len);
17828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
17928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (skip_len % out->block_size) {
18028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("don't care size %llu is not a multiple of the block size %u",
18128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				skip_len, out->block_size);
18228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
18328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
18428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
18528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	/* We are skipping data, so emit a don't care chunk. */
18628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.chunk_type = CHUNK_TYPE_DONT_CARE;
18728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.reserved1 = 0;
18828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.chunk_sz = skip_len / out->block_size;
18928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.total_sz = CHUNK_HEADER_LEN;
19028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	ret = out->ops->write(out, (u8 *)&chunk_header, sizeof(chunk_header));
19128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (ret < 0)
19228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
19328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
19428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->cur_out_ptr += skip_len;
19528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->chunk_cnt++;
19628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
19728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return 0;
19828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
19928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
20028fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic int write_chunk_fill(struct output_file *out, int64_t off, u32 fill_val, int len)
20128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
20228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header_t chunk_header;
20328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int rnd_up_len, zero_len, count;
20428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret;
20528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	unsigned int i;
20628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	u32 fill_buf[4096/sizeof(u32)]; /* Maximum size of a block */
20728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
20828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	/* We can assume that all the chunks to be written are in
20928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 * ascending order, block-size aligned, and non-overlapping.
21028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 * So, if the offset is less than the current output pointer,
21128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 * throw an error, and if there is a gap, emit a "don't care"
21228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 * chunk.  The first write (of the super block) may not be
21328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 * blocksize aligned, so we need to deal with that too.
21428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 */
21528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	//DBG printf("write chunk: offset 0x%llx, length 0x%x bytes\n", off, len);
21628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
21728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off < out->cur_out_ptr) {
21828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("offset %llu is less than the current output offset %llu",
21928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				off, out->cur_out_ptr);
22028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
22128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
22228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
22328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off > out->cur_out_ptr) {
22428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		emit_skip_chunk(out, off - out->cur_out_ptr);
22528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
22628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
22728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off % out->block_size) {
22828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("write chunk offset %llu is not a multiple of the block size %u",
22928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				off, out->block_size);
23028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
23128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
23228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
23328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off != out->cur_out_ptr) {
23428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("internal error, offset accounting screwy in write_chunk_raw()");
23528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
23628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
23728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
23828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	/* Round up the file length to a multiple of the block size */
23928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	rnd_up_len = (len + (out->block_size - 1)) & (~(out->block_size -1));
24028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
24128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	/* Finally we can safely emit a chunk of data */
24228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.chunk_type = CHUNK_TYPE_FILL;
24328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.reserved1 = 0;
24428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.chunk_sz = rnd_up_len / out->block_size;
24528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.total_sz = CHUNK_HEADER_LEN + sizeof(fill_val);
24628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	ret = out->ops->write(out, (u8 *)&chunk_header, sizeof(chunk_header));
24728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
24828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (ret < 0)
24928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
25028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	ret = out->ops->write(out, (u8 *)&fill_val, sizeof(fill_val));
25128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (ret < 0)
25228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
25328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
25428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (out->use_crc) {
25528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross                /* Initialize fill_buf with the fill_val */
25628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		for (i = 0; i < (out->block_size / sizeof(u32)); i++) {
25728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			fill_buf[i] = fill_val;
25828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		}
25928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
26028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		count = chunk_header.chunk_sz;
26128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		while (count) {
26228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			out->crc32 = sparse_crc32(out->crc32, fill_buf, out->block_size);
26328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			count--;
26428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		}
26528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
26628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
26728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->cur_out_ptr += rnd_up_len;
26828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->chunk_cnt++;
26928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
27028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return 0;
27128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
27228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
27328fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstatic int write_chunk_raw(struct output_file *out, int64_t off, u8 *data, int len)
27428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
27528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header_t chunk_header;
27628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int rnd_up_len, zero_len;
27728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret;
27828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
27928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	/* We can assume that all the chunks to be written are in
28028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 * ascending order, block-size aligned, and non-overlapping.
28128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 * So, if the offset is less than the current output pointer,
28228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 * throw an error, and if there is a gap, emit a "don't care"
28328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 * chunk.  The first write (of the super block) may not be
28428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 * blocksize aligned, so we need to deal with that too.
28528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	 */
28628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	//DBG printf("write chunk: offset 0x%llx, length 0x%x bytes\n", off, len);
28728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
28828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off < out->cur_out_ptr) {
28928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("offset %llu is less than the current output offset %llu",
29028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				off, out->cur_out_ptr);
29128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
29228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
29328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
29428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off > out->cur_out_ptr) {
29528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		emit_skip_chunk(out, off - out->cur_out_ptr);
29628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
29728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
29828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off % out->block_size) {
29928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("write chunk offset %llu is not a multiple of the block size %u",
30028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				off, out->block_size);
30128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
30228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
30328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
30428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off != out->cur_out_ptr) {
30528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("internal error, offset accounting screwy in write_chunk_raw()");
30628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
30728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
30828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
30928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	/* Round up the file length to a multiple of the block size */
31028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	rnd_up_len = (len + (out->block_size - 1)) & (~(out->block_size -1));
31128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	zero_len = rnd_up_len - len;
31228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
31328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	/* Finally we can safely emit a chunk of data */
31428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.chunk_type = CHUNK_TYPE_RAW;
31528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.reserved1 = 0;
31628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.chunk_sz = rnd_up_len / out->block_size;
31728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header.total_sz = CHUNK_HEADER_LEN + rnd_up_len;
31828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	ret = out->ops->write(out, (u8 *)&chunk_header, sizeof(chunk_header));
31928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
32028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (ret < 0)
32128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
32228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	ret = out->ops->write(out, data, len);
32328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (ret < 0)
32428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return -1;
32528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (zero_len) {
32628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		ret = out->ops->write(out, zero_buf, zero_len);
32728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (ret < 0)
32828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			return -1;
32928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
33028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
33128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (out->use_crc) {
33228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		out->crc32 = sparse_crc32(out->crc32, data, len);
33328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (zero_len)
33428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			out->crc32 = sparse_crc32(out->crc32, zero_buf, zero_len);
33528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
33628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
33728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->cur_out_ptr += rnd_up_len;
33828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->chunk_cnt++;
33928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
34028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return 0;
34128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
34228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
34328fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossvoid close_output_file(struct output_file *out)
34428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
34528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret;
34628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	chunk_header_t chunk_header;
34728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
34828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (out->sparse) {
34928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (out->use_crc) {
35028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			chunk_header.chunk_type = CHUNK_TYPE_CRC32;
35128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			chunk_header.reserved1 = 0;
35228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			chunk_header.chunk_sz = 0;
35328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			chunk_header.total_sz = CHUNK_HEADER_LEN + 4;
35428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
35528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			out->ops->write(out, (u8 *)&chunk_header, sizeof(chunk_header));
35628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			out->ops->write(out, (u8 *)&out->crc32, 4);
35728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
35828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			out->chunk_cnt++;
35928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		}
36028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
36128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (out->chunk_cnt != sparse_header.total_chunks)
36228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			error("sparse chunk count did not match: %d %d", out->chunk_cnt,
36328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross					sparse_header.total_chunks);
36428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
36528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->ops->close(out);
36628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
36728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
36828fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file *open_output_fd(int fd, unsigned int block_size, int64_t len,
36928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		int gz, int sparse, int chunks, int crc)
37028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
37128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret;
37228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	struct output_file *out = malloc(sizeof(struct output_file));
37328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (!out) {
37428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error_errno("malloc struct out");
37528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return NULL;
37628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
37728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	zero_buf = malloc(out->block_size);
37828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (!zero_buf) {
37928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error_errno("malloc zero_buf");
38028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		free(out);
38128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return NULL;
38228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
38328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	memset(zero_buf, '\0', out->block_size);
38428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
38528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (gz) {
38628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		out->ops = &gz_file_ops;
38728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		out->gz_fd = gzdopen(fd, "wb9");
38828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (!out->gz_fd) {
38928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			error_errno("gzopen");
39028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			free(out);
39128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			return NULL;
39228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		}
39328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	} else {
39428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		out->fd = fd;
39528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		out->ops = &file_ops;
39628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
39728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->close_fd = false;
39828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->sparse = sparse;
39928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->cur_out_ptr = 0ll;
40028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->chunk_cnt = 0;
40128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
40228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	/* Initialize the crc32 value */
40328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->crc32 = 0;
40428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->use_crc = crc;
40528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
40628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->len = len;
40728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	out->block_size = block_size;
40828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
40928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (out->sparse) {
41028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		sparse_header.blk_sz = out->block_size,
41128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		sparse_header.total_blks = out->len / out->block_size,
41228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		sparse_header.total_chunks = chunks;
41328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (out->use_crc)
41428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			sparse_header.total_chunks++;
41528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
41628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		ret = out->ops->write(out, (u8 *)&sparse_header, sizeof(sparse_header));
41728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (ret < 0)
41828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			return NULL;
41928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
42028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
42128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return out;
42228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
42328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
42428fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossstruct output_file *open_output_file(const char *filename,
42528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		unsigned int block_size, int64_t len,
42628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		int gz, int sparse, int chunks, int crc)
42728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
42828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int fd;
42928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	struct output_file *file;
43028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
43128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (strcmp(filename, "-")) {
43228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
43328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (fd < 0) {
43428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			error_errno("open");
43528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			return NULL;
43628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		}
43728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	} else {
43828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		fd = STDOUT_FILENO;
43928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
44028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
44128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	file = open_output_fd(fd, block_size, len, gz, sparse, chunks, crc);
44228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (!file) {
44328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		close(fd);
44428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return NULL;
44528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
44628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
44728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	file->close_fd = true; // we opened descriptor thus we responsible for closing it
44828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
44928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	return file;
45028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
45128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
45228fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossvoid pad_output_file(struct output_file *out, int64_t len)
45328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
45428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret;
45528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
45628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (len > out->len) {
45728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("attempted to pad file %llu bytes past end of filesystem",
45828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				len - out->len);
45928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return;
46028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
46128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (out->sparse) {
46228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		/* We need to emit a DONT_CARE chunk to pad out the file if the
46328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		 * cur_out_ptr is not already at the end of the filesystem.
46428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		 */
46528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (len < out->cur_out_ptr) {
46628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			error("attempted to pad file %llu bytes less than the current output pointer",
46728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross					out->cur_out_ptr - len);
46828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			return;
46928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		}
47028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (len > out->cur_out_ptr) {
47128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			emit_skip_chunk(out, len - out->cur_out_ptr);
47228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		}
47328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	} else {
47428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		//KEN TODO: Fixme.  If the filesystem image needs no padding,
47528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		//          this will overwrite the last byte in the file with 0
47628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		//          The answer is to do accounting like the sparse image
47728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		//          code does and know if there is already data there.
47828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		ret = out->ops->seek(out, len - 1);
47928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (ret < 0)
48028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			return;
48128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
48228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		ret = out->ops->write(out, (u8*)"", 1);
48328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (ret < 0)
48428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			return;
48528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
48628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
48728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
48828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Write a contiguous region of data blocks from a memory buffer */
48928fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossvoid write_data_block(struct output_file *out, int64_t off, void *data, int len)
49028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
49128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret;
49228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
49328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off + len > out->len) {
49428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("attempted to write block %llu past end of filesystem",
49528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				off + len - out->len);
49628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return;
49728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
49828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
49928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (out->sparse) {
50028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		write_chunk_raw(out, off, data, len);
50128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	} else {
50228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		ret = out->ops->seek(out, off);
50328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (ret < 0)
50428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			return;
50528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
50628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		ret = out->ops->write(out, data, len);
50728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (ret < 0)
50828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			return;
50928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
51028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
51128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
51228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Write a contiguous region of data blocks with a fill value */
51328fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossvoid write_fill_block(struct output_file *out, int64_t off, unsigned int fill_val, int len)
51428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
51528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret;
51628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	unsigned int i;
51728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int write_len;
51828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	u32 fill_buf[4096/sizeof(u32)]; /* Maximum size of a block */
51928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
52028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off + len > out->len) {
52128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("attempted to write block %llu past end of filesystem",
52228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				off + len - out->len);
52328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return;
52428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
52528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
52628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (out->sparse) {
52728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		write_chunk_fill(out, off, fill_val, len);
52828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	} else {
52928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		/* Initialize fill_buf with the fill_val */
53028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		for (i = 0; i < sizeof(fill_buf)/sizeof(u32); i++) {
53128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			fill_buf[i] = fill_val;
53228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		}
53328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
53428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		ret = out->ops->seek(out, off);
53528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (ret < 0)
53628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			return;
53728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
53828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		while (len) {
53928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			write_len = (len > (int)sizeof(fill_buf) ? (int)sizeof(fill_buf) : len);
54028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			ret = out->ops->write(out, (u8 *)fill_buf, write_len);
54128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			if (ret < 0) {
54228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				return;
54328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			} else {
54428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				len -= write_len;
54528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			}
54628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		}
54728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
54828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
54928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
55028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross/* Write a contiguous region of data blocks from a file */
55128fa5bc347390480fe190294c6c385b6a9f0d68bColin Crossvoid write_data_file(struct output_file *out, int64_t off, const char *file,
55228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		int64_t offset, int len)
55328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross{
55428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int ret;
55528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int64_t aligned_offset;
55628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int aligned_diff;
55728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int buffer_size;
55828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
55928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (off + len >= out->len) {
56028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error("attempted to write block %llu past end of filesystem",
56128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross				off + len - out->len);
56228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return;
56328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
56428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
56528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	int file_fd = open(file, O_RDONLY | O_BINARY);
56628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (file_fd < 0) {
56728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error_errno("open");
56828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return;
56928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
57028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
57128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	aligned_offset = offset & ~(4096 - 1);
57228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	aligned_diff = offset - aligned_offset;
57328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	buffer_size = len + aligned_diff;
57428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
57528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW
57628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	u8 *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, file_fd,
57728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			aligned_offset);
57828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (data == MAP_FAILED) {
57928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error_errno("mmap64");
58028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		close(file_fd);
58128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return;
58228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
58328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#else
58428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	u8 *data = malloc(buffer_size);
58528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (!data) {
58628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		error_errno("malloc");
58728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		close(file_fd);
58828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		return;
58928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
59028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	memset(data, 0, buffer_size);
59128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif
59228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
59328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	if (out->sparse) {
59428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		write_chunk_raw(out, off, data + aligned_diff, len);
59528fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	} else {
59628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		ret = out->ops->seek(out, off);
59728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (ret < 0)
59828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			goto err;
59928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
60028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		ret = out->ops->write(out, data + aligned_diff, len);
60128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross		if (ret < 0)
60228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross			goto err;
60328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	}
60428fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross
60528fa5bc347390480fe190294c6c385b6a9f0d68bColin Crosserr:
60628fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#ifndef USE_MINGW
60728fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	munmap(data, buffer_size);
60828fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#else
60928fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	write(file_fd, data, buffer_size);
61028fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	free(data);
61128fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross#endif
61228fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross	close(file_fd);
61328fa5bc347390480fe190294c6c385b6a9f0d68bColin Cross}
614