getdir.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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. #ifndef __linux__
  24. /*
  25. * 32-bit Solaris and Open UNIX do not have 64-bit getdents(); but
  26. * having _FILE_OFFSET_BITS=64 will make it use a dirent64 struct
  27. * on Open UNIX -> SEGV.
  28. */
  29. #undef _FILE_OFFSET_BITS
  30. #endif /* !__linux__ */
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <stdlib.h>
  34. #include <errno.h>
  35. #include <string.h>
  36. #if defined (__UCLIBC__)
  37. #include <linux/types.h>
  38. #include <linux/dirent.h>
  39. #define getdents(a, b, c) __getdents64(a, b, c)
  40. #define dirent dirent64
  41. extern int getdents(int, struct dirent *, size_t);
  42. #elif defined (__GLIBC__) || defined (__FreeBSD__) || defined (_AIX) || \
  43. defined (__NetBSD__) || defined (__OpenBSD__) || \
  44. defined (__DragonFly__) || defined (__APPLE__)
  45. #include <dirent.h>
  46. #define getdents(a, b, c) getdirentries((a), (char *)(b), (c), &(db->g_offs))
  47. #if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
  48. defined (__DragonFly__) || defined (__APPLE__)
  49. #undef d_ino
  50. #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__
  51. || __APPLE__ */
  52. #elif defined (__dietlibc__)
  53. #include <dirent.h>
  54. #include <unistd.h>
  55. #else /* !__GLIBC__, !__dietlibc__ */
  56. #ifdef __hpux
  57. #define _KERNEL
  58. #endif /* __hpux */
  59. #include <sys/dirent.h>
  60. #ifdef __hpux
  61. #ifndef _INO64_T
  62. typedef unsigned long long uint64_t;
  63. typedef uint64_t ino64_t;
  64. #endif /* !_INO64_T */
  65. #ifdef __LP64__
  66. #define dirent __dirent64
  67. #else /* !__LP64__ */
  68. #define dirent __dirent32
  69. #endif /* !__LP64__ */
  70. #define d_reclen __d_reclen
  71. #define d_name __d_name
  72. #define d_ino __d_ino
  73. #endif /* __hpux */
  74. #endif /* !__GLIBC__, !__dietlibc__ */
  75. #include "getdir.h"
  76. #define DIBSIZE 5120
  77. struct getdb {
  78. #if !defined (__FreeBSD__) && !defined (__NetBSD__) && !defined (__OpenBSD__) \
  79. && !defined (__DragonFly__) && !defined (__APPLE__)
  80. off_t g_offs;
  81. #else /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */
  82. long g_offs;
  83. #endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */
  84. struct dirent *g_dirp;
  85. const char *g_path;
  86. struct direc g_dic;
  87. union {
  88. char g_dirbuf[DIBSIZE+1];
  89. struct dirent g_dummy[1];
  90. } g_u;
  91. int g_num;
  92. int g_fd;
  93. };
  94. struct getdb *
  95. getdb_alloc(const char *path, int fd)
  96. {
  97. struct getdb *db;
  98. if ((db = malloc(sizeof *db)) == NULL)
  99. return NULL;
  100. db->g_dirp = NULL;
  101. db->g_offs = 0;
  102. db->g_fd = fd;
  103. db->g_path = path;
  104. return db;
  105. }
  106. void
  107. getdb_free(struct getdb *db)
  108. {
  109. free(db);
  110. }
  111. struct direc *
  112. getdir(struct getdb *db, int *err)
  113. {
  114. int reclen;
  115. *err = 0;
  116. while (db->g_dirp == NULL)
  117. {
  118. /*LINTED*/
  119. db->g_num = getdents(db->g_fd,
  120. (struct dirent *)db->g_u.g_dirbuf,
  121. DIBSIZE);
  122. if (db->g_num <= 0) {
  123. if (db->g_num < 0)
  124. *err = errno;
  125. db->g_offs = 0;
  126. return NULL;
  127. }
  128. /*LINTED*/
  129. db->g_dirp = (struct dirent *)db->g_u.g_dirbuf;
  130. while (db->g_dirp &&
  131. #if !defined (__FreeBSD__) && !defined (__NetBSD__) && !defined (__OpenBSD__) \
  132. && !defined (__DragonFly__) && !defined (__APPLE__)
  133. db->g_dirp->d_ino == 0
  134. #else /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */
  135. (db->g_dirp->d_fileno == 0
  136. #ifdef DT_WHT
  137. || db->g_dirp->d_type == DT_WHT
  138. #endif
  139. )
  140. #endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */
  141. )
  142. {
  143. next:
  144. #ifndef __DragonFly__
  145. reclen = db->g_dirp->d_reclen;
  146. #else
  147. reclen = _DIRENT_DIRSIZ(db->g_dirp);
  148. #endif
  149. if ((db->g_num -= reclen) == 0 || reclen == 0)
  150. db->g_dirp = NULL;
  151. else
  152. db->g_dirp =
  153. /*LINTED*/
  154. (struct dirent *)((char *)db->g_dirp
  155. + reclen);
  156. }
  157. }
  158. #if !defined (__FreeBSD__) && !defined (__NetBSD__) && !defined (__OpenBSD__) \
  159. && !defined (__DragonFly__) && !defined (__APPLE__)
  160. if (db->g_dirp->d_ino == 0)
  161. goto next;
  162. db->g_dic.d_ino = db->g_dirp->d_ino;
  163. #else /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */
  164. if (db->g_dirp->d_fileno == 0
  165. #ifdef DT_WHT
  166. || db->g_dirp->d_type == DT_WHT
  167. #endif
  168. )
  169. {
  170. goto next;
  171. }
  172. db->g_dic.d_ino = db->g_dirp->d_fileno;
  173. #endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */
  174. db->g_dic.d_name = db->g_dirp->d_name;
  175. #ifndef __DragonFly__
  176. reclen = db->g_dirp->d_reclen;
  177. #else
  178. reclen = _DIRENT_DIRSIZ(db->g_dirp);
  179. #endif
  180. if ((db->g_num -= reclen) == 0 || reclen == 0)
  181. db->g_dirp = NULL;
  182. else
  183. /*LINTED*/
  184. db->g_dirp = (struct dirent *)((char *)db->g_dirp + reclen);
  185. return &(db->g_dic);
  186. }