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