1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2001
4f08c3bdfSopenharmony_ci * Copyright (c) 2013 Cyril Hrubis <chrubis@suse.cz>
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * This program is free software;  you can redistribute it and/or modify
7f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by
8f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or
9f08c3bdfSopenharmony_ci * (at your option) any later version.
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful,
12f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY;  without even the implied warranty of
13f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14f08c3bdfSopenharmony_ci * the GNU General Public License for more details.
15f08c3bdfSopenharmony_ci *
16f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License
17f08c3bdfSopenharmony_ci * along with this program;  if not, write to the Free Software
18f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19f08c3bdfSopenharmony_ci */
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_ci#ifndef GETDENTS_H
22f08c3bdfSopenharmony_ci#define GETDENTS_H
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_ci#include <stdint.h>
25f08c3bdfSopenharmony_ci#include "config.h"
26f08c3bdfSopenharmony_ci#include "lapi/syscalls.h"
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_ci#if HAVE_GETDENTS || HAVE_GETDENTS64
29f08c3bdfSopenharmony_ci#include <unistd.h>
30f08c3bdfSopenharmony_ci#endif
31f08c3bdfSopenharmony_ci
32f08c3bdfSopenharmony_ci/*
33f08c3bdfSopenharmony_ci * See fs/compat.c struct compat_linux_dirent
34f08c3bdfSopenharmony_ci */
35f08c3bdfSopenharmony_cistruct linux_dirent {
36f08c3bdfSopenharmony_ci	unsigned long   d_ino;
37f08c3bdfSopenharmony_ci	unsigned long   d_off;
38f08c3bdfSopenharmony_ci	unsigned short  d_reclen;
39f08c3bdfSopenharmony_ci	char            d_name[];
40f08c3bdfSopenharmony_ci};
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_cistatic inline int
43f08c3bdfSopenharmony_cilinux_getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int size)
44f08c3bdfSopenharmony_ci{
45f08c3bdfSopenharmony_ci	return tst_syscall(__NR_getdents, fd, dirp, size);
46f08c3bdfSopenharmony_ci}
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_cistruct linux_dirent64 {
49f08c3bdfSopenharmony_ci	uint64_t	d_ino;
50f08c3bdfSopenharmony_ci	int64_t		d_off;
51f08c3bdfSopenharmony_ci	unsigned short	d_reclen;
52f08c3bdfSopenharmony_ci	unsigned char	d_type;
53f08c3bdfSopenharmony_ci	char		d_name[];
54f08c3bdfSopenharmony_ci};
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_cistatic inline int
57f08c3bdfSopenharmony_cilinux_getdents64(unsigned int fd, struct linux_dirent64 *dirp64, unsigned int size)
58f08c3bdfSopenharmony_ci{
59f08c3bdfSopenharmony_ci	return tst_syscall(__NR_getdents64, fd, dirp64, size);
60f08c3bdfSopenharmony_ci}
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_cistatic inline size_t
63f08c3bdfSopenharmony_citst_dirp_size(void)
64f08c3bdfSopenharmony_ci{
65f08c3bdfSopenharmony_ci	switch (tst_variant) {
66f08c3bdfSopenharmony_ci	case 0:
67f08c3bdfSopenharmony_ci		return sizeof(struct linux_dirent);
68f08c3bdfSopenharmony_ci	case 1:
69f08c3bdfSopenharmony_ci		return sizeof(struct linux_dirent64);
70f08c3bdfSopenharmony_ci#if HAVE_GETDENTS
71f08c3bdfSopenharmony_ci	case 2:
72f08c3bdfSopenharmony_ci		return sizeof(struct dirent);
73f08c3bdfSopenharmony_ci#endif
74f08c3bdfSopenharmony_ci#if HAVE_GETDENTS64
75f08c3bdfSopenharmony_ci	case 3:
76f08c3bdfSopenharmony_ci		return sizeof(struct dirent64);
77f08c3bdfSopenharmony_ci#endif
78f08c3bdfSopenharmony_ci	}
79f08c3bdfSopenharmony_ci	return 0;
80f08c3bdfSopenharmony_ci}
81f08c3bdfSopenharmony_ci
82f08c3bdfSopenharmony_cistatic inline const char *
83f08c3bdfSopenharmony_citst_dirp_name(void *dirp)
84f08c3bdfSopenharmony_ci{
85f08c3bdfSopenharmony_ci	switch (tst_variant) {
86f08c3bdfSopenharmony_ci	case 0:
87f08c3bdfSopenharmony_ci		return ((struct linux_dirent *)dirp)->d_name;
88f08c3bdfSopenharmony_ci	case 1:
89f08c3bdfSopenharmony_ci		return ((struct linux_dirent64 *)dirp)->d_name;
90f08c3bdfSopenharmony_ci#if HAVE_GETDENTS
91f08c3bdfSopenharmony_ci	case 2:
92f08c3bdfSopenharmony_ci		return ((struct dirent *)dirp)->d_name;
93f08c3bdfSopenharmony_ci#endif
94f08c3bdfSopenharmony_ci#if HAVE_GETDENTS64
95f08c3bdfSopenharmony_ci	case 3:
96f08c3bdfSopenharmony_ci		return ((struct dirent64 *)dirp)->d_name;
97f08c3bdfSopenharmony_ci#endif
98f08c3bdfSopenharmony_ci	}
99f08c3bdfSopenharmony_ci	return NULL;
100f08c3bdfSopenharmony_ci}
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_cistatic inline size_t
103f08c3bdfSopenharmony_citst_dirp_reclen(void *dirp)
104f08c3bdfSopenharmony_ci{
105f08c3bdfSopenharmony_ci	switch (tst_variant) {
106f08c3bdfSopenharmony_ci	case 0:
107f08c3bdfSopenharmony_ci		return ((struct linux_dirent *)dirp)->d_reclen;
108f08c3bdfSopenharmony_ci	case 1:
109f08c3bdfSopenharmony_ci		return ((struct linux_dirent64 *)dirp)->d_reclen;
110f08c3bdfSopenharmony_ci#if HAVE_GETDENTS
111f08c3bdfSopenharmony_ci	case 2:
112f08c3bdfSopenharmony_ci		return ((struct dirent *)dirp)->d_reclen;
113f08c3bdfSopenharmony_ci#endif
114f08c3bdfSopenharmony_ci#if HAVE_GETDENTS64
115f08c3bdfSopenharmony_ci	case 3:
116f08c3bdfSopenharmony_ci		return ((struct dirent64 *)dirp)->d_reclen;
117f08c3bdfSopenharmony_ci#endif
118f08c3bdfSopenharmony_ci
119f08c3bdfSopenharmony_ci	}
120f08c3bdfSopenharmony_ci	return 0;
121f08c3bdfSopenharmony_ci}
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_cistatic inline int
124f08c3bdfSopenharmony_citst_getdents(int fd, void *dirp, unsigned int size)
125f08c3bdfSopenharmony_ci{
126f08c3bdfSopenharmony_ci	switch (tst_variant) {
127f08c3bdfSopenharmony_ci	case 0:
128f08c3bdfSopenharmony_ci		return linux_getdents(fd, dirp, size);
129f08c3bdfSopenharmony_ci	case 1:
130f08c3bdfSopenharmony_ci		return linux_getdents64(fd, dirp, size);
131f08c3bdfSopenharmony_ci#if HAVE_GETDENTS
132f08c3bdfSopenharmony_ci	case 2:
133f08c3bdfSopenharmony_ci		return getdents(fd, dirp, size);
134f08c3bdfSopenharmony_ci#endif
135f08c3bdfSopenharmony_ci#if HAVE_GETDENTS64
136f08c3bdfSopenharmony_ci	case 3:
137f08c3bdfSopenharmony_ci		return getdents64(fd, dirp, size);
138f08c3bdfSopenharmony_ci#endif
139f08c3bdfSopenharmony_ci	}
140f08c3bdfSopenharmony_ci	return -1;
141f08c3bdfSopenharmony_ci}
142f08c3bdfSopenharmony_ci
143f08c3bdfSopenharmony_cistatic inline void
144f08c3bdfSopenharmony_cigetdents_info(void)
145f08c3bdfSopenharmony_ci{
146f08c3bdfSopenharmony_ci	switch (tst_variant) {
147f08c3bdfSopenharmony_ci	case 0:
148f08c3bdfSopenharmony_ci		tst_res(TINFO, "Testing the SYS_getdents syscall");
149f08c3bdfSopenharmony_ci		break;
150f08c3bdfSopenharmony_ci	case 1:
151f08c3bdfSopenharmony_ci		tst_res(TINFO, "Testing the SYS_getdents64 syscall");
152f08c3bdfSopenharmony_ci		break;
153f08c3bdfSopenharmony_ci	case 2:
154f08c3bdfSopenharmony_ci#if HAVE_GETDENTS
155f08c3bdfSopenharmony_ci		tst_res(TINFO, "Testing libc getdents()");
156f08c3bdfSopenharmony_ci#else
157f08c3bdfSopenharmony_ci		tst_brk(TCONF, "libc getdents() is not implemented");
158f08c3bdfSopenharmony_ci#endif
159f08c3bdfSopenharmony_ci		break;
160f08c3bdfSopenharmony_ci	case 3:
161f08c3bdfSopenharmony_ci#if HAVE_GETDENTS64
162f08c3bdfSopenharmony_ci		tst_res(TINFO, "Testing libc getdents64()");
163f08c3bdfSopenharmony_ci#else
164f08c3bdfSopenharmony_ci		tst_brk(TCONF, "libc getdents64() is not implemented");
165f08c3bdfSopenharmony_ci#endif
166f08c3bdfSopenharmony_ci		break;
167f08c3bdfSopenharmony_ci	}
168f08c3bdfSopenharmony_ci}
169f08c3bdfSopenharmony_ci
170f08c3bdfSopenharmony_ci#define TEST_VARIANTS 4
171f08c3bdfSopenharmony_ci
172f08c3bdfSopenharmony_ci#endif /* GETDENTS_H */
173