[PATCH v2 10/16] erofs-utils: add erofs_rebuild_get_dentry() helper
Jingbo Xu
jefflexu at linux.alibaba.com
Wed Aug 2 19:17:44 AEST 2023
Rename tarerofs_get_dentry() to erofs_rebuild_get_dentry().
Also make `whout` and 'opq' parameter optional when `aufs` is false.
Signed-off-by: Jingbo Xu <jefflexu at linux.alibaba.com>
---
include/erofs/rebuild.h | 19 +++++++
lib/Makefile.am | 3 +-
lib/rebuild.c | 117 ++++++++++++++++++++++++++++++++++++++++
lib/tar.c | 109 ++-----------------------------------
4 files changed, 141 insertions(+), 107 deletions(-)
create mode 100644 include/erofs/rebuild.h
create mode 100644 lib/rebuild.c
diff --git a/include/erofs/rebuild.h b/include/erofs/rebuild.h
new file mode 100644
index 0000000..92873c9
--- /dev/null
+++ b/include/erofs/rebuild.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0 */
+#ifndef __EROFS_REBUILD_H
+#define __EROFS_REBUILD_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "internal.h"
+
+struct erofs_dentry *erofs_rebuild_get_dentry(struct erofs_inode *pwd,
+ char *path, bool aufs, bool *whout, bool *opq);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 08e986e..0dae4b3 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -25,6 +25,7 @@ noinst_HEADERS = $(top_srcdir)/include/erofs_fs.h \
$(top_srcdir)/include/erofs/xattr.h \
$(top_srcdir)/include/erofs/compress_hints.h \
$(top_srcdir)/include/erofs/fragments.h \
+ $(top_srcdir)/include/erofs/rebuild.h \
$(top_srcdir)/lib/liberofs_private.h
noinst_HEADERS += compressor.h
@@ -32,7 +33,7 @@ liberofs_la_SOURCES = config.c io.c cache.c super.c inode.c xattr.c exclude.c \
namei.c data.c compress.c compressor.c zmap.c decompress.c \
compress_hints.c hashmap.c sha256.c blobchunk.c dir.c \
fragments.c rb_tree.c dedupe.c uuid_unparse.c uuid.c tar.c \
- block_list.c bitops.c
+ block_list.c bitops.c rebuild.c
liberofs_la_CFLAGS = -Wall ${libuuid_CFLAGS} -I$(top_srcdir)/include
if ENABLE_LZ4
diff --git a/lib/rebuild.c b/lib/rebuild.c
new file mode 100644
index 0000000..7aaa071
--- /dev/null
+++ b/lib/rebuild.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include "erofs/print.h"
+#include "erofs/inode.h"
+#include "erofs/rebuild.h"
+#include "erofs/internal.h"
+
+#ifdef HAVE_LINUX_AUFS_TYPE_H
+#include <linux/aufs_type.h>
+#else
+#define AUFS_WH_PFX ".wh."
+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq"
+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
+#endif
+
+static struct erofs_dentry *erofs_rebuild_mkdir(struct erofs_inode *dir,
+ const char *s)
+{
+ struct erofs_inode *inode;
+ struct erofs_dentry *d;
+
+ inode = erofs_new_inode();
+ if (IS_ERR(inode))
+ return ERR_CAST(inode);
+
+ inode->i_mode = S_IFDIR | 0755;
+ inode->i_parent = dir;
+ inode->i_uid = getuid();
+ inode->i_gid = getgid();
+ inode->i_mtime = inode->sbi->build_time;
+ inode->i_mtime_nsec = inode->sbi->build_time_nsec;
+ erofs_init_empty_dir(inode);
+
+ d = erofs_d_alloc(dir, s);
+ if (!IS_ERR(d)) {
+ d->type = EROFS_FT_DIR;
+ d->inode = inode;
+ }
+ return d;
+}
+
+struct erofs_dentry *erofs_rebuild_get_dentry(struct erofs_inode *pwd,
+ char *path, bool aufs, bool *whout, bool *opq)
+{
+ struct erofs_dentry *d = NULL;
+ unsigned int len = strlen(path);
+ char *s = path;
+
+ if (aufs) {
+ *whout = false;
+ *opq = false;
+ }
+
+ while (s < path + len) {
+ char *slash = memchr(s, '/', path + len - s);
+ if (slash) {
+ if (s == slash) {
+ while (*++s == '/'); /* skip '//...' */
+ continue;
+ }
+ *slash = '\0';
+ }
+
+ if (!memcmp(s, ".", 2)) {
+ /* null */
+ } else if (!memcmp(s, "..", 3)) {
+ pwd = pwd->i_parent;
+ } else {
+ struct erofs_inode *inode = NULL;
+
+ if (aufs && !slash) {
+ if (!memcmp(s, AUFS_WH_DIROPQ, sizeof(AUFS_WH_DIROPQ))) {
+ *opq = true;
+ break;
+ }
+ if (!memcmp(s, AUFS_WH_PFX, sizeof(AUFS_WH_PFX) - 1)) {
+ s += sizeof(AUFS_WH_PFX) - 1;
+ *whout = true;
+ }
+ }
+
+ list_for_each_entry(d, &pwd->i_subdirs, d_child) {
+ if (!strcmp(d->name, s)) {
+ if (d->type != EROFS_FT_DIR && slash)
+ return ERR_PTR(-EIO);
+ inode = d->inode;
+ break;
+ }
+ }
+
+ if (inode) {
+ pwd = inode;
+ } else if (!slash) {
+ d = erofs_d_alloc(pwd, s);
+ if (IS_ERR(d))
+ return d;
+ d->type = EROFS_FT_UNKNOWN;
+ d->inode = pwd;
+ } else {
+ d = erofs_rebuild_mkdir(pwd, s);
+ if (IS_ERR(d))
+ return d;
+ pwd = d->inode;
+ }
+ }
+ if (slash) {
+ *slash = '/';
+ s = slash + 1;
+ } else {
+ break;
+ }
+ }
+ return d;
+}
diff --git a/lib/tar.c b/lib/tar.c
index 5382c54..c3e864b 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -3,13 +3,6 @@
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
-#ifdef HAVE_LINUX_AUFS_TYPE_H
-#include <linux/aufs_type.h>
-#else
-#define AUFS_WH_PFX ".wh."
-#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq"
-#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
-#endif
#include "erofs/print.h"
#include "erofs/cache.h"
#include "erofs/inode.h"
@@ -18,6 +11,7 @@
#include "erofs/io.h"
#include "erofs/xattr.h"
#include "erofs/blobchunk.h"
+#include "erofs/rebuild.h"
static char erofs_libbuf[16384];
@@ -131,103 +125,6 @@ static long long tarerofs_parsenum(const char *ptr, int len)
return tarerofs_otoi(ptr, len);
}
-static struct erofs_dentry *tarerofs_mkdir(struct erofs_inode *dir, const char *s)
-{
- struct erofs_inode *inode;
- struct erofs_dentry *d;
-
- inode = erofs_new_inode();
- if (IS_ERR(inode))
- return ERR_CAST(inode);
-
- inode->i_mode = S_IFDIR | 0755;
- inode->i_parent = dir;
- inode->i_uid = getuid();
- inode->i_gid = getgid();
- inode->i_mtime = inode->sbi->build_time;
- inode->i_mtime_nsec = inode->sbi->build_time_nsec;
- erofs_init_empty_dir(inode);
-
- d = erofs_d_alloc(dir, s);
- if (!IS_ERR(d)) {
- d->type = EROFS_FT_DIR;
- d->inode = inode;
- }
- return d;
-}
-
-static struct erofs_dentry *tarerofs_get_dentry(struct erofs_inode *pwd, char *path,
- bool aufs, bool *whout, bool *opq)
-{
- struct erofs_dentry *d = NULL;
- unsigned int len = strlen(path);
- char *s = path;
-
- *whout = false;
- *opq = false;
-
- while (s < path + len) {
- char *slash = memchr(s, '/', path + len - s);
- if (slash) {
- if (s == slash) {
- while (*++s == '/'); /* skip '//...' */
- continue;
- }
- *slash = '\0';
- }
-
- if (!memcmp(s, ".", 2)) {
- /* null */
- } else if (!memcmp(s, "..", 3)) {
- pwd = pwd->i_parent;
- } else {
- struct erofs_inode *inode = NULL;
-
- if (aufs && !slash) {
- if (!memcmp(s, AUFS_WH_DIROPQ, sizeof(AUFS_WH_DIROPQ))) {
- *opq = true;
- break;
- }
- if (!memcmp(s, AUFS_WH_PFX, sizeof(AUFS_WH_PFX) - 1)) {
- s += sizeof(AUFS_WH_PFX) - 1;
- *whout = true;
- }
- }
-
- list_for_each_entry(d, &pwd->i_subdirs, d_child) {
- if (!strcmp(d->name, s)) {
- if (d->type != EROFS_FT_DIR && slash)
- return ERR_PTR(-EIO);
- inode = d->inode;
- break;
- }
- }
-
- if (inode) {
- pwd = inode;
- } else if (!slash) {
- d = erofs_d_alloc(pwd, s);
- if (IS_ERR(d))
- return d;
- d->type = EROFS_FT_UNKNOWN;
- d->inode = pwd;
- } else {
- d = tarerofs_mkdir(pwd, s);
- if (IS_ERR(d))
- return d;
- pwd = d->inode;
- }
- }
- if (slash) {
- *slash = '/';
- s = slash + 1;
- } else {
- break;
- }
- }
- return d;
-}
-
int tarerofs_parse_pax_header(int fd, struct erofs_pax_header *eh, u32 size)
{
char *buf, *p;
@@ -572,7 +469,7 @@ restart:
erofs_dbg("parsing %s (mode %05o)", eh.path, st.st_mode);
- d = tarerofs_get_dentry(root, eh.path, tar->aufs, &whout, &opq);
+ d = erofs_rebuild_get_dentry(root, eh.path, tar->aufs, &whout, &opq);
if (IS_ERR(d)) {
ret = PTR_ERR(d);
goto out;
@@ -605,7 +502,7 @@ restart:
}
d->inode = NULL;
- d2 = tarerofs_get_dentry(root, eh.link, tar->aufs, &dumb, &dumb);
+ d2 = erofs_rebuild_get_dentry(root, eh.link, tar->aufs, &dumb, &dumb);
if (IS_ERR(d2)) {
ret = PTR_ERR(d2);
goto out;
--
2.19.1.6.gb485710b
More information about the Linux-erofs
mailing list