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