Changeset 32115 in vbox
- Timestamp:
- Aug 31, 2010 8:59:51 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/linux/HostHardwareLinux.cpp
r32079 r32115 59 59 60 60 #include <errno.h> 61 #include <dirent.h> 62 #include <limits.h> 63 #include <stdio.h> 64 #include <stdlib.h> 65 #include <sys/types.h> 61 66 62 67 /****************************************************************************** … … 106 111 } 107 112 113 /** Vector of char *-s for holding directory entries */ 114 #define VECTOR_TYPE char * 115 #define VECTOR_TYPENAME filePaths 116 static inline void filePathsCleanup(char **ppsz) 117 { 118 free(*ppsz); 119 } 120 #define VECTOR_DESTRUCTOR filePathsCleanup 121 #include "vector.h" 122 108 123 static int walkDirectory(const char *pcszPath, pathHandler *pHandler, 109 bool useRealPath); 110 static int getDeviceInfoFromSysfs(const char *pcszPath, pathHandler *pHandler); 124 int withRealPath); 111 125 # endif 112 126 #endif /* VBOX_USB_WITH_SYSFS */ … … 1366 1380 #ifdef VBOX_USB_WITH_SYSFS 1367 1381 # ifdef VBOX_USB_WITH_INOTIFY 1382 /** Helper for readFilePathsFromDir(). Adds a path to the vector if it is not 1383 * NULL and not a dotfile (".", "..", ".*"). */ 1384 static int maybeAddPathToVector(const char *pcszPath, const char *pcszEntry, 1385 filePaths *pvpchDevs) 1386 { 1387 filePaths_op_table *pOps = &filePaths_ops; 1388 char *pszPath; 1389 1390 if (!pcszPath) 1391 return 0; 1392 if (pcszEntry[0] == '.') 1393 return 0; 1394 pszPath = strdup(pcszPath); 1395 if (!pszPath) 1396 return ENOMEM; 1397 if (!pOps->push_back(pvpchDevs, &pszPath)) 1398 return ENOMEM; 1399 return 0; 1400 } 1401 1402 /** Helper for readFilePaths(). Adds the entries from the open directory 1403 * @a pDir to the vector @a pvpchDevs using either the full path or the 1404 * realpath() and skipping hidden files and files on which realpath() fails. */ 1405 static int readFilePathsFromDir(const char *pcszPath, DIR *pDir, 1406 filePaths *pvpchDevs, int withRealPath) 1407 { 1408 struct dirent entry, *pResult; 1409 int err; 1410 1411 for (err = readdir_r(pDir, &entry, &pResult); pResult; 1412 err = readdir_r(pDir, &entry, &pResult)) 1413 { 1414 /* We (implicitly) require that PATH_MAX be defined */ 1415 char szPath[PATH_MAX + 1], szRealPath[PATH_MAX + 1], *pszPath; 1416 if (snprintf(szPath, sizeof(szPath), "%s/%s", pcszPath, 1417 entry.d_name) < 0) 1418 return errno; 1419 if (withRealPath) 1420 pszPath = realpath(szPath, szRealPath); 1421 else 1422 pszPath = szPath; 1423 if ((err = maybeAddPathToVector(pszPath, entry.d_name, pvpchDevs))) 1424 return err; 1425 } 1426 return err; 1427 } 1428 1429 1368 1430 /** 1369 * Helper function to walk a directory, calling a function object on its files 1431 * Helper for walkDirectory to dump the names of a directory's entries into a 1432 * vector of char pointers. 1433 * 1434 * @returns zero on success or (positive) posix error value. 1435 * @param pcszPath the path to dump. 1436 * @param pvpchDevs an empty vector of char pointers - must be cleaned up 1437 * by the caller even on failure. 1438 * @param withRealPath whether to canonicalise the filename with realpath 1439 */ 1440 static int readFilePaths(const char *pcszPath, filePaths *pvpchDevs, 1441 int withRealPath) 1442 { 1443 filePaths_op_table *pOps = &filePaths_ops; 1444 DIR *pDir; 1445 int err; 1446 1447 AssertPtrReturn(pvpchDevs, EINVAL); 1448 AssertReturn(pOps->size(pvpchDevs) == 0, EINVAL); 1449 AssertPtrReturn(pcszPath, EINVAL); 1450 1451 pDir = opendir(pcszPath); 1452 if (!pDir) 1453 return errno; 1454 err = readFilePathsFromDir(pcszPath, pDir, pvpchDevs, withRealPath); 1455 if (closedir(pDir) < 0 && !err) 1456 err = errno; 1457 return err; 1458 } 1459 1460 1461 /** 1462 * Helper for walkDirectory to walk a set of files, calling a function 1463 * object on each. 1464 * 1465 * @returns zero on success or (positive) posix error value. 1466 * @param pcszPath the path of the directory 1467 * @param pvpchDevs vector of char strings containing the directory entry 1468 * names 1469 * @param pHandler Handler object which will be invoked on each file 1470 */ 1471 static int walkFiles(const char *pcszPath, filePaths *pvpchDevs, 1472 pathHandler *pHandler) 1473 { 1474 filePaths_op_table *pOps = &filePaths_ops; 1475 filePaths_iter_op_table *pItOps = &filePaths_iter_ops; 1476 filePaths_iterator it; 1477 1478 AssertPtrReturn(pvpchDevs, EINVAL); 1479 AssertPtrReturn(pHandler, EINVAL); 1480 1481 pItOps->init(&it, pOps->begin(pvpchDevs)); 1482 for (; !pItOps->eq(&it, pOps->end(pvpchDevs)); pItOps->incr(&it)) 1483 { 1484 const char *pszEntry; 1485 1486 pszEntry = *pItOps->target(&it); 1487 if (!pszEntry) 1488 return ENOMEM; 1489 if (!phDoHandle(pHandler, pszEntry)) 1490 break; 1491 } 1492 return 0; 1493 } 1494 1495 1496 /** 1497 * Walk a directory and applying a function object to each entry which doesn't 1498 * start with a dot. 1370 1499 * @returns iprt status code 1371 * @param pcszPath Directory to walk. 1372 * @param pHandler Handler object which will be invoked on each file 1373 * @param useRealPath Whether to resolve the filename to its real path 1374 * before calling the handler. In this case the target 1375 * must exist. 1376 * 1377 * @returns IPRT status code 1500 * @param pcszPath Directory to walk. May not be '/'-terminated. 1501 * @param pHandler Handler object which will be invoked on each 1502 * directoryentry 1503 * @param withRealPath Whether to apply realpath() to each entry before 1504 * invoking the handler 1378 1505 */ 1379 1506 /* static */ 1380 int walkDirectory(const char *pcszPath, pathHandler *pHandler, bool useRealPath) 1381 { 1507 int walkDirectory(const char *pcszPath, pathHandler *pHandler, int withRealPath) 1508 { 1509 filePaths vpchDevs; 1510 filePaths_init(&vpchDevs); 1511 int rc; 1512 1382 1513 AssertPtrReturn(pcszPath, VERR_INVALID_POINTER); 1383 AssertPtrReturn(pHandler, VERR_INVALID_POINTER); 1384 LogFlowFunc (("pcszPath=%s, pHandler=%p\n", pcszPath, pHandler)); 1385 PRTDIR pDir = NULL; 1386 int rc; 1387 1388 rc = RTDirOpen(&pDir, pcszPath); 1389 if (RT_FAILURE(rc)) 1390 return rc; 1391 while (RT_SUCCESS(rc)) 1392 { 1393 RTDIRENTRY entry; 1394 char szPath[RTPATH_MAX], szAbsPath[RTPATH_MAX]; 1395 1396 rc = RTDirRead(pDir, &entry, NULL); 1397 Assert(rc != VERR_BUFFER_OVERFLOW); /* Should never happen... */ 1398 /* We break on "no more files" as well as on "real" errors */ 1399 if (RT_FAILURE(rc)) 1400 break; 1401 if (entry.szName[0] == '.') 1402 continue; 1403 if (RTStrPrintf(szPath, sizeof(szPath), "%s/%s", pcszPath, 1404 entry.szName) >= sizeof(szPath)) 1405 rc = VERR_BUFFER_OVERFLOW; 1406 if (RT_FAILURE(rc)) 1407 break; 1408 if (useRealPath) 1409 { 1410 rc = RTPathReal(szPath, szAbsPath, sizeof(szAbsPath)); 1411 if (RT_FAILURE(rc)) 1412 break; /* The file can vanish if a device is unplugged. */ 1413 if (!phDoHandle(pHandler, szAbsPath)) 1414 break; 1415 } 1416 else 1417 if (!phDoHandle(pHandler, szPath)) 1418 break; 1419 } 1420 RTDirClose(pDir); 1421 if (rc == VERR_NO_MORE_FILES) 1422 rc = VINF_SUCCESS; 1423 LogFlow (("rc=%Rrc\n", rc)); 1424 return rc; 1425 } 1426 1427 1428 /** 1429 * Helper function to walk a sysfs directory for extracting information about 1430 * devices. 1431 * @returns iprt status code 1432 * @param pcszPath Sysfs directory to walk. Must exist. 1433 * @param pHandler Handler object which will be invoked on each directory 1434 * entry 1435 * 1436 * @returns IPRT status code 1437 */ 1438 /* static */ 1439 int getDeviceInfoFromSysfs(const char *pcszPath, pathHandler *pHandler) 1440 { 1441 return walkDirectory(pcszPath, pHandler, true); 1514 AssertReturn(pcszPath[strlen(pcszPath)] != '/', VERR_INVALID_PARAMETER); 1515 1516 rc = readFilePaths(pcszPath, &vpchDevs, withRealPath); 1517 if (!rc) 1518 rc = walkFiles(pcszPath, &vpchDevs, pHandler); 1519 filePaths_cleanup(&vpchDevs); 1520 return RTErrConvertFromErrno(rc); 1442 1521 } 1443 1522 … … 1488 1567 Assert(usbBusFromDevNum(makedev(USBDEVICE_MAJOR, 517)) == 5); 1489 1568 Assert(usbDeviceFromDevNum(makedev(USBDEVICE_MAJOR, 517)) == 6); 1490 AssertReturn (devnum, true); 1569 if (!devnum) 1570 return true; 1491 1571 char szDevPath[RTPATH_MAX]; 1492 1572 ssize_t cchDevPath; … … 1604 1684 matchUSBDevice devHandler; 1605 1685 mudInit(&devHandler, pList); 1606 int rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &devHandler.mParent);1686 int rc = walkDirectory("/sys/bus/usb/devices", &devHandler.mParent, true); 1607 1687 do { 1608 1688 if (RT_FAILURE(rc)) … … 1616 1696 matchUSBInterface ifaceHandler; 1617 1697 muiInit(&ifaceHandler, USBDeviceInfoList_iter_target(&info)); 1618 rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices",1619 &ifaceHandler.mParent);1698 rc = walkDirectory("/sys/bus/usb/devices", &ifaceHandler.mParent, 1699 true); 1620 1700 if (RT_FAILURE(rc)) 1621 1701 break;
Note:
See TracChangeset
for help on using the changeset viewer.