image.c revision 265725
1265574Smarcel/*- 2265574Smarcel * Copyright (c) 2014 Juniper Networks, Inc. 3265574Smarcel * All rights reserved. 4265574Smarcel * 5265574Smarcel * Redistribution and use in source and binary forms, with or without 6265574Smarcel * modification, are permitted provided that the following conditions 7265574Smarcel * are met: 8265574Smarcel * 1. Redistributions of source code must retain the above copyright 9265574Smarcel * notice, this list of conditions and the following disclaimer. 10265574Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11265574Smarcel * notice, this list of conditions and the following disclaimer in the 12265574Smarcel * documentation and/or other materials provided with the distribution. 13265574Smarcel * 14265574Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15265574Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16265574Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17265574Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18265574Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19265574Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20265574Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21265574Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22265574Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23265574Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24265574Smarcel * SUCH DAMAGE. 25265574Smarcel */ 26265574Smarcel 27265574Smarcel#include <sys/cdefs.h> 28265574Smarcel__FBSDID("$FreeBSD: user/marcel/mkimg/image.c 265725 2014-05-09 01:13:14Z marcel $"); 29265574Smarcel 30265574Smarcel#include <sys/types.h> 31265574Smarcel#include <assert.h> 32265574Smarcel#include <errno.h> 33265574Smarcel#include <stdlib.h> 34265574Smarcel#include <unistd.h> 35265574Smarcel 36265579Smarcel#include "image.h" 37265574Smarcel#include "mkimg.h" 38265574Smarcel 39265574Smarcel#define BUFFER_SIZE (1024*1024) 40265574Smarcel 41265618Smarcelstatic char image_tmpfile[] = "/tmp/mkimg-XXXXXX"; 42265618Smarcelstatic int image_fd = -1; 43265725Smarcelstatic lba_t image_size; 44265618Smarcel 45265618Smarcelstatic void 46265618Smarcelcleanup(void) 47265618Smarcel{ 48265618Smarcel 49265618Smarcel if (image_fd != -1) 50265618Smarcel close(image_fd); 51265618Smarcel unlink(image_tmpfile); 52265618Smarcel} 53265618Smarcel 54265574Smarcelint 55265574Smarcelimage_copyin(lba_t blk, int fd, uint64_t *sizep) 56265574Smarcel{ 57265574Smarcel char *buffer; 58265574Smarcel uint64_t bytesize; 59265574Smarcel ssize_t bcnt, rdsz; 60265574Smarcel int error, partial; 61265574Smarcel 62265574Smarcel assert(BUFFER_SIZE % secsz == 0); 63265574Smarcel 64265574Smarcel buffer = malloc(BUFFER_SIZE); 65265574Smarcel if (buffer == NULL) 66265574Smarcel return (ENOMEM); 67265574Smarcel bytesize = 0; 68265574Smarcel partial = 0; 69265574Smarcel while (1) { 70265574Smarcel rdsz = read(fd, buffer, BUFFER_SIZE); 71265574Smarcel if (rdsz <= 0) { 72265574Smarcel error = (rdsz < 0) ? errno : 0; 73265574Smarcel break; 74265574Smarcel } 75265574Smarcel if (partial) 76265574Smarcel abort(); 77265574Smarcel bytesize += rdsz; 78265574Smarcel bcnt = (rdsz + secsz - 1) / secsz; 79265574Smarcel error = image_write(blk, buffer, bcnt); 80265574Smarcel if (error) 81265574Smarcel break; 82265574Smarcel blk += bcnt; 83265574Smarcel partial = (bcnt * secsz != rdsz) ? 1 : 0; 84265574Smarcel } 85265574Smarcel free(buffer); 86265574Smarcel if (sizep != NULL) 87265574Smarcel *sizep = bytesize; 88265574Smarcel return (error); 89265574Smarcel} 90265574Smarcel 91265574Smarcelint 92265618Smarcelimage_copyout(int fd) 93265574Smarcel{ 94265618Smarcel char *buffer; 95265618Smarcel off_t ofs; 96265618Smarcel ssize_t rdsz, wrsz; 97265618Smarcel int error; 98265574Smarcel 99265618Smarcel ofs = lseek(fd, 0L, SEEK_CUR); 100265618Smarcel 101265618Smarcel buffer = malloc(BUFFER_SIZE); 102265618Smarcel if (buffer == NULL) 103265618Smarcel return (errno); 104265618Smarcel if (lseek(image_fd, 0, SEEK_SET) != 0) 105265618Smarcel return (errno); 106265618Smarcel error = 0; 107265618Smarcel while (1) { 108265618Smarcel rdsz = read(image_fd, buffer, BUFFER_SIZE); 109265618Smarcel if (rdsz <= 0) { 110265618Smarcel error = (rdsz < 0) ? errno : 0; 111265618Smarcel break; 112265618Smarcel } 113265618Smarcel wrsz = (ofs == -1) ? 114265618Smarcel write(fd, buffer, rdsz) : 115265618Smarcel sparse_write(fd, buffer, rdsz); 116265618Smarcel if (wrsz < 0) { 117265618Smarcel error = errno; 118265618Smarcel break; 119265618Smarcel } 120265618Smarcel } 121265618Smarcel free(buffer); 122265623Smarcel ofs = lseek(fd, 0L, SEEK_CUR); 123265623Smarcel ftruncate(fd, ofs); 124265618Smarcel return (error); 125265618Smarcel} 126265618Smarcel 127265725Smarcellba_t 128265725Smarcelimage_get_size(void) 129265725Smarcel{ 130265725Smarcel 131265725Smarcel return (image_size); 132265725Smarcel} 133265725Smarcel 134265618Smarcelint 135265618Smarcelimage_set_size(lba_t blk) 136265618Smarcel{ 137265618Smarcel 138265725Smarcel image_size = blk; 139265618Smarcel if (ftruncate(image_fd, blk * secsz) == -1) 140265618Smarcel return (errno); 141265574Smarcel return (0); 142265574Smarcel} 143265574Smarcel 144265574Smarcelint 145265618Smarcelimage_write(lba_t blk, void *buf, ssize_t len) 146265574Smarcel{ 147265574Smarcel 148265618Smarcel blk *= secsz; 149265618Smarcel if (lseek(image_fd, blk, SEEK_SET) != blk) 150265618Smarcel return (errno); 151265618Smarcel len *= secsz; 152265685Smarcel if (sparse_write(image_fd, buf, len) != len) 153265618Smarcel return (errno); 154265574Smarcel return (0); 155265574Smarcel} 156265618Smarcel 157265618Smarcelint 158265618Smarcelimage_init(void) 159265618Smarcel{ 160265618Smarcel 161265618Smarcel if (atexit(cleanup) == -1) 162265618Smarcel return (errno); 163265618Smarcel image_fd = mkstemp(image_tmpfile); 164265618Smarcel if (image_fd == -1) 165265618Smarcel return (errno); 166265618Smarcel return (0); 167265618Smarcel} 168