1 // SPDX-License-Identifier: GPL-2.0+
4 #define makedev(major, minor) ((dev_t)((((major) & 0xfff) << 8) | ((minor) & 0xff)))
5 static dev_t
erofs_new_decode_dev(u32 dev
)
7 const unsigned int major
= (dev
& 0xfff00) >> 8;
8 const unsigned int minor
= (dev
& 0xff) | ((dev
>> 12) & 0xfff00);
10 return makedev(major
, minor
);
13 int erofs_read_inode_from_disk(struct erofs_inode
*vi
)
16 char buf
[sizeof(struct erofs_inode_extended
)];
17 struct erofs_inode_compact
*dic
;
18 struct erofs_inode_extended
*die
;
19 const erofs_off_t inode_loc
= iloc(vi
->nid
);
21 ret
= erofs_dev_read(0, buf
, inode_loc
, sizeof(*dic
));
25 dic
= (struct erofs_inode_compact
*)buf
;
26 ifmt
= le16_to_cpu(dic
->i_format
);
28 vi
->datalayout
= erofs_inode_datalayout(ifmt
);
29 if (vi
->datalayout
>= EROFS_INODE_DATALAYOUT_MAX
) {
30 erofs_err("unsupported datalayout %u of nid %llu",
31 vi
->datalayout
, vi
->nid
| 0ULL);
34 switch (erofs_inode_version(ifmt
)) {
35 case EROFS_INODE_LAYOUT_EXTENDED
:
36 vi
->inode_isize
= sizeof(struct erofs_inode_extended
);
38 ret
= erofs_dev_read(0, buf
+ sizeof(*dic
),
39 inode_loc
+ sizeof(*dic
),
40 sizeof(*die
) - sizeof(*dic
));
44 die
= (struct erofs_inode_extended
*)buf
;
45 vi
->xattr_isize
= erofs_xattr_ibody_size(die
->i_xattr_icount
);
46 vi
->i_mode
= le16_to_cpu(die
->i_mode
);
48 switch (vi
->i_mode
& S_IFMT
) {
52 vi
->u
.i_blkaddr
= le32_to_cpu(die
->i_u
.raw_blkaddr
);
57 erofs_new_decode_dev(le32_to_cpu(die
->i_u
.rdev
));
67 vi
->i_uid
= le32_to_cpu(die
->i_uid
);
68 vi
->i_gid
= le32_to_cpu(die
->i_gid
);
69 vi
->i_nlink
= le32_to_cpu(die
->i_nlink
);
71 vi
->i_mtime
= le64_to_cpu(die
->i_mtime
);
72 vi
->i_mtime_nsec
= le64_to_cpu(die
->i_mtime_nsec
);
73 vi
->i_size
= le64_to_cpu(die
->i_size
);
74 if (vi
->datalayout
== EROFS_INODE_CHUNK_BASED
)
75 /* fill chunked inode summary info */
76 vi
->u
.chunkformat
= le16_to_cpu(die
->i_u
.c
.format
);
78 case EROFS_INODE_LAYOUT_COMPACT
:
79 vi
->inode_isize
= sizeof(struct erofs_inode_compact
);
80 vi
->xattr_isize
= erofs_xattr_ibody_size(dic
->i_xattr_icount
);
81 vi
->i_mode
= le16_to_cpu(dic
->i_mode
);
83 switch (vi
->i_mode
& S_IFMT
) {
87 vi
->u
.i_blkaddr
= le32_to_cpu(dic
->i_u
.raw_blkaddr
);
92 erofs_new_decode_dev(le32_to_cpu(dic
->i_u
.rdev
));
102 vi
->i_uid
= le16_to_cpu(dic
->i_uid
);
103 vi
->i_gid
= le16_to_cpu(dic
->i_gid
);
104 vi
->i_nlink
= le16_to_cpu(dic
->i_nlink
);
106 vi
->i_mtime
= sbi
.build_time
;
107 vi
->i_mtime_nsec
= sbi
.build_time_nsec
;
109 vi
->i_size
= le32_to_cpu(dic
->i_size
);
110 if (vi
->datalayout
== EROFS_INODE_CHUNK_BASED
)
111 vi
->u
.chunkformat
= le16_to_cpu(dic
->i_u
.c
.format
);
114 erofs_err("unsupported on-disk inode version %u of nid %llu",
115 erofs_inode_version(ifmt
), vi
->nid
| 0ULL);
120 if (vi
->datalayout
== EROFS_INODE_CHUNK_BASED
) {
121 if (vi
->u
.chunkformat
& ~EROFS_CHUNK_FORMAT_ALL
) {
122 erofs_err("unsupported chunk format %x of nid %llu",
123 vi
->u
.chunkformat
, vi
->nid
| 0ULL);
126 vi
->u
.chunkbits
= sbi
.blkszbits
+
127 (vi
->u
.chunkformat
& EROFS_CHUNK_FORMAT_BLKBITS_MASK
);
128 } else if (erofs_inode_is_data_compressed(vi
->datalayout
)) {
129 if (erofs_blksiz() != EROFS_MAX_BLOCK_SIZE
)
131 return z_erofs_fill_inode(vi
);
135 erofs_err("bogus i_mode (%o) @ nid %llu", vi
->i_mode
, vi
->nid
| 0ULL);
136 return -EFSCORRUPTED
;
139 struct erofs_dirent
*find_target_dirent(erofs_nid_t pnid
,
141 const char *name
, unsigned int len
,
142 unsigned int nameoff
,
143 unsigned int maxsize
)
145 struct erofs_dirent
*de
= dentry_blk
;
146 const struct erofs_dirent
*end
= dentry_blk
+ nameoff
;
150 unsigned int de_namelen
;
152 nameoff
= le16_to_cpu(de
->nameoff
);
153 de_name
= (char *)dentry_blk
+ nameoff
;
155 /* the last dirent in the block? */
157 de_namelen
= strnlen(de_name
, maxsize
- nameoff
);
159 de_namelen
= le16_to_cpu(de
[1].nameoff
) - nameoff
;
161 /* a corrupted entry is found */
162 if (nameoff
+ de_namelen
> maxsize
||
163 de_namelen
> EROFS_NAME_LEN
) {
164 erofs_err("bogus dirent @ nid %llu", pnid
| 0ULL);
166 return ERR_PTR(-EFSCORRUPTED
);
169 if (len
== de_namelen
&& !memcmp(de_name
, name
, de_namelen
))
181 int erofs_namei(struct nameidata
*nd
, const char *name
, unsigned int len
)
183 erofs_nid_t nid
= nd
->nid
;
185 char buf
[EROFS_MAX_BLOCK_SIZE
];
186 struct erofs_inode vi
= { .nid
= nid
};
189 ret
= erofs_read_inode_from_disk(&vi
);
194 while (offset
< vi
.i_size
) {
195 erofs_off_t maxsize
= min_t(erofs_off_t
,
196 vi
.i_size
- offset
, erofs_blksiz());
197 struct erofs_dirent
*de
= (void *)buf
;
198 unsigned int nameoff
;
200 ret
= erofs_pread(&vi
, buf
, maxsize
, offset
);
204 nameoff
= le16_to_cpu(de
->nameoff
);
205 if (nameoff
< sizeof(struct erofs_dirent
) ||
206 nameoff
>= erofs_blksiz()) {
207 erofs_err("invalid de[0].nameoff %u @ nid %llu",
208 nameoff
, nid
| 0ULL);
209 return -EFSCORRUPTED
;
212 de
= find_target_dirent(nid
, buf
, name
, len
,
218 nd
->nid
= le64_to_cpu(de
->nid
);
226 static int link_path_walk(const char *name
, struct nameidata
*nd
)
228 nd
->nid
= sbi
.root_nid
;
233 /* At this point we know we have a real path component. */
234 while (*name
!= '\0') {
235 const char *p
= name
;
240 } while (*p
!= '\0' && *p
!= '/');
242 DBG_BUGON(p
<= name
);
243 ret
= erofs_namei(nd
, name
, p
- name
);
248 /* Skip until no more slashes. */
249 for (name
= p
; *name
== '/'; ++name
)
255 int erofs_ilookup(const char *path
, struct erofs_inode
*vi
)
260 ret
= link_path_walk(path
, &nd
);
265 return erofs_read_inode_from_disk(vi
);