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/11.0/lib/libc/gen/readdir.c 288029 2015-09-20 20:23:16Z rodrigc $"); 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 * 52288029Srodrigc_readdir_unlocked(DIR *dirp, int skip) 531573Srgrimes{ 5469656Sdeischen struct dirent *dp; 55282485Sjulian long initial_seek; 56282485Sjulian long initial_loc = 0; 571573Srgrimes 581573Srgrimes for (;;) { 5923658Speter if (dirp->dd_loc >= dirp->dd_size) { 6023658Speter if (dirp->dd_flags & __DTF_READALL) 6123658Speter return (NULL); 62282485Sjulian initial_loc = dirp->dd_loc; 63282485Sjulian dirp->dd_flags &= ~__DTF_SKIPREAD; 6423658Speter dirp->dd_loc = 0; 6523658Speter } 66268531Sjhb if (dirp->dd_loc == 0 && 67268531Sjhb !(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) { 68282485Sjulian initial_seek = dirp->dd_seek; 6971579Sdeischen dirp->dd_size = _getdirentries(dirp->dd_fd, 701573Srgrimes dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); 711573Srgrimes if (dirp->dd_size <= 0) 7223658Speter return (NULL); 73282485Sjulian _fixtelldir(dirp, initial_seek, initial_loc); 741573Srgrimes } 75268531Sjhb dirp->dd_flags &= ~__DTF_SKIPREAD; 761573Srgrimes dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc); 7733665Sjb if ((long)dp & 03L) /* bogus pointer check */ 7823658Speter return (NULL); 791573Srgrimes if (dp->d_reclen <= 0 || 801573Srgrimes dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) 8123658Speter return (NULL); 821573Srgrimes dirp->dd_loc += dp->d_reclen; 83178772Skib if (dp->d_ino == 0 && skip) 841573Srgrimes continue; 8523658Speter if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW)) 8623658Speter continue; 871573Srgrimes return (dp); 881573Srgrimes } 891573Srgrimes} 9053812Salfred 9171579Sdeischenstruct dirent * 92288029Srodrigcreaddir(DIR *dirp) 9371579Sdeischen{ 9471579Sdeischen struct dirent *dp; 9571579Sdeischen 9671579Sdeischen if (__isthreaded) { 97174221Sdes _pthread_mutex_lock(&dirp->dd_lock); 98178772Skib dp = _readdir_unlocked(dirp, 1); 99174221Sdes _pthread_mutex_unlock(&dirp->dd_lock); 10071579Sdeischen } 10171579Sdeischen else 102178772Skib dp = _readdir_unlocked(dirp, 1); 10371579Sdeischen return (dp); 10471579Sdeischen} 10571579Sdeischen 10653812Salfredint 107288029Srodrigcreaddir_r(DIR *dirp, struct dirent *entry, 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