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