On 2025/9/16 23:34, ChengyuZhu6 wrote:
From: Chengyu Zhu <[email protected]>

Add support for indexing by layer_digest string for more precise
and reliable OCI layer identification. This change affects both mkfs.erofs
and mount.erofs tools.

Signed-off-by: Chengyu Zhu <[email protected]>
---
  lib/liberofs_oci.h |   6 +-
  lib/remotes/oci.c  |  89 +++++++++++++++++++------
  mkfs/main.c        |  75 +++++++++++++--------
  mount/main.c       | 160 +++++++++++++++++++++++++++++++++------------
  4 files changed, 240 insertions(+), 90 deletions(-)

diff --git a/lib/liberofs_oci.h b/lib/liberofs_oci.h
index aa41141..621eb2b 100644
--- a/lib/liberofs_oci.h
+++ b/lib/liberofs_oci.h
@@ -21,7 +21,8 @@ struct erofs_importer;
   * @platform: target platform in "os/arch" format (e.g., "linux/amd64")
   * @username: username for authentication (optional)
   * @password: password for authentication (optional)
- * @layer_index: specific layer to extract (-1 for all layers)
+ * @layer_digest: specific layer digest to extract (NULL for all layers)
+ * @layer_index: specific layer index to extract (negative for all layers)
   *
   * Configuration structure for OCI image parameters including registry
   * location, image identification, platform specification, and authentication
@@ -32,6 +33,7 @@ struct ocierofs_config {
        char *platform;
        char *username;
        char *password;
+       char *layer_digest;
        int layer_index;
  };
@@ -51,7 +53,7 @@ struct ocierofs_ctx {
        char *tag;
        char *manifest_digest;
        struct ocierofs_layer_info **layers;
-       int layer_index;
+       char *layer_digest;
        int layer_count;
  };
diff --git a/lib/remotes/oci.c b/lib/remotes/oci.c
index 26aec27..d22aa2e 100644
--- a/lib/remotes/oci.c
+++ b/lib/remotes/oci.c
@@ -898,6 +898,21 @@ static int ocierofs_prepare_auth(struct ocierofs_ctx *ctx,
        return 0;
  }
+static int ocierofs_find_layer_by_digest(struct ocierofs_ctx *ctx, const char *digest)
+{
+       int i;
+
+       if (!digest || !ctx->layers)
+               return -1;

It's an internal function, let's not check input argument validity (`digest`).
Or if users misuse an internal function, I'd rather to have a coredump instead
of slient failure.

In principle, `ctx->layers` won't be NULL here too (if ctx->layer_count > 0),
if it really needs to check, I suggest using `DBG_BUGON(!ctx->layers)` or
just get rid of this check.

+
+       for (i = 0; i < ctx->layer_count; i++) {

                DBG_BUGON(!ctx->layers[i]);
                DBG_BUGON(!ctx->layers[i]->digest);

                if (!strcmp(ctx->layers[i]->digest, digest))
                        return i;


+               if (ctx->layers[i] && ctx->layers[i]->digest &&
+                   !strcmp(ctx->layers[i]->digest, digest))
+                       return i;
+       }
+       return -1;
+}
+
  static int ocierofs_prepare_layers(struct ocierofs_ctx *ctx,
                                   const struct ocierofs_config *config)
  {
@@ -925,16 +940,35 @@ static int ocierofs_prepare_layers(struct ocierofs_ctx 
*ctx,
                goto out_manifest;
        }
- if (ctx->layer_index >= ctx->layer_count) {
-               erofs_err("layer index %d exceeds available layers (%d)",
-                         ctx->layer_index, ctx->layer_count);
-               ret = -EINVAL;
-               goto out_layers;
+       if (config->layer_index >= 0) {
+               if (config->layer_index >= ctx->layer_count) {
+                       erofs_err("layer index %d out of range (0..%d)",
+                                 config->layer_index, ctx->layer_count - 1);
+                       ret = -EINVAL;
+                       goto out_layers;
+               }
+               if (!ctx->layers[config->layer_index] ||
+                   !ctx->layers[config->layer_index]->digest) {
+                       ret = -EINVAL;
+                       goto out_layers;
+               }

                DBG_BUGON(!ctx->layers[config->layer_index]);
                DBG_BUGON(!ctx->layers[config->layer_index]->digest);

+               ctx->layer_digest = 
strdup(ctx->layers[config->layer_index]->digest);
+               if (!ctx->layer_digest) {
+                       ret = -ENOMEM;
+                       goto out_layers;
+               }
+       } else if (ctx->layer_digest) {
+               if (ocierofs_find_layer_by_digest(ctx, ctx->layer_digest) < 0) {

        } else if (ctx->layer_digest &&
                   ocierofs_find_layer_by_digest(ctx, ctx->layer_digest) < 0) {

                erofs_err("layer digest %s not found in image layers",
                          ctx->layer_digest);
                ret = -ENOENT;
                goto out_layers;
        }


...

-/* Parse input string in format: "image_ref platform layer [b64cred]" */
+/* Parse input string in format: "image_ref platform layer [b64cred]"
+ * where layer is one of:
+ *   - "digest:<sha256...>" (layer_digest)
+ *   - "index:<N>"          (layer_index)
+ *   - ""                   (no specific layer)


can we just add another tag for this?
        OCI_LAYER and OCI_DIGEST

Thanks,
Gao Xiang

Reply via email to