1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1985-2011 AT&T Intellectual Property * 5* and is licensed under the * 6* Eclipse Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.eclipse.org/org/documents/epl-v10.html * 11* (with md5 checksum b35adb5213ca9657e911e9befb180842) * 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 28NoN(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 45extern int dirread(int, char*, int); 46#endif 47#if _lib_getdirentries 48extern int getdirentries(int, char*, int, long*); 49#endif 50 51ssize_t 52getdents(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