2 * Copyright (c) 2012-2013 Paulo Alcantara <pcacjr@zytor.com>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write the Free Software Foundation,
15 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "xfs_types.h"
27 #include "xfs_dinode.h"
30 #include "xfs_readdir.h"
32 static int fill_dirent(struct fs_info
*fs
, struct dirent
*dirent
,
33 uint32_t offset
, xfs_ino_t ino
, char *name
,
38 xfs_debug("fs %p, dirent %p offset %lu ino %llu name %s namelen %llu", fs
,
39 dirent
, offset
, ino
, name
, namelen
);
42 dirent
->d_off
= offset
;
43 dirent
->d_reclen
= offsetof(struct dirent
, d_name
) + namelen
+ 1;
45 core
= xfs_dinode_get_core(fs
, ino
);
47 xfs_error("Failed to get dinode from disk (ino 0x%llx)", ino
);
51 if (be16_to_cpu(core
->di_mode
) & S_IFDIR
)
52 dirent
->d_type
= DT_DIR
;
53 else if (be16_to_cpu(core
->di_mode
) & S_IFREG
)
54 dirent
->d_type
= DT_REG
;
55 else if (be16_to_cpu(core
->di_mode
) & S_IFLNK
)
56 dirent
->d_type
= DT_LNK
;
58 memcpy(dirent
->d_name
, name
, namelen
);
59 dirent
->d_name
[namelen
] = '\0';
64 int xfs_readdir_dir2_local(struct file
*file
, struct dirent
*dirent
,
67 xfs_dir2_sf_t
*sf
= (xfs_dir2_sf_t
*)&core
->di_literal_area
[0];
68 xfs_dir2_sf_entry_t
*sf_entry
;
69 uint8_t count
= sf
->hdr
.i8count
? sf
->hdr
.i8count
: sf
->hdr
.count
;
70 uint32_t offset
= file
->offset
;
74 struct fs_info
*fs
= file
->fs
;
77 xfs_debug("file %p dirent %p core %p", file
, dirent
, core
);
78 xfs_debug("count %hhu i8count %hhu", sf
->hdr
.count
, sf
->hdr
.i8count
);
80 if (file
->offset
+ 1 > count
)
85 sf_entry
= (xfs_dir2_sf_entry_t
*)((uint8_t *)&sf
->list
[0] -
86 (!sf
->hdr
.i8count
? 4 : 0));
88 if (file
->offset
- 1) {
89 offset
= file
->offset
;
91 sf_entry
= (xfs_dir2_sf_entry_t
*)(
93 offsetof(struct xfs_dir2_sf_entry
,
96 (sf
->hdr
.i8count
? 8 : 4));
100 start_name
= &sf_entry
->name
[0];
101 end_name
= start_name
+ sf_entry
->namelen
;
103 ino
= xfs_dir2_sf_get_inumber(sf
, (xfs_dir2_inou_t
*)(
104 (uint8_t *)sf_entry
+
105 offsetof(struct xfs_dir2_sf_entry
,
109 retval
= fill_dirent(fs
, dirent
, file
->offset
, ino
, (char *)start_name
,
110 end_name
- start_name
);
112 xfs_error("Failed to fill in dirent structure");
117 xfs_dir2_dirblks_flush_cache();
122 int xfs_readdir_dir2_block(struct file
*file
, struct dirent
*dirent
,
127 struct fs_info
*fs
= file
->fs
;
128 const uint8_t *dirblk_buf
;
131 xfs_dir2_data_hdr_t
*hdr
;
132 xfs_dir2_block_tail_t
*btp
;
133 xfs_dir2_data_unused_t
*dup
;
134 xfs_dir2_data_entry_t
*dep
;
140 xfs_debug("file %p dirent %p core %p", file
, dirent
, core
);
142 bmbt_irec_get(&r
, (xfs_bmbt_rec_t
*)&core
->di_literal_area
[0]);
143 dir_blk
= fsblock_to_bytes(fs
, r
.br_startblock
) >> BLOCK_SHIFT(fs
);
145 dirblk_buf
= xfs_dir2_dirblks_get_cached(fs
, dir_blk
, r
.br_blockcount
);
146 hdr
= (xfs_dir2_data_hdr_t
*)dirblk_buf
;
147 if (be32_to_cpu(hdr
->magic
) != XFS_DIR2_BLOCK_MAGIC
) {
148 xfs_error("Block directory header's magic number does not match!");
149 xfs_debug("hdr->magic: 0x%lx", be32_to_cpu(hdr
->magic
));
153 btp
= xfs_dir2_block_tail_p(XFS_INFO(fs
), hdr
);
155 if (file
->offset
+ 1 > be32_to_cpu(btp
->count
))
160 p
= (uint8_t *)(hdr
+ 1);
162 if (file
->offset
- 1) {
163 offset
= file
->offset
;
165 dep
= (xfs_dir2_data_entry_t
*)p
;
167 dup
= (xfs_dir2_data_unused_t
*)p
;
168 if (be16_to_cpu(dup
->freetag
) == XFS_DIR2_DATA_FREE_TAG
) {
169 p
+= be16_to_cpu(dup
->length
);
173 p
+= xfs_dir2_data_entsize(dep
->namelen
);
177 dep
= (xfs_dir2_data_entry_t
*)p
;
179 start_name
= &dep
->name
[0];
180 end_name
= start_name
+ dep
->namelen
;
182 ino
= be64_to_cpu(dep
->inumber
);
184 retval
= fill_dirent(fs
, dirent
, file
->offset
, ino
, (char *)start_name
,
185 end_name
- start_name
);
187 xfs_error("Failed to fill in dirent structure");
192 xfs_dir2_dirblks_flush_cache();
197 int xfs_readdir_dir2_leaf(struct file
*file
, struct dirent
*dirent
,
200 xfs_bmbt_irec_t irec
;
201 struct fs_info
*fs
= file
->fs
;
202 xfs_dir2_leaf_t
*leaf
;
203 block_t leaf_blk
, dir_blk
;
204 xfs_dir2_leaf_entry_t
*lep
;
207 xfs_dir2_data_entry_t
*dep
;
208 xfs_dir2_data_hdr_t
*data_hdr
;
212 const uint8_t *buf
= NULL
;
215 xfs_debug("file %p dirent %p core %p", file
, dirent
, core
);
217 bmbt_irec_get(&irec
, ((xfs_bmbt_rec_t
*)&core
->di_literal_area
[0]) +
218 be32_to_cpu(core
->di_nextents
) - 1);
219 leaf_blk
= fsblock_to_bytes(fs
, irec
.br_startblock
) >>
220 BLOCK_SHIFT(file
->fs
);
222 leaf
= (xfs_dir2_leaf_t
*)xfs_dir2_dirblks_get_cached(fs
, leaf_blk
,
224 if (be16_to_cpu(leaf
->hdr
.info
.magic
) != XFS_DIR2_LEAF1_MAGIC
) {
225 xfs_error("Single leaf block header's magic number does not match!");
229 if (!leaf
->hdr
.count
)
232 if (file
->offset
+ 1 > be16_to_cpu(leaf
->hdr
.count
))
235 lep
= &leaf
->ents
[file
->offset
++];
237 /* Skip over stale leaf entries */
238 for ( ; be32_to_cpu(lep
->address
) == XFS_DIR2_NULL_DATAPTR
;
239 lep
++, file
->offset
++);
241 db
= xfs_dir2_dataptr_to_db(fs
, be32_to_cpu(lep
->address
));
243 bmbt_irec_get(&irec
, (xfs_bmbt_rec_t
*)&core
->di_literal_area
[0] + db
);
245 dir_blk
= fsblock_to_bytes(fs
, irec
.br_startblock
) >> BLOCK_SHIFT(fs
);
247 buf
= xfs_dir2_dirblks_get_cached(fs
, dir_blk
, irec
.br_blockcount
);
248 data_hdr
= (xfs_dir2_data_hdr_t
*)buf
;
249 if (be32_to_cpu(data_hdr
->magic
) != XFS_DIR2_DATA_MAGIC
) {
250 xfs_error("Leaf directory's data magic number does not match!");
254 offset
= xfs_dir2_dataptr_to_off(fs
, be32_to_cpu(lep
->address
));
256 dep
= (xfs_dir2_data_entry_t
*)((uint8_t *)buf
+ offset
);
258 start_name
= &dep
->name
[0];
259 end_name
= start_name
+ dep
->namelen
;
261 ino
= be64_to_cpu(dep
->inumber
);
263 retval
= fill_dirent(fs
, dirent
, file
->offset
, ino
, (char *)start_name
,
264 end_name
- start_name
);
266 xfs_error("Failed to fill in dirent structure");
271 xfs_dir2_dirblks_flush_cache();
276 int xfs_readdir_dir2_node(struct file
*file
, struct dirent
*dirent
,
279 struct fs_info
*fs
= file
->fs
;
280 xfs_bmbt_irec_t irec
;
281 uint32_t node_off
= 0;
283 xfs_da_intnode_t
*node
= NULL
;
284 struct inode
*inode
= file
->inode
;
286 xfs_dir2_data_hdr_t
*data_hdr
;
287 xfs_dir2_leaf_t
*leaf
;
288 xfs_dir2_leaf_entry_t
*lep
;
290 xfs_dir2_data_entry_t
*dep
;
294 const uint8_t *buf
= NULL
;
297 xfs_debug("file %p dirent %p core %p", file
, dirent
, core
);
300 bmbt_irec_get(&irec
, (xfs_bmbt_rec_t
*)&core
->di_literal_area
[0] +
302 } while (irec
.br_startoff
< xfs_dir2_byte_to_db(fs
, XFS_DIR2_LEAF_OFFSET
));
304 fsblkno
= fsblock_to_bytes(fs
, irec
.br_startblock
) >> BLOCK_SHIFT(fs
);
306 node
= (xfs_da_intnode_t
*)xfs_dir2_dirblks_get_cached(fs
, fsblkno
, 1);
307 if (be16_to_cpu(node
->hdr
.info
.magic
) != XFS_DA_NODE_MAGIC
) {
308 xfs_error("Node's magic number does not match!");
313 if (!node
->hdr
.count
||
314 XFS_PVT(inode
)->i_btree_offset
>= be16_to_cpu(node
->hdr
.count
))
317 fsblkno
= be32_to_cpu(node
->btree
[XFS_PVT(inode
)->i_btree_offset
].before
);
318 fsblkno
= xfs_dir2_get_right_blk(fs
, core
, fsblkno
, &error
);
320 xfs_error("Cannot find leaf rec!");
324 leaf
= (xfs_dir2_leaf_t
*)xfs_dir2_dirblks_get_cached(fs
, fsblkno
, 1);
325 if (be16_to_cpu(leaf
->hdr
.info
.magic
) != XFS_DIR2_LEAFN_MAGIC
) {
326 xfs_error("Leaf's magic number does not match!");
330 if (!leaf
->hdr
.count
||
331 XFS_PVT(inode
)->i_leaf_ent_offset
>= be16_to_cpu(leaf
->hdr
.count
)) {
332 XFS_PVT(inode
)->i_btree_offset
++;
333 XFS_PVT(inode
)->i_leaf_ent_offset
= 0;
337 lep
= &leaf
->ents
[XFS_PVT(inode
)->i_leaf_ent_offset
];
339 /* Skip over stale leaf entries */
340 for ( ; XFS_PVT(inode
)->i_leaf_ent_offset
< be16_to_cpu(leaf
->hdr
.count
) &&
341 be32_to_cpu(lep
->address
) == XFS_DIR2_NULL_DATAPTR
;
342 lep
++, XFS_PVT(inode
)->i_leaf_ent_offset
++);
344 if (XFS_PVT(inode
)->i_leaf_ent_offset
== be16_to_cpu(leaf
->hdr
.count
)) {
345 XFS_PVT(inode
)->i_btree_offset
++;
346 XFS_PVT(inode
)->i_leaf_ent_offset
= 0;
349 XFS_PVT(inode
)->i_leaf_ent_offset
++;
352 db
= xfs_dir2_dataptr_to_db(fs
, be32_to_cpu(lep
->address
));
354 fsblkno
= xfs_dir2_get_right_blk(fs
, core
, db
, &error
);
356 xfs_error("Cannot find data block!");
360 buf
= xfs_dir2_dirblks_get_cached(fs
, fsblkno
, 1);
361 data_hdr
= (xfs_dir2_data_hdr_t
*)buf
;
362 if (be32_to_cpu(data_hdr
->magic
) != XFS_DIR2_DATA_MAGIC
) {
363 xfs_error("Leaf directory's data magic No. does not match!");
367 offset
= xfs_dir2_dataptr_to_off(fs
, be32_to_cpu(lep
->address
));
369 dep
= (xfs_dir2_data_entry_t
*)((uint8_t *)buf
+ offset
);
371 start_name
= &dep
->name
[0];
372 end_name
= start_name
+ dep
->namelen
;
374 retval
= fill_dirent(fs
, dirent
, 0, be64_to_cpu(dep
->inumber
),
375 (char *)start_name
, end_name
- start_name
);
377 xfs_error("Failed to fill in dirent structure");
382 xfs_dir2_dirblks_flush_cache();
384 XFS_PVT(inode
)->i_btree_offset
= 0;
385 XFS_PVT(inode
)->i_leaf_ent_offset
= 0;