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 2014 Garrett D'Amore <garrett@damore.org>
25 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
29 /* Copyright (c) 1988 AT&T */
30 /* All Rights Reserved */
33 * readdir_r -- C library extension routine
36 #include <sys/feature_tests.h>
39 #pragma weak _readdir64_r = readdir64_r
54 * POSIX.1c standard version of the thread function readdir_r.
58 readdir_r(DIR *dirp
, dirent_t
*entry
, dirent_t
**result
)
60 private_DIR
*pdirp
= (private_DIR
*)dirp
;
61 dirent_t
*dp
; /* -> directory data */
64 lmutex_lock(&pdirp
->dd_lock
);
65 if (dirp
->dd_size
!= 0) {
66 dp
= (dirent_t
*)(uintptr_t)&dirp
->dd_buf
[dirp
->dd_loc
];
67 saveloc
= dirp
->dd_loc
; /* save for possible EOF */
68 dirp
->dd_loc
+= (int)dp
->d_reclen
;
71 if (dirp
->dd_loc
>= dirp
->dd_size
)
72 dirp
->dd_loc
= dirp
->dd_size
= 0;
74 if (dirp
->dd_size
== 0 && /* refill buffer */
75 (dirp
->dd_size
= getdents(dirp
->dd_fd
,
76 (dirent_t
*)(uintptr_t)dirp
->dd_buf
, DIRBUF
)) <= 0) {
77 if (dirp
->dd_size
== 0) { /* This means EOF */
78 dirp
->dd_loc
= saveloc
; /* so save for telldir */
79 lmutex_unlock(&pdirp
->dd_lock
);
83 lmutex_unlock(&pdirp
->dd_lock
);
85 return (errno
); /* error */
88 dp
= (dirent_t
*)(uintptr_t)&dirp
->dd_buf
[dirp
->dd_loc
];
89 (void) memcpy(entry
, dp
, (size_t)dp
->d_reclen
);
90 lmutex_unlock(&pdirp
->dd_lock
);
98 * POSIX.1c standard version of the thr function readdir_r.
103 readdir64_r(DIR *dirp
, dirent64_t
*entry
, dirent64_t
**result
)
105 private_DIR
*pdirp
= (private_DIR
*)(uintptr_t)dirp
;
106 dirent64_t
*dp64
; /* -> directory data */
109 lmutex_lock(&pdirp
->dd_lock
);
110 if (dirp
->dd_size
!= 0) {
111 dp64
= (dirent64_t
*)(uintptr_t)&dirp
->dd_buf
[dirp
->dd_loc
];
112 /* was converted by readdir and needs to be reversed */
113 if (dp64
->d_ino
== (ino64_t
)-1) {
114 dirent_t
*dp32
; /* -> 32 bit directory data */
116 dp32
= (dirent_t
*)(&dp64
->d_off
);
117 dp64
->d_ino
= (ino64_t
)dp32
->d_ino
;
118 dp64
->d_off
= (off64_t
)dp32
->d_off
;
119 dp64
->d_reclen
= (unsigned short)(dp32
->d_reclen
+
120 ((char *)&dp64
->d_off
- (char *)dp64
));
122 saveloc
= dirp
->dd_loc
; /* save for possible EOF */
123 dirp
->dd_loc
+= (int)dp64
->d_reclen
;
126 if (dirp
->dd_loc
>= dirp
->dd_size
)
127 dirp
->dd_loc
= dirp
->dd_size
= 0;
129 if (dirp
->dd_size
== 0 && /* refill buffer */
130 (dirp
->dd_size
= getdents64(dirp
->dd_fd
,
131 (dirent64_t
*)(uintptr_t)dirp
->dd_buf
, DIRBUF
)) <= 0) {
132 if (dirp
->dd_size
== 0) { /* This means EOF */
133 dirp
->dd_loc
= saveloc
; /* so save for telldir */
134 lmutex_unlock(&pdirp
->dd_lock
);
138 lmutex_unlock(&pdirp
->dd_lock
);
140 return (errno
); /* error */
143 dp64
= (dirent64_t
*)(uintptr_t)&dirp
->dd_buf
[dirp
->dd_loc
];
144 (void) memcpy(entry
, dp64
, (size_t)dp64
->d_reclen
);
146 lmutex_unlock(&pdirp
->dd_lock
);
151 * POSIX.1c standard version of the function readdir_r.
155 readdir_r(DIR *dirp
, dirent_t
*entry
, dirent_t
**result
)
161 char chars
[MAXNAMLEN
];
164 error
= readdir64_r(dirp
, (dirent64_t
*)&buf
, &dp64
);
165 if (error
!= 0 || dp64
== NULL
) {
170 if (dp64
->d_ino
> SIZE_MAX
||
171 (uint64_t)dp64
->d_off
> (uint64_t)UINT32_MAX
) {
176 entry
->d_ino
= (ino_t
)dp64
->d_ino
;
177 entry
->d_off
= (off_t
)dp64
->d_off
;
178 entry
->d_reclen
= (unsigned short)((((char *)entry
->d_name
-
179 (char *)entry
) + strlen(dp64
->d_name
) + 1 + 3) & ~3);
180 (void) strcpy(entry
->d_name
, dp64
->d_name
);
186 * Compatibility alias. Solaris and illumos default to non-POSIX readdir_r,
187 * and the posix version gets a mangled name. We keep this symbol here to
188 * allow for a smoother transition.
190 #pragma weak __posix_readdir_r = readdir_r