getdir.c (5320B)
1 /* 2 * Copyright (c) 2003 Gunnar Ritter 3 * 4 * This software is provided 'as-is', without any express or implied 5 * warranty. In no event will the authors be held liable for any damages 6 * arising from the use of this software. 7 * 8 * Permission is granted to anyone to use this software for any purpose, 9 * including commercial applications, and to alter it and redistribute 10 * it freely, subject to the following restrictions: 11 * 12 * 1. The origin of this software must not be misrepresented; you must not 13 * claim that you wrote the original software. If you use this software 14 * in a product, an acknowledgment in the product documentation would be 15 * appreciated but is not required. 16 * 17 * 2. Altered source versions must be plainly marked as such, and must not be 18 * misrepresented as being the original software. 19 * 20 * 3. This notice may not be removed or altered from any source distribution. 21 */ 22 /* Sccsid @(#)getdir.c 1.20 (gritter) 5/14/06 */ 23 24 #ifndef __linux__ 25 /* 26 * 32-bit Solaris and Open UNIX do not have 64-bit getdents(); but 27 * having _FILE_OFFSET_BITS=64 will make it use a dirent64 struct 28 * on Open UNIX -> SEGV. 29 */ 30 #undef _FILE_OFFSET_BITS 31 #endif /* !__linux__ */ 32 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <stdlib.h> 36 #include <errno.h> 37 #include <string.h> 38 39 #if defined (__UCLIBC__) 40 #include <linux/types.h> 41 #include <linux/dirent.h> 42 #define getdents(a, b, c) __getdents64(a, b, c) 43 #define dirent dirent64 44 extern int getdents(int, struct dirent *, size_t); 45 #elif defined (__GLIBC__) || defined (__FreeBSD__) || defined (_AIX) || \ 46 defined (__NetBSD__) || defined (__OpenBSD__) || \ 47 defined (__DragonFly__) || defined (__APPLE__) 48 #include <dirent.h> 49 #define getdents(a, b, c) getdirentries((a), (char *)(b), (c), &(db->g_offs)) 50 #if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \ 51 defined (__DragonFly__) || defined (__APPLE__) 52 #undef d_ino 53 #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ 54 || __APPLE__ */ 55 #elif defined (__dietlibc__) 56 #include <dirent.h> 57 #include <unistd.h> 58 #else /* !__GLIBC__, !__dietlibc__ */ 59 #ifdef __hpux 60 #define _KERNEL 61 #endif /* __hpux */ 62 #include <dirent.h> 63 #ifdef __hpux 64 #ifndef _INO64_T 65 typedef unsigned long long uint64_t; 66 typedef uint64_t ino64_t; 67 #endif /* !_INO64_T */ 68 #ifdef __LP64__ 69 #define dirent __dirent64 70 #else /* !__LP64__ */ 71 #define dirent __dirent32 72 #endif /* !__LP64__ */ 73 #define d_reclen __d_reclen 74 #define d_name __d_name 75 #define d_ino __d_ino 76 #endif /* __hpux */ 77 #endif /* !__GLIBC__, !__dietlibc__ */ 78 79 #include "getdir.h" 80 81 #define DIBSIZE 5120 82 83 struct getdb { 84 #if !defined (__FreeBSD__) && !defined (__NetBSD__) && !defined (__OpenBSD__) \ 85 && !defined (__DragonFly__) && !defined (__APPLE__) 86 off_t g_offs; 87 #else /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ 88 long g_offs; 89 #endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ 90 struct dirent *g_dirp; 91 const char *g_path; 92 struct direc g_dic; 93 union { 94 char g_dirbuf[DIBSIZE+1]; 95 struct dirent g_dummy[1]; 96 } g_u; 97 int g_num; 98 int g_fd; 99 }; 100 101 struct getdb * 102 getdb_alloc(const char *path, int fd) 103 { 104 struct getdb *db; 105 106 if ((db = malloc(sizeof *db)) == NULL) 107 return NULL; 108 db->g_dirp = NULL; 109 db->g_offs = 0; 110 db->g_fd = fd; 111 db->g_path = path; 112 return db; 113 } 114 115 void 116 getdb_free(struct getdb *db) 117 { 118 free(db); 119 } 120 121 struct direc * 122 getdir(struct getdb *db, int *err) 123 { 124 int reclen; 125 126 *err = 0; 127 while (db->g_dirp == NULL) 128 { 129 /*LINTED*/ 130 db->g_num = getdents(db->g_fd, 131 (struct dirent *)db->g_u.g_dirbuf, 132 DIBSIZE); 133 if (db->g_num <= 0) { 134 if (db->g_num < 0) 135 *err = errno; 136 db->g_offs = 0; 137 return NULL; 138 } 139 /*LINTED*/ 140 db->g_dirp = (struct dirent *)db->g_u.g_dirbuf; 141 while (db->g_dirp && 142 #if !defined (__FreeBSD__) && !defined (__NetBSD__) && !defined (__OpenBSD__) \ 143 && !defined (__DragonFly__) && !defined (__APPLE__) 144 db->g_dirp->d_ino == 0 145 #else /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ 146 (db->g_dirp->d_fileno == 0 147 #ifdef DT_WHT 148 || db->g_dirp->d_type == DT_WHT 149 #endif 150 ) 151 #endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ 152 ) 153 { 154 next: 155 #ifndef __DragonFly__ 156 reclen = db->g_dirp->d_reclen; 157 #else 158 reclen = _DIRENT_DIRSIZ(db->g_dirp); 159 #endif 160 if ((db->g_num -= reclen) == 0 || reclen == 0) 161 db->g_dirp = NULL; 162 else 163 db->g_dirp = 164 /*LINTED*/ 165 (struct dirent *)((char *)db->g_dirp 166 + reclen); 167 } 168 } 169 #if !defined (__FreeBSD__) && !defined (__NetBSD__) && !defined (__OpenBSD__) \ 170 && !defined (__DragonFly__) && !defined (__APPLE__) 171 if (db->g_dirp->d_ino == 0) 172 goto next; 173 db->g_dic.d_ino = db->g_dirp->d_ino; 174 #else /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ 175 if (db->g_dirp->d_fileno == 0 176 #ifdef DT_WHT 177 || db->g_dirp->d_type == DT_WHT 178 #endif 179 ) 180 { 181 goto next; 182 } 183 db->g_dic.d_ino = db->g_dirp->d_fileno; 184 #endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ 185 db->g_dic.d_name = db->g_dirp->d_name; 186 #ifndef __DragonFly__ 187 reclen = db->g_dirp->d_reclen; 188 #else 189 reclen = _DIRENT_DIRSIZ(db->g_dirp); 190 #endif 191 if ((db->g_num -= reclen) == 0 || reclen == 0) 192 db->g_dirp = NULL; 193 else 194 /*LINTED*/ 195 db->g_dirp = (struct dirent *)((char *)db->g_dirp + reclen); 196 return &(db->g_dic); 197 }