1a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner/*
2a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner * Copyright (C) 2012 The Android Open Source Project
3a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner *
4a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner * Licensed under the Apache License, Version 2.0 (the "License");
5a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner * you may not use this file except in compliance with the License.
6a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner * You may obtain a copy of the License at
7a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner *
8a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner *      http://www.apache.org/licenses/LICENSE-2.0
9a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner *
10a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner * Unless required by applicable law or agreed to in writing, software
11a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner * distributed under the License is distributed on an "AS IS" BASIS,
12a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner * See the License for the specific language governing permissions and
14a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner * limitations under the License.
15a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner */
16a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
17a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#define _FILE_OFFSET_BITS 64
18a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#define _LARGEFILE64_SOURCE 1
19a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
20a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#include <fcntl.h>
21a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#include <stdbool.h>
22a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#include <stdio.h>
23a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#include <stdlib.h>
24a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#include <string.h>
25a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#include <sys/types.h>
26a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#include <sys/stat.h>
27a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#include <sys/types.h>
28a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#include <unistd.h>
29a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
30a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#include <sparse/sparse.h>
31a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
32a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#ifndef O_BINARY
33a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#define O_BINARY 0
34a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#endif
35a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
36a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#if defined(__APPLE__) && defined(__MACH__)
37a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#define lseek64 lseek
38a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#define off64_t off_t
39a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner#endif
40a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
41a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turnervoid usage()
42a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner{
43a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner    fprintf(stderr, "Usage: img2simg <raw_image_file> <sparse_image_file> [<block_size>]\n");
44a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner}
45a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
46a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turnerint main(int argc, char *argv[])
47a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner{
48a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	int in;
49a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	int out;
50a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	int ret;
51a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	struct sparse_file *s;
52a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	unsigned int block_size = 4096;
53a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	off64_t len;
54a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
55a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	if (argc < 3 || argc > 4) {
56a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		usage();
57a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		exit(-1);
58a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	}
59a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
60a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	if (argc == 4) {
61a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		block_size = atoi(argv[3]);
62a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	}
63a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
64a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	if (block_size < 1024 || block_size % 4 != 0) {
65a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		usage();
66a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		exit(-1);
67a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	}
68a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
69a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	if (strcmp(argv[1], "-") == 0) {
70a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		in = STDIN_FILENO;
71a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	} else {
72a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		in = open(argv[1], O_RDONLY | O_BINARY);
73a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		if (in < 0) {
74a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner			fprintf(stderr, "Cannot open input file %s\n", argv[1]);
75a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner			exit(-1);
76a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		}
77a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	}
78a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
79a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	if (strcmp(argv[2], "-") == 0) {
80a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		out = STDOUT_FILENO;
81a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	} else {
82a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
83a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		if (out < 0) {
84a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner			fprintf(stderr, "Cannot open output file %s\n", argv[2]);
85a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner			exit(-1);
86a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		}
87a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	}
88a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
89a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	len = lseek64(in, 0, SEEK_END);
90a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	lseek64(in, 0, SEEK_SET);
91a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
92a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	s = sparse_file_new(block_size, len);
93a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	if (!s) {
94a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		fprintf(stderr, "Failed to create sparse file\n");
95a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		exit(-1);
96a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	}
97a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
98a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	sparse_file_verbose(s);
99a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	ret = sparse_file_read(s, in, false, false);
100a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	if (ret) {
101a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		fprintf(stderr, "Failed to read file\n");
102a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		exit(-1);
103a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	}
104a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
105a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	ret = sparse_file_write(s, out, false, true, false);
106a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	if (ret) {
107a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		fprintf(stderr, "Failed to write sparse file\n");
108a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner		exit(-1);
109a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	}
110a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
111a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	close(in);
112a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	close(out);
113a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner
114a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner	exit(0);
115a2394cf2fab37ca4ec91e57db74f06f15a3656beDavid 'Digit' Turner}
116