Changeset 23332 in vbox for trunk/src/VBox
- Timestamp:
- Sep 25, 2009 1:26:57 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/linux/sysfs.cpp
r23309 r23332 50 50 #include <errno.h> 51 51 52 /** @todo r=bird: This whole API should be rewritten to use IPRT status codes. 53 * using errno was a mistake and only results in horrible code. */ 54 52 55 53 56 /** … … 56 59 * 57 60 * @returns The number of characters returned, or -1 and errno set to ERANGE on 58 * failure.61 * failure. 59 62 * 60 63 * @param pszPrefix The prefix to prepend if the path is relative. Must end … … 63 66 * sizeof(@a pszPrefix) characters long 64 67 * @param cchBuf The size of the buffer pointed to by @a pszBuf. 65 * @param pszFormat The name format, either absolute or relative to "/sys/". 68 * @param pszFormat The name format, either absolute or relative to the 69 * prefix specified by @a pszPrefix. 66 70 * @param va The format args. 67 71 */ … … 74 78 AssertReturnStmt(cchBuf > cchPrefix + 1, errno = ERANGE, -1); 75 79 80 /** @todo While RTStrPrintfV prevents overflows, it doesn't make it easy to 81 * check for truncations. RTPath should provide some formatters and 82 * joiners which can take over this rather common task that is 83 * performed here. */ 76 84 size_t cch = RTStrPrintfV(pszBuf, cchBuf, pszFormat, va); 77 85 if (*pszBuf != '/') … … 245 253 return 0; 246 254 247 dev_t devNum = 0;255 dev_t DevNum = 0; 248 256 char szNum[128]; 249 257 ssize_t cchNum = RTLinuxSysFsReadStr(fd, szNum, sizeof(szNum)); … … 266 274 { 267 275 errno = 0; 268 devNum = makedev(u32Maj, u32Min);276 DevNum = makedev(u32Maj, u32Min); 269 277 } 270 278 } … … 274 282 275 283 RTLinuxSysFsClose(fd); 276 return devNum;284 return DevNum; 277 285 } 278 286 … … 282 290 va_list va; 283 291 va_start(va, pszFormat); 284 dev_t devNum = RTLinuxSysFsReadDevNumFileV(pszFormat, va);285 va_end(va); 286 return devNum;292 dev_t DevNum = RTLinuxSysFsReadDevNumFileV(pszFormat, va); 293 va_end(va); 294 return DevNum; 287 295 } 288 296 … … 346 354 if (pszName) 347 355 { 348 cchName = strlen(pszName); 356 cchName = strlen(pszName); /* = &szLink[rc] - pszName; */ 349 357 if (cchName >= cchBuf) 350 358 { … … 352 360 return -1; 353 361 } 354 memcpy(pszBuf, pszName, cchName );362 memcpy(pszBuf, pszName, cchName + 1); 355 363 } 356 364 else … … 373 381 374 382 375 static ssize_t rtLinuxFindDevicePathRecursive(dev_t devNum, RTFMODE fMode, 376 const char *pszBasePath, 383 static ssize_t rtLinuxFindDevicePathRecursive(dev_t DevNum, RTFMODE fMode, const char *pszBasePath, 377 384 char *pszBuf, size_t cchBuf) 378 385 { 379 PRTDIR pDir = NULL; 380 RTDIRENTRYEX entry = { {0} }; 381 int vrc = VINF_SUCCESS; 382 ssize_t rc; 383 384 vrc = RTDirOpen(&pDir, pszBasePath); 385 if (RT_SUCCESS(vrc)) 386 while (true) 386 /* 387 * Check assumptions made by the code below. 388 */ 389 size_t const cchBasePath = strlen(pszBasePath); 390 AssertReturnStmt(cchBasePath < RTPATH_MAX - 10U, errno = ENAMETOOLONG, -1); 391 392 ssize_t rcRet; 393 PRTDIR pDir; 394 int rc = RTDirOpen(&pDir, pszBasePath); 395 if (RT_SUCCESS(rc)) 396 { 397 char szPath[RTPATH_MAX]; /** @todo 4K per recursion - can easily be optimized away by passing it along pszBasePath 398 and only remember the length. */ 399 memcpy(szPath, pszBasePath, cchBasePath + 1); 400 401 for (;;) 387 402 { 388 vrc = RTDirReadEx(pDir, &entry, NULL, RTFSOBJATTRADD_UNIX); 389 if (RT_FAILURE(vrc)) 403 RTDIRENTRYEX Entry; 404 rc = RTDirReadEx(pDir, &Entry, NULL, RTFSOBJATTRADD_UNIX); 405 if (RT_FAILURE(rc)) 390 406 { 391 errno = (vrc == VERR_NO_MORE_FILES) ? ENOENT 392 : (vrc == VERR_BUFFER_OVERFLOW) ? EOVERFLOW 393 : EIO; 394 rc = -1; 407 errno = rc == VERR_NO_MORE_FILES 408 ? ENOENT 409 : rc == VERR_BUFFER_OVERFLOW 410 ? EOVERFLOW 411 : EIO; 412 rcRet = -1; 395 413 break; 396 414 } 397 if (RTFS_IS_SYMLINK( entry.Info.Attr.fMode))415 if (RTFS_IS_SYMLINK(Entry.Info.Attr.fMode)) /* paranoia */ 398 416 continue; 399 if ( (entry.Info.Attr.u.Unix.Device == devNum) 400 && ( ( (fMode == RTFS_TYPE_DEV_CHAR) 401 && RTFS_IS_DEV_CHAR(entry.Info.Attr.fMode)) 402 || ( (fMode == RTFS_TYPE_DEV_BLOCK) 403 && RTFS_IS_DEV_BLOCK(entry.Info.Attr.fMode)))) 417 418 /* Do the matching. */ 419 if ( Entry.Info.Attr.u.Unix.Device == DevNum 420 && (Entry.Info.Attr.fMode & RTFS_TYPE_MASK) == fMode) 404 421 { 405 rc = rtLinuxConstructPath(pszBuf, cchBuf, pszBasePath, "%s", 406 entry.szName); 422 rcRet = rtLinuxConstructPath(pszBuf, cchBuf, pszBasePath, "%s", Entry.szName); 407 423 break; 408 424 } 409 if (!RTFS_IS_DIRECTORY(entry.Info.Attr.fMode)) 425 426 /* Recurse into subdirectories. */ 427 if (!RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode)) 410 428 continue; 411 if ( entry.szName[0] == '.')429 if (Entry.szName[0] == '.') 412 430 continue; 413 char szPath[RTPATH_MAX]; 414 /** @todo this is a temporary hack, as RTDirReadEx currently 415 * doesn't know about symbolic links */ 416 rc = rtLinuxConstructPath(szPath, sizeof(szPath), pszBasePath, 417 "%s", entry.szName); 418 if (rc < 0) 431 432 szPath[cchBasePath] = '\0'; 433 rc = RTPathAppend(szPath, sizeof(szPath) - 1, Entry.szName); /* -1: for slash */ 434 if (RT_FAILURE(rc)) 435 { 436 errno = ENAMETOOLONG; 437 rcRet = -1; 419 438 break; 439 } 440 #if 1 /** @todo This is a temporary hack, as RTDirReadEx in 3.0 doesn't know about symbolic links. */ 420 441 struct stat Stat = { 0 }; 421 442 if ( lstat(szPath, &Stat) < 0 422 443 || S_ISLNK(Stat.st_mode)) 423 444 continue; 424 /* @todo ends here */ 425 rc = rtLinuxConstructPath(szPath, sizeof(szPath), pszBasePath, 426 "%s/", entry.szName); 427 if (rc < 0) 428 break; 429 rc = rtLinuxFindDevicePathRecursive(devNum, fMode, szPath, 430 pszBuf, cchBuf); 431 if ((rc >= 0) || errno != ENOENT) 445 #endif 446 strcat(&szPath[cchBasePath], "/"); 447 rcRet = rtLinuxFindDevicePathRecursive(DevNum, fMode, szPath, pszBuf, cchBuf); 448 if (rcRet >= 0 || errno != ENOENT) 432 449 break; 433 450 } 451 RTDirClose(pDir); 452 } 434 453 else 435 454 { 436 rc = -1; 437 errno = RTErrConvertToErrno(vrc); 438 } 439 RTDirClose(pDir); 440 return rc; 441 } 442 443 444 RTDECL(ssize_t) RTLinuxFindDevicePathV(dev_t devNum, RTFMODE fMode, 445 char *pszBuf, size_t cchBuf, 455 rcRet = -1; 456 errno = RTErrConvertToErrno(rc); 457 } 458 return rcRet; 459 } 460 461 462 RTDECL(ssize_t) RTLinuxFindDevicePathV(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf, 446 463 const char *pszSuggestion, va_list va) 447 464 { 448 465 AssertReturnStmt(cchBuf >= 2, errno = EINVAL, -1); 449 AssertReturnStmt( (fMode == RTFS_TYPE_DEV_CHAR)450 || (fMode == RTFS_TYPE_DEV_BLOCK),466 AssertReturnStmt( fMode == RTFS_TYPE_DEV_CHAR 467 || fMode == RTFS_TYPE_DEV_BLOCK, 451 468 errno = EINVAL, -1); 452 469 453 if (!pszSuggestion) 454 return rtLinuxFindDevicePathRecursive(devNum, fMode, "/dev/", 455 pszBuf, cchBuf); 456 457 /* 458 * Construct the filename and read the link. 459 */ 460 char szFilename[RTPATH_MAX]; 461 int rc = rtLinuxConstructPathV(szFilename, sizeof(szFilename), "/dev/", 462 pszSuggestion, va); 463 if (rc == -1) 464 return -1; 465 466 /* 467 * Check whether the caller's suggestion was right. 468 */ 469 /** @todo Should we just be using POSIX stat here? */ 470 RTFSOBJINFO info = {0}; 471 int vrc = RTPathQueryInfo(szFilename, &info, RTFSOBJATTRADD_UNIX); 472 if (RT_FAILURE(vrc)) 473 { 474 errno = (vrc == VERR_PATH_NOT_FOUND) ? ENOENT 475 : (vrc == VERR_FILE_NOT_FOUND) ? ENOENT 476 : EIO; 477 return -1; 478 } 479 if ( (info.Attr.u.Unix.Device == devNum) 480 && ( ( (fMode == RTFS_TYPE_DEV_CHAR) 481 && RTFS_IS_DEV_CHAR(info.Attr.fMode)) 482 || ( (fMode == RTFS_TYPE_DEV_BLOCK) 483 && RTFS_IS_DEV_BLOCK(info.Attr.fMode)))) 484 { 485 size_t cchPath = strlen(szFilename) + 1; 486 if (cchPath > cchBuf) 470 if (pszSuggestion) 471 { 472 /* 473 * Construct the filename and read the link. 474 */ 475 char szFilename[RTPATH_MAX]; 476 int rc = rtLinuxConstructPathV(szFilename, sizeof(szFilename), "/dev/", pszSuggestion, va); 477 if (rc == -1) 478 return -1; 479 480 /* 481 * Check whether the caller's suggestion was right. 482 */ 483 RTFSOBJINFO Info; 484 rc = RTPathQueryInfo(szFilename, &Info, RTFSOBJATTRADD_UNIX); 485 if (RT_FAILURE(rc)) 487 486 { 488 errno = EOVERFLOW; 487 /**@todo r=bird: This isn't exactly "tried before searching", it's more like "tried instead of searching"... */ 488 errno = rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND 489 ? ENOENT 490 : EIO; 489 491 return -1; 490 492 } 491 strcpy(pszBuf, szFilename); 492 return cchPath; 493 } 494 495 /* If the suggestion was wrong, try the brute force method */ 496 return rtLinuxFindDevicePathRecursive(devNum, fMode, "/dev/", 497 pszBuf, cchBuf); 498 } 499 500 501 RTDECL(ssize_t) RTLinuxFindDevicePath(dev_t devNum, RTFMODE fMode, 502 char *pszBuf, size_t cchBuf, 493 if ( Info.Attr.u.Unix.Device == DevNum 494 && (Info.Attr.fMode & RTFS_TYPE_MASK) == fMode) 495 { 496 size_t cchPath = strlen(szFilename); 497 if (cchPath >= cchBuf) 498 { 499 errno = EOVERFLOW; 500 return -1; 501 } 502 memcpy(pszBuf, szFilename, cchPath + 1); 503 return cchPath; 504 } 505 506 /* The suggestion was wrong, fall back on the brute force attack. */ 507 } 508 509 return rtLinuxFindDevicePathRecursive(DevNum, fMode, "/dev/", pszBuf, cchBuf); 510 } 511 512 513 RTDECL(ssize_t) RTLinuxFindDevicePath(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf, 503 514 const char *pszSuggestion, ...) 504 515 { 505 516 va_list va; 506 517 va_start(va, pszSuggestion); 507 int rc = RTLinuxFindDevicePathV(devNum, fMode, pszBuf, cchBuf, 508 pszSuggestion, va); 518 int rc = RTLinuxFindDevicePathV(DevNum, fMode, pszBuf, cchBuf, pszSuggestion, va); 509 519 va_end(va); 510 520 return rc; 511 521 } 522
Note:
See TracChangeset
for help on using the changeset viewer.