4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
40 #pragma ident "%Z%%M% %I% %E% SMI"
43 * readdir -- C library extension routine
46 #include <sys/feature_tests.h>
49 #pragma weak _readdir64 = readdir64
51 #pragma weak _readdir = readdir
64 dirent_t
*dp
; /* -> directory data */
67 if (dirp
->dd_size
!= 0) {
68 dp
= (dirent_t
*)(uintptr_t)&dirp
->dd_buf
[dirp
->dd_loc
];
69 saveloc
= dirp
->dd_loc
; /* save for possible EOF */
70 dirp
->dd_loc
+= (int)dp
->d_reclen
;
72 if (dirp
->dd_loc
>= dirp
->dd_size
)
73 dirp
->dd_loc
= dirp
->dd_size
= 0;
75 if (dirp
->dd_size
== 0 && /* refill buffer */
76 (dirp
->dd_size
= getdents(dirp
->dd_fd
,
77 (dirent_t
*)(uintptr_t)dirp
->dd_buf
, DIRBUF
)) <= 0) {
78 if (dirp
->dd_size
== 0) /* This means EOF */
79 dirp
->dd_loc
= saveloc
; /* so save for telldir */
80 return (NULL
); /* error or EOF */
83 return ((dirent_t
*)(uintptr_t)&dirp
->dd_buf
[dirp
->dd_loc
]);
89 * Welcome to the complicated world of large files on a small system.
95 dirent64_t
*dp64
; /* -> directory data */
98 if (dirp
->dd_size
!= 0) {
99 dp64
= (dirent64_t
*)(uintptr_t)&dirp
->dd_buf
[dirp
->dd_loc
];
100 /* was converted by readdir and needs to be reversed */
101 if (dp64
->d_ino
== (ino64_t
)-1) {
104 dp32
= (dirent_t
*)(&dp64
->d_off
);
105 dp64
->d_ino
= (ino64_t
)dp32
->d_ino
;
106 dp64
->d_off
= (off64_t
)dp32
->d_off
;
107 dp64
->d_reclen
= (unsigned short)(dp32
->d_reclen
+
108 ((char *)&dp64
->d_off
- (char *)dp64
));
110 saveloc
= dirp
->dd_loc
; /* save for possible EOF */
111 dirp
->dd_loc
+= (int)dp64
->d_reclen
;
113 if (dirp
->dd_loc
>= dirp
->dd_size
)
114 dirp
->dd_loc
= dirp
->dd_size
= 0;
116 if (dirp
->dd_size
== 0 && /* refill buffer */
117 (dirp
->dd_size
= getdents64(dirp
->dd_fd
,
118 (dirent64_t
*)(uintptr_t)dirp
->dd_buf
, DIRBUF
)) <= 0) {
119 if (dirp
->dd_size
== 0) /* This means EOF */
120 dirp
->dd_loc
= saveloc
; /* so save for telldir */
121 return (NULL
); /* error or EOF */
124 dp64
= (dirent64_t
*)(uintptr_t)&dirp
->dd_buf
[dirp
->dd_loc
];
129 * readdir now does translation of dirent64 entries into dirent entries.
130 * We rely on the fact that dirents are smaller than dirent64s and we
131 * reuse the space accordingly.
136 dirent64_t
*dp64
; /* -> directory data */
137 dirent_t
*dp32
; /* -> directory data */
139 if ((dp64
= readdir64(dirp
)) == NULL
)
143 * Make sure that the offset fits in 32 bits.
145 if (((off_t
)dp64
->d_off
!= dp64
->d_off
&&
146 (uint64_t)dp64
->d_off
> (uint64_t)UINT32_MAX
) ||
147 dp64
->d_ino
> SIZE_MAX
) {
152 dp32
= (dirent_t
*)(&dp64
->d_off
);
153 dp32
->d_off
= (off_t
)dp64
->d_off
;
154 dp32
->d_ino
= (ino_t
)dp64
->d_ino
;
155 dp32
->d_reclen
= (unsigned short)(dp64
->d_reclen
-
156 ((char *)&dp64
->d_off
- (char *)dp64
));
157 dp64
->d_ino
= (ino64_t
)-1; /* flag as converted for readdir64 */
158 /* d_name d_reclen should not move */