1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2008 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 24 #include "dirlib.h" 25 26 #if _dir_ok || _lib_getdents 27 28 NoN(getdents) 29 30 #else 31 32 /* 33 * getdents 34 * 35 * read directory entries into directory block 36 * 37 * NOTE: directory entries must fit within DIRBLKSIZ boundaries 38 */ 39 40 #ifndef MAXNAMLEN 41 #define MAXNAMLEN 255 42 #endif 43 44 #if _lib_dirread 45 extern int dirread(int, char*, int); 46 #endif 47 #if _lib_getdirentries 48 extern int getdirentries(int, char*, int, long*); 49 #endif 50 51 ssize_t 52 getdents(int fd, void* buf, size_t siz) 53 { 54 struct stat st; 55 56 if (siz < DIRBLKSIZ) 57 { 58 errno = EINVAL; 59 return(-1); 60 } 61 if (fstat(fd, &st)) return(-1); 62 if (!S_ISDIR(st.st_mode)) 63 { 64 #ifdef ENOTDIR 65 errno = ENOTDIR; 66 #else 67 errno = EBADF; 68 #endif 69 return(-1); 70 } 71 #if _lib_getdirentries 72 { 73 long off; 74 return(getdirentries(fd, buf, siz, &off)); 75 } 76 #else 77 #if _lib_dirread 78 { 79 register char* sp; /* system */ 80 register struct dirent* up; /* user */ 81 char* u; 82 int n; 83 int m; 84 int i; 85 86 m = (siz * 6) / 10; 87 m = roundof(m, 8); 88 sp = (char*)buf + siz - m - 1; 89 if (!(n = dirread(fd, sp, m))) return(0); 90 if (n > 0) 91 { 92 up = (struct dirent*)buf; 93 sp[n] = 0; 94 while (sp < (char*)buf + siz - m + n) 95 { 96 i = 0; 97 while (*sp >= '0' && *sp <= '9') 98 i = 10 * i + *sp++ - '0'; 99 while (*sp && *sp != '\t') sp++; 100 if (*sp++) 101 { 102 up->d_fileno = i; 103 u = up->d_name; 104 while ((*u = *sp++) && u < up->d_name + MAXNAMLEN) u++; 105 *u = 0; 106 up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - up->d_name) + 1; 107 up->d_reclen = roundof(up->d_reclen, 8); 108 up = (struct dirent*)((char*)up + up->d_reclen); 109 } 110 } 111 return((char*)up - (char*)buf); 112 } 113 } 114 #else 115 #if _mem_d_reclen_direct 116 return(read(fd, buf, siz)); 117 #else 118 { 119 120 #define MAXREC roundof(sizeof(*up)-sizeof(up->d_name)+sizeof(sp->d_name)+1,8) 121 122 register struct direct* sp; /* system */ 123 register struct dirent* up; /* user */ 124 register char* s; 125 register char* u; 126 int n; 127 int m; 128 char tmp[sizeof(sp->d_name) + 1]; 129 130 /* 131 * we assume sizeof(struct dirent) > sizeof(struct direct) 132 */ 133 134 up = (struct dirent*)buf; 135 n = (siz / MAXREC) * sizeof(struct direct); 136 if ((!(m = n & ~511) || m < MAXREC) && (!(m = n & ~255) || m < MAXREC)) m = n; 137 do 138 { 139 if ((n = read(fd, (char*)buf + siz - m, m)) <= 0) break; 140 sp = (struct direct*)((char*)buf + siz - m); 141 while (sp < (struct direct*)((char*)buf + siz - m + n)) 142 { 143 if (sp->d_ino) 144 { 145 up->d_fileno = sp->d_ino; 146 s = sp->d_name; 147 u = tmp; 148 while (s < sp->d_name + sizeof(sp->d_name) && *s) 149 *u++ = *s++; 150 *u = 0; 151 strcpy(up->d_name, tmp); 152 up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - tmp) + 1; 153 up->d_reclen = roundof(up->d_reclen, 8); 154 up = (struct dirent*)((char*)up + up->d_reclen); 155 } 156 sp++; 157 } 158 } while (up == (struct dirent*)buf); 159 return((char*)up - (char*)buf); 160 } 161 #endif 162 #endif 163 #endif 164 } 165 166 #endif 167