readdir.c revision 71579
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 * 3. All advertising materials mentioning features or use of this software
141573Srgrimes *    must display the following acknowledgement:
151573Srgrimes *	This product includes software developed by the University of
161573Srgrimes *	California, Berkeley and its contributors.
171573Srgrimes * 4. Neither the name of the University nor the names of its contributors
181573Srgrimes *    may be used to endorse or promote products derived from this software
191573Srgrimes *    without specific prior written permission.
201573Srgrimes *
211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311573Srgrimes * SUCH DAMAGE.
3253812Salfred *
3353812Salfred * $FreeBSD: head/lib/libc/gen/readdir.c 71579 2001-01-24 13:01:12Z deischen $
3453812Salfred *
351573Srgrimes */
361573Srgrimes
371573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
3823658Speterstatic char sccsid[] = "@(#)readdir.c	8.3 (Berkeley) 9/29/94";
391573Srgrimes#endif /* LIBC_SCCS and not lint */
401573Srgrimes
4171579Sdeischen#include "namespace.h"
421573Srgrimes#include <sys/param.h>
431573Srgrimes#include <dirent.h>
4453812Salfred#include <errno.h>
4561193Skris#include <string.h>
4653812Salfred#include <pthread.h>
4771579Sdeischen#include "un-namespace.h"
481573Srgrimes
4971579Sdeischen#include "libc_private.h"
5071579Sdeischen
511573Srgrimes/*
521573Srgrimes * get next entry in a directory.
531573Srgrimes */
541573Srgrimesstruct dirent *
5571579Sdeischen_readdir_unlocked(dirp)
5669656Sdeischen	DIR *dirp;
571573Srgrimes{
5869656Sdeischen	struct dirent *dp;
591573Srgrimes
601573Srgrimes	for (;;) {
6123658Speter		if (dirp->dd_loc >= dirp->dd_size) {
6223658Speter			if (dirp->dd_flags & __DTF_READALL)
6323658Speter				return (NULL);
6423658Speter			dirp->dd_loc = 0;
6523658Speter		}
6623658Speter		if (dirp->dd_loc == 0 && !(dirp->dd_flags & __DTF_READALL)) {
6771579Sdeischen			dirp->dd_size = _getdirentries(dirp->dd_fd,
681573Srgrimes			    dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
691573Srgrimes			if (dirp->dd_size <= 0)
7023658Speter				return (NULL);
711573Srgrimes		}
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;
791573Srgrimes		if (dp->d_ino == 0)
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) {
9471579Sdeischen		_pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
9571579Sdeischen		dp = _readdir_unlocked(dirp);
9671579Sdeischen		_pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
9771579Sdeischen	}
9871579Sdeischen	else
9971579Sdeischen		dp = _readdir_unlocked(dirp);
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) {
11571579Sdeischen		_pthread_mutex_lock((pthread_mutex_t *)&dirp->dd_lock);
11671579Sdeischen		if ((dp = _readdir_unlocked(dirp)) != NULL)
11771579Sdeischen			memcpy(entry, dp, sizeof *entry);
11871579Sdeischen		_pthread_mutex_unlock((pthread_mutex_t *)&dirp->dd_lock);
11971579Sdeischen	}
12071579Sdeischen	else if ((dp = _readdir_unlocked(dirp)) != NULL)
12171579Sdeischen		memcpy(entry, dp, sizeof *entry);
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