VirtualBox

Changeset 32115 in vbox


Ignore:
Timestamp:
Aug 31, 2010 8:59:51 AM (14 years ago)
Author:
vboxsync
Message:

Main/HostHardwareLinux: directory enumeration clean-up

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/linux/HostHardwareLinux.cpp

    r32079 r32115  
    5959
    6060#include <errno.h>
     61#include <dirent.h>
     62#include <limits.h>
     63#include <stdio.h>
     64#include <stdlib.h>
     65#include <sys/types.h>
    6166
    6267/******************************************************************************
     
    106111}
    107112
     113/** Vector of char *-s for holding directory entries */
     114#define VECTOR_TYPE       char *
     115#define VECTOR_TYPENAME   filePaths
     116static inline void filePathsCleanup(char **ppsz)
     117{
     118    free(*ppsz);
     119}
     120#define VECTOR_DESTRUCTOR filePathsCleanup
     121#include "vector.h"
     122
    108123static int walkDirectory(const char *pcszPath, pathHandler *pHandler,
    109                          bool useRealPath);
    110 static int getDeviceInfoFromSysfs(const char *pcszPath, pathHandler *pHandler);
     124                         int withRealPath);
    111125# endif
    112126#endif /* VBOX_USB_WITH_SYSFS */
     
    13661380#ifdef VBOX_USB_WITH_SYSFS
    13671381# 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 (".", "..", ".*"). */
     1384static 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. */
     1405static 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
    13681430/**
    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 */
     1440static 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 */
     1471static 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.
    13701499 * @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
    13781505 */
    13791506/* static */
    1380 int walkDirectory(const char *pcszPath, pathHandler *pHandler, bool useRealPath)
    1381 {
     1507int walkDirectory(const char *pcszPath, pathHandler *pHandler, int withRealPath)
     1508{
     1509    filePaths vpchDevs;
     1510    filePaths_init(&vpchDevs);
     1511    int rc;
     1512
    13821513    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);
    14421521}
    14431522
     
    14881567    Assert(usbBusFromDevNum(makedev(USBDEVICE_MAJOR, 517)) == 5);
    14891568    Assert(usbDeviceFromDevNum(makedev(USBDEVICE_MAJOR, 517)) == 6);
    1490     AssertReturn (devnum, true);
     1569    if (!devnum)
     1570        return true;
    14911571    char szDevPath[RTPATH_MAX];
    14921572    ssize_t cchDevPath;
     
    16041684    matchUSBDevice devHandler;
    16051685    mudInit(&devHandler, pList);
    1606     int rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &devHandler.mParent);
     1686    int rc = walkDirectory("/sys/bus/usb/devices", &devHandler.mParent, true);
    16071687    do {
    16081688        if (RT_FAILURE(rc))
     
    16161696            matchUSBInterface ifaceHandler;
    16171697            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);
    16201700            if (RT_FAILURE(rc))
    16211701                break;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette