From: Chengyu Zhu <hudson...@tencent.com>

Introduce OCI tarindex mode and optional zinfo generation.

e.g.:
mkfs.erofs --oci=i,platform=linux/amd64,layer=3 \
--gzinfo=golang.zinfo golang.erofs golang:1.22.8

Signed-off-by: Chengyu Zhu <hudson...@tencent.com>
---
 lib/remotes/oci.c | 57 ++++++++++++++++++++++++++++++++++++++---
 mkfs/main.c       | 65 ++++++++++++++++++++++++++++-------------------
 2 files changed, 92 insertions(+), 30 deletions(-)

diff --git a/lib/remotes/oci.c b/lib/remotes/oci.c
index b25e0b2..349e080 100644
--- a/lib/remotes/oci.c
+++ b/lib/remotes/oci.c
@@ -27,6 +27,7 @@
 #include "liberofs_base64.h"
 #include "liberofs_oci.h"
 #include "liberofs_private.h"
+#include "liberofs_gzran.h"
 
 #ifdef OCIEROFS_ENABLED
 
@@ -840,14 +841,33 @@ out:
        return ret;
 }
 
-static int ocierofs_process_tar_stream(struct erofs_importer *importer, int fd)
+static int ocierofs_process_tar_stream(struct erofs_importer *importer, int fd,
+                                      const struct ocierofs_config *config,
+                                      u64 *tar_offset_out)
 {
        struct erofs_tarfile tarfile = {};
-       int ret;
+       int ret, decoder, zinfo_fd;
+       struct erofs_vfile vf;
 
        init_list_head(&tarfile.global.xattrs);
 
-       ret = erofs_iostream_open(&tarfile.ios, fd, EROFS_IOS_DECODER_GZIP);
+       /*
+        * Choose decoder based on config:
+        * - tarindex + zinfo  → tar.gzip (GZRAN decoder)
+        * - tarindex only → tar (no decoder, raw)
+        * - neither → default gzip decoder
+        */
+       if (config && config->tarindex_path) {
+               tarfile.index_mode = true;
+               if (config->zinfo_path)
+                       decoder = EROFS_IOS_DECODER_GZRAN;
+               else
+                       decoder = EROFS_IOS_DECODER_NONE;
+       } else {
+               decoder = EROFS_IOS_DECODER_GZIP;
+       }
+
+       ret = erofs_iostream_open(&tarfile.ios, fd, decoder);
        if (ret) {
                erofs_err("failed to initialize tar stream: %s",
                          erofs_strerror(ret));
@@ -858,6 +878,25 @@ static int ocierofs_process_tar_stream(struct 
erofs_importer *importer, int fd)
                ret = tarerofs_parse_tar(importer, &tarfile);
                /* Continue parsing until end of archive */
        } while (!ret);
+
+       if (decoder == EROFS_IOS_DECODER_GZRAN) {
+               zinfo_fd = open(config->zinfo_path, O_WRONLY | O_CREAT | 
O_TRUNC, 0644);
+               if (zinfo_fd < 0) {
+                       ret = -errno;
+               } else {
+                       vf = (struct erofs_vfile){ .fd = zinfo_fd };
+                       ret = erofs_gzran_builder_export_zinfo(tarfile.ios.gb, 
&vf);
+                       close(zinfo_fd);
+                       if (ret < 0) {
+                               erofs_err("failed to export zinfo: %s",
+                                         erofs_strerror(ret));
+                       }
+               }
+       }
+
+       if (tar_offset_out)
+               *tar_offset_out = tarfile.offset;
+
        erofs_iostream_close(&tarfile.ios);
 
        if (ret < 0 && ret != -ENODATA) {
@@ -1230,6 +1269,7 @@ int ocierofs_build_trees(struct erofs_importer *importer,
 {
        struct ocierofs_ctx ctx = {};
        int ret, i, end, fd;
+       u64 tar_offset = 0;
 
        ret = ocierofs_init(&ctx, config);
        if (ret) {
@@ -1250,6 +1290,12 @@ int ocierofs_build_trees(struct erofs_importer *importer,
                end = ctx.layer_count;
        }
 
+       if (config->tarindex_path && (end - i) != 1) {
+               erofs_err("tarindex mode requires exactly one layer (use blob= 
or layer= option)");
+               ret = -EINVAL;
+               goto out;
+       }
+
        while (i < end) {
                char *trimmed = 
erofs_trim_for_progressinfo(ctx.layers[i]->digest,
                                sizeof("Extracting layer  ...") - 1);
@@ -1263,7 +1309,7 @@ int ocierofs_build_trees(struct erofs_importer *importer,
                        ret = fd;
                        break;
                }
-               ret = ocierofs_process_tar_stream(importer, fd);
+               ret = ocierofs_process_tar_stream(importer, fd, config, 
&tar_offset);
                close(fd);
                if (ret) {
                        erofs_err("failed to process tar stream for layer %s: 
%s",
@@ -1273,6 +1319,9 @@ int ocierofs_build_trees(struct erofs_importer *importer,
                i++;
        }
 out:
+       if (config->tarindex_path && importer->sbi)
+               importer->sbi->devs[0].blocks = BLK_ROUND_UP(importer->sbi, 
tar_offset);
+
        ocierofs_ctx_cleanup(&ctx);
        return ret;
 }
diff --git a/mkfs/main.c b/mkfs/main.c
index 1c37576..c7359f6 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -218,6 +218,8 @@ static void usage(int argc, char **argv)
                "   [,blob=Y]           Y=blob digest to extract (omit to 
extract all layers)\n"
                "   [,username=Z]       Z=username for authentication 
(optional)\n"
                "   [,password=W]       W=password for authentication 
(optional)\n"
+               "   [,i]                generate tarindex file (requires layer 
or blob selection)\n"
+
 #endif
                " --tar=X               generate a full or index-only image 
from a tarball(-ish) source\n"
                "                       (X = f|i|headerball; f=full mode, 
i=index mode,\n"
@@ -285,7 +287,7 @@ static struct erofs_s3 s3cfg;
 
 #ifdef OCIEROFS_ENABLED
 static struct ocierofs_config ocicfg;
-static char *mkfs_oci_options;
+static bool mkfs_oci_tarindex_mode;
 #endif
 
 enum {
@@ -727,7 +729,7 @@ static int mkfs_parse_s3_cfg(char *cfg_str)
  * @options_str: comma-separated options string
  *
  * Parse OCI options string containing comma-separated key=value pairs.
- * Supported options include platform, blob, layer, username, and password.
+ * Supported options include platform, blob, layer, username, password, i 
(tarindex mode), and zinfo.
  *
  * Return: 0 on success, negative errno on failure
  */
@@ -745,6 +747,7 @@ static int mkfs_parse_oci_options(struct ocierofs_config 
*oci_cfg, char *options
                if (q)
                        *q = '\0';
 
+
                p = strstr(opt, "platform=");
                if (p) {
                        p += strlen("platform=");
@@ -790,19 +793,23 @@ static int mkfs_parse_oci_options(struct ocierofs_config 
*oci_cfg, char *options
                                                oci_cfg->username = strdup(p);
                                                if (!oci_cfg->username)
                                                        return -ENOMEM;
+                                       } else {
+                                               p = strstr(opt, "password=");
+                                               if (p) {
+                                                       p += 
strlen("password=");
+                                                       free(oci_cfg->password);
+                                                       oci_cfg->password = 
strdup(p);
+                                                       if (!oci_cfg->password)
+                                                               return -ENOMEM;
+                                               } else {
+                                                       if (!strcmp(opt, "i"))
+                                                               
mkfs_oci_tarindex_mode = true;
+                                                       else {
+                                                               
erofs_err("mkfs: invalid --oci value %s", opt);
+                                                               return -EINVAL;
+                                                       }
+                                               }
                                        }
-
-                                       p = strstr(opt, "password=");
-                                       if (p) {
-                                               p += strlen("password=");
-                                               free(oci_cfg->password);
-                                               oci_cfg->password = strdup(p);
-                                               if (!oci_cfg->password)
-                                                       return -ENOMEM;
-                                       }
-
-                                       erofs_err("mkfs: invalid --oci value 
%s", opt);
-                                       return -EINVAL;
                                }
                        }
                }
@@ -1378,10 +1385,13 @@ static int mkfs_parse_options_cfg(struct 
erofs_importer_params *params,
                        break;
 #endif
 #ifdef OCIEROFS_ENABLED
-               case 534:
-                       mkfs_oci_options = optarg;
+               case 534: {
                        source_mode = EROFS_MKFS_SOURCE_OCI;
+                       err = mkfs_parse_oci_options(&ocicfg, optarg);
+                       if (err)
+                               return err;
                        break;
+               }
 #endif
                case 535:
                        if (optarg)
@@ -1757,6 +1767,9 @@ int main(int argc, char **argv)
                        goto exit;
                }
                mkfs_blkszbits = src->blkszbits;
+       } else if (mkfs_oci_tarindex_mode) {
+               mkfs_blkszbits = 9;
+               tar_index_512b = true;
        }
 
        if (!incremental_mode)
@@ -1883,13 +1896,11 @@ int main(int argc, char **argv)
 #endif
 #ifdef OCIEROFS_ENABLED
                } else if (source_mode == EROFS_MKFS_SOURCE_OCI) {
-                       ocicfg.blob_digest = NULL;
-                       ocicfg.layer_index = -1;
-
-                       err = mkfs_parse_oci_options(&ocicfg, mkfs_oci_options);
-                       if (err)
-                               goto exit;
                        ocicfg.image_ref = cfg.c_src_path;
+                       if (mkfs_oci_tarindex_mode)
+                               ocicfg.tarindex_path = strdup(cfg.c_src_path);
+                       if (!ocicfg.zinfo_path)
+                               ocicfg.zinfo_path = mkfs_aws_zinfo_file;
 
                        if (incremental_mode ||
                            dataimport_mode == EROFS_MKFS_DATA_IMPORT_RVSP ||
@@ -1914,10 +1925,12 @@ int main(int argc, char **argv)
                if (!g_sbi.extra_devices) {
                        DBG_BUGON(1);
                } else {
-                       if (cfg.c_src_path)
-                               g_sbi.devs[0].src_path = strdup(cfg.c_src_path);
-                       g_sbi.devs[0].blocks =
-                               BLK_ROUND_UP(&g_sbi, erofstar.offset);
+                       if (source_mode != EROFS_MKFS_SOURCE_OCI) {
+                               if (cfg.c_src_path)
+                                       g_sbi.devs[0].src_path = 
strdup(cfg.c_src_path);
+                               g_sbi.devs[0].blocks =
+                                       BLK_ROUND_UP(&g_sbi, erofstar.offset);
+                       }
                }
        }
 
-- 
2.47.1


Reply via email to