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