1 /*
2 * Copyright (c) 2020-2021 Dmitry V. Levin <ldv@strace.io>
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7
8 #include "xgetdents.h"
9 #include "kernel_dirent.h"
10
11 #define D_NAME_LEN_MAX 256
12
13 static void
14 print_dentry_head(const kernel_dirent64_t *const dent)
15 {
16 tprint_struct_begin();
17 PRINT_FIELD_U(*dent, d_ino);
18 tprint_struct_next();
19 PRINT_FIELD_U(*dent, d_off);
20 tprint_struct_next();
21 PRINT_FIELD_U(*dent, d_reclen);
22 }
23
24 static unsigned int
25 decode_dentry_head(struct tcb *const tcp, const void *const arg)
26 {
27 const kernel_dirent64_t *const dent = arg;
28
29 if (!abbrev(tcp))
30 print_dentry_head(dent);
31
32 return dent->d_reclen;
33 }
34
35 static int
36 decode_dentry_tail(struct tcb *const tcp, kernel_ulong_t addr,
37 const void *const arg, unsigned int d_name_len)
38 {
39 const kernel_dirent64_t *const dent = arg;
40 int rc = 0;
41
42 /* !abbrev(tcp) */
43
44 tprint_struct_next();
45 PRINT_FIELD_XVAL(*dent, d_type, dirent_types, "DT_???");
46
47 if (d_name_len) {
48 if (d_name_len > D_NAME_LEN_MAX)
49 d_name_len = D_NAME_LEN_MAX;
50 tprint_struct_next();
51 tprints_field_name("d_name");
52 rc = printpathn(tcp, addr, d_name_len - 1);
53 }
54 tprint_struct_end();
55
56 return rc;
57 }
58
59 SYS_FUNC(getdents64)
60 {
61 /* The minimum size of a valid directory entry. */
62 static const unsigned int header_size =
63 offsetof(kernel_dirent64_t, d_name);
64
65 return xgetdents(tcp, header_size,
66 decode_dentry_head, decode_dentry_tail);
67 }