if (ios->decoder == EROFS_IOS_DECODER_GZIP) {
#if defined(HAVE_ZLIB)
gzclose(ios->handler);
+#endif
+ return;
+ } else if (ios->decoder == EROFS_IOS_DECODER_LIBLZMA) {
+#if defined(HAVE_LIBLZMA)
+ lzma_end(&ios->lzma->strm);
+ close(ios->lzma->fd);
+ free(ios->lzma);
#endif
return;
}
{
s64 fsz;
+ ios->feof = false;
ios->tail = ios->head = 0;
ios->decoder = decoder;
ios->dumpfd = -1;
ios->bufsize = 32768;
#else
return -EOPNOTSUPP;
+#endif
+ } else if (decoder == EROFS_IOS_DECODER_LIBLZMA) {
+#ifdef HAVE_LIBLZMA
+ lzma_ret ret;
+
+ ios->lzma = malloc(sizeof(*ios->lzma));
+ if (!ios->lzma)
+ return -ENOMEM;
+ ios->lzma->fd = fd;
+ ios->lzma->strm = (lzma_stream)LZMA_STREAM_INIT;
+ ret = lzma_auto_decoder(&ios->lzma->strm,
+ UINT64_MAX, LZMA_CONCATENATED);
+ if (ret != LZMA_OK)
+ return -EFAULT;
+ ios->sz = fsz = 0;
+ ios->bufsize = 32768;
+#else
+ return -EOPNOTSUPP;
#endif
} else {
ios->fd = fd;
ios->feof = !fsz;
ios->sz = 0;
} else {
- ios->feof = false;
ios->sz = fsz;
if (lseek(fd, 0, SEEK_SET))
return -EIO;
ios->tail += ret;
#else
return -EOPNOTSUPP;
+#endif
+ } else if (ios->decoder == EROFS_IOS_DECODER_LIBLZMA) {
+#ifdef HAVE_LIBLZMA
+ struct erofs_iostream_liblzma *lzma = ios->lzma;
+ lzma_action action = LZMA_RUN;
+ lzma_ret ret2;
+
+ if (!lzma->strm.avail_in) {
+ lzma->strm.next_in = lzma->inbuf;
+ ret = read(lzma->fd, lzma->inbuf,
+ sizeof(lzma->inbuf));
+ if (ret < 0)
+ return -errno;
+ lzma->strm.avail_in = ret;
+ if (ret < sizeof(lzma->inbuf))
+ action = LZMA_FINISH;
+ }
+ lzma->strm.next_out = (u8 *)ios->buffer + rabytes;
+ lzma->strm.avail_out = ios->bufsize - rabytes;
+
+ ret2 = lzma_code(&lzma->strm, action);
+ if (ret2 != LZMA_OK) {
+ if (ret2 == LZMA_STREAM_END)
+ ios->feof = true;
+ else
+ return -EIO;
+ }
+ ret = ios->bufsize - rabytes - lzma->strm.avail_out;
+ ios->tail += ret;
+#else
+ return -EOPNOTSUPP;
#endif
} else {
ret = erofs_read_from_fd(ios->fd, ios->buffer + rabytes,
the final file gids are
set to \fIGID\fR + \fIGID-OFFSET\fR.
.TP
-.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.
.TP
the final file uids are
set to \fIUID\fR + \fIUIDOFFSET\fR.
.TP
+.BI \-\-ungzip\fR[\fP= file \fR]\fP
+Filter tarball streams through gzip. Optionally, raw streams can be dumped
+together.
+.TP
+.BI \-\-unxz\fR[\fP= file \fR]\fP
+Filter tarball streams through xz, lzma, or lzip. Optionally, raw streams can
+be dumped together.
+.TP
.BI "\-\-xattr-prefix=" PREFIX
Specify a customized extended attribute namespace prefix for space saving,
e.g. "trusted.overlay.". You may give multiple
{"block-list-file", required_argument, NULL, 515},
#endif
{"ovlfs-strip", optional_argument, NULL, 516},
+ {"offset", required_argument, NULL, 517},
#ifdef HAVE_ZLIB
- {"gzip", no_argument, NULL, 517},
- {"ungzip", optional_argument, NULL, 517},
+ {"gzip", no_argument, NULL, 518},
+ {"ungzip", optional_argument, NULL, 518},
+#endif
+#ifdef HAVE_LIBLZMA
+ {"unlzma", optional_argument, NULL, 519},
+ {"unxz", optional_argument, NULL, 519},
#endif
- {"offset", required_argument, NULL, 518},
{0, 0, 0, 0},
};
" --force-gid=# set all file gids to # (# = GID)\n"
" --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
- " --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"
" --preserve-mtime keep per-file modification time strictly\n"
#ifndef NDEBUG
" --random-pclusterblks randomize pclusterblks for big pcluster (debugging only)\n"
" --random-algorithms randomize per-file algorithms (debugging only)\n"
+#endif
+#ifdef HAVE_ZLIB
+ " --ungzip[=X] try to filter the tarball stream through gzip\n"
+ " (and optionally dump the raw stream to X together)\n"
+#endif
+#ifdef HAVE_LIBLZMA
+ " --unxz[=X] try to filter the tarball stream through xz/lzma/lzip\n"
+ " (and optionally dump the raw stream to X together)\n"
#endif
" --xattr-prefix=X X=extra xattr name prefix\n"
" --mount-point=X X=prefix of target fs path (default: /)\n"
static struct erofs_tarfile erofstar = {
.global.xattrs = LIST_HEAD_INIT(erofstar.global.xattrs)
};
-static bool tar_mode, rebuild_mode, gzip_supported;
+static bool tar_mode, rebuild_mode;
static unsigned int rebuild_src_count;
static LIST_HEAD(rebuild_src_list);
char *endptr;
int opt, i, err;
bool quiet = false;
+ int tarerofs_decoder = 0;
while ((opt = getopt_long(argc, argv, "C:E:L:T:U:b:d:x:z:Vh",
long_options, NULL)) != -1) {
cfg.c_ovlfs_strip = false;
break;
case 517:
- if (optarg)
- erofstar.dumpfile = strdup(optarg);
- gzip_supported = true;
- break;
- case 518:
sbi.diskoffset = strtoull(optarg, &endptr, 0);
if (*endptr != '\0') {
erofs_err("invalid disk offset %s", optarg);
return -EINVAL;
}
break;
+ case 518:
+ case 519:
+ if (optarg)
+ erofstar.dumpfile = strdup(optarg);
+ tarerofs_decoder = EROFS_IOS_DECODER_GZIP + (opt - 518);
+ break;
case 'V':
version();
exit(0);
strerror(errno));
return -errno;
}
- err = erofs_iostream_open(&erofstar.ios, dupfd, gzip_supported);
+ err = erofs_iostream_open(&erofstar.ios, dupfd,
+ tarerofs_decoder);
if (err)
return err;
}
erofs_err("failed to open file: %s", cfg.c_src_path);
return -errno;
}
- err = erofs_iostream_open(&erofstar.ios, fd, gzip_supported);
+ err = erofs_iostream_open(&erofstar.ios, fd,
+ tarerofs_decoder);
if (err)
return err;