17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*494a4c51Sraf * Common Development and Distribution License (the "License"). 6*494a4c51Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*494a4c51Sraf 227c478bd9Sstevel@tonic-gate /* 23*494a4c51Sraf * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 307c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate /* 337c478bd9Sstevel@tonic-gate * readdir_r -- C library extension routine 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <sys/feature_tests.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #if !defined(_LP64) 397c478bd9Sstevel@tonic-gate #pragma weak readdir64_r = _readdir64_r 407c478bd9Sstevel@tonic-gate #endif 417c478bd9Sstevel@tonic-gate #pragma weak readdir_r = _readdir_r 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #include "synonyms.h" 44*494a4c51Sraf #include "libc.h" 457c478bd9Sstevel@tonic-gate #include <mtlib.h> 46*494a4c51Sraf #include <unistd.h> 477c478bd9Sstevel@tonic-gate #include <dirent.h> 487c478bd9Sstevel@tonic-gate #include <string.h> 497c478bd9Sstevel@tonic-gate #include <limits.h> 507c478bd9Sstevel@tonic-gate #include <errno.h> 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #ifdef _LP64 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * POSIX.1c standard version of the thread function readdir_r. 567c478bd9Sstevel@tonic-gate */ 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate int 59*494a4c51Sraf readdir_r(DIR *dirp, dirent_t *entry, dirent_t **result) 607c478bd9Sstevel@tonic-gate { 61*494a4c51Sraf private_DIR *pdirp = (private_DIR *)dirp; 62*494a4c51Sraf dirent_t *dp; /* -> directory data */ 637c478bd9Sstevel@tonic-gate int saveloc = 0; 647c478bd9Sstevel@tonic-gate 65*494a4c51Sraf lmutex_lock(&pdirp->dd_lock); 667c478bd9Sstevel@tonic-gate if (dirp->dd_size != 0) { 67*494a4c51Sraf dp = (dirent_t *)(uintptr_t)&dirp->dd_buf[dirp->dd_loc]; 687c478bd9Sstevel@tonic-gate saveloc = dirp->dd_loc; /* save for possible EOF */ 697c478bd9Sstevel@tonic-gate dirp->dd_loc += (int)dp->d_reclen; 707c478bd9Sstevel@tonic-gate } 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate if (dirp->dd_loc >= dirp->dd_size) 737c478bd9Sstevel@tonic-gate dirp->dd_loc = dirp->dd_size = 0; 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate if (dirp->dd_size == 0 && /* refill buffer */ 767c478bd9Sstevel@tonic-gate (dirp->dd_size = getdents(dirp->dd_fd, 77*494a4c51Sraf (dirent_t *)(uintptr_t)dirp->dd_buf, DIRBUF)) <= 0) { 787c478bd9Sstevel@tonic-gate if (dirp->dd_size == 0) { /* This means EOF */ 79*494a4c51Sraf dirp->dd_loc = saveloc; /* so save for telldir */ 80*494a4c51Sraf lmutex_unlock(&pdirp->dd_lock); 817c478bd9Sstevel@tonic-gate *result = NULL; 82*494a4c51Sraf return (0); 837c478bd9Sstevel@tonic-gate } 84*494a4c51Sraf lmutex_unlock(&pdirp->dd_lock); 857c478bd9Sstevel@tonic-gate *result = NULL; 867c478bd9Sstevel@tonic-gate return (errno); /* error */ 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate 89*494a4c51Sraf dp = (dirent_t *)(uintptr_t)&dirp->dd_buf[dirp->dd_loc]; 907c478bd9Sstevel@tonic-gate (void) memcpy(entry, dp, (size_t)dp->d_reclen); 91*494a4c51Sraf lmutex_unlock(&pdirp->dd_lock); 927c478bd9Sstevel@tonic-gate *result = entry; 937c478bd9Sstevel@tonic-gate return (0); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate #else /* _LP64 */ 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * POSIX.1c standard version of the thr function readdir_r. 1007c478bd9Sstevel@tonic-gate * Large file version. 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate int 104*494a4c51Sraf readdir64_r(DIR *dirp, dirent64_t *entry, dirent64_t **result) 1057c478bd9Sstevel@tonic-gate { 106*494a4c51Sraf private_DIR *pdirp = (private_DIR *)(uintptr_t)dirp; 107*494a4c51Sraf dirent64_t *dp64; /* -> directory data */ 1087c478bd9Sstevel@tonic-gate int saveloc = 0; 1097c478bd9Sstevel@tonic-gate 110*494a4c51Sraf lmutex_lock(&pdirp->dd_lock); 1117c478bd9Sstevel@tonic-gate if (dirp->dd_size != 0) { 112*494a4c51Sraf dp64 = (dirent64_t *)(uintptr_t)&dirp->dd_buf[dirp->dd_loc]; 1137c478bd9Sstevel@tonic-gate /* was converted by readdir and needs to be reversed */ 1147c478bd9Sstevel@tonic-gate if (dp64->d_ino == (ino64_t)-1) { 115*494a4c51Sraf dirent_t *dp32; /* -> 32 bit directory data */ 1167c478bd9Sstevel@tonic-gate 117*494a4c51Sraf dp32 = (dirent_t *)(&dp64->d_off); 1187c478bd9Sstevel@tonic-gate dp64->d_ino = (ino64_t)dp32->d_ino; 1197c478bd9Sstevel@tonic-gate dp64->d_off = (off64_t)dp32->d_off; 1207c478bd9Sstevel@tonic-gate dp64->d_reclen = (unsigned short)(dp32->d_reclen + 1217c478bd9Sstevel@tonic-gate ((char *)&dp64->d_off - (char *)dp64)); 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate saveloc = dirp->dd_loc; /* save for possible EOF */ 1247c478bd9Sstevel@tonic-gate dirp->dd_loc += (int)dp64->d_reclen; 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate if (dirp->dd_loc >= dirp->dd_size) 1287c478bd9Sstevel@tonic-gate dirp->dd_loc = dirp->dd_size = 0; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate if (dirp->dd_size == 0 && /* refill buffer */ 1317c478bd9Sstevel@tonic-gate (dirp->dd_size = getdents64(dirp->dd_fd, 132*494a4c51Sraf (dirent64_t *)(uintptr_t)dirp->dd_buf, DIRBUF)) <= 0) { 1337c478bd9Sstevel@tonic-gate if (dirp->dd_size == 0) { /* This means EOF */ 134*494a4c51Sraf dirp->dd_loc = saveloc; /* so save for telldir */ 135*494a4c51Sraf lmutex_unlock(&pdirp->dd_lock); 1367c478bd9Sstevel@tonic-gate *result = NULL; 137*494a4c51Sraf return (0); 1387c478bd9Sstevel@tonic-gate } 139*494a4c51Sraf lmutex_unlock(&pdirp->dd_lock); 1407c478bd9Sstevel@tonic-gate *result = NULL; 1417c478bd9Sstevel@tonic-gate return (errno); /* error */ 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 144*494a4c51Sraf dp64 = (dirent64_t *)(uintptr_t)&dirp->dd_buf[dirp->dd_loc]; 1457c478bd9Sstevel@tonic-gate (void) memcpy(entry, dp64, (size_t)dp64->d_reclen); 1467c478bd9Sstevel@tonic-gate *result = entry; 147*494a4c51Sraf lmutex_unlock(&pdirp->dd_lock); 1487c478bd9Sstevel@tonic-gate return (0); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* 152*494a4c51Sraf * POSIX.1c standard version of the function readdir_r. 1537c478bd9Sstevel@tonic-gate * User gets it via static readdir_r from header file. 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate int 157*494a4c51Sraf __posix_readdir_r(DIR *dirp, dirent_t *entry, dirent_t **result) 1587c478bd9Sstevel@tonic-gate { 159*494a4c51Sraf int error; 160*494a4c51Sraf dirent64_t *dp64; 161*494a4c51Sraf struct { 162*494a4c51Sraf dirent64_t dirent64; 163*494a4c51Sraf char chars[MAXNAMLEN]; 164*494a4c51Sraf } buf; 1657c478bd9Sstevel@tonic-gate 166*494a4c51Sraf error = readdir64_r(dirp, (dirent64_t *)&buf, &dp64); 167*494a4c51Sraf if (error != 0 || dp64 == NULL) { 1687c478bd9Sstevel@tonic-gate *result = NULL; 169*494a4c51Sraf return (error); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 172*494a4c51Sraf if (dp64->d_ino > SIZE_MAX || 173*494a4c51Sraf (uint64_t)dp64->d_off > (uint64_t)UINT32_MAX) { 1747c478bd9Sstevel@tonic-gate *result = NULL; 1757c478bd9Sstevel@tonic-gate return (EOVERFLOW); 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate entry->d_ino = (ino_t)dp64->d_ino; 1797c478bd9Sstevel@tonic-gate entry->d_off = (off_t)dp64->d_off; 1807c478bd9Sstevel@tonic-gate entry->d_reclen = (unsigned short)((((char *)entry->d_name - 1817c478bd9Sstevel@tonic-gate (char *)entry) + strlen(dp64->d_name) + 1 + 3) & ~3); 1827c478bd9Sstevel@tonic-gate (void) strcpy(entry->d_name, dp64->d_name); 1837c478bd9Sstevel@tonic-gate *result = entry; 1847c478bd9Sstevel@tonic-gate return (0); 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 187*494a4c51Sraf /* 188*494a4c51Sraf * POSIX.1c Draft-6 version of the function readdir_r. 189*494a4c51Sraf * It was implemented by Solaris 2.3. 190*494a4c51Sraf */ 191*494a4c51Sraf 192*494a4c51Sraf dirent_t * 193*494a4c51Sraf readdir_r(DIR *dirp, dirent_t *entry) 194*494a4c51Sraf { 195*494a4c51Sraf int error; 196*494a4c51Sraf dirent_t *result; 197*494a4c51Sraf 198*494a4c51Sraf if ((error = __posix_readdir_r(dirp, entry, &result)) != 0) 199*494a4c51Sraf errno = error; 200*494a4c51Sraf return (result); 201*494a4c51Sraf } 202*494a4c51Sraf 2037c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 204