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