1*33b1fccfSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2*33b1fccfSAndroid Build Coastguard Worker #include <stdlib.h>
3*33b1fccfSAndroid Build Coastguard Worker #include <sys/stat.h>
4*33b1fccfSAndroid Build Coastguard Worker #include "erofs/print.h"
5*33b1fccfSAndroid Build Coastguard Worker #include "erofs/dir.h"
6*33b1fccfSAndroid Build Coastguard Worker
7*33b1fccfSAndroid Build Coastguard Worker /* filename should not have a '/' in the name string */
erofs_validate_filename(const char * dname,int size)8*33b1fccfSAndroid Build Coastguard Worker static bool erofs_validate_filename(const char *dname, int size)
9*33b1fccfSAndroid Build Coastguard Worker {
10*33b1fccfSAndroid Build Coastguard Worker char *name = (char *)dname;
11*33b1fccfSAndroid Build Coastguard Worker
12*33b1fccfSAndroid Build Coastguard Worker while (name - dname < size && *name != '\0') {
13*33b1fccfSAndroid Build Coastguard Worker if (*name == '/')
14*33b1fccfSAndroid Build Coastguard Worker return false;
15*33b1fccfSAndroid Build Coastguard Worker ++name;
16*33b1fccfSAndroid Build Coastguard Worker }
17*33b1fccfSAndroid Build Coastguard Worker return true;
18*33b1fccfSAndroid Build Coastguard Worker }
19*33b1fccfSAndroid Build Coastguard Worker
traverse_dirents(struct erofs_dir_context * ctx,void * dentry_blk,unsigned int lblk,unsigned int next_nameoff,unsigned int maxsize,bool fsck)20*33b1fccfSAndroid Build Coastguard Worker static int traverse_dirents(struct erofs_dir_context *ctx,
21*33b1fccfSAndroid Build Coastguard Worker void *dentry_blk, unsigned int lblk,
22*33b1fccfSAndroid Build Coastguard Worker unsigned int next_nameoff, unsigned int maxsize,
23*33b1fccfSAndroid Build Coastguard Worker bool fsck)
24*33b1fccfSAndroid Build Coastguard Worker {
25*33b1fccfSAndroid Build Coastguard Worker struct erofs_sb_info *sbi = ctx->dir->sbi;
26*33b1fccfSAndroid Build Coastguard Worker struct erofs_dirent *de = dentry_blk;
27*33b1fccfSAndroid Build Coastguard Worker const struct erofs_dirent *end = dentry_blk + next_nameoff;
28*33b1fccfSAndroid Build Coastguard Worker const char *prev_name = NULL;
29*33b1fccfSAndroid Build Coastguard Worker const char *errmsg;
30*33b1fccfSAndroid Build Coastguard Worker unsigned int prev_namelen = 0;
31*33b1fccfSAndroid Build Coastguard Worker int ret = 0;
32*33b1fccfSAndroid Build Coastguard Worker bool silent = false;
33*33b1fccfSAndroid Build Coastguard Worker
34*33b1fccfSAndroid Build Coastguard Worker while (de < end) {
35*33b1fccfSAndroid Build Coastguard Worker const char *de_name;
36*33b1fccfSAndroid Build Coastguard Worker unsigned int de_namelen;
37*33b1fccfSAndroid Build Coastguard Worker unsigned int nameoff;
38*33b1fccfSAndroid Build Coastguard Worker
39*33b1fccfSAndroid Build Coastguard Worker nameoff = le16_to_cpu(de->nameoff);
40*33b1fccfSAndroid Build Coastguard Worker de_name = (char *)dentry_blk + nameoff;
41*33b1fccfSAndroid Build Coastguard Worker
42*33b1fccfSAndroid Build Coastguard Worker /* the last dirent check */
43*33b1fccfSAndroid Build Coastguard Worker if (de + 1 >= end)
44*33b1fccfSAndroid Build Coastguard Worker de_namelen = strnlen(de_name, maxsize - nameoff);
45*33b1fccfSAndroid Build Coastguard Worker else
46*33b1fccfSAndroid Build Coastguard Worker de_namelen = le16_to_cpu(de[1].nameoff) - nameoff;
47*33b1fccfSAndroid Build Coastguard Worker
48*33b1fccfSAndroid Build Coastguard Worker ctx->de_nid = le64_to_cpu(de->nid);
49*33b1fccfSAndroid Build Coastguard Worker erofs_dbg("traversed nid (%llu)", ctx->de_nid | 0ULL);
50*33b1fccfSAndroid Build Coastguard Worker
51*33b1fccfSAndroid Build Coastguard Worker ret = -EFSCORRUPTED;
52*33b1fccfSAndroid Build Coastguard Worker /* corrupted entry check */
53*33b1fccfSAndroid Build Coastguard Worker if (nameoff != next_nameoff) {
54*33b1fccfSAndroid Build Coastguard Worker errmsg = "bogus dirent nameoff";
55*33b1fccfSAndroid Build Coastguard Worker break;
56*33b1fccfSAndroid Build Coastguard Worker }
57*33b1fccfSAndroid Build Coastguard Worker
58*33b1fccfSAndroid Build Coastguard Worker if (nameoff + de_namelen > maxsize || !de_namelen ||
59*33b1fccfSAndroid Build Coastguard Worker de_namelen > EROFS_NAME_LEN) {
60*33b1fccfSAndroid Build Coastguard Worker errmsg = "bogus dirent namelen";
61*33b1fccfSAndroid Build Coastguard Worker break;
62*33b1fccfSAndroid Build Coastguard Worker }
63*33b1fccfSAndroid Build Coastguard Worker
64*33b1fccfSAndroid Build Coastguard Worker if (fsck && prev_name) {
65*33b1fccfSAndroid Build Coastguard Worker int cmp = strncmp(prev_name, de_name,
66*33b1fccfSAndroid Build Coastguard Worker min(prev_namelen, de_namelen));
67*33b1fccfSAndroid Build Coastguard Worker
68*33b1fccfSAndroid Build Coastguard Worker if (cmp > 0 || (cmp == 0 &&
69*33b1fccfSAndroid Build Coastguard Worker prev_namelen >= de_namelen)) {
70*33b1fccfSAndroid Build Coastguard Worker errmsg = "wrong dirent name order";
71*33b1fccfSAndroid Build Coastguard Worker break;
72*33b1fccfSAndroid Build Coastguard Worker }
73*33b1fccfSAndroid Build Coastguard Worker }
74*33b1fccfSAndroid Build Coastguard Worker
75*33b1fccfSAndroid Build Coastguard Worker if (fsck && de->file_type >= EROFS_FT_MAX) {
76*33b1fccfSAndroid Build Coastguard Worker errmsg = "invalid file type %u";
77*33b1fccfSAndroid Build Coastguard Worker break;
78*33b1fccfSAndroid Build Coastguard Worker }
79*33b1fccfSAndroid Build Coastguard Worker
80*33b1fccfSAndroid Build Coastguard Worker ctx->dname = de_name;
81*33b1fccfSAndroid Build Coastguard Worker ctx->de_namelen = de_namelen;
82*33b1fccfSAndroid Build Coastguard Worker ctx->de_ftype = de->file_type;
83*33b1fccfSAndroid Build Coastguard Worker ctx->dot_dotdot = is_dot_dotdot_len(de_name, de_namelen);
84*33b1fccfSAndroid Build Coastguard Worker if (ctx->dot_dotdot) {
85*33b1fccfSAndroid Build Coastguard Worker switch (de_namelen) {
86*33b1fccfSAndroid Build Coastguard Worker case 2:
87*33b1fccfSAndroid Build Coastguard Worker if (fsck &&
88*33b1fccfSAndroid Build Coastguard Worker (ctx->flags & EROFS_READDIR_DOTDOT_FOUND)) {
89*33b1fccfSAndroid Build Coastguard Worker errmsg = "duplicated `..' dirent";
90*33b1fccfSAndroid Build Coastguard Worker goto out;
91*33b1fccfSAndroid Build Coastguard Worker }
92*33b1fccfSAndroid Build Coastguard Worker ctx->flags |= EROFS_READDIR_DOTDOT_FOUND;
93*33b1fccfSAndroid Build Coastguard Worker if (sbi->root_nid == ctx->dir->nid) {
94*33b1fccfSAndroid Build Coastguard Worker ctx->pnid = sbi->root_nid;
95*33b1fccfSAndroid Build Coastguard Worker ctx->flags |= EROFS_READDIR_VALID_PNID;
96*33b1fccfSAndroid Build Coastguard Worker }
97*33b1fccfSAndroid Build Coastguard Worker if (fsck &&
98*33b1fccfSAndroid Build Coastguard Worker (ctx->flags & EROFS_READDIR_VALID_PNID) &&
99*33b1fccfSAndroid Build Coastguard Worker ctx->de_nid != ctx->pnid) {
100*33b1fccfSAndroid Build Coastguard Worker errmsg = "corrupted `..' dirent";
101*33b1fccfSAndroid Build Coastguard Worker goto out;
102*33b1fccfSAndroid Build Coastguard Worker }
103*33b1fccfSAndroid Build Coastguard Worker break;
104*33b1fccfSAndroid Build Coastguard Worker case 1:
105*33b1fccfSAndroid Build Coastguard Worker if (fsck &&
106*33b1fccfSAndroid Build Coastguard Worker (ctx->flags & EROFS_READDIR_DOT_FOUND)) {
107*33b1fccfSAndroid Build Coastguard Worker errmsg = "duplicated `.' dirent";
108*33b1fccfSAndroid Build Coastguard Worker goto out;
109*33b1fccfSAndroid Build Coastguard Worker }
110*33b1fccfSAndroid Build Coastguard Worker
111*33b1fccfSAndroid Build Coastguard Worker ctx->flags |= EROFS_READDIR_DOT_FOUND;
112*33b1fccfSAndroid Build Coastguard Worker if (fsck && ctx->de_nid != ctx->dir->nid) {
113*33b1fccfSAndroid Build Coastguard Worker errmsg = "corrupted `.' dirent";
114*33b1fccfSAndroid Build Coastguard Worker goto out;
115*33b1fccfSAndroid Build Coastguard Worker }
116*33b1fccfSAndroid Build Coastguard Worker break;
117*33b1fccfSAndroid Build Coastguard Worker }
118*33b1fccfSAndroid Build Coastguard Worker } else if (fsck &&
119*33b1fccfSAndroid Build Coastguard Worker !erofs_validate_filename(de_name, de_namelen)) {
120*33b1fccfSAndroid Build Coastguard Worker errmsg = "corrupted dirent with illegal filename";
121*33b1fccfSAndroid Build Coastguard Worker goto out;
122*33b1fccfSAndroid Build Coastguard Worker }
123*33b1fccfSAndroid Build Coastguard Worker ret = ctx->cb(ctx);
124*33b1fccfSAndroid Build Coastguard Worker if (ret) {
125*33b1fccfSAndroid Build Coastguard Worker silent = true;
126*33b1fccfSAndroid Build Coastguard Worker break;
127*33b1fccfSAndroid Build Coastguard Worker }
128*33b1fccfSAndroid Build Coastguard Worker prev_name = de_name;
129*33b1fccfSAndroid Build Coastguard Worker prev_namelen = de_namelen;
130*33b1fccfSAndroid Build Coastguard Worker next_nameoff += de_namelen;
131*33b1fccfSAndroid Build Coastguard Worker ++de;
132*33b1fccfSAndroid Build Coastguard Worker }
133*33b1fccfSAndroid Build Coastguard Worker out:
134*33b1fccfSAndroid Build Coastguard Worker if (ret && !silent)
135*33b1fccfSAndroid Build Coastguard Worker erofs_err("%s @ nid %llu, lblk %u, index %lu",
136*33b1fccfSAndroid Build Coastguard Worker errmsg, ctx->dir->nid | 0ULL, lblk,
137*33b1fccfSAndroid Build Coastguard Worker (de - (struct erofs_dirent *)dentry_blk) | 0UL);
138*33b1fccfSAndroid Build Coastguard Worker return ret;
139*33b1fccfSAndroid Build Coastguard Worker }
140*33b1fccfSAndroid Build Coastguard Worker
erofs_iterate_dir(struct erofs_dir_context * ctx,bool fsck)141*33b1fccfSAndroid Build Coastguard Worker int erofs_iterate_dir(struct erofs_dir_context *ctx, bool fsck)
142*33b1fccfSAndroid Build Coastguard Worker {
143*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *dir = ctx->dir;
144*33b1fccfSAndroid Build Coastguard Worker struct erofs_sb_info *sbi = dir->sbi;
145*33b1fccfSAndroid Build Coastguard Worker int err = 0;
146*33b1fccfSAndroid Build Coastguard Worker erofs_off_t pos;
147*33b1fccfSAndroid Build Coastguard Worker char buf[EROFS_MAX_BLOCK_SIZE];
148*33b1fccfSAndroid Build Coastguard Worker
149*33b1fccfSAndroid Build Coastguard Worker if (!S_ISDIR(dir->i_mode))
150*33b1fccfSAndroid Build Coastguard Worker return -ENOTDIR;
151*33b1fccfSAndroid Build Coastguard Worker
152*33b1fccfSAndroid Build Coastguard Worker ctx->flags &= ~EROFS_READDIR_ALL_SPECIAL_FOUND;
153*33b1fccfSAndroid Build Coastguard Worker pos = 0;
154*33b1fccfSAndroid Build Coastguard Worker while (pos < dir->i_size) {
155*33b1fccfSAndroid Build Coastguard Worker erofs_blk_t lblk = erofs_blknr(sbi, pos);
156*33b1fccfSAndroid Build Coastguard Worker erofs_off_t maxsize = min_t(erofs_off_t,
157*33b1fccfSAndroid Build Coastguard Worker dir->i_size - pos, erofs_blksiz(sbi));
158*33b1fccfSAndroid Build Coastguard Worker const struct erofs_dirent *de = (const void *)buf;
159*33b1fccfSAndroid Build Coastguard Worker unsigned int nameoff;
160*33b1fccfSAndroid Build Coastguard Worker
161*33b1fccfSAndroid Build Coastguard Worker err = erofs_pread(dir, buf, maxsize, pos);
162*33b1fccfSAndroid Build Coastguard Worker if (err) {
163*33b1fccfSAndroid Build Coastguard Worker erofs_err("I/O error occurred when reading dirents @ nid %llu, lblk %u: %d",
164*33b1fccfSAndroid Build Coastguard Worker dir->nid | 0ULL, lblk, err);
165*33b1fccfSAndroid Build Coastguard Worker return err;
166*33b1fccfSAndroid Build Coastguard Worker }
167*33b1fccfSAndroid Build Coastguard Worker
168*33b1fccfSAndroid Build Coastguard Worker nameoff = le16_to_cpu(de->nameoff);
169*33b1fccfSAndroid Build Coastguard Worker if (nameoff < sizeof(struct erofs_dirent) ||
170*33b1fccfSAndroid Build Coastguard Worker nameoff >= erofs_blksiz(sbi)) {
171*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid de[0].nameoff %u @ nid %llu, lblk %u",
172*33b1fccfSAndroid Build Coastguard Worker nameoff, dir->nid | 0ULL, lblk);
173*33b1fccfSAndroid Build Coastguard Worker return -EFSCORRUPTED;
174*33b1fccfSAndroid Build Coastguard Worker }
175*33b1fccfSAndroid Build Coastguard Worker err = traverse_dirents(ctx, buf, lblk, nameoff, maxsize, fsck);
176*33b1fccfSAndroid Build Coastguard Worker if (err)
177*33b1fccfSAndroid Build Coastguard Worker break;
178*33b1fccfSAndroid Build Coastguard Worker pos += maxsize;
179*33b1fccfSAndroid Build Coastguard Worker }
180*33b1fccfSAndroid Build Coastguard Worker
181*33b1fccfSAndroid Build Coastguard Worker if (fsck && (ctx->flags & EROFS_READDIR_ALL_SPECIAL_FOUND) !=
182*33b1fccfSAndroid Build Coastguard Worker EROFS_READDIR_ALL_SPECIAL_FOUND) {
183*33b1fccfSAndroid Build Coastguard Worker erofs_err("`.' or `..' dirent is missing @ nid %llu",
184*33b1fccfSAndroid Build Coastguard Worker dir->nid | 0ULL);
185*33b1fccfSAndroid Build Coastguard Worker return -EFSCORRUPTED;
186*33b1fccfSAndroid Build Coastguard Worker }
187*33b1fccfSAndroid Build Coastguard Worker return err;
188*33b1fccfSAndroid Build Coastguard Worker }
189*33b1fccfSAndroid Build Coastguard Worker
190*33b1fccfSAndroid Build Coastguard Worker #define EROFS_PATHNAME_FOUND 1
191*33b1fccfSAndroid Build Coastguard Worker
192*33b1fccfSAndroid Build Coastguard Worker struct erofs_get_pathname_context {
193*33b1fccfSAndroid Build Coastguard Worker struct erofs_dir_context ctx;
194*33b1fccfSAndroid Build Coastguard Worker erofs_nid_t target_nid;
195*33b1fccfSAndroid Build Coastguard Worker char *buf;
196*33b1fccfSAndroid Build Coastguard Worker size_t size;
197*33b1fccfSAndroid Build Coastguard Worker size_t pos;
198*33b1fccfSAndroid Build Coastguard Worker };
199*33b1fccfSAndroid Build Coastguard Worker
erofs_get_pathname_iter(struct erofs_dir_context * ctx)200*33b1fccfSAndroid Build Coastguard Worker static int erofs_get_pathname_iter(struct erofs_dir_context *ctx)
201*33b1fccfSAndroid Build Coastguard Worker {
202*33b1fccfSAndroid Build Coastguard Worker int ret;
203*33b1fccfSAndroid Build Coastguard Worker struct erofs_get_pathname_context *pathctx = (void *)ctx;
204*33b1fccfSAndroid Build Coastguard Worker const char *dname = ctx->dname;
205*33b1fccfSAndroid Build Coastguard Worker size_t len = ctx->de_namelen;
206*33b1fccfSAndroid Build Coastguard Worker size_t pos = pathctx->pos;
207*33b1fccfSAndroid Build Coastguard Worker
208*33b1fccfSAndroid Build Coastguard Worker if (ctx->dot_dotdot)
209*33b1fccfSAndroid Build Coastguard Worker return 0;
210*33b1fccfSAndroid Build Coastguard Worker
211*33b1fccfSAndroid Build Coastguard Worker if (ctx->de_nid == pathctx->target_nid) {
212*33b1fccfSAndroid Build Coastguard Worker if (pos + len + 2 > pathctx->size) {
213*33b1fccfSAndroid Build Coastguard Worker erofs_err("get_pathname buffer not large enough: len %zd, size %zd",
214*33b1fccfSAndroid Build Coastguard Worker pos + len + 2, pathctx->size);
215*33b1fccfSAndroid Build Coastguard Worker return -ERANGE;
216*33b1fccfSAndroid Build Coastguard Worker }
217*33b1fccfSAndroid Build Coastguard Worker
218*33b1fccfSAndroid Build Coastguard Worker pathctx->buf[pos++] = '/';
219*33b1fccfSAndroid Build Coastguard Worker strncpy(pathctx->buf + pos, dname, len);
220*33b1fccfSAndroid Build Coastguard Worker pathctx->buf[pos + len] = '\0';
221*33b1fccfSAndroid Build Coastguard Worker return EROFS_PATHNAME_FOUND;
222*33b1fccfSAndroid Build Coastguard Worker }
223*33b1fccfSAndroid Build Coastguard Worker
224*33b1fccfSAndroid Build Coastguard Worker if (ctx->de_ftype == EROFS_FT_DIR || ctx->de_ftype == EROFS_FT_UNKNOWN) {
225*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode dir = {
226*33b1fccfSAndroid Build Coastguard Worker .sbi = ctx->dir->sbi,
227*33b1fccfSAndroid Build Coastguard Worker .nid = ctx->de_nid
228*33b1fccfSAndroid Build Coastguard Worker };
229*33b1fccfSAndroid Build Coastguard Worker
230*33b1fccfSAndroid Build Coastguard Worker ret = erofs_read_inode_from_disk(&dir);
231*33b1fccfSAndroid Build Coastguard Worker if (ret) {
232*33b1fccfSAndroid Build Coastguard Worker erofs_err("read inode failed @ nid %llu", dir.nid | 0ULL);
233*33b1fccfSAndroid Build Coastguard Worker return ret;
234*33b1fccfSAndroid Build Coastguard Worker }
235*33b1fccfSAndroid Build Coastguard Worker
236*33b1fccfSAndroid Build Coastguard Worker if (S_ISDIR(dir.i_mode)) {
237*33b1fccfSAndroid Build Coastguard Worker struct erofs_get_pathname_context nctx = {
238*33b1fccfSAndroid Build Coastguard Worker .ctx.flags = 0,
239*33b1fccfSAndroid Build Coastguard Worker .ctx.dir = &dir,
240*33b1fccfSAndroid Build Coastguard Worker .ctx.cb = erofs_get_pathname_iter,
241*33b1fccfSAndroid Build Coastguard Worker .target_nid = pathctx->target_nid,
242*33b1fccfSAndroid Build Coastguard Worker .buf = pathctx->buf,
243*33b1fccfSAndroid Build Coastguard Worker .size = pathctx->size,
244*33b1fccfSAndroid Build Coastguard Worker .pos = pos + len + 1,
245*33b1fccfSAndroid Build Coastguard Worker };
246*33b1fccfSAndroid Build Coastguard Worker ret = erofs_iterate_dir(&nctx.ctx, false);
247*33b1fccfSAndroid Build Coastguard Worker if (ret == EROFS_PATHNAME_FOUND) {
248*33b1fccfSAndroid Build Coastguard Worker pathctx->buf[pos++] = '/';
249*33b1fccfSAndroid Build Coastguard Worker strncpy(pathctx->buf + pos, dname, len);
250*33b1fccfSAndroid Build Coastguard Worker }
251*33b1fccfSAndroid Build Coastguard Worker return ret;
252*33b1fccfSAndroid Build Coastguard Worker } else if (ctx->de_ftype == EROFS_FT_DIR) {
253*33b1fccfSAndroid Build Coastguard Worker erofs_err("i_mode and file_type are inconsistent @ nid %llu",
254*33b1fccfSAndroid Build Coastguard Worker dir.nid | 0ULL);
255*33b1fccfSAndroid Build Coastguard Worker }
256*33b1fccfSAndroid Build Coastguard Worker }
257*33b1fccfSAndroid Build Coastguard Worker return 0;
258*33b1fccfSAndroid Build Coastguard Worker }
259*33b1fccfSAndroid Build Coastguard Worker
erofs_get_pathname(struct erofs_sb_info * sbi,erofs_nid_t nid,char * buf,size_t size)260*33b1fccfSAndroid Build Coastguard Worker int erofs_get_pathname(struct erofs_sb_info *sbi, erofs_nid_t nid,
261*33b1fccfSAndroid Build Coastguard Worker char *buf, size_t size)
262*33b1fccfSAndroid Build Coastguard Worker {
263*33b1fccfSAndroid Build Coastguard Worker int ret;
264*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode root = {
265*33b1fccfSAndroid Build Coastguard Worker .sbi = sbi,
266*33b1fccfSAndroid Build Coastguard Worker .nid = sbi->root_nid,
267*33b1fccfSAndroid Build Coastguard Worker };
268*33b1fccfSAndroid Build Coastguard Worker struct erofs_get_pathname_context pathctx = {
269*33b1fccfSAndroid Build Coastguard Worker .ctx.flags = 0,
270*33b1fccfSAndroid Build Coastguard Worker .ctx.dir = &root,
271*33b1fccfSAndroid Build Coastguard Worker .ctx.cb = erofs_get_pathname_iter,
272*33b1fccfSAndroid Build Coastguard Worker .target_nid = nid,
273*33b1fccfSAndroid Build Coastguard Worker .buf = buf,
274*33b1fccfSAndroid Build Coastguard Worker .size = size,
275*33b1fccfSAndroid Build Coastguard Worker .pos = 0,
276*33b1fccfSAndroid Build Coastguard Worker };
277*33b1fccfSAndroid Build Coastguard Worker
278*33b1fccfSAndroid Build Coastguard Worker if (nid == root.nid) {
279*33b1fccfSAndroid Build Coastguard Worker if (size < 2) {
280*33b1fccfSAndroid Build Coastguard Worker erofs_err("get_pathname buffer not large enough: len 2, size %zd",
281*33b1fccfSAndroid Build Coastguard Worker size);
282*33b1fccfSAndroid Build Coastguard Worker return -ERANGE;
283*33b1fccfSAndroid Build Coastguard Worker }
284*33b1fccfSAndroid Build Coastguard Worker
285*33b1fccfSAndroid Build Coastguard Worker buf[0] = '/';
286*33b1fccfSAndroid Build Coastguard Worker buf[1] = '\0';
287*33b1fccfSAndroid Build Coastguard Worker return 0;
288*33b1fccfSAndroid Build Coastguard Worker }
289*33b1fccfSAndroid Build Coastguard Worker
290*33b1fccfSAndroid Build Coastguard Worker ret = erofs_read_inode_from_disk(&root);
291*33b1fccfSAndroid Build Coastguard Worker if (ret) {
292*33b1fccfSAndroid Build Coastguard Worker erofs_err("read inode failed @ nid %llu", root.nid | 0ULL);
293*33b1fccfSAndroid Build Coastguard Worker return ret;
294*33b1fccfSAndroid Build Coastguard Worker }
295*33b1fccfSAndroid Build Coastguard Worker
296*33b1fccfSAndroid Build Coastguard Worker ret = erofs_iterate_dir(&pathctx.ctx, false);
297*33b1fccfSAndroid Build Coastguard Worker if (ret == EROFS_PATHNAME_FOUND)
298*33b1fccfSAndroid Build Coastguard Worker return 0;
299*33b1fccfSAndroid Build Coastguard Worker if (!ret)
300*33b1fccfSAndroid Build Coastguard Worker return -ENOENT;
301*33b1fccfSAndroid Build Coastguard Worker return ret;
302*33b1fccfSAndroid Build Coastguard Worker }
303