1de807f2ed8af63a75174933c13705a7529a82914Geremy Condra/* 2de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * Copyright (C) 2013 The Android Open Source Project 3de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * 4de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * Licensed under the Apache License, Version 2.0 (the "License"); 5de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * you may not use this file except in compliance with the License. 6de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * You may obtain a copy of the License at 7de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * 8de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * http://www.apache.org/licenses/LICENSE-2.0 9de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * 10de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * Unless required by applicable law or agreed to in writing, software 11de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * distributed under the License is distributed on an "AS IS" BASIS, 12de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * See the License for the specific language governing permissions and 14de807f2ed8af63a75174933c13705a7529a82914Geremy Condra * limitations under the License. 15de807f2ed8af63a75174933c13705a7529a82914Geremy Condra */ 16de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 17de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#define _FILE_OFFSET_BITS 64 18de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#define _LARGEFILE64_SOURCE 1 190e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross#define _GNU_SOURCE 20de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 21de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#include <errno.h> 22de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#include <fcntl.h> 23de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#include <stdio.h> 24de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#include <stdlib.h> 25de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#include <string.h> 26de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#include <unistd.h> 27de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 28de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#include <sparse/sparse.h> 29de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#include "sparse_file.h" 30de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#include "backed_block.h" 31de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 32de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#ifndef O_BINARY 33de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#define O_BINARY 0 34de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#endif 35de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 36de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#if defined(__APPLE__) && defined(__MACH__) 37de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#define lseek64 lseek 38de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#endif 39de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#if defined(__APPLE__) && defined(__MACH__) 40de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#define lseek64 lseek 41de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#define off64_t off_t 42de807f2ed8af63a75174933c13705a7529a82914Geremy Condra#endif 43de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 44de807f2ed8af63a75174933c13705a7529a82914Geremy Condravoid usage() 45de807f2ed8af63a75174933c13705a7529a82914Geremy Condra{ 46de807f2ed8af63a75174933c13705a7529a82914Geremy Condra fprintf(stderr, "Usage: append2simg <output> <input>\n"); 47de807f2ed8af63a75174933c13705a7529a82914Geremy Condra} 48de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 49de807f2ed8af63a75174933c13705a7529a82914Geremy Condraint main(int argc, char *argv[]) 50de807f2ed8af63a75174933c13705a7529a82914Geremy Condra{ 51de807f2ed8af63a75174933c13705a7529a82914Geremy Condra int output; 52de807f2ed8af63a75174933c13705a7529a82914Geremy Condra int output_block; 53de807f2ed8af63a75174933c13705a7529a82914Geremy Condra char *output_path; 54de807f2ed8af63a75174933c13705a7529a82914Geremy Condra struct sparse_file *sparse_output; 55de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 56de807f2ed8af63a75174933c13705a7529a82914Geremy Condra int input; 57de807f2ed8af63a75174933c13705a7529a82914Geremy Condra char *input_path; 58de807f2ed8af63a75174933c13705a7529a82914Geremy Condra off64_t input_len; 59de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 600e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross int tmp_fd; 610e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross char *tmp_path; 620e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross 630e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross int ret; 640e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross 65de807f2ed8af63a75174933c13705a7529a82914Geremy Condra if (argc == 3) { 66de807f2ed8af63a75174933c13705a7529a82914Geremy Condra output_path = argv[1]; 67de807f2ed8af63a75174933c13705a7529a82914Geremy Condra input_path = argv[2]; 68de807f2ed8af63a75174933c13705a7529a82914Geremy Condra } else { 69de807f2ed8af63a75174933c13705a7529a82914Geremy Condra usage(); 70de807f2ed8af63a75174933c13705a7529a82914Geremy Condra exit(-1); 71de807f2ed8af63a75174933c13705a7529a82914Geremy Condra } 72de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 730e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross ret = asprintf(&tmp_path, "%s.append2simg", output_path); 740e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross if (ret < 0) { 750e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross fprintf(stderr, "Couldn't allocate filename\n"); 760e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross exit(-1); 770e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross } 780e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross 79de807f2ed8af63a75174933c13705a7529a82914Geremy Condra output = open(output_path, O_RDWR | O_BINARY); 80de807f2ed8af63a75174933c13705a7529a82914Geremy Condra if (output < 0) { 81de807f2ed8af63a75174933c13705a7529a82914Geremy Condra fprintf(stderr, "Couldn't open output file (%s)\n", strerror(errno)); 82de807f2ed8af63a75174933c13705a7529a82914Geremy Condra exit(-1); 83de807f2ed8af63a75174933c13705a7529a82914Geremy Condra } 84de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 85de807f2ed8af63a75174933c13705a7529a82914Geremy Condra sparse_output = sparse_file_import_auto(output, true); 86de807f2ed8af63a75174933c13705a7529a82914Geremy Condra if (!sparse_output) { 87de807f2ed8af63a75174933c13705a7529a82914Geremy Condra fprintf(stderr, "Couldn't import output file\n"); 88de807f2ed8af63a75174933c13705a7529a82914Geremy Condra exit(-1); 89de807f2ed8af63a75174933c13705a7529a82914Geremy Condra } 90de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 91de807f2ed8af63a75174933c13705a7529a82914Geremy Condra input = open(input_path, O_RDONLY | O_BINARY); 92de807f2ed8af63a75174933c13705a7529a82914Geremy Condra if (input < 0) { 93de807f2ed8af63a75174933c13705a7529a82914Geremy Condra fprintf(stderr, "Couldn't open input file (%s)\n", strerror(errno)); 94de807f2ed8af63a75174933c13705a7529a82914Geremy Condra exit(-1); 95de807f2ed8af63a75174933c13705a7529a82914Geremy Condra } 96de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 97de807f2ed8af63a75174933c13705a7529a82914Geremy Condra input_len = lseek64(input, 0, SEEK_END); 98de807f2ed8af63a75174933c13705a7529a82914Geremy Condra if (input_len < 0) { 99de807f2ed8af63a75174933c13705a7529a82914Geremy Condra fprintf(stderr, "Couldn't get input file length (%s)\n", strerror(errno)); 100de807f2ed8af63a75174933c13705a7529a82914Geremy Condra exit(-1); 101de807f2ed8af63a75174933c13705a7529a82914Geremy Condra } else if (input_len % sparse_output->block_size) { 102de807f2ed8af63a75174933c13705a7529a82914Geremy Condra fprintf(stderr, "Input file is not a multiple of the output file's block size"); 103de807f2ed8af63a75174933c13705a7529a82914Geremy Condra exit(-1); 104de807f2ed8af63a75174933c13705a7529a82914Geremy Condra } 105de807f2ed8af63a75174933c13705a7529a82914Geremy Condra lseek64(input, 0, SEEK_SET); 106de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 107de807f2ed8af63a75174933c13705a7529a82914Geremy Condra output_block = sparse_output->len / sparse_output->block_size; 108de807f2ed8af63a75174933c13705a7529a82914Geremy Condra if (sparse_file_add_fd(sparse_output, input, 0, input_len, output_block) < 0) { 109de807f2ed8af63a75174933c13705a7529a82914Geremy Condra fprintf(stderr, "Couldn't add input file\n"); 110de807f2ed8af63a75174933c13705a7529a82914Geremy Condra exit(-1); 111de807f2ed8af63a75174933c13705a7529a82914Geremy Condra } 112de807f2ed8af63a75174933c13705a7529a82914Geremy Condra sparse_output->len += input_len; 113de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 1140e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross tmp_fd = open(tmp_path, O_WRONLY | O_CREAT | O_BINARY, 0664); 1150e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross if (tmp_fd < 0) { 1160e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross fprintf(stderr, "Couldn't open temporary file (%s)\n", strerror(errno)); 1170e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross exit(-1); 1180e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross } 1190e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross 120de807f2ed8af63a75174933c13705a7529a82914Geremy Condra lseek64(output, 0, SEEK_SET); 1210e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross if (sparse_file_write(sparse_output, tmp_fd, false, true, false) < 0) { 122de807f2ed8af63a75174933c13705a7529a82914Geremy Condra fprintf(stderr, "Failed to write sparse file\n"); 123de807f2ed8af63a75174933c13705a7529a82914Geremy Condra exit(-1); 124de807f2ed8af63a75174933c13705a7529a82914Geremy Condra } 125de807f2ed8af63a75174933c13705a7529a82914Geremy Condra 126de807f2ed8af63a75174933c13705a7529a82914Geremy Condra sparse_file_destroy(sparse_output); 1270e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross close(tmp_fd); 128de807f2ed8af63a75174933c13705a7529a82914Geremy Condra close(output); 129de807f2ed8af63a75174933c13705a7529a82914Geremy Condra close(input); 1300e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross 1310e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross ret = rename(tmp_path, output_path); 1320e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross if (ret < 0) { 1330e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross fprintf(stderr, "Failed to rename temporary file (%s)\n", strerror(errno)); 1340e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross exit(-1); 1350e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross } 1360e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross 1370e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross free(tmp_path); 1380e3f47e4827a067b9b9795a3ae7297b51c9f0776Colin Cross 139de807f2ed8af63a75174933c13705a7529a82914Geremy Condra exit(0); 140de807f2ed8af63a75174933c13705a7529a82914Geremy Condra} 141