readdir.c revision 69656
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 69656 2000-12-06 03:15:49Z 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
411573Srgrimes#include <sys/param.h>
421573Srgrimes#include <dirent.h>
4353812Salfred#include <errno.h>
4461193Skris#include <string.h>
4553812Salfred#ifdef _THREAD_SAFE
4653812Salfred#include <pthread.h>
4753812Salfred#include "pthread_private.h"
4853812Salfred#endif _THREAD_SAFE
491573Srgrimes
501573Srgrimes/*
511573Srgrimes * get next entry in a directory.
521573Srgrimes */
531573Srgrimesstruct dirent *
541573Srgrimesreaddir(dirp)
5569656Sdeischen	DIR *dirp;
561573Srgrimes{
5769656Sdeischen	struct dirent *dp;
581573Srgrimes
591573Srgrimes	for (;;) {
6023658Speter		if (dirp->dd_loc >= dirp->dd_size) {
6123658Speter			if (dirp->dd_flags & __DTF_READALL)
6223658Speter				return (NULL);
6323658Speter			dirp->dd_loc = 0;
6423658Speter		}
6523658Speter		if (dirp->dd_loc == 0 && !(dirp->dd_flags & __DTF_READALL)) {
661573Srgrimes			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		}
711573Srgrimes		dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
7233665Sjb		if ((long)dp & 03L)	/* bogus pointer check */
7323658Speter			return (NULL);
741573Srgrimes		if (dp->d_reclen <= 0 ||
751573Srgrimes		    dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
7623658Speter			return (NULL);
771573Srgrimes		dirp->dd_loc += dp->d_reclen;
781573Srgrimes		if (dp->d_ino == 0)
791573Srgrimes			continue;
8023658Speter		if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW))
8123658Speter			continue;
821573Srgrimes		return (dp);
831573Srgrimes	}
841573Srgrimes}
8553812Salfred
8653812Salfredint
8753812Salfredreaddir_r(dirp, entry, result)
8853812Salfred	DIR *dirp;
8953812Salfred	struct dirent *entry;
9053812Salfred	struct dirent **result;
9153812Salfred{
9253812Salfred	struct dirent *dp;
9369656Sdeischen	int saved_errno;
9469656Sdeischen#ifdef _THREAD_SAFE
9569656Sdeischen	int ret;
9653812Salfred
9753892Salfred	if ((ret = _FD_LOCK(dirp->dd_fd, FD_READ, NULL)) != 0)
9853892Salfred		return (ret);
9953812Salfred#endif
10053892Salfred
10153892Salfred	saved_errno = errno;
10253812Salfred	errno = 0;
10353812Salfred	dp = readdir(dirp);
10453892Salfred	if (errno != 0) {
10553892Salfred		if (dp == NULL) {
10653812Salfred#ifdef _THREAD_SAFE
10753892Salfred			_FD_UNLOCK(dirp->dd_fd, FD_READ);
10853812Salfred#endif
10953892Salfred			return (errno);
11053892Salfred		}
11153892Salfred	} else
11253892Salfred		errno = saved_errno;
11353892Salfred
11453892Salfred	if (dp != NULL)
11553812Salfred		memcpy(entry, dp, sizeof *entry);
11653892Salfred
11753812Salfred#ifdef _THREAD_SAFE
11853812Salfred	_FD_UNLOCK(dirp->dd_fd, FD_READ);
11953812Salfred#endif
12053892Salfred
12153892Salfred	if (dp != NULL)
12253872Swes		*result = entry;
12353892Salfred	else
12453812Salfred		*result = NULL;
12553892Salfred
12653892Salfred	return (0);
12753812Salfred}
128