readdir.c revision 268531
11573Srgrimes/* 21573Srgrimes * Copyright (c) 1983, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * Redistribution and use in source and binary forms, with or without 61573Srgrimes * modification, are permitted provided that the following conditions 71573Srgrimes * are met: 81573Srgrimes * 1. Redistributions of source code must retain the above copyright 91573Srgrimes * notice, this list of conditions and the following disclaimer. 101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111573Srgrimes * notice, this list of conditions and the following disclaimer in the 121573Srgrimes * documentation and/or other materials provided with the distribution. 131573Srgrimes * 4. Neither the name of the University nor the names of its contributors 141573Srgrimes * may be used to endorse or promote products derived from this software 151573Srgrimes * without specific prior written permission. 161573Srgrimes * 171573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271573Srgrimes * SUCH DAMAGE. 281573Srgrimes */ 291573Srgrimes 301573Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 3123658Speterstatic char sccsid[] = "@(#)readdir.c 8.3 (Berkeley) 9/29/94"; 321573Srgrimes#endif /* LIBC_SCCS and not lint */ 3390039Sobrien#include <sys/cdefs.h> 3490039Sobrien__FBSDID("$FreeBSD: head/lib/libc/gen/readdir.c 268531 2014-07-11 16:16:26Z jhb $"); 351573Srgrimes 3671579Sdeischen#include "namespace.h" 371573Srgrimes#include <sys/param.h> 381573Srgrimes#include <dirent.h> 3953812Salfred#include <errno.h> 4061193Skris#include <string.h> 4153812Salfred#include <pthread.h> 4271579Sdeischen#include "un-namespace.h" 431573Srgrimes 4471579Sdeischen#include "libc_private.h" 45235647Sgleb#include "gen-private.h" 46150065Sstefanf#include "telldir.h" 4771579Sdeischen 481573Srgrimes/* 491573Srgrimes * get next entry in a directory. 501573Srgrimes */ 511573Srgrimesstruct dirent * 52178772Skib_readdir_unlocked(dirp, skip) 5369656Sdeischen DIR *dirp; 54178772Skib int skip; 551573Srgrimes{ 5669656Sdeischen struct dirent *dp; 571573Srgrimes 581573Srgrimes for (;;) { 5923658Speter if (dirp->dd_loc >= dirp->dd_size) { 6023658Speter if (dirp->dd_flags & __DTF_READALL) 6123658Speter return (NULL); 6223658Speter dirp->dd_loc = 0; 6323658Speter } 64268531Sjhb if (dirp->dd_loc == 0 && 65268531Sjhb !(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) { 6671579Sdeischen dirp->dd_size = _getdirentries(dirp->dd_fd, 671573Srgrimes dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); 681573Srgrimes if (dirp->dd_size <= 0) 6923658Speter return (NULL); 701573Srgrimes } 71268531Sjhb dirp->dd_flags &= ~__DTF_SKIPREAD; 721573Srgrimes dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc); 7333665Sjb if ((long)dp & 03L) /* bogus pointer check */ 7423658Speter return (NULL); 751573Srgrimes if (dp->d_reclen <= 0 || 761573Srgrimes dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) 7723658Speter return (NULL); 781573Srgrimes dirp->dd_loc += dp->d_reclen; 79178772Skib if (dp->d_ino == 0 && skip) 801573Srgrimes continue; 8123658Speter if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW)) 8223658Speter continue; 831573Srgrimes return (dp); 841573Srgrimes } 851573Srgrimes} 8653812Salfred 8771579Sdeischenstruct dirent * 8871579Sdeischenreaddir(dirp) 8971579Sdeischen DIR *dirp; 9071579Sdeischen{ 9171579Sdeischen struct dirent *dp; 9271579Sdeischen 9371579Sdeischen if (__isthreaded) { 94174221Sdes _pthread_mutex_lock(&dirp->dd_lock); 95178772Skib dp = _readdir_unlocked(dirp, 1); 96174221Sdes _pthread_mutex_unlock(&dirp->dd_lock); 9771579Sdeischen } 9871579Sdeischen else 99178772Skib dp = _readdir_unlocked(dirp, 1); 10071579Sdeischen return (dp); 10171579Sdeischen} 10271579Sdeischen 10353812Salfredint 10453812Salfredreaddir_r(dirp, entry, result) 10553812Salfred DIR *dirp; 10653812Salfred struct dirent *entry; 10753812Salfred struct dirent **result; 10853812Salfred{ 10953812Salfred struct dirent *dp; 11069656Sdeischen int saved_errno; 11153812Salfred 11253892Salfred saved_errno = errno; 11353812Salfred errno = 0; 11471579Sdeischen if (__isthreaded) { 115174221Sdes _pthread_mutex_lock(&dirp->dd_lock); 116178772Skib if ((dp = _readdir_unlocked(dirp, 1)) != NULL) 11791330Salfred memcpy(entry, dp, _GENERIC_DIRSIZ(dp)); 118174221Sdes _pthread_mutex_unlock(&dirp->dd_lock); 11971579Sdeischen } 120178772Skib else if ((dp = _readdir_unlocked(dirp, 1)) != NULL) 12191330Salfred memcpy(entry, dp, _GENERIC_DIRSIZ(dp)); 12271579Sdeischen 12353892Salfred if (errno != 0) { 12471579Sdeischen if (dp == NULL) 12553892Salfred return (errno); 12653892Salfred } else 12753892Salfred errno = saved_errno; 12853892Salfred 12953892Salfred if (dp != NULL) 13053872Swes *result = entry; 13153892Salfred else 13253812Salfred *result = NULL; 13353892Salfred 13453892Salfred return (0); 13553812Salfred} 136