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: releng/10.3/lib/libc/gen/readdir.c 282979 2015-05-15 15:49:24Z julian $"); 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; 57282979Sjulian long initial_seek; 58282979Sjulian long initial_loc = 0; 591573Srgrimes 601573Srgrimes for (;;) { 6123658Speter if (dirp->dd_loc >= dirp->dd_size) { 6223658Speter if (dirp->dd_flags & __DTF_READALL) 6323658Speter return (NULL); 64282979Sjulian initial_loc = dirp->dd_loc; 65282979Sjulian dirp->dd_flags &= ~__DTF_SKIPREAD; 6623658Speter dirp->dd_loc = 0; 6723658Speter } 68270002Sjhb if (dirp->dd_loc == 0 && 69270002Sjhb !(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) { 70282979Sjulian initial_seek = dirp->dd_seek; 7171579Sdeischen dirp->dd_size = _getdirentries(dirp->dd_fd, 721573Srgrimes dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); 731573Srgrimes if (dirp->dd_size <= 0) 7423658Speter return (NULL); 75282979Sjulian _fixtelldir(dirp, initial_seek, initial_loc); 761573Srgrimes } 77270002Sjhb dirp->dd_flags &= ~__DTF_SKIPREAD; 781573Srgrimes dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc); 7933665Sjb if ((long)dp & 03L) /* bogus pointer check */ 8023658Speter return (NULL); 811573Srgrimes if (dp->d_reclen <= 0 || 821573Srgrimes dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) 8323658Speter return (NULL); 841573Srgrimes dirp->dd_loc += dp->d_reclen; 85178772Skib if (dp->d_ino == 0 && skip) 861573Srgrimes continue; 8723658Speter if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW)) 8823658Speter continue; 891573Srgrimes return (dp); 901573Srgrimes } 911573Srgrimes} 9253812Salfred 9371579Sdeischenstruct dirent * 9471579Sdeischenreaddir(dirp) 9571579Sdeischen DIR *dirp; 9671579Sdeischen{ 9771579Sdeischen struct dirent *dp; 9871579Sdeischen 9971579Sdeischen if (__isthreaded) { 100174221Sdes _pthread_mutex_lock(&dirp->dd_lock); 101178772Skib dp = _readdir_unlocked(dirp, 1); 102174221Sdes _pthread_mutex_unlock(&dirp->dd_lock); 10371579Sdeischen } 10471579Sdeischen else 105178772Skib dp = _readdir_unlocked(dirp, 1); 10671579Sdeischen return (dp); 10771579Sdeischen} 10871579Sdeischen 10953812Salfredint 11053812Salfredreaddir_r(dirp, entry, result) 11153812Salfred DIR *dirp; 11253812Salfred struct dirent *entry; 11353812Salfred struct dirent **result; 11453812Salfred{ 11553812Salfred struct dirent *dp; 11669656Sdeischen int saved_errno; 11753812Salfred 11853892Salfred saved_errno = errno; 11953812Salfred errno = 0; 12071579Sdeischen if (__isthreaded) { 121174221Sdes _pthread_mutex_lock(&dirp->dd_lock); 122178772Skib if ((dp = _readdir_unlocked(dirp, 1)) != NULL) 12391330Salfred memcpy(entry, dp, _GENERIC_DIRSIZ(dp)); 124174221Sdes _pthread_mutex_unlock(&dirp->dd_lock); 12571579Sdeischen } 126178772Skib else if ((dp = _readdir_unlocked(dirp, 1)) != NULL) 12791330Salfred memcpy(entry, dp, _GENERIC_DIRSIZ(dp)); 12871579Sdeischen 12953892Salfred if (errno != 0) { 13071579Sdeischen if (dp == NULL) 13153892Salfred return (errno); 13253892Salfred } else 13353892Salfred errno = saved_errno; 13453892Salfred 13553892Salfred if (dp != NULL) 13653872Swes *result = entry; 13753892Salfred else 13853812Salfred *result = NULL; 13953892Salfred 14053892Salfred return (0); 14153812Salfred} 142