readdir.c revision 178772
158314Sache/* 2136759Speter * Copyright (c) 1983, 1993 321308Sache * The Regents of the University of California. All rights reserved. 421308Sache * 5136759Speter * Redistribution and use in source and binary forms, with or without 621308Sache * modification, are permitted provided that the following conditions 721308Sache * are met: 821308Sache * 1. Redistributions of source code must retain the above copyright 921308Sache * notice, this list of conditions and the following disclaimer. 1021308Sache * 2. Redistributions in binary form must reproduce the above copyright 1121308Sache * notice, this list of conditions and the following disclaimer in the 1258314Sache * documentation and/or other materials provided with the distribution. 1321308Sache * 4. Neither the name of the University nor the names of its contributors 1421308Sache * may be used to endorse or promote products derived from this software 1521308Sache * without specific prior written permission. 1621308Sache * 1721308Sache * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1821308Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1921308Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2021308Sache * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2121308Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2221308Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2358314Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2421308Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2521308Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2621308Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2721308Sache * SUCH DAMAGE. 2821308Sache */ 2921308Sache 3021308Sache#if defined(LIBC_SCCS) && !defined(lint) 3121308Sachestatic char sccsid[] = "@(#)readdir.c 8.3 (Berkeley) 9/29/94"; 3221308Sache#endif /* LIBC_SCCS and not lint */ 3321308Sache#include <sys/cdefs.h> 3421308Sache__FBSDID("$FreeBSD: head/lib/libc/gen/readdir.c 178772 2008-05-05 14:05:23Z kib $"); 3521308Sache 3626497Sache#include "namespace.h" 3726497Sache#include <sys/param.h> 3821308Sache#include <dirent.h> 3921308Sache#include <errno.h> 4021308Sache#include <string.h> 4121308Sache#include <pthread.h> 4221308Sache#include "un-namespace.h" 4321308Sache 4426497Sache#include "libc_private.h" 4521308Sache#include "telldir.h" 4621308Sache 4721308Sache/* 48119614Sache * get next entry in a directory. 4921308Sache */ 5021308Sachestruct dirent * 5121308Sache_readdir_unlocked(dirp, skip) 5221308Sache DIR *dirp; 5321308Sache int skip; 5421308Sache{ 5521308Sache struct dirent *dp; 5621308Sache 5758314Sache for (;;) { 5858314Sache if (dirp->dd_loc >= dirp->dd_size) { 5958314Sache if (dirp->dd_flags & __DTF_READALL) 6021308Sache return (NULL); 6121308Sache dirp->dd_loc = 0; 6221308Sache } 6321308Sache if (dirp->dd_loc == 0 && !(dirp->dd_flags & __DTF_READALL)) { 6458314Sache dirp->dd_size = _getdirentries(dirp->dd_fd, 6575409Sache dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); 6635486Sache if (dirp->dd_size <= 0) 6721308Sache return (NULL); 68119614Sache } 69119614Sache dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc); 70119614Sache if ((long)dp & 03L) /* bogus pointer check */ 71119614Sache return (NULL); 72119614Sache if (dp->d_reclen <= 0 || 7321308Sache dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) 74119614Sache return (NULL); 75136759Speter dirp->dd_loc += dp->d_reclen; 76119614Sache if (dp->d_ino == 0 && skip) 77119614Sache continue; 78119614Sache if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW)) 79119614Sache continue; 80119614Sache return (dp); 8121308Sache } 8258314Sache} 8321308Sache 8421308Sachestruct dirent * 8521308Sachereaddir(dirp) 8621308Sache DIR *dirp; 8721308Sache{ 8821308Sache struct dirent *dp; 8921308Sache 9021308Sache if (__isthreaded) { 9121308Sache _pthread_mutex_lock(&dirp->dd_lock); 9221308Sache dp = _readdir_unlocked(dirp, 1); 9321308Sache _pthread_mutex_unlock(&dirp->dd_lock); 9421308Sache } 9521308Sache else 9621308Sache dp = _readdir_unlocked(dirp, 1); 9721308Sache return (dp); 9821308Sache} 9921308Sache 10021308Sacheint 10121308Sachereaddir_r(dirp, entry, result) 10221308Sache DIR *dirp; 10321308Sache struct dirent *entry; 10421308Sache struct dirent **result; 10521308Sache{ 10621308Sache struct dirent *dp; 10721308Sache int saved_errno; 10821308Sache 10921308Sache saved_errno = errno; 11021308Sache errno = 0; 11121308Sache if (__isthreaded) { 11221308Sache _pthread_mutex_lock(&dirp->dd_lock); 11321308Sache if ((dp = _readdir_unlocked(dirp, 1)) != NULL) 11421308Sache memcpy(entry, dp, _GENERIC_DIRSIZ(dp)); 11521308Sache _pthread_mutex_unlock(&dirp->dd_lock); 11675409Sache } 11721308Sache else if ((dp = _readdir_unlocked(dirp, 1)) != NULL) 11821308Sache memcpy(entry, dp, _GENERIC_DIRSIZ(dp)); 11921308Sache 12021308Sache if (errno != 0) { 12121308Sache if (dp == NULL) 12221308Sache return (errno); 12321308Sache } else 12421308Sache errno = saved_errno; 12521308Sache 12621308Sache if (dp != NULL) 12721308Sache *result = entry; 12821308Sache else 12921308Sache *result = NULL; 13021308Sache 13121308Sache return (0); 13221308Sache} 13321308Sache