[PATCH] erofs-utils: support dumping raw tar streams together
Gao Xiang
hsiangkao at linux.alibaba.com
Thu Feb 22 20:01:45 AEDT 2024
Since commit e3dfe4b8db26 ("erofs-utils: mkfs: support tgz streams for
tarerofs"), tgz streams can be converted to EROFS directly.
However, many use cases also require raw tar streams. Let's add
support for dumping raw streams with `--ungzip=FILE` option.
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
include/erofs/tar.h | 4 ++--
lib/tar.c | 7 ++++++-
man/mkfs.erofs.1 | 5 +++--
mkfs/main.c | 20 ++++++++++++++++++--
4 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/include/erofs/tar.h b/include/erofs/tar.h
index a76f740..be03d1b 100644
--- a/include/erofs/tar.h
+++ b/include/erofs/tar.h
@@ -35,14 +35,14 @@ struct erofs_iostream {
u64 sz;
char *buffer;
unsigned int head, tail, bufsize;
- int decoder;
+ int decoder, dumpfd;
bool feof;
};
struct erofs_tarfile {
struct erofs_pax_header global;
struct erofs_iostream ios;
- char *mapfile;
+ char *mapfile, *dumpfile;
int fd;
u64 offset;
diff --git a/lib/tar.c b/lib/tar.c
index ead74ba..1d764b2 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -82,6 +82,7 @@ int erofs_iostream_open(struct erofs_iostream *ios, int fd, int decoder)
ios->tail = ios->head = 0;
ios->decoder = decoder;
+ ios->dumpfd = -1;
if (decoder == EROFS_IOS_DECODER_GZIP) {
#if defined(HAVE_ZLIB)
ios->handler = gzdopen(fd, "r");
@@ -170,6 +171,10 @@ int erofs_iostream_read(struct erofs_iostream *ios, void **buf, u64 bytes)
if (ret < ios->bufsize - rabytes)
ios->feof = true;
}
+ if (unlikely(ios->dumpfd >= 0))
+ if (write(ios->dumpfd, ios->buffer + rabytes, ret) < ret)
+ erofs_err("failed to dump %d bytes of the raw stream: %s",
+ ret, erofs_strerror(-errno));
}
*buf = ios->buffer;
ret = min_t(int, ios->tail, bytes);
@@ -210,7 +215,7 @@ int erofs_iostream_lskip(struct erofs_iostream *ios, u64 sz)
if (ios->feof)
return sz;
- if (ios->sz) {
+ if (ios->sz && likely(ios->dumpfd < 0)) {
s64 cur = lseek(ios->fd, sz, SEEK_CUR);
if (cur > ios->sz)
diff --git a/man/mkfs.erofs.1 b/man/mkfs.erofs.1
index 45be11a..f32dc26 100644
--- a/man/mkfs.erofs.1
+++ b/man/mkfs.erofs.1
@@ -162,8 +162,9 @@ When this option is used together with
the final file gids are
set to \fIGID\fR + \fIGID-OFFSET\fR.
.TP
-.B \-\-gzip
-Filter tarball streams through gzip.
+.BI \-\-ungzip\fR[\fP= file \fR]\fP
+Filter tarball streams through gzip. Optionally, raw streams can be dumped
+together.
.TP
\fB\-V\fR, \fB\-\-version\fR
Print the version number and exit.
diff --git a/mkfs/main.c b/mkfs/main.c
index 7aea64a..75b80ab 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -71,6 +71,7 @@ static struct option long_options[] = {
{"ovlfs-strip", optional_argument, NULL, 516},
#ifdef HAVE_ZLIB
{"gzip", no_argument, NULL, 517},
+ {"ungzip", optional_argument, NULL, 517},
#endif
{"offset", required_argument, NULL, 518},
{0, 0, 0, 0},
@@ -153,7 +154,8 @@ static void usage(int argc, char **argv)
" --uid-offset=# add offset # to all file uids (# = id offset)\n"
" --gid-offset=# add offset # to all file gids (# = id offset)\n"
#ifdef HAVE_ZLIB
- " --gzip try to filter the tarball stream through gzip\n"
+ " --ungzip[=X] try to filter the tarball stream through gzip\n"
+ " (and optionally dump the raw stream to X together)\n"
#endif
" --ignore-mtime use build time instead of strict per-file modification time\n"
" --max-extent-bytes=# set maximum decompressed extent size # in bytes\n"
@@ -633,6 +635,8 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
cfg.c_ovlfs_strip = false;
break;
case 517:
+ if (optarg)
+ erofstar.dumpfile = strdup(optarg);
gzip_supported = true;
break;
case 518:
@@ -712,6 +716,15 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
err = erofs_iostream_open(&erofstar.ios, fd, gzip_supported);
if (err)
return err;
+
+ fd = open(erofstar.dumpfile,
+ O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd < 0) {
+ erofs_err("failed to open dumpfile: %s",
+ erofstar.dumpfile);
+ return -errno;
+ }
+ erofstar.ios.dumpfd = fd;
} else {
err = lstat(cfg.c_src_path, &st);
if (err)
@@ -1315,8 +1328,11 @@ exit:
erofs_rebuild_cleanup();
erofs_diskbuf_exit();
erofs_exit_configure();
- if (tar_mode)
+ if (tar_mode) {
erofs_iostream_close(&erofstar.ios);
+ if (erofstar.ios.dumpfd >= 0)
+ close(erofstar.ios.dumpfd);
+ }
if (err) {
erofs_err("\tCould not format the device : %s\n",
--
2.39.3
More information about the Linux-erofs
mailing list