1*33b1fccfSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2*33b1fccfSAndroid Build Coastguard Worker #define _GNU_SOURCE
3*33b1fccfSAndroid Build Coastguard Worker #include <unistd.h>
4*33b1fccfSAndroid Build Coastguard Worker #include <stdlib.h>
5*33b1fccfSAndroid Build Coastguard Worker #include <string.h>
6*33b1fccfSAndroid Build Coastguard Worker #include <sys/stat.h>
7*33b1fccfSAndroid Build Coastguard Worker #include <config.h>
8*33b1fccfSAndroid Build Coastguard Worker #if defined(HAVE_SYS_SYSMACROS_H)
9*33b1fccfSAndroid Build Coastguard Worker #include <sys/sysmacros.h>
10*33b1fccfSAndroid Build Coastguard Worker #endif
11*33b1fccfSAndroid Build Coastguard Worker #include "erofs/print.h"
12*33b1fccfSAndroid Build Coastguard Worker #include "erofs/inode.h"
13*33b1fccfSAndroid Build Coastguard Worker #include "erofs/rebuild.h"
14*33b1fccfSAndroid Build Coastguard Worker #include "erofs/dir.h"
15*33b1fccfSAndroid Build Coastguard Worker #include "erofs/xattr.h"
16*33b1fccfSAndroid Build Coastguard Worker #include "erofs/blobchunk.h"
17*33b1fccfSAndroid Build Coastguard Worker #include "erofs/internal.h"
18*33b1fccfSAndroid Build Coastguard Worker #include "liberofs_uuid.h"
19*33b1fccfSAndroid Build Coastguard Worker
20*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_AUFS_TYPE_H
21*33b1fccfSAndroid Build Coastguard Worker #include <linux/aufs_type.h>
22*33b1fccfSAndroid Build Coastguard Worker #else
23*33b1fccfSAndroid Build Coastguard Worker #define AUFS_WH_PFX ".wh."
24*33b1fccfSAndroid Build Coastguard Worker #define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq"
25*33b1fccfSAndroid Build Coastguard Worker #define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
26*33b1fccfSAndroid Build Coastguard Worker #endif
27*33b1fccfSAndroid Build Coastguard Worker
erofs_rebuild_mkdir(struct erofs_inode * dir,const char * s)28*33b1fccfSAndroid Build Coastguard Worker static struct erofs_dentry *erofs_rebuild_mkdir(struct erofs_inode *dir,
29*33b1fccfSAndroid Build Coastguard Worker const char *s)
30*33b1fccfSAndroid Build Coastguard Worker {
31*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *inode;
32*33b1fccfSAndroid Build Coastguard Worker struct erofs_dentry *d;
33*33b1fccfSAndroid Build Coastguard Worker
34*33b1fccfSAndroid Build Coastguard Worker inode = erofs_new_inode(dir->sbi);
35*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(inode))
36*33b1fccfSAndroid Build Coastguard Worker return ERR_CAST(inode);
37*33b1fccfSAndroid Build Coastguard Worker
38*33b1fccfSAndroid Build Coastguard Worker if (asprintf(&inode->i_srcpath, "%s/%s",
39*33b1fccfSAndroid Build Coastguard Worker dir->i_srcpath ? : "", s) < 0) {
40*33b1fccfSAndroid Build Coastguard Worker erofs_iput(inode);
41*33b1fccfSAndroid Build Coastguard Worker return ERR_PTR(-ENOMEM);
42*33b1fccfSAndroid Build Coastguard Worker }
43*33b1fccfSAndroid Build Coastguard Worker inode->i_mode = S_IFDIR | 0755;
44*33b1fccfSAndroid Build Coastguard Worker inode->i_parent = dir;
45*33b1fccfSAndroid Build Coastguard Worker inode->i_uid = getuid();
46*33b1fccfSAndroid Build Coastguard Worker inode->i_gid = getgid();
47*33b1fccfSAndroid Build Coastguard Worker inode->i_mtime = inode->sbi->build_time;
48*33b1fccfSAndroid Build Coastguard Worker inode->i_mtime_nsec = inode->sbi->build_time_nsec;
49*33b1fccfSAndroid Build Coastguard Worker erofs_init_empty_dir(inode);
50*33b1fccfSAndroid Build Coastguard Worker
51*33b1fccfSAndroid Build Coastguard Worker d = erofs_d_alloc(dir, s);
52*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(d)) {
53*33b1fccfSAndroid Build Coastguard Worker erofs_iput(inode);
54*33b1fccfSAndroid Build Coastguard Worker } else {
55*33b1fccfSAndroid Build Coastguard Worker d->type = EROFS_FT_DIR;
56*33b1fccfSAndroid Build Coastguard Worker d->inode = inode;
57*33b1fccfSAndroid Build Coastguard Worker }
58*33b1fccfSAndroid Build Coastguard Worker return d;
59*33b1fccfSAndroid Build Coastguard Worker }
60*33b1fccfSAndroid Build Coastguard Worker
erofs_rebuild_get_dentry(struct erofs_inode * pwd,char * path,bool aufs,bool * whout,bool * opq,bool to_head)61*33b1fccfSAndroid Build Coastguard Worker struct erofs_dentry *erofs_rebuild_get_dentry(struct erofs_inode *pwd,
62*33b1fccfSAndroid Build Coastguard Worker char *path, bool aufs, bool *whout, bool *opq, bool to_head)
63*33b1fccfSAndroid Build Coastguard Worker {
64*33b1fccfSAndroid Build Coastguard Worker struct erofs_dentry *d = NULL;
65*33b1fccfSAndroid Build Coastguard Worker unsigned int len = strlen(path);
66*33b1fccfSAndroid Build Coastguard Worker char *s = path;
67*33b1fccfSAndroid Build Coastguard Worker
68*33b1fccfSAndroid Build Coastguard Worker *whout = false;
69*33b1fccfSAndroid Build Coastguard Worker *opq = false;
70*33b1fccfSAndroid Build Coastguard Worker
71*33b1fccfSAndroid Build Coastguard Worker while (s < path + len) {
72*33b1fccfSAndroid Build Coastguard Worker char *slash = memchr(s, '/', path + len - s);
73*33b1fccfSAndroid Build Coastguard Worker
74*33b1fccfSAndroid Build Coastguard Worker if (slash) {
75*33b1fccfSAndroid Build Coastguard Worker if (s == slash) {
76*33b1fccfSAndroid Build Coastguard Worker while (*++s == '/'); /* skip '//...' */
77*33b1fccfSAndroid Build Coastguard Worker continue;
78*33b1fccfSAndroid Build Coastguard Worker }
79*33b1fccfSAndroid Build Coastguard Worker *slash = '\0';
80*33b1fccfSAndroid Build Coastguard Worker }
81*33b1fccfSAndroid Build Coastguard Worker
82*33b1fccfSAndroid Build Coastguard Worker if (!memcmp(s, ".", 2)) {
83*33b1fccfSAndroid Build Coastguard Worker /* null */
84*33b1fccfSAndroid Build Coastguard Worker } else if (!memcmp(s, "..", 3)) {
85*33b1fccfSAndroid Build Coastguard Worker pwd = pwd->i_parent;
86*33b1fccfSAndroid Build Coastguard Worker } else {
87*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *inode = NULL;
88*33b1fccfSAndroid Build Coastguard Worker
89*33b1fccfSAndroid Build Coastguard Worker if (aufs && !slash) {
90*33b1fccfSAndroid Build Coastguard Worker if (!memcmp(s, AUFS_WH_DIROPQ, sizeof(AUFS_WH_DIROPQ))) {
91*33b1fccfSAndroid Build Coastguard Worker *opq = true;
92*33b1fccfSAndroid Build Coastguard Worker break;
93*33b1fccfSAndroid Build Coastguard Worker }
94*33b1fccfSAndroid Build Coastguard Worker if (!memcmp(s, AUFS_WH_PFX, sizeof(AUFS_WH_PFX) - 1)) {
95*33b1fccfSAndroid Build Coastguard Worker s += sizeof(AUFS_WH_PFX) - 1;
96*33b1fccfSAndroid Build Coastguard Worker *whout = true;
97*33b1fccfSAndroid Build Coastguard Worker }
98*33b1fccfSAndroid Build Coastguard Worker }
99*33b1fccfSAndroid Build Coastguard Worker
100*33b1fccfSAndroid Build Coastguard Worker list_for_each_entry(d, &pwd->i_subdirs, d_child) {
101*33b1fccfSAndroid Build Coastguard Worker if (!strcmp(d->name, s)) {
102*33b1fccfSAndroid Build Coastguard Worker if (d->type != EROFS_FT_DIR && slash)
103*33b1fccfSAndroid Build Coastguard Worker return ERR_PTR(-EIO);
104*33b1fccfSAndroid Build Coastguard Worker inode = d->inode;
105*33b1fccfSAndroid Build Coastguard Worker break;
106*33b1fccfSAndroid Build Coastguard Worker }
107*33b1fccfSAndroid Build Coastguard Worker }
108*33b1fccfSAndroid Build Coastguard Worker
109*33b1fccfSAndroid Build Coastguard Worker if (inode) {
110*33b1fccfSAndroid Build Coastguard Worker if (to_head) {
111*33b1fccfSAndroid Build Coastguard Worker list_del(&d->d_child);
112*33b1fccfSAndroid Build Coastguard Worker list_add(&d->d_child, &pwd->i_subdirs);
113*33b1fccfSAndroid Build Coastguard Worker }
114*33b1fccfSAndroid Build Coastguard Worker pwd = inode;
115*33b1fccfSAndroid Build Coastguard Worker } else if (!slash) {
116*33b1fccfSAndroid Build Coastguard Worker d = erofs_d_alloc(pwd, s);
117*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(d))
118*33b1fccfSAndroid Build Coastguard Worker return d;
119*33b1fccfSAndroid Build Coastguard Worker d->type = EROFS_FT_UNKNOWN;
120*33b1fccfSAndroid Build Coastguard Worker d->inode = pwd;
121*33b1fccfSAndroid Build Coastguard Worker } else {
122*33b1fccfSAndroid Build Coastguard Worker d = erofs_rebuild_mkdir(pwd, s);
123*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(d))
124*33b1fccfSAndroid Build Coastguard Worker return d;
125*33b1fccfSAndroid Build Coastguard Worker pwd = d->inode;
126*33b1fccfSAndroid Build Coastguard Worker }
127*33b1fccfSAndroid Build Coastguard Worker }
128*33b1fccfSAndroid Build Coastguard Worker if (slash) {
129*33b1fccfSAndroid Build Coastguard Worker *slash = '/';
130*33b1fccfSAndroid Build Coastguard Worker s = slash + 1;
131*33b1fccfSAndroid Build Coastguard Worker } else {
132*33b1fccfSAndroid Build Coastguard Worker break;
133*33b1fccfSAndroid Build Coastguard Worker }
134*33b1fccfSAndroid Build Coastguard Worker }
135*33b1fccfSAndroid Build Coastguard Worker return d;
136*33b1fccfSAndroid Build Coastguard Worker }
137*33b1fccfSAndroid Build Coastguard Worker
erofs_rebuild_write_blob_index(struct erofs_sb_info * dst_sb,struct erofs_inode * inode)138*33b1fccfSAndroid Build Coastguard Worker static int erofs_rebuild_write_blob_index(struct erofs_sb_info *dst_sb,
139*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *inode)
140*33b1fccfSAndroid Build Coastguard Worker {
141*33b1fccfSAndroid Build Coastguard Worker int ret;
142*33b1fccfSAndroid Build Coastguard Worker unsigned int count, unit, chunkbits, i;
143*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode_chunk_index *idx;
144*33b1fccfSAndroid Build Coastguard Worker erofs_off_t chunksize;
145*33b1fccfSAndroid Build Coastguard Worker erofs_blk_t blkaddr;
146*33b1fccfSAndroid Build Coastguard Worker
147*33b1fccfSAndroid Build Coastguard Worker /* TODO: fill data map in other layouts */
148*33b1fccfSAndroid Build Coastguard Worker if (inode->datalayout == EROFS_INODE_CHUNK_BASED) {
149*33b1fccfSAndroid Build Coastguard Worker chunkbits = inode->u.chunkbits;
150*33b1fccfSAndroid Build Coastguard Worker if (chunkbits < dst_sb->blkszbits) {
151*33b1fccfSAndroid Build Coastguard Worker erofs_err("%s: chunk size %u is smaller than the target block size %u",
152*33b1fccfSAndroid Build Coastguard Worker inode->i_srcpath, 1U << chunkbits,
153*33b1fccfSAndroid Build Coastguard Worker 1U << dst_sb->blkszbits);
154*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
155*33b1fccfSAndroid Build Coastguard Worker }
156*33b1fccfSAndroid Build Coastguard Worker } else if (inode->datalayout == EROFS_INODE_FLAT_PLAIN) {
157*33b1fccfSAndroid Build Coastguard Worker chunkbits = ilog2(inode->i_size - 1) + 1;
158*33b1fccfSAndroid Build Coastguard Worker if (chunkbits < dst_sb->blkszbits)
159*33b1fccfSAndroid Build Coastguard Worker chunkbits = dst_sb->blkszbits;
160*33b1fccfSAndroid Build Coastguard Worker if (chunkbits - dst_sb->blkszbits > EROFS_CHUNK_FORMAT_BLKBITS_MASK)
161*33b1fccfSAndroid Build Coastguard Worker chunkbits = EROFS_CHUNK_FORMAT_BLKBITS_MASK + dst_sb->blkszbits;
162*33b1fccfSAndroid Build Coastguard Worker } else {
163*33b1fccfSAndroid Build Coastguard Worker erofs_err("%s: unsupported datalayout %d ", inode->i_srcpath,
164*33b1fccfSAndroid Build Coastguard Worker inode->datalayout);
165*33b1fccfSAndroid Build Coastguard Worker return -EOPNOTSUPP;
166*33b1fccfSAndroid Build Coastguard Worker }
167*33b1fccfSAndroid Build Coastguard Worker
168*33b1fccfSAndroid Build Coastguard Worker chunksize = 1ULL << chunkbits;
169*33b1fccfSAndroid Build Coastguard Worker count = DIV_ROUND_UP(inode->i_size, chunksize);
170*33b1fccfSAndroid Build Coastguard Worker
171*33b1fccfSAndroid Build Coastguard Worker unit = sizeof(struct erofs_inode_chunk_index);
172*33b1fccfSAndroid Build Coastguard Worker inode->extent_isize = count * unit;
173*33b1fccfSAndroid Build Coastguard Worker idx = malloc(max(sizeof(*idx), sizeof(void *)));
174*33b1fccfSAndroid Build Coastguard Worker if (!idx)
175*33b1fccfSAndroid Build Coastguard Worker return -ENOMEM;
176*33b1fccfSAndroid Build Coastguard Worker inode->chunkindexes = idx;
177*33b1fccfSAndroid Build Coastguard Worker
178*33b1fccfSAndroid Build Coastguard Worker for (i = 0; i < count; i++) {
179*33b1fccfSAndroid Build Coastguard Worker struct erofs_blobchunk *chunk;
180*33b1fccfSAndroid Build Coastguard Worker struct erofs_map_blocks map = {
181*33b1fccfSAndroid Build Coastguard Worker .index = UINT_MAX,
182*33b1fccfSAndroid Build Coastguard Worker };
183*33b1fccfSAndroid Build Coastguard Worker
184*33b1fccfSAndroid Build Coastguard Worker map.m_la = i << chunkbits;
185*33b1fccfSAndroid Build Coastguard Worker ret = erofs_map_blocks(inode, &map, 0);
186*33b1fccfSAndroid Build Coastguard Worker if (ret)
187*33b1fccfSAndroid Build Coastguard Worker goto err;
188*33b1fccfSAndroid Build Coastguard Worker
189*33b1fccfSAndroid Build Coastguard Worker blkaddr = erofs_blknr(dst_sb, map.m_pa);
190*33b1fccfSAndroid Build Coastguard Worker chunk = erofs_get_unhashed_chunk(inode->dev, blkaddr, 0);
191*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(chunk)) {
192*33b1fccfSAndroid Build Coastguard Worker ret = PTR_ERR(chunk);
193*33b1fccfSAndroid Build Coastguard Worker goto err;
194*33b1fccfSAndroid Build Coastguard Worker }
195*33b1fccfSAndroid Build Coastguard Worker *(void **)idx++ = chunk;
196*33b1fccfSAndroid Build Coastguard Worker
197*33b1fccfSAndroid Build Coastguard Worker }
198*33b1fccfSAndroid Build Coastguard Worker inode->datalayout = EROFS_INODE_CHUNK_BASED;
199*33b1fccfSAndroid Build Coastguard Worker inode->u.chunkformat = EROFS_CHUNK_FORMAT_INDEXES;
200*33b1fccfSAndroid Build Coastguard Worker inode->u.chunkformat |= chunkbits - dst_sb->blkszbits;
201*33b1fccfSAndroid Build Coastguard Worker return 0;
202*33b1fccfSAndroid Build Coastguard Worker err:
203*33b1fccfSAndroid Build Coastguard Worker free(inode->chunkindexes);
204*33b1fccfSAndroid Build Coastguard Worker inode->chunkindexes = NULL;
205*33b1fccfSAndroid Build Coastguard Worker return ret;
206*33b1fccfSAndroid Build Coastguard Worker }
207*33b1fccfSAndroid Build Coastguard Worker
erofs_rebuild_update_inode(struct erofs_sb_info * dst_sb,struct erofs_inode * inode,enum erofs_rebuild_datamode datamode)208*33b1fccfSAndroid Build Coastguard Worker static int erofs_rebuild_update_inode(struct erofs_sb_info *dst_sb,
209*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *inode,
210*33b1fccfSAndroid Build Coastguard Worker enum erofs_rebuild_datamode datamode)
211*33b1fccfSAndroid Build Coastguard Worker {
212*33b1fccfSAndroid Build Coastguard Worker int err = 0;
213*33b1fccfSAndroid Build Coastguard Worker
214*33b1fccfSAndroid Build Coastguard Worker switch (inode->i_mode & S_IFMT) {
215*33b1fccfSAndroid Build Coastguard Worker case S_IFCHR:
216*33b1fccfSAndroid Build Coastguard Worker if (erofs_inode_is_whiteout(inode))
217*33b1fccfSAndroid Build Coastguard Worker inode->i_parent->whiteouts = true;
218*33b1fccfSAndroid Build Coastguard Worker /* fallthrough */
219*33b1fccfSAndroid Build Coastguard Worker case S_IFBLK:
220*33b1fccfSAndroid Build Coastguard Worker case S_IFIFO:
221*33b1fccfSAndroid Build Coastguard Worker case S_IFSOCK:
222*33b1fccfSAndroid Build Coastguard Worker inode->i_size = 0;
223*33b1fccfSAndroid Build Coastguard Worker erofs_dbg("\tdev: %d %d", major(inode->u.i_rdev),
224*33b1fccfSAndroid Build Coastguard Worker minor(inode->u.i_rdev));
225*33b1fccfSAndroid Build Coastguard Worker inode->u.i_rdev = erofs_new_encode_dev(inode->u.i_rdev);
226*33b1fccfSAndroid Build Coastguard Worker break;
227*33b1fccfSAndroid Build Coastguard Worker case S_IFDIR:
228*33b1fccfSAndroid Build Coastguard Worker err = erofs_init_empty_dir(inode);
229*33b1fccfSAndroid Build Coastguard Worker break;
230*33b1fccfSAndroid Build Coastguard Worker case S_IFLNK:
231*33b1fccfSAndroid Build Coastguard Worker inode->i_link = malloc(inode->i_size + 1);
232*33b1fccfSAndroid Build Coastguard Worker if (!inode->i_link)
233*33b1fccfSAndroid Build Coastguard Worker return -ENOMEM;
234*33b1fccfSAndroid Build Coastguard Worker err = erofs_pread(inode, inode->i_link, inode->i_size, 0);
235*33b1fccfSAndroid Build Coastguard Worker erofs_dbg("\tsymlink: %s -> %s", inode->i_srcpath, inode->i_link);
236*33b1fccfSAndroid Build Coastguard Worker break;
237*33b1fccfSAndroid Build Coastguard Worker case S_IFREG:
238*33b1fccfSAndroid Build Coastguard Worker if (!inode->i_size) {
239*33b1fccfSAndroid Build Coastguard Worker inode->u.i_blkaddr = NULL_ADDR;
240*33b1fccfSAndroid Build Coastguard Worker break;
241*33b1fccfSAndroid Build Coastguard Worker }
242*33b1fccfSAndroid Build Coastguard Worker if (datamode == EROFS_REBUILD_DATA_BLOB_INDEX)
243*33b1fccfSAndroid Build Coastguard Worker err = erofs_rebuild_write_blob_index(dst_sb, inode);
244*33b1fccfSAndroid Build Coastguard Worker else if (datamode == EROFS_REBUILD_DATA_RESVSP)
245*33b1fccfSAndroid Build Coastguard Worker inode->datasource = EROFS_INODE_DATA_SOURCE_RESVSP;
246*33b1fccfSAndroid Build Coastguard Worker else
247*33b1fccfSAndroid Build Coastguard Worker err = -EOPNOTSUPP;
248*33b1fccfSAndroid Build Coastguard Worker break;
249*33b1fccfSAndroid Build Coastguard Worker default:
250*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
251*33b1fccfSAndroid Build Coastguard Worker }
252*33b1fccfSAndroid Build Coastguard Worker return err;
253*33b1fccfSAndroid Build Coastguard Worker }
254*33b1fccfSAndroid Build Coastguard Worker
255*33b1fccfSAndroid Build Coastguard Worker /*
256*33b1fccfSAndroid Build Coastguard Worker * @mergedir: parent directory in the merged tree
257*33b1fccfSAndroid Build Coastguard Worker * @ctx.dir: parent directory when itering erofs_iterate_dir()
258*33b1fccfSAndroid Build Coastguard Worker * @datamode: indicate how to import inode data
259*33b1fccfSAndroid Build Coastguard Worker */
260*33b1fccfSAndroid Build Coastguard Worker struct erofs_rebuild_dir_context {
261*33b1fccfSAndroid Build Coastguard Worker struct erofs_dir_context ctx;
262*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *mergedir;
263*33b1fccfSAndroid Build Coastguard Worker enum erofs_rebuild_datamode datamode;
264*33b1fccfSAndroid Build Coastguard Worker };
265*33b1fccfSAndroid Build Coastguard Worker
erofs_rebuild_dirent_iter(struct erofs_dir_context * ctx)266*33b1fccfSAndroid Build Coastguard Worker static int erofs_rebuild_dirent_iter(struct erofs_dir_context *ctx)
267*33b1fccfSAndroid Build Coastguard Worker {
268*33b1fccfSAndroid Build Coastguard Worker struct erofs_rebuild_dir_context *rctx = (void *)ctx;
269*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *mergedir = rctx->mergedir;
270*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *dir = ctx->dir;
271*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *inode, *candidate;
272*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode src;
273*33b1fccfSAndroid Build Coastguard Worker struct erofs_dentry *d;
274*33b1fccfSAndroid Build Coastguard Worker char *path, *dname;
275*33b1fccfSAndroid Build Coastguard Worker bool dumb;
276*33b1fccfSAndroid Build Coastguard Worker int ret;
277*33b1fccfSAndroid Build Coastguard Worker
278*33b1fccfSAndroid Build Coastguard Worker if (ctx->dot_dotdot)
279*33b1fccfSAndroid Build Coastguard Worker return 0;
280*33b1fccfSAndroid Build Coastguard Worker
281*33b1fccfSAndroid Build Coastguard Worker ret = asprintf(&path, "%s/%.*s", rctx->mergedir->i_srcpath,
282*33b1fccfSAndroid Build Coastguard Worker ctx->de_namelen, ctx->dname);
283*33b1fccfSAndroid Build Coastguard Worker if (ret < 0)
284*33b1fccfSAndroid Build Coastguard Worker return ret;
285*33b1fccfSAndroid Build Coastguard Worker
286*33b1fccfSAndroid Build Coastguard Worker erofs_dbg("parsing %s", path);
287*33b1fccfSAndroid Build Coastguard Worker dname = path + strlen(mergedir->i_srcpath) + 1;
288*33b1fccfSAndroid Build Coastguard Worker
289*33b1fccfSAndroid Build Coastguard Worker d = erofs_rebuild_get_dentry(mergedir, dname, false,
290*33b1fccfSAndroid Build Coastguard Worker &dumb, &dumb, false);
291*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(d)) {
292*33b1fccfSAndroid Build Coastguard Worker ret = PTR_ERR(d);
293*33b1fccfSAndroid Build Coastguard Worker goto out;
294*33b1fccfSAndroid Build Coastguard Worker }
295*33b1fccfSAndroid Build Coastguard Worker
296*33b1fccfSAndroid Build Coastguard Worker ret = 0;
297*33b1fccfSAndroid Build Coastguard Worker if (d->type != EROFS_FT_UNKNOWN) {
298*33b1fccfSAndroid Build Coastguard Worker /*
299*33b1fccfSAndroid Build Coastguard Worker * bail out if the file exists in the upper layers. (Note that
300*33b1fccfSAndroid Build Coastguard Worker * extended attributes won't be merged too even for dirs.)
301*33b1fccfSAndroid Build Coastguard Worker */
302*33b1fccfSAndroid Build Coastguard Worker if (!S_ISDIR(d->inode->i_mode) || d->inode->opaque)
303*33b1fccfSAndroid Build Coastguard Worker goto out;
304*33b1fccfSAndroid Build Coastguard Worker
305*33b1fccfSAndroid Build Coastguard Worker /* merge directory entries */
306*33b1fccfSAndroid Build Coastguard Worker src = (struct erofs_inode) {
307*33b1fccfSAndroid Build Coastguard Worker .sbi = dir->sbi,
308*33b1fccfSAndroid Build Coastguard Worker .nid = ctx->de_nid
309*33b1fccfSAndroid Build Coastguard Worker };
310*33b1fccfSAndroid Build Coastguard Worker ret = erofs_read_inode_from_disk(&src);
311*33b1fccfSAndroid Build Coastguard Worker if (ret || !S_ISDIR(src.i_mode))
312*33b1fccfSAndroid Build Coastguard Worker goto out;
313*33b1fccfSAndroid Build Coastguard Worker mergedir = d->inode;
314*33b1fccfSAndroid Build Coastguard Worker inode = dir = &src;
315*33b1fccfSAndroid Build Coastguard Worker } else {
316*33b1fccfSAndroid Build Coastguard Worker u64 nid;
317*33b1fccfSAndroid Build Coastguard Worker
318*33b1fccfSAndroid Build Coastguard Worker DBG_BUGON(mergedir != d->inode);
319*33b1fccfSAndroid Build Coastguard Worker inode = erofs_new_inode(dir->sbi);
320*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(inode)) {
321*33b1fccfSAndroid Build Coastguard Worker ret = PTR_ERR(inode);
322*33b1fccfSAndroid Build Coastguard Worker goto out;
323*33b1fccfSAndroid Build Coastguard Worker }
324*33b1fccfSAndroid Build Coastguard Worker
325*33b1fccfSAndroid Build Coastguard Worker /* reuse i_ino[0] to read nid in source fs */
326*33b1fccfSAndroid Build Coastguard Worker nid = inode->i_ino[0];
327*33b1fccfSAndroid Build Coastguard Worker inode->sbi = dir->sbi;
328*33b1fccfSAndroid Build Coastguard Worker inode->nid = ctx->de_nid;
329*33b1fccfSAndroid Build Coastguard Worker ret = erofs_read_inode_from_disk(inode);
330*33b1fccfSAndroid Build Coastguard Worker if (ret)
331*33b1fccfSAndroid Build Coastguard Worker goto out;
332*33b1fccfSAndroid Build Coastguard Worker
333*33b1fccfSAndroid Build Coastguard Worker /* restore nid in new generated fs */
334*33b1fccfSAndroid Build Coastguard Worker inode->i_ino[1] = inode->i_ino[0];
335*33b1fccfSAndroid Build Coastguard Worker inode->i_ino[0] = nid;
336*33b1fccfSAndroid Build Coastguard Worker inode->dev = inode->sbi->dev;
337*33b1fccfSAndroid Build Coastguard Worker
338*33b1fccfSAndroid Build Coastguard Worker if (S_ISREG(inode->i_mode) && inode->i_nlink > 1 &&
339*33b1fccfSAndroid Build Coastguard Worker (candidate = erofs_iget(inode->dev, ctx->de_nid))) {
340*33b1fccfSAndroid Build Coastguard Worker /* hardlink file */
341*33b1fccfSAndroid Build Coastguard Worker erofs_iput(inode);
342*33b1fccfSAndroid Build Coastguard Worker inode = candidate;
343*33b1fccfSAndroid Build Coastguard Worker if (S_ISDIR(inode->i_mode)) {
344*33b1fccfSAndroid Build Coastguard Worker erofs_err("hardlink directory not supported");
345*33b1fccfSAndroid Build Coastguard Worker ret = -EISDIR;
346*33b1fccfSAndroid Build Coastguard Worker goto out;
347*33b1fccfSAndroid Build Coastguard Worker }
348*33b1fccfSAndroid Build Coastguard Worker inode->i_nlink++;
349*33b1fccfSAndroid Build Coastguard Worker erofs_dbg("\thardlink: %s -> %s", path, inode->i_srcpath);
350*33b1fccfSAndroid Build Coastguard Worker } else {
351*33b1fccfSAndroid Build Coastguard Worker ret = erofs_read_xattrs_from_disk(inode);
352*33b1fccfSAndroid Build Coastguard Worker if (ret) {
353*33b1fccfSAndroid Build Coastguard Worker erofs_iput(inode);
354*33b1fccfSAndroid Build Coastguard Worker goto out;
355*33b1fccfSAndroid Build Coastguard Worker }
356*33b1fccfSAndroid Build Coastguard Worker
357*33b1fccfSAndroid Build Coastguard Worker inode->i_parent = d->inode;
358*33b1fccfSAndroid Build Coastguard Worker inode->i_srcpath = path;
359*33b1fccfSAndroid Build Coastguard Worker path = NULL;
360*33b1fccfSAndroid Build Coastguard Worker inode->i_ino[1] = inode->nid;
361*33b1fccfSAndroid Build Coastguard Worker inode->i_nlink = 1;
362*33b1fccfSAndroid Build Coastguard Worker
363*33b1fccfSAndroid Build Coastguard Worker ret = erofs_rebuild_update_inode(&g_sbi, inode,
364*33b1fccfSAndroid Build Coastguard Worker rctx->datamode);
365*33b1fccfSAndroid Build Coastguard Worker if (ret) {
366*33b1fccfSAndroid Build Coastguard Worker erofs_iput(inode);
367*33b1fccfSAndroid Build Coastguard Worker goto out;
368*33b1fccfSAndroid Build Coastguard Worker }
369*33b1fccfSAndroid Build Coastguard Worker
370*33b1fccfSAndroid Build Coastguard Worker erofs_insert_ihash(inode);
371*33b1fccfSAndroid Build Coastguard Worker mergedir = dir = inode;
372*33b1fccfSAndroid Build Coastguard Worker }
373*33b1fccfSAndroid Build Coastguard Worker
374*33b1fccfSAndroid Build Coastguard Worker d->inode = inode;
375*33b1fccfSAndroid Build Coastguard Worker d->type = erofs_mode_to_ftype(inode->i_mode);
376*33b1fccfSAndroid Build Coastguard Worker }
377*33b1fccfSAndroid Build Coastguard Worker
378*33b1fccfSAndroid Build Coastguard Worker if (S_ISDIR(inode->i_mode)) {
379*33b1fccfSAndroid Build Coastguard Worker struct erofs_rebuild_dir_context nctx = *rctx;
380*33b1fccfSAndroid Build Coastguard Worker
381*33b1fccfSAndroid Build Coastguard Worker nctx.mergedir = mergedir;
382*33b1fccfSAndroid Build Coastguard Worker nctx.ctx.dir = dir;
383*33b1fccfSAndroid Build Coastguard Worker ret = erofs_iterate_dir(&nctx.ctx, false);
384*33b1fccfSAndroid Build Coastguard Worker if (ret)
385*33b1fccfSAndroid Build Coastguard Worker goto out;
386*33b1fccfSAndroid Build Coastguard Worker }
387*33b1fccfSAndroid Build Coastguard Worker
388*33b1fccfSAndroid Build Coastguard Worker /* reset sbi, nid after subdirs are all loaded for the final dump */
389*33b1fccfSAndroid Build Coastguard Worker inode->sbi = &g_sbi;
390*33b1fccfSAndroid Build Coastguard Worker inode->nid = 0;
391*33b1fccfSAndroid Build Coastguard Worker out:
392*33b1fccfSAndroid Build Coastguard Worker free(path);
393*33b1fccfSAndroid Build Coastguard Worker return ret;
394*33b1fccfSAndroid Build Coastguard Worker }
395*33b1fccfSAndroid Build Coastguard Worker
erofs_rebuild_load_tree(struct erofs_inode * root,struct erofs_sb_info * sbi,enum erofs_rebuild_datamode mode)396*33b1fccfSAndroid Build Coastguard Worker int erofs_rebuild_load_tree(struct erofs_inode *root, struct erofs_sb_info *sbi,
397*33b1fccfSAndroid Build Coastguard Worker enum erofs_rebuild_datamode mode)
398*33b1fccfSAndroid Build Coastguard Worker {
399*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode inode = {};
400*33b1fccfSAndroid Build Coastguard Worker struct erofs_rebuild_dir_context ctx;
401*33b1fccfSAndroid Build Coastguard Worker char uuid_str[37];
402*33b1fccfSAndroid Build Coastguard Worker char *fsid = sbi->devname;
403*33b1fccfSAndroid Build Coastguard Worker int ret;
404*33b1fccfSAndroid Build Coastguard Worker
405*33b1fccfSAndroid Build Coastguard Worker if (!fsid) {
406*33b1fccfSAndroid Build Coastguard Worker erofs_uuid_unparse_lower(sbi->uuid, uuid_str);
407*33b1fccfSAndroid Build Coastguard Worker fsid = uuid_str;
408*33b1fccfSAndroid Build Coastguard Worker }
409*33b1fccfSAndroid Build Coastguard Worker ret = erofs_read_superblock(sbi);
410*33b1fccfSAndroid Build Coastguard Worker if (ret) {
411*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to read superblock of %s", fsid);
412*33b1fccfSAndroid Build Coastguard Worker return ret;
413*33b1fccfSAndroid Build Coastguard Worker }
414*33b1fccfSAndroid Build Coastguard Worker
415*33b1fccfSAndroid Build Coastguard Worker inode.nid = sbi->root_nid;
416*33b1fccfSAndroid Build Coastguard Worker inode.sbi = sbi;
417*33b1fccfSAndroid Build Coastguard Worker ret = erofs_read_inode_from_disk(&inode);
418*33b1fccfSAndroid Build Coastguard Worker if (ret) {
419*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to read root inode of %s", fsid);
420*33b1fccfSAndroid Build Coastguard Worker return ret;
421*33b1fccfSAndroid Build Coastguard Worker }
422*33b1fccfSAndroid Build Coastguard Worker inode.i_srcpath = strdup("/");
423*33b1fccfSAndroid Build Coastguard Worker
424*33b1fccfSAndroid Build Coastguard Worker ctx = (struct erofs_rebuild_dir_context) {
425*33b1fccfSAndroid Build Coastguard Worker .ctx.dir = &inode,
426*33b1fccfSAndroid Build Coastguard Worker .ctx.cb = erofs_rebuild_dirent_iter,
427*33b1fccfSAndroid Build Coastguard Worker .mergedir = root,
428*33b1fccfSAndroid Build Coastguard Worker .datamode = mode,
429*33b1fccfSAndroid Build Coastguard Worker };
430*33b1fccfSAndroid Build Coastguard Worker ret = erofs_iterate_dir(&ctx.ctx, false);
431*33b1fccfSAndroid Build Coastguard Worker free(inode.i_srcpath);
432*33b1fccfSAndroid Build Coastguard Worker return ret;
433*33b1fccfSAndroid Build Coastguard Worker }
434*33b1fccfSAndroid Build Coastguard Worker
erofs_rebuild_basedir_dirent_iter(struct erofs_dir_context * ctx)435*33b1fccfSAndroid Build Coastguard Worker static int erofs_rebuild_basedir_dirent_iter(struct erofs_dir_context *ctx)
436*33b1fccfSAndroid Build Coastguard Worker {
437*33b1fccfSAndroid Build Coastguard Worker struct erofs_rebuild_dir_context *rctx = (void *)ctx;
438*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *dir = ctx->dir;
439*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *mergedir = rctx->mergedir;
440*33b1fccfSAndroid Build Coastguard Worker struct erofs_dentry *d;
441*33b1fccfSAndroid Build Coastguard Worker char *dname;
442*33b1fccfSAndroid Build Coastguard Worker bool dumb;
443*33b1fccfSAndroid Build Coastguard Worker int ret;
444*33b1fccfSAndroid Build Coastguard Worker
445*33b1fccfSAndroid Build Coastguard Worker if (ctx->dot_dotdot)
446*33b1fccfSAndroid Build Coastguard Worker return 0;
447*33b1fccfSAndroid Build Coastguard Worker
448*33b1fccfSAndroid Build Coastguard Worker dname = strndup(ctx->dname, ctx->de_namelen);
449*33b1fccfSAndroid Build Coastguard Worker if (!dname)
450*33b1fccfSAndroid Build Coastguard Worker return -ENOMEM;
451*33b1fccfSAndroid Build Coastguard Worker d = erofs_rebuild_get_dentry(mergedir, dname, false,
452*33b1fccfSAndroid Build Coastguard Worker &dumb, &dumb, false);
453*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(d)) {
454*33b1fccfSAndroid Build Coastguard Worker ret = PTR_ERR(d);
455*33b1fccfSAndroid Build Coastguard Worker goto out;
456*33b1fccfSAndroid Build Coastguard Worker }
457*33b1fccfSAndroid Build Coastguard Worker
458*33b1fccfSAndroid Build Coastguard Worker if (d->type == EROFS_FT_UNKNOWN) {
459*33b1fccfSAndroid Build Coastguard Worker d->nid = ctx->de_nid;
460*33b1fccfSAndroid Build Coastguard Worker d->type = ctx->de_ftype;
461*33b1fccfSAndroid Build Coastguard Worker d->validnid = true;
462*33b1fccfSAndroid Build Coastguard Worker if (!mergedir->whiteouts && erofs_dentry_is_wht(dir->sbi, d))
463*33b1fccfSAndroid Build Coastguard Worker mergedir->whiteouts = true;
464*33b1fccfSAndroid Build Coastguard Worker } else {
465*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *inode = d->inode;
466*33b1fccfSAndroid Build Coastguard Worker
467*33b1fccfSAndroid Build Coastguard Worker /* update sub-directories only for recursively loading */
468*33b1fccfSAndroid Build Coastguard Worker if (S_ISDIR(inode->i_mode)) {
469*33b1fccfSAndroid Build Coastguard Worker list_del(&inode->i_hash);
470*33b1fccfSAndroid Build Coastguard Worker inode->dev = dir->sbi->dev;
471*33b1fccfSAndroid Build Coastguard Worker inode->i_ino[1] = ctx->de_nid;
472*33b1fccfSAndroid Build Coastguard Worker erofs_insert_ihash(inode);
473*33b1fccfSAndroid Build Coastguard Worker }
474*33b1fccfSAndroid Build Coastguard Worker }
475*33b1fccfSAndroid Build Coastguard Worker ret = 0;
476*33b1fccfSAndroid Build Coastguard Worker out:
477*33b1fccfSAndroid Build Coastguard Worker free(dname);
478*33b1fccfSAndroid Build Coastguard Worker return ret;
479*33b1fccfSAndroid Build Coastguard Worker }
480*33b1fccfSAndroid Build Coastguard Worker
erofs_rebuild_load_basedir(struct erofs_inode * dir)481*33b1fccfSAndroid Build Coastguard Worker int erofs_rebuild_load_basedir(struct erofs_inode *dir)
482*33b1fccfSAndroid Build Coastguard Worker {
483*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode fakeinode = {
484*33b1fccfSAndroid Build Coastguard Worker .sbi = dir->sbi,
485*33b1fccfSAndroid Build Coastguard Worker .nid = dir->i_ino[1],
486*33b1fccfSAndroid Build Coastguard Worker };
487*33b1fccfSAndroid Build Coastguard Worker struct erofs_rebuild_dir_context ctx;
488*33b1fccfSAndroid Build Coastguard Worker int ret;
489*33b1fccfSAndroid Build Coastguard Worker
490*33b1fccfSAndroid Build Coastguard Worker ret = erofs_read_inode_from_disk(&fakeinode);
491*33b1fccfSAndroid Build Coastguard Worker if (ret) {
492*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to read inode @ %llu", fakeinode.nid);
493*33b1fccfSAndroid Build Coastguard Worker return ret;
494*33b1fccfSAndroid Build Coastguard Worker }
495*33b1fccfSAndroid Build Coastguard Worker
496*33b1fccfSAndroid Build Coastguard Worker /* Inherit the maximum xattr size for the root directory */
497*33b1fccfSAndroid Build Coastguard Worker if (__erofs_unlikely(IS_ROOT(dir)))
498*33b1fccfSAndroid Build Coastguard Worker dir->xattr_isize = fakeinode.xattr_isize;
499*33b1fccfSAndroid Build Coastguard Worker
500*33b1fccfSAndroid Build Coastguard Worker ctx = (struct erofs_rebuild_dir_context) {
501*33b1fccfSAndroid Build Coastguard Worker .ctx.dir = &fakeinode,
502*33b1fccfSAndroid Build Coastguard Worker .ctx.cb = erofs_rebuild_basedir_dirent_iter,
503*33b1fccfSAndroid Build Coastguard Worker .mergedir = dir,
504*33b1fccfSAndroid Build Coastguard Worker };
505*33b1fccfSAndroid Build Coastguard Worker return erofs_iterate_dir(&ctx.ctx, false);
506*33b1fccfSAndroid Build Coastguard Worker }
507