All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gao Xiang <hsiangkao@linux.alibaba.com>
To: ChengyuZhu6 <hudson@cyzhu.com>, linux-erofs@lists.ozlabs.org
Cc: xiang@kernel.org, Chengyu Zhu <hudsonzhu@tencent.com>
Subject: Re: [PATCH v1-changed] erofs-utils: refactor OCI code for better modularity
Date: Tue, 2 Sep 2025 09:52:26 +0800	[thread overview]
Message-ID: <86166f85-5ebb-453a-adcd-7eb8f6bea372@linux.alibaba.com> (raw)
In-Reply-To: <20250901070115.70603-1-hudson@cyzhu.com>



On 2025/9/1 15:01, ChengyuZhu6 wrote:
> From: Chengyu Zhu <hudsonzhu@tencent.com>
> 
> Refactor OCI code to improve code organization and maintainability:
> 
> - Add `struct ocierofs_layer_info` to encapsulate layer metadata
> - Extract authentication logic into `ocierofs_prepare_auth()`
> - Split layer processing into `ocierofs_prepare_layers()`
> - Move OCI parsing functions from `mkfs/main.c` to `lib/remotes/oci.c`
> - Add `ocierofs_process_tar_stream()` for separate tar processing
> - Improve error handling with `ocierofs_free_layers_info()`
> - Refactor `ocierofs_extract_layer()` to return file descriptor
> 
> Signed-off-by: Chengyu Zhu <hudsonzhu@tencent.com>
> ---
>   lib/liberofs_oci.h | 100 +++++++++
>   lib/remotes/oci.c  | 540 +++++++++++++++++++++++++++++++++------------
>   mkfs/main.c        | 200 +----------------
>   3 files changed, 506 insertions(+), 334 deletions(-)
> 
> diff --git a/lib/liberofs_oci.h b/lib/liberofs_oci.h
> index 3a8108b..698fe07 100644
> --- a/lib/liberofs_oci.h
> +++ b/lib/liberofs_oci.h
> @@ -19,6 +19,23 @@ struct erofs_inode;
>   struct CURL;
>   struct erofs_importer;
>   
> +/**
> + * struct ocierofs_layer_info
> + * @digest: OCI content-addressable digest (e.g. "sha256:...")
> + * @media_type: mediaType string from the manifest
> + * @size: layer size in bytes from the manifest (0 if not available)
> + *
> + * This structure is exposed to callers so they can enumerate image layers,
> + * decide which ones to fetch, and pass the digest back to download APIs.
> + * Fields are heap-allocated NUL-terminated strings owned by the caller
> + * once returned from public APIs; the caller must free them.
> + */
> +struct ocierofs_layer_info {
> +	char *digest;
> +	char *media_type;
> +	u64 size;
> +};
> +
>   /**
>    * struct erofs_oci_params - OCI configuration parameters
>    * @registry: registry hostname (e.g., "registry-1.docker.io")
> @@ -88,6 +105,89 @@ int erofs_oci_params_set_string(char **field, const char *value);
>    */
>   int ocierofs_build_trees(struct erofs_importer *importer, struct erofs_oci *oci);
>   
> +/*
> + * ocierofs_parse_options - Parse comma-separated OCI options string
> + * @oci: OCI client structure to update
> + * @options_str: comma-separated options string
> + *
> + * Parse OCI options string containing comma-separated key=value pairs.
> + * Supported options include platform, layer, username, and password.
> + *
> + * Return: 0 on success, negative errno on failure
> + */
> +int ocierofs_parse_options(struct erofs_oci *oci, char *options_str);

Can we leave this functionality in `mkfs/main.c`.

liberofs is not the place to keep option parser.

> +
> +/*
> + * ocierofs_parse_ref - Parse OCI image reference string
> + * @oci: OCI client structure to update
> + * @ref_str: OCI image reference in various formats
> + *
> + * Parse OCI image reference which can be in formats:
> + * - registry.example.com/namespace/repo:tag
> + * - namespace/repo:tag (uses default registry)
> + * - repo:tag (adds library/ prefix for Docker Hub)

Is there some reference for this rule?

> + * - repo (uses default tag "latest")
> + *
> + * Return: 0 on success, negative errno on failure
> + */
> +int ocierofs_parse_ref(struct erofs_oci *oci, const char *ref_str);
> +
> +/*
> + * ocierofs_prepare_layers - Prepare OCI layers for processing
> + * @oci: OCI client structure with configured parameters
> + * @auth_header: Pointer to store authentication header
> + * @using_basic: Pointer to store basic auth flag
> + * @manifest_digest: Pointer to store manifest digest
> + * @layers: Pointer to store layers information
> + * @layer_count: Pointer to store number of layers
> + * @start_index: Pointer to store starting layer index
> + *
> + * Prepare authentication, get manifest digest and layers information
> + * for OCI image processing. This function handles all the preparation
> + * work needed before processing OCI layers.
> + *
> + * Return: 0 on success, negative errno on failure
> + */
> +int ocierofs_prepare_layers(struct erofs_oci *oci, char **auth_header,
> +			   bool *using_basic, char **manifest_digest,
> +			   struct ocierofs_layer_info ***layers,
> +			   int *layer_count, int *start_index);

Could we have a way to wrap these arguments into
a structure too?

> +
> +/**
> + * ocierofs_free_layers_info - Free layer information array
> + * @layers: array of layer information structures
> + * @count: number of layers in the array
> + *
> + * Free all layer information structures and the array itself.
> + * This function handles NULL pointers safely.
> + */
> +void ocierofs_free_layers_info(struct ocierofs_layer_info **layers, int count);
> +
> +/**
> + * ocierofs_prepare_auth - Prepare authentication for OCI requests
> + * @oci: OCI client structure
> + * @auth_header_out: pointer to store authentication header
> + * @using_basic_auth: pointer to store basic auth flag
> + *
> + * Prepare authentication header for OCI registry requests.
> + * This function handles both token-based and basic authentication.
> + *
> + * Return: 0 on success, negative errno on failure
> + */
> +int ocierofs_prepare_auth(struct erofs_oci *oci, char **auth_header_out,
> +			  bool *using_basic_auth);
> +
> +/**
> + * ocierofs_curl_clear_auth - Clear basic authentication from CURL handle
> + * @curl: CURL handle to clear authentication from
> + *
> + * Clear basic authentication credentials from a CURL handle.
> + * This should be called after using basic authentication to clean up.
> + *
> + * Return: 0 on success, negative errno on failure
> + */
> +int ocierofs_curl_clear_auth(struct CURL *curl);

pass in `erofs_oci` instead?

> +
>   #ifdef __cplusplus
>   }
>   #endif
> diff --git a/lib/remotes/oci.c b/lib/remotes/oci.c
> index 0fb8c1f..9774d8d 100644
> --- a/lib/remotes/oci.c
> +++ b/lib/remotes/oci.c
> @@ -42,7 +42,6 @@ struct erofs_oci_response {
>   };
>   
>   struct erofs_oci_stream {
> -	struct erofs_tarfile tarfile;
>   	const char *digest;
>   	int blobfd;
>   };
> @@ -111,7 +110,7 @@ static int ocierofs_curl_setup_basic_auth(struct CURL *curl, const char *usernam
>   	return 0;
>   }
>   
> -static int ocierofs_curl_clear_auth(struct CURL *curl)
> +int ocierofs_curl_clear_auth(struct CURL *curl)
>   {
>   	curl_easy_setopt(curl, CURLOPT_USERPWD, NULL);
>   	curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_NONE);
> @@ -181,7 +180,7 @@ static int ocierofs_request_perform(struct erofs_oci *oci,
>   
>   	ret = ocierofs_curl_setup_rq(oci->curl, req->url,
>   				     OCIEROFS_HTTP_GET, req->headers,
> -			             ocierofs_write_callback, resp,
> +				     ocierofs_write_callback, resp,
>   				     NULL, NULL);
>   	if (ret)
>   		return ret;
> @@ -568,7 +567,7 @@ static char *ocierofs_get_manifest_digest(struct erofs_oci *oci,
>   	const char *api_registry;
>   	int ret = 0, len, i;
>   
> -	if (!registry || !repository || !tag || !platform)
> +	if (!registry || !repository || !tag)
>   		return ERR_PTR(-EINVAL);
>   
>   	api_registry = (!strcmp(registry, DOCKER_REGISTRY)) ? DOCKER_API_REGISTRY : registry;
> @@ -581,8 +580,8 @@ static char *ocierofs_get_manifest_digest(struct erofs_oci *oci,
>   
>   	req.headers = curl_slist_append(req.headers,
>   		"Accept: " DOCKER_MEDIATYPE_MANIFEST_LIST ","
> -		OCI_MEDIATYPE_INDEX "," DOCKER_MEDIATYPE_MANIFEST_V1 ","
> -		DOCKER_MEDIATYPE_MANIFEST_V2);
> +		OCI_MEDIATYPE_INDEX "," OCI_MEDIATYPE_MANIFEST ","
> +		DOCKER_MEDIATYPE_MANIFEST_V1 "," DOCKER_MEDIATYPE_MANIFEST_V2);
>   
>   	ret = ocierofs_request_perform(oci, &req, &resp);
>   	if (ret)
> @@ -663,7 +662,24 @@ out:
>   	return ret ? ERR_PTR(ret) : digest;
>   }
>   
> -static char **ocierofs_get_layers_info(struct erofs_oci *oci,
> +void ocierofs_free_layers_info(struct ocierofs_layer_info **layers, int count)
> +{
> +	int i;
> +
> +	if (!layers)
> +		return;
> +
> +	for (i = 0; i < count; i++) {
> +		if (layers[i]) {
> +			free(layers[i]->digest);
> +			free(layers[i]->media_type);
> +			free(layers[i]);
> +		}
> +	}
> +	free(layers);
> +}
> +
> +static struct ocierofs_layer_info **ocierofs_fetch_layers_info(struct erofs_oci *oci,
>   				       const char *registry,
>   				       const char *repository,
>   				       const char *digest,
> @@ -672,10 +688,10 @@ static char **ocierofs_get_layers_info(struct erofs_oci *oci,
>   {
>   	struct erofs_oci_request req = {};
>   	struct erofs_oci_response resp = {};
> -	json_object *root, *layers, *layer, *digest_obj;
> -	char **layers_info = NULL;
> +	json_object *root, *layers, *layer, *digest_obj, *media_type_obj, *size_obj;
> +	struct ocierofs_layer_info **layers_info = NULL;
>   	const char *api_registry;
> -	int ret, len, i, j;
> +	int ret, len, i;
>   
>   	if (!registry || !repository || !digest || !layer_count)
>   		return ERR_PTR(-EINVAL);
> @@ -725,7 +741,7 @@ static char **ocierofs_get_layers_info(struct erofs_oci *oci,
>   		goto out_json;
>   	}
>   
> -	layers_info = calloc(len, sizeof(char *));
> +	layers_info = calloc(len, sizeof(*layers_info));
>   	if (!layers_info) {
>   		ret = -ENOMEM;
>   		goto out_json;
> @@ -740,11 +756,25 @@ static char **ocierofs_get_layers_info(struct erofs_oci *oci,
>   			goto out_free;
>   		}
>   
> -		layers_info[i] = strdup(json_object_get_string(digest_obj));
> +		layers_info[i] = calloc(1, sizeof(**layers_info));
>   		if (!layers_info[i]) {
>   			ret = -ENOMEM;
>   			goto out_free;
>   		}
> +		layers_info[i]->digest = strdup(json_object_get_string(digest_obj));
> +		if (!layers_info[i]->digest) {
> +			ret = -ENOMEM;
> +			goto out_free;
> +		}
> +		if (json_object_object_get_ex(layer, "mediaType", &media_type_obj))
> +			layers_info[i]->media_type = strdup(json_object_get_string(media_type_obj));
> +		else
> +			layers_info[i]->media_type = NULL;
> +
> +		if (json_object_object_get_ex(layer, "size", &size_obj))
> +			layers_info[i]->size = json_object_get_int64(size_obj);
> +		else
> +			layers_info[i]->size = 0;
>   	}
>   
>   	*layer_count = len;
> @@ -756,11 +786,7 @@ static char **ocierofs_get_layers_info(struct erofs_oci *oci,
>   	return layers_info;
>   
>   out_free:
> -	if (layers_info) {
> -		for (j = 0; j < i; j++)
> -			free(layers_info[j]);
> -	}
> -	free(layers_info);
> +	ocierofs_free_layers_info(layers_info, i);
>   out_json:
>   	json_object_put(root);
>   out:
> @@ -771,8 +797,93 @@ out:
>   	return ERR_PTR(ret);
>   }
>   
> -static int ocierofs_extract_layer(struct erofs_oci *oci, struct erofs_importer *importer,
> -				  const char *digest, const char *auth_header)
> +/**
> + * ocierofs_process_tar_stream - Process tar stream from file descriptor
> + * @importer: EROFS importer structure
> + * @fd: File descriptor containing tar data
> + *
> + * Initialize tar stream, parse all entries, and clean up resources.
> + *
> + * Return: 0 on success, negative errno on failure
> + */
> +static int ocierofs_process_tar_stream(struct erofs_importer *importer, int fd)
> +{
> +	struct erofs_tarfile tarfile = {};
> +	int ret;
> +
> +	memset(&tarfile, 0, sizeof(tarfile));

	struct erofs_tarfile tarfile = {};

already indicates
	memset(&tarfile, 0, sizeof(tarfile));

Thanks,
Gao Xiang


  reply	other threads:[~2025-09-02  1:52 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-01  5:10 [PATCH v1] erofs-utils: refactor OCI code for better modularity ChengyuZhu6
2025-09-01  7:01 ` [PATCH v1-changed] " ChengyuZhu6
2025-09-02  1:52   ` Gao Xiang [this message]
2025-09-02  3:17 ` [PATCH v2] " ChengyuZhu6
2025-09-02  3:29 ` [PATCH v2-changed] " ChengyuZhu6
2025-09-03  8:29 ` [PATCH v3 0/2] erofs-utils: refactor OCI and add NBD-backed OCI image mounting ChengyuZhu6
2025-09-03  8:29   ` [PATCH v3 1/2] erofs-utils: refactor OCI code for better modularity ChengyuZhu6
2025-09-03  8:47     ` Gao Xiang
2025-09-03  8:29   ` [PATCH v3 2/2] erofs-utils: add NBD-backed OCI image mounting ChengyuZhu6
2025-09-04  5:33 ` [PATCH v4 0/3] erofs-utils: refactor OCI and " ChengyuZhu6
2025-09-04  5:33   ` [PATCH v4 1/3] erofs-utils:mkfs: move parse_oci_ref to lib ChengyuZhu6
2025-09-04  5:33   ` [PATCH v4 2/3] erofs-utils: refactor OCI code for better modularity ChengyuZhu6
2025-09-04  5:53     ` Gao Xiang
2025-09-04  5:33   ` [PATCH v4 3/3] erofs-utils: add NBD-backed OCI image mounting ChengyuZhu6
2025-09-04  6:36 ` [PATCH v5 0/3] erofs-utils: refactor OCI and " ChengyuZhu6
2025-09-04  6:36   ` [PATCH v5 1/3] erofs-utils:mkfs: move parse_oci_ref to lib ChengyuZhu6
2025-09-04  6:36   ` [PATCH v5 2/3] erofs-utils: refactor OCI code for better modularity ChengyuZhu6
2025-09-04  6:36   ` [PATCH v5 3/3] erofs-utils: add NBD-backed OCI image mounting ChengyuZhu6
2025-09-04  7:19   ` [PATCH v5 0/3] erofs-utils: refactor OCI and " Gao Xiang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=86166f85-5ebb-453a-adcd-7eb8f6bea372@linux.alibaba.com \
    --to=hsiangkao@linux.alibaba.com \
    --cc=hudson@cyzhu.com \
    --cc=hudsonzhu@tencent.com \
    --cc=linux-erofs@lists.ozlabs.org \
    --cc=xiang@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.