From 8e16ce11e9da448f72495feeccb599245f9dcfae Mon Sep 17 00:00:00 2001 From: marcel Date: Wed, 7 May 2014 22:06:54 +0000 Subject: [PATCH] Provide a file-based implementation for the image API. This almost copies the logic verbatim from mkimg.c to image.c. The difference is that in image.c the temporary file is always created, whereas before we only created a temporary file when writing to stdout. Cleanup mkimg.c now that the song and dance of using a temporary file is gone. --- image.c | 72 ++++++++++++++++++++++++++++++++++-- image.h | 2 + mkimg.c | 111 ++++++++++--------------------------------------------- mkimg.h | 6 +++ scheme.c | 2 - 5 files changed, 96 insertions(+), 97 deletions(-) diff --git a/image.c b/image.c index 1fb502d7fc6f..988eb2108c67 100644 --- a/image.c +++ b/image.c @@ -38,6 +38,18 @@ __FBSDID("$FreeBSD$"); #define BUFFER_SIZE (1024*1024) +static char image_tmpfile[] = "/tmp/mkimg-XXXXXX"; +static int image_fd = -1; + +static void +cleanup(void) +{ + + if (image_fd != -1) + close(image_fd); + unlink(image_tmpfile); +} + int image_copyin(lba_t blk, int fd, uint64_t *sizep) { @@ -76,17 +88,69 @@ image_copyin(lba_t blk, int fd, uint64_t *sizep) } int -image_set_size(lba_t blk __unused) +image_copyout(int fd) +{ + char *buffer; + off_t ofs; + ssize_t rdsz, wrsz; + int error; + + ofs = lseek(fd, 0L, SEEK_CUR); + + buffer = malloc(BUFFER_SIZE); + if (buffer == NULL) + return (errno); + if (lseek(image_fd, 0, SEEK_SET) != 0) + return (errno); + error = 0; + while (1) { + rdsz = read(image_fd, buffer, BUFFER_SIZE); + if (rdsz <= 0) { + error = (rdsz < 0) ? errno : 0; + break; + } + wrsz = (ofs == -1) ? + write(fd, buffer, rdsz) : + sparse_write(fd, buffer, rdsz); + if (wrsz < 0) { + error = errno; + break; + } + } + free(buffer); + return (error); +} + +int +image_set_size(lba_t blk) { - /* TODO */ + if (ftruncate(image_fd, blk * secsz) == -1) + return (errno); return (0); } int -image_write(lba_t blk __unused, void *buf __unused, ssize_t len __unused) +image_write(lba_t blk, void *buf, ssize_t len) { - /* TODO */ + blk *= secsz; + if (lseek(image_fd, blk, SEEK_SET) != blk) + return (errno); + len *= secsz; + if (write(image_fd, buf, len) != len) + return (errno); + return (0); +} + +int +image_init(void) +{ + + if (atexit(cleanup) == -1) + return (errno); + image_fd = mkstemp(image_tmpfile); + if (image_fd == -1) + return (errno); return (0); } diff --git a/image.h b/image.h index d1ff07296500..53b11d3b8db3 100644 --- a/image.h +++ b/image.h @@ -32,6 +32,8 @@ typedef int64_t lba_t; int image_copyin(lba_t blk, int fd, uint64_t *sizep); +int image_copyout(int fd); +int image_init(void); int image_set_size(lba_t blk); int image_write(lba_t blk, void *buf, ssize_t len); diff --git a/mkimg.c b/mkimg.c index 5580e8a04465..9d365f905734 100644 --- a/mkimg.c +++ b/mkimg.c @@ -46,12 +46,6 @@ __FBSDID("$FreeBSD$"); #include "mkimg.h" #include "scheme.h" -#if !defined(SPARSE_WRITE) -#define sparse_write write -#endif - -#define BUFFER_SIZE (1024*1024) - struct partlisthead partlist = STAILQ_HEAD_INITIALIZER(partlist); u_int nparts = 0; @@ -63,21 +57,6 @@ u_int nsecs = 1; u_int secsz = 512; u_int blksz = 0; -static int bcfd = -1; -static int outfd = 0; -static int tmpfd = -1; - -static char tmpfname[] = "/tmp/mkimg-XXXXXX"; - -static void -cleanup(void) -{ - - if (tmpfd != -1) - close(tmpfd); - unlink(tmpfname); -} - static void usage(const char *why) { @@ -229,7 +208,7 @@ parse_part(const char *spec) } #if defined(SPARSE_WRITE) -static ssize_t +ssize_t sparse_write(int fd, const char *buf, size_t sz) { const char *p; @@ -269,56 +248,8 @@ sparse_write(int fd, const char *buf, size_t sz) } #endif /* SPARSE_WRITE */ -static int -fdcopy(int src, lba_t sblk, int dst, lba_t dblk, uint64_t *count) -{ - char *buffer; - off_t ofs; - ssize_t rdsz, wrsz; - - if (sblk != -1) { - ofs = sblk * secsz; - if (lseek(src, ofs, SEEK_SET) != ofs) - return (errno); - } - - if (dblk != -1) { - ofs = dblk * secsz; - if (lseek(dst, ofs, SEEK_SET) != ofs) - return (errno); - } else - ofs = lseek(dst, 0L, SEEK_CUR); - - /* - * We can't write a sparse file when ofs holds -1 at this point. - */ - - if (count != NULL) - *count = 0; - - buffer = malloc(BUFFER_SIZE); - if (buffer == NULL) - return (errno); - while (1) { - rdsz = read(src, buffer, BUFFER_SIZE); - if (rdsz <= 0) { - free(buffer); - return ((rdsz < 0) ? errno : 0); - } - if (count != NULL) - *count += rdsz; - wrsz = (ofs == -1) ? - write(dst, buffer, rdsz) : - sparse_write(dst, buffer, rdsz); - if (wrsz < 0) - break; - } - free(buffer); - return (errno); -} - static void -mkimg(int bfd) +mkimg(void) { FILE *fp; struct part *part; @@ -326,10 +257,6 @@ mkimg(int bfd) off_t bytesize; int error, fd; - error = scheme_bootcode(bfd); - if (error) - errc(EX_DATAERR, error, "boot code"); - /* First check partition information */ STAILQ_FOREACH(part, &partlist, link) { error = scheme_check_part(part); @@ -386,8 +313,11 @@ mkimg(int bfd) int main(int argc, char *argv[]) { + int bcfd, outfd; int c, error; + bcfd = -1; + outfd = 1; /* Write to stdout by default */ while ((c = getopt(argc, argv, "b:o:p:s:vH:P:S:T:")) != -1) { switch (c) { case 'b': /* BOOT CODE */ @@ -398,7 +328,7 @@ main(int argc, char *argv[]) err(EX_UNAVAILABLE, "%s", optarg); break; case 'o': /* OUTPUT FILE */ - if (outfd != 0) + if (outfd != 1) usage("multiple output files given"); outfd = open(optarg, O_WRONLY | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); @@ -471,15 +401,12 @@ main(int argc, char *argv[]) errx(EX_DATAERR, "%d partitions supported; %d given", scheme_max_parts(), nparts); - if (outfd == 0) { - if (atexit(cleanup) == -1) - err(EX_OSERR, "cannot register cleanup function"); - outfd = 1; - tmpfd = mkstemp(tmpfname); - if (tmpfd == -1) - err(EX_OSERR, "cannot create temporary file"); - } else - tmpfd = outfd; + if (bcfd != -1) { + error = scheme_bootcode(bcfd); + close(bcfd); + if (error) + errc(EX_DATAERR, error, "boot code"); + } if (verbose) { fprintf(stderr, "Logical sector size: %u\n", secsz); @@ -488,16 +415,18 @@ main(int argc, char *argv[]) fprintf(stderr, "Number of heads: %u\n", nheads); } - mkimg(bcfd); + error = image_init(); + if (error) + errc(EX_OSERR, error, "cannot initialize"); + + mkimg(); if (verbose) fprintf(stderr, "Number of cylinders: %u\n", ncyls); - if (tmpfd != outfd) { - error = fdcopy(tmpfd, 0, outfd, -1, NULL); - if (error) - errc(EX_IOERR, error, "writing to stdout"); - } + error = image_copyout(outfd); + if (error) + errc(EX_IOERR, error, "writing image"); return (0); } diff --git a/mkimg.h b/mkimg.h index 825e5cae2529..9595e6844b34 100644 --- a/mkimg.h +++ b/mkimg.h @@ -65,4 +65,10 @@ round_block(lba_t n) return ((n + b - 1) & ~(b - 1)); } +#if !defined(SPARSE_WRITE) +#define sparse_write write +#else +ssize_t sparse_write(int, const char *, size_t); +#endif + #endif /* _MKIMG_MKIMG_H_ */ diff --git a/scheme.c b/scheme.c index 424a99faf966..fa1bc7f9ea5e 100644 --- a/scheme.c +++ b/scheme.c @@ -105,8 +105,6 @@ scheme_bootcode(int fd) struct stat sb; int error; - if (fd == -1) - return (0); if (scheme->bootcode == 0) return (ENXIO);