14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #pragma prototyped 234887Schin 244887Schin #include "dirlib.h" 254887Schin 264887Schin #if _dir_ok || _lib_getdents 274887Schin 284887Schin NoN(getdents) 294887Schin 304887Schin #else 314887Schin 324887Schin /* 334887Schin * getdents 344887Schin * 354887Schin * read directory entries into directory block 364887Schin * 374887Schin * NOTE: directory entries must fit within DIRBLKSIZ boundaries 384887Schin */ 394887Schin 404887Schin #ifndef MAXNAMLEN 414887Schin #define MAXNAMLEN 255 424887Schin #endif 434887Schin 444887Schin #if _lib_dirread 454887Schin extern int dirread(int, char*, int); 464887Schin #endif 474887Schin #if _lib_getdirentries 484887Schin extern int getdirentries(int, char*, int, long*); 494887Schin #endif 504887Schin 514887Schin ssize_t 524887Schin getdents(int fd, void* buf, size_t siz) 534887Schin { 544887Schin struct stat st; 554887Schin 564887Schin if (siz < DIRBLKSIZ) 574887Schin { 584887Schin errno = EINVAL; 594887Schin return(-1); 604887Schin } 614887Schin if (fstat(fd, &st)) return(-1); 624887Schin if (!S_ISDIR(st.st_mode)) 634887Schin { 644887Schin #ifdef ENOTDIR 654887Schin errno = ENOTDIR; 664887Schin #else 674887Schin errno = EBADF; 684887Schin #endif 694887Schin return(-1); 704887Schin } 714887Schin #if _lib_getdirentries 724887Schin { 734887Schin long off; 744887Schin return(getdirentries(fd, buf, siz, &off)); 754887Schin } 764887Schin #else 774887Schin #if _lib_dirread 784887Schin { 794887Schin register char* sp; /* system */ 804887Schin register struct dirent* up; /* user */ 814887Schin char* u; 824887Schin int n; 834887Schin int m; 844887Schin int i; 854887Schin 864887Schin m = (siz * 6) / 10; 874887Schin m = roundof(m, 8); 884887Schin sp = (char*)buf + siz - m - 1; 894887Schin if (!(n = dirread(fd, sp, m))) return(0); 904887Schin if (n > 0) 914887Schin { 924887Schin up = (struct dirent*)buf; 934887Schin sp[n] = 0; 944887Schin while (sp < (char*)buf + siz - m + n) 954887Schin { 964887Schin i = 0; 974887Schin while (*sp >= '0' && *sp <= '9') 984887Schin i = 10 * i + *sp++ - '0'; 994887Schin while (*sp && *sp != '\t') sp++; 1004887Schin if (*sp++) 1014887Schin { 1024887Schin up->d_fileno = i; 1034887Schin u = up->d_name; 1044887Schin while ((*u = *sp++) && u < up->d_name + MAXNAMLEN) u++; 1054887Schin *u = 0; 1064887Schin up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - up->d_name) + 1; 1074887Schin up->d_reclen = roundof(up->d_reclen, 8); 1084887Schin up = (struct dirent*)((char*)up + up->d_reclen); 1094887Schin } 1104887Schin } 1114887Schin return((char*)up - (char*)buf); 1124887Schin } 1134887Schin } 1144887Schin #else 1154887Schin #if _mem_d_reclen_direct 1164887Schin return(read(fd, buf, siz)); 1174887Schin #else 1184887Schin { 1194887Schin 1204887Schin #define MAXREC roundof(sizeof(*up)-sizeof(up->d_name)+sizeof(sp->d_name)+1,8) 1214887Schin 1224887Schin register struct direct* sp; /* system */ 1234887Schin register struct dirent* up; /* user */ 1244887Schin register char* s; 1254887Schin register char* u; 1264887Schin int n; 1274887Schin int m; 1284887Schin char tmp[sizeof(sp->d_name) + 1]; 1294887Schin 1304887Schin /* 1314887Schin * we assume sizeof(struct dirent) > sizeof(struct direct) 1324887Schin */ 1334887Schin 1344887Schin up = (struct dirent*)buf; 1354887Schin n = (siz / MAXREC) * sizeof(struct direct); 1364887Schin if ((!(m = n & ~511) || m < MAXREC) && (!(m = n & ~255) || m < MAXREC)) m = n; 1374887Schin do 1384887Schin { 1394887Schin if ((n = read(fd, (char*)buf + siz - m, m)) <= 0) break; 1404887Schin sp = (struct direct*)((char*)buf + siz - m); 1414887Schin while (sp < (struct direct*)((char*)buf + siz - m + n)) 1424887Schin { 1434887Schin if (sp->d_ino) 1444887Schin { 1454887Schin up->d_fileno = sp->d_ino; 1464887Schin s = sp->d_name; 1474887Schin u = tmp; 1484887Schin while (s < sp->d_name + sizeof(sp->d_name) && *s) 1494887Schin *u++ = *s++; 1504887Schin *u = 0; 1514887Schin strcpy(up->d_name, tmp); 1524887Schin up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - tmp) + 1; 1534887Schin up->d_reclen = roundof(up->d_reclen, 8); 1544887Schin up = (struct dirent*)((char*)up + up->d_reclen); 1554887Schin } 1564887Schin sp++; 1574887Schin } 1584887Schin } while (up == (struct dirent*)buf); 1594887Schin return((char*)up - (char*)buf); 1604887Schin } 1614887Schin #endif 1624887Schin #endif 1634887Schin #endif 1644887Schin } 1654887Schin 1664887Schin #endif 167