Initial revision
[kopensolaris-gnu/glibc.git] / sysdeps / unix / bsd / readdir.c
1 /* Copyright (C) 1991 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is distributed in the hope that it will be useful, but
5 WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility for
6 the consequences of using it or for whether it serves any particular
7 purpose or works at all, unless he says so in writing.  Refer to the GNU
8 C Library General Public License (in the file COPYING) for full details.
9
10 Everyone is granted permission to copy, modify and redistribute
11 the GNU C Library, but only under the conditions described in the
12 GNU C Library General Public License.  Among other things, this notice
13 must not be changed and a copy of the license must be included.  */
14
15 #include <ansidecl.h>
16 #include <errno.h>
17 #include <limits.h>
18 #include <stddef.h>
19 #include <string.h>
20 #include <dirent.h>
21 #include <unistd.h>
22 #include <bsddir.h>
23 #include <sys/types.h>
24
25 #ifndef READ_DIRECTORY
26 #define READ_DIRECTORY                                                        \
27 {                                                                             \
28   int bytes = __read(dirp->__fd, dirp->__data, dirp->__allocation);           \
29   if (bytes <= 0)                                                             \
30     return NULL;                                                              \
31   dirp->__size = (size_t) bytes;                                              \
32 }
33 #endif
34
35 /* Read a directory entry from DIRP.  */
36 struct dirent *
37 DEFUN(readdir, (dirp), DIR *dirp)
38 {
39   if (dirp == NULL || dirp->__data == NULL)
40     {
41       errno = EINVAL;
42       return NULL;
43     }
44
45   for (;;)
46     {
47       struct direct *dp;
48
49       if (dirp->__offset >= dirp->__size)
50         {
51           /* We've emptied out our buffer.  Refill it.  */
52           READ_DIRECTORY;
53           /* Reset the offset into the buffer.  */
54           dirp->__offset = 0;
55         }
56
57       dp = (struct direct *) &dirp->__data[dirp->__offset];
58       dirp->__offset += dp->d_reclen;
59
60       if (dp->d_ino != 0)
61         {
62           /* Not a deleted file.  */
63           register struct dirent *d = &dirp->__entry;
64           d->d_fileno = (ino_t) dp->d_ino;
65           d->d_namlen = (size_t) dp->d_namlen;
66           if (d->d_namlen > NAME_MAX)
67             d->d_namlen = NAME_MAX;
68           (void) strncpy(d->d_name, dp->d_name, d->d_namlen + 1);
69           return d;
70         }
71     }
72 }