Changeset 70890 in vbox for trunk/src/VBox/Runtime/r3/posix
- Timestamp:
- Feb 7, 2018 2:05:43 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 120716
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/dir-posix.cpp
r70884 r70890 36 36 #include <fcntl.h> 37 37 #include <dirent.h> 38 #include <dlfcn.h> 38 39 #include <stdio.h> 39 40 … … 42 43 43 44 #include <iprt/alloca.h> 45 #include <iprt/asm.h> 44 46 #include <iprt/assert.h> 45 47 #include <iprt/err.h> … … 233 235 * Convert to a native path and try opendir. 234 236 */ 237 char *pszSlash = NULL; 235 238 char const *pszNativePath; 236 int rc = rtPathToNative(&pszNativePath, pDir->pszPath, NULL); 239 int rc; 240 if ( !(pDir->fFlags & RTDIR_F_NO_FOLLOW) 241 || pDir->fDirSlash 242 || pDir->cchPath <= 1) 243 rc = rtPathToNative(&pszNativePath, pDir->pszPath, NULL); 244 else 245 { 246 pszSlash = (char *)&pDir->pszPath[pDir->cchPath - 1]; 247 *pszSlash = '\0'; 248 rc = rtPathToNative(&pszNativePath, pDir->pszPath, NULL); 249 } 237 250 if (RT_SUCCESS(rc)) 238 251 { 239 if (!(pDir->fFlags & RTDIR_F_NO_FOLLOW)) 252 if ( !(pDir->fFlags & RTDIR_F_NO_FOLLOW) 253 || pDir->fDirSlash) 240 254 pDir->pDir = opendir(pszNativePath); 241 255 else 242 256 { 243 AssertMsgFailed(("implement RTDIR_F_NO_FOLLOW\n")); 244 pDir->pDir = opendir(pszNativePath); 257 /* 258 * If we can get fdopendir() and have both O_NOFOLLOW and O_DIRECTORY, 259 * we will use open() to safely open the directory without following 260 * symlinks in the final component, and then use fdopendir to get a DIR 261 * from the file descriptor. 262 * 263 * If we cannot get that, we will use lstat() + opendir() as a fallback. 264 * 265 * We ASSUME that support for the O_NOFOLLOW and O_DIRECTORY flags is 266 * older than fdopendir(). 267 */ 268 #if defined(O_NOFOLLOW) && defined(O_DIRECTORY) 269 /* Need to resolve fdopendir dynamically. */ 270 typedef DIR * (*PFNFDOPENDIR)(int); 271 static PFNFDOPENDIR s_pfnFdOpenDir = NULL; 272 static bool volatile s_fInitalized = false; 273 274 PFNFDOPENDIR pfnFdOpenDir = s_pfnFdOpenDir; 275 ASMCompilerBarrier(); 276 if (s_fInitalized) 277 { /* likely */ } 278 else 279 { 280 pfnFdOpenDir = (PFNFDOPENDIR)dlsym(RTLD_DEFAULT, "fdopendir"); 281 s_pfnFdOpenDir = pfnFdOpenDir; 282 ASMAtomicWriteBool(&s_fInitalized, true); 283 } 284 285 if (pfnFdOpenDir) 286 { 287 int fd = open(pszNativePath, O_RDONLY | O_DIRECTORY | O_NOFOLLOW, 0); 288 if (fd >= 0) 289 { 290 pDir->pDir = pfnFdOpenDir(fd); 291 if (RT_UNLIKELY(!pDir->pDir)) 292 { 293 rc = RTErrConvertFromErrno(errno); 294 close(fd); 295 } 296 } 297 else 298 { 299 /* WSL returns ELOOP here, but we take no chances that O_NOFOLLOW 300 takes precedence over O_DIRECTORY everywhere. */ 301 int iErr = errno; 302 if (iErr == ELOOP || iErr == ENOTDIR) 303 { 304 struct stat St; 305 if ( lstat(pszNativePath, &St) == 0 306 && S_ISLNK(St.st_mode)) 307 rc = VERR_IS_A_SYMLINK; 308 else 309 rc = RTErrConvertFromErrno(iErr); 310 } 311 } 312 } 313 else 314 #endif 315 { 316 /* Fallback. This contains a race condition. */ 317 struct stat St; 318 if ( lstat(pszNativePath, &St) != 0 319 || !S_ISLNK(St.st_mode)) 320 pDir->pDir = opendir(pszNativePath); 321 else 322 rc = VERR_IS_A_SYMLINK; 323 } 245 324 } 246 325 if (pDir->pDir) … … 251 330 pDir->fDataUnread = false; /* spelling it out */ 252 331 } 253 else 332 else if (RT_SUCCESS_NP(rc)) 254 333 rc = RTErrConvertFromErrno(errno); 255 334 256 335 rtPathFreeNative(pszNativePath, pDir->pszPath); 257 336 } 258 337 if (pszSlash) 338 *pszSlash = RTPATH_SLASH; 259 339 return rc; 260 340 }
Note:
See TracChangeset
for help on using the changeset viewer.