From: Wenyuan Xu <sereno.xu@deepseek.com>
To: xiang@kernel.org, linux-erofs@lists.ozlabs.org
Cc: sereno.xu@deepseek.com
Subject: [RFC 5/7] erofs-utils: mkfs: support two-field manifest records
Date: Wed, 4 Nov 2026 04:07:23 +0000 [thread overview]
Message-ID: <20261104040725.2473313-6-sereno.xu@deepseek.com> (raw)
In-Reply-To: <20261104040725.2473313-1-sereno.xu@deepseek.com>
Accept PATH PAYLOAD records alongside complete manifest records. Import
metadata and xattrs from the backing file using local import policies,
without recursively scanning directories. Read symbolic links without
following their targets.
Preserve source hard links unless hard dereferencing is requested, and
count only entries imported into the image. Allow explicit hard links
to refer to entries imported from backing files.
Assisted-by: LLM
Signed-off-by: Wenyuan Xu <sereno.xu@deepseek.com>
---
lib/manifest.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 86 insertions(+), 2 deletions(-)
diff --git a/lib/manifest.c b/lib/manifest.c
index bf8eb8c..244c1a0 100644
--- a/lib/manifest.c
+++ b/lib/manifest.c
@@ -175,6 +175,75 @@ enum erofs_manifest_field {
EROFS_MANIFEST_FIELD_COUNT,
};
+static struct erofs_inode *erofs_manifest_load_local(struct erofs_importer *im,
+ struct erofs_inode *parent, char *payload)
+{
+ struct erofs_inode *inode;
+ struct stat st;
+ char *path;
+ size_t len;
+ int ret;
+
+ /* PAYLOAD */
+ if (erofs_manifest_decode(payload, false, &len) || *payload != '/')
+ return ERR_PTR(-EINVAL);
+ if (asprintf(&path, "%s%s", im->params->source, payload) < 0)
+ return ERR_PTR(-ENOMEM);
+
+ ret = lstat(path, &st) ? -errno : 0;
+ if (ret)
+ goto out_path;
+ if (!S_ISDIR(st.st_mode) && !im->params->hard_dereference) {
+ inode = erofs_iget(st.st_dev, st.st_ino);
+ if (inode) {
+ free(path);
+ if (inode->i_nlink == UINT_MAX) {
+ erofs_iput(inode);
+ return ERR_PTR(-EOVERFLOW);
+ }
+ ++inode->i_nlink;
+ return inode;
+ }
+ }
+
+ inode = erofs_new_inode(im->sbi);
+ if (IS_ERR(inode)) {
+ ret = PTR_ERR(inode);
+ goto out_path;
+ }
+ ret = erofs_fill_inode(im, inode, &st, path);
+ if (ret)
+ goto out_inode;
+ inode->i_parent = parent;
+ inode->datasource = EROFS_INODE_DATA_SOURCE_LOCALPATH;
+ if (S_ISLNK(inode->i_mode)) {
+ inode->i_link = malloc(st.st_size);
+ if (!inode->i_link) {
+ ret = -ENOMEM;
+ goto out_inode;
+ }
+ if (readlink(path, inode->i_link, st.st_size) < 0) {
+ ret = -errno;
+ goto out_inode;
+ }
+ }
+
+ if (!im->params->no_xattrs) {
+ /* XATTR */
+ ret = erofs_scan_file_xattrs(inode);
+ if (ret)
+ goto out_inode;
+ }
+
+ free(path);
+ return inode;
+out_inode:
+ erofs_iput(inode);
+out_path:
+ free(path);
+ return ERR_PTR(ret);
+}
+
static int erofs_manifest_parse_record(struct erofs_importer *im,
struct erofs_inode *sentinel, char *line)
{
@@ -183,7 +252,7 @@ static int erofs_manifest_parse_record(struct erofs_importer *im,
struct erofs_dentry *d;
char *f[EROFS_MANIFEST_FIELD_COUNT], *token, *dot;
char name[EROFS_NAME_LEN + 1];
- bool hardlink, is_root;
+ bool hardlink, is_root, short_record = false;
u64 mode, size = 0, uid, gid, rdev = 0, sec, nsec;
size_t len;
int i, ret = -EINVAL;
@@ -196,8 +265,13 @@ static int erofs_manifest_parse_record(struct erofs_importer *im,
do {
token = strsep(&line, " ");
} while (token && !*token);
- if (!token)
+ if (!token) {
+ if (i == EROFS_MANIFEST_PAYLOAD + 1) {
+ short_record = true;
+ break;
+ }
return -EINVAL;
+ }
f[i] = token;
}
@@ -212,6 +286,16 @@ static int erofs_manifest_parse_record(struct erofs_importer *im,
return -EEXIST;
is_root = parent == sentinel;
+ if (short_record) {
+ inode = erofs_manifest_load_local(im, parent,
+ f[EROFS_MANIFEST_PAYLOAD]);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+ if (is_root && !S_ISDIR(inode->i_mode))
+ goto out;
+ goto link;
+ }
+
/* MODE */
hardlink = f[EROFS_MANIFEST_MODE][0] == '@';
if (hardlink) {
--
2.43.0
next prev parent reply other threads:[~2026-11-04 4:12 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 4:07 [RFC 0/7] erofs-utils: add manifest input support Wenyuan Xu
2026-11-04 4:07 ` [RFC 1/7] erofs-utils: mkfs: init root inode in local source mode Wenyuan Xu
2026-11-04 4:07 ` [RFC 2/7] erofs-utils: lib: add erofs_inode_has_xattr helper Wenyuan Xu
2026-11-04 4:07 ` [RFC 3/7] erofs-utils: lib: add erofs_build_shared_xattrs() helper Wenyuan Xu
2026-11-04 4:07 ` [RFC 4/7] erofs-utils: mkfs: add manifest input mode Wenyuan Xu
2026-11-04 4:07 ` Wenyuan Xu [this message]
2026-11-04 4:07 ` [RFC 6/7] erofs-utils: man: document manifest input formats Wenyuan Xu
2026-11-04 4:07 ` [RFC 7/7] erofs-utils: tests: cover manifest input Wenyuan Xu
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=20261104040725.2473313-6-sereno.xu@deepseek.com \
--to=sereno.xu@deepseek.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox