diff options
author | Michael Olbrich <m.olbrich@pengutronix.de> | 2018-12-17 13:45:31 +0100 |
---|---|---|
committer | Michael Olbrich <m.olbrich@pengutronix.de> | 2019-03-01 16:38:16 +0100 |
commit | 8687e9c639621e1de65297cb7d56335b2add7701 (patch) | |
tree | e5b2f0bf8e9a711c0c6203d1a0a2e8e1073850fb | |
parent | 1033272349805b0afdff39ec7339f583ef30daac (diff) | |
download | genimage-8687e9c639621e1de65297cb7d56335b2add7701.tar.gz genimage-8687e9c639621e1de65297cb7d56335b2add7701.tar.xz |
pad_file/insert_data: support writing to block devices
Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
-rw-r--r-- | genimage.h | 2 | ||||
-rw-r--r-- | util.c | 89 |
2 files changed, 74 insertions, 17 deletions
@@ -65,6 +65,7 @@ struct image { struct mountpoint *mp; char *outfile; int seen; + off_t last_offset; }; struct image_handler { @@ -135,6 +136,7 @@ enum pad_mode { MODE_OVERWRITE, }; +int is_block_device(const char *filename); int pad_file(struct image *image, const char *infile, size_t size, unsigned char fillpattern, enum pad_mode mode); int insert_data(struct image *image, const char *data, const char *outfile, @@ -285,13 +285,39 @@ static size_t min(size_t a, size_t b) return a < b ? a : b; } +int is_block_device(const char *filename) { + struct stat s; + return stat(filename, &s) == 0 && ((s.st_mode & S_IFMT) == S_IFBLK); +} + +static int open_file(struct image *image, const char *filename, int extra_flags) +{ + int flags = O_WRONLY | extra_flags; + int ret, fd; + + /* make sure block devices are unused before writing */ + if (is_block_device(filename)) + flags |= O_EXCL; + else + flags |= O_CREAT; + + fd = open(filename, flags, 0666); + if (fd < 0) { + ret = -errno; + image_error(image, "open %s: %s\n", filename, strerror(errno)); + return ret; + } + return fd; +} + int pad_file(struct image *image, const char *infile, size_t size, unsigned char fillpattern, enum pad_mode mode) { const char *outfile = imageoutfile(image); - int f = -1, outf = -1; + int f = -1, outf = -1, flags = 0; void *buf = NULL; int now, r, w; + struct stat s; int ret = 0; if (infile) { @@ -302,22 +328,53 @@ int pad_file(struct image *image, const char *infile, goto err_out; } } - - outf = open(outfile, mode == MODE_OVERWRITE ? - O_WRONLY|O_CREAT|O_TRUNC : O_WRONLY|O_APPEND, 0666); + if (mode == MODE_OVERWRITE) { + image->last_offset = 0; + flags = O_TRUNC; + } + outf = open_file(image, outfile, flags); if (outf < 0) { + ret = outf; + goto err_out; + } + + ret = fstat(outf, &s); + if (ret) { ret = -errno; - image_error(image, "open %s: %s\n", outfile, strerror(errno)); + image_error(image, "stat %s: %s\n", outfile, strerror(errno)); + goto err_out; + } + if (((s.st_mode & S_IFMT) == S_IFREG) && (mode == MODE_APPEND)) { + off_t offset = lseek(outf, 0, SEEK_END); + if (offset < 0) { + ret = -errno; + image_error(image, "seek: %s\n", strerror(errno)); + goto err_out; + } + if (offset != image->last_offset) { + ret = -EINVAL; + image_error(image, "pad_file: unexpected offset: %lld != %lld\n", + (long long)offset, (long long)image->last_offset); + goto err_out; + } + } + if (((s.st_mode & S_IFMT) == S_IFBLK) && (mode == MODE_APPEND)) { + if (lseek(outf, image->last_offset, SEEK_SET) < 0) { + ret = -errno; + image_error(image, "seek: %s\n", strerror(errno)); + goto err_out; + } + } + if (((s.st_mode & S_IFMT) != S_IFREG) && + ((s.st_mode & S_IFMT) != S_IFBLK)) { + ret = -EINVAL; + image_error(image, "pad_file: not a regular file or block device\n"); goto err_out; } buf = xzalloc(4096); if (!infile) { - struct stat s; - ret = stat(outfile, &s); - if (ret) - goto err_out; if ((unsigned long long)s.st_size > size) { image_error(image, "input file '%s' too large\n", outfile); ret = -EINVAL; @@ -364,6 +421,7 @@ fill: } size -= now; } + image->last_offset = lseek(outf, 0, SEEK_CUR); err_out: free(buf); if (f >= 0) @@ -381,12 +439,10 @@ int insert_data(struct image *image, const char *data, const char *outfile, int now, r; int ret = 0; - outf = open(outfile, O_WRONLY|O_CREAT, 0666); - if (outf < 0) { - ret = -errno; - image_error(image, "open %s: %s\n", outfile, strerror(errno)); - goto err_out; - } + outf = open_file(image, outfile, 0); + if (outf < 0) + return outf; + if (lseek(outf, offset, SEEK_SET) < 0) { ret = -errno; image_error(image, "seek %s: %s\n", outfile, strerror(errno)); @@ -405,8 +461,7 @@ int insert_data(struct image *image, const char *data, const char *outfile, data += now; } err_out: - if (outf >= 0) - close(outf); + close(outf); return ret; } |