/*********************************************************************** * * * This software is part of the ast package * * Copyright (c) 1985-2009 AT&T Intellectual Property * * and is licensed under the * * Common Public License, Version 1.0 * * by AT&T Intellectual Property * * * * A copy of the License is available at * * http://www.opensource.org/licenses/cpl1.0.txt * * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * * * * Information and Software Systems Research * * AT&T Research * * Florham Park NJ * * * * Glenn Fowler * * David Korn * * Phong Vo * * * ***********************************************************************/ #pragma prototyped #include "dirlib.h" #if _dir_ok || _lib_getdents NoN(getdents) #else /* * getdents * * read directory entries into directory block * * NOTE: directory entries must fit within DIRBLKSIZ boundaries */ #ifndef MAXNAMLEN #define MAXNAMLEN 255 #endif #if _lib_dirread extern int dirread(int, char*, int); #endif #if _lib_getdirentries extern int getdirentries(int, char*, int, long*); #endif ssize_t getdents(int fd, void* buf, size_t siz) { struct stat st; if (siz < DIRBLKSIZ) { errno = EINVAL; return(-1); } if (fstat(fd, &st)) return(-1); if (!S_ISDIR(st.st_mode)) { #ifdef ENOTDIR errno = ENOTDIR; #else errno = EBADF; #endif return(-1); } #if _lib_getdirentries { long off; return(getdirentries(fd, buf, siz, &off)); } #else #if _lib_dirread { register char* sp; /* system */ register struct dirent* up; /* user */ char* u; int n; int m; int i; m = (siz * 6) / 10; m = roundof(m, 8); sp = (char*)buf + siz - m - 1; if (!(n = dirread(fd, sp, m))) return(0); if (n > 0) { up = (struct dirent*)buf; sp[n] = 0; while (sp < (char*)buf + siz - m + n) { i = 0; while (*sp >= '0' && *sp <= '9') i = 10 * i + *sp++ - '0'; while (*sp && *sp != '\t') sp++; if (*sp++) { up->d_fileno = i; u = up->d_name; while ((*u = *sp++) && u < up->d_name + MAXNAMLEN) u++; *u = 0; up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - up->d_name) + 1; up->d_reclen = roundof(up->d_reclen, 8); up = (struct dirent*)((char*)up + up->d_reclen); } } return((char*)up - (char*)buf); } } #else #if _mem_d_reclen_direct return(read(fd, buf, siz)); #else { #define MAXREC roundof(sizeof(*up)-sizeof(up->d_name)+sizeof(sp->d_name)+1,8) register struct direct* sp; /* system */ register struct dirent* up; /* user */ register char* s; register char* u; int n; int m; char tmp[sizeof(sp->d_name) + 1]; /* * we assume sizeof(struct dirent) > sizeof(struct direct) */ up = (struct dirent*)buf; n = (siz / MAXREC) * sizeof(struct direct); if ((!(m = n & ~511) || m < MAXREC) && (!(m = n & ~255) || m < MAXREC)) m = n; do { if ((n = read(fd, (char*)buf + siz - m, m)) <= 0) break; sp = (struct direct*)((char*)buf + siz - m); while (sp < (struct direct*)((char*)buf + siz - m + n)) { if (sp->d_ino) { up->d_fileno = sp->d_ino; s = sp->d_name; u = tmp; while (s < sp->d_name + sizeof(sp->d_name) && *s) *u++ = *s++; *u = 0; strcpy(up->d_name, tmp); up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - tmp) + 1; up->d_reclen = roundof(up->d_reclen, 8); up = (struct dirent*)((char*)up + up->d_reclen); } sp++; } } while (up == (struct dirent*)buf); return((char*)up - (char*)buf); } #endif #endif #endif } #endif