VirtualBox

Changeset 23332 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 25, 2009 1:26:57 PM (15 years ago)
Author:
vboxsync
Message:

iprt/linux/sysfs.h/cpp: code review, fixing RTLinuxSysFsGetLinkDest[V] termination issue, use RTPathAppend as rtLinuxConstructPath[V] isn't entirely safe, RTLinuxFindDevicePath[V] return value clearification, code style cleanups. Untested.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/linux/sysfs.cpp

    r23309 r23332  
    5050#include <errno.h>
    5151
     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
    5255
    5356/**
     
    5659 *
    5760 * @returns The number of characters returned, or -1 and errno set to ERANGE on
    58  *        failure.
     61 *          failure.
    5962 *
    6063 * @param   pszPrefix  The prefix to prepend if the path is relative.  Must end
     
    6366 *                     sizeof(@a pszPrefix) characters long
    6467 * @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.
    6670 * @param   va         The format args.
    6771 */
     
    7478    AssertReturnStmt(cchBuf > cchPrefix + 1, errno = ERANGE, -1);
    7579
     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. */
    7684    size_t cch = RTStrPrintfV(pszBuf, cchBuf, pszFormat, va);
    7785    if (*pszBuf != '/')
     
    245253        return 0;
    246254
    247     dev_t devNum = 0;
     255    dev_t DevNum = 0;
    248256    char szNum[128];
    249257    ssize_t cchNum = RTLinuxSysFsReadStr(fd, szNum, sizeof(szNum));
     
    266274            {
    267275                errno = 0;
    268                 devNum = makedev(u32Maj, u32Min);
     276                DevNum = makedev(u32Maj, u32Min);
    269277            }
    270278        }
     
    274282
    275283    RTLinuxSysFsClose(fd);
    276     return devNum;
     284    return DevNum;
    277285}
    278286
     
    282290    va_list va;
    283291    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;
    287295}
    288296
     
    346354    if (pszName)
    347355    {
    348         cchName = strlen(pszName);
     356        cchName = strlen(pszName); /* = &szLink[rc] - pszName; */
    349357        if (cchName >= cchBuf)
    350358        {
     
    352360            return -1;
    353361        }
    354         memcpy(pszBuf, pszName, cchName);
     362        memcpy(pszBuf, pszName, cchName + 1);
    355363    }
    356364    else
     
    373381
    374382
    375 static ssize_t rtLinuxFindDevicePathRecursive(dev_t devNum, RTFMODE fMode,
    376                                               const char *pszBasePath,
     383static ssize_t rtLinuxFindDevicePathRecursive(dev_t DevNum, RTFMODE fMode, const char *pszBasePath,
    377384                                              char *pszBuf, size_t cchBuf)
    378385{
    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 (;;)
    387402        {
    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))
    390406            {
    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;
    395413                break;
    396414            }
    397             if (RTFS_IS_SYMLINK(entry.Info.Attr.fMode))
     415            if (RTFS_IS_SYMLINK(Entry.Info.Attr.fMode)) /* paranoia */
    398416                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)
    404421            {
    405                 rc = rtLinuxConstructPath(pszBuf, cchBuf, pszBasePath, "%s",
    406                                           entry.szName);
     422                rcRet = rtLinuxConstructPath(pszBuf, cchBuf, pszBasePath, "%s", Entry.szName);
    407423                break;
    408424            }
    409             if (!RTFS_IS_DIRECTORY(entry.Info.Attr.fMode))
     425
     426            /* Recurse into subdirectories. */
     427            if (!RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode))
    410428                continue;
    411             if (entry.szName[0] == '.')
     429            if (Entry.szName[0] == '.')
    412430                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;
    419438                break;
     439            }
     440#if 1 /** @todo This is a temporary hack, as RTDirReadEx in 3.0 doesn't know about symbolic links. */
    420441            struct stat Stat = { 0 };
    421442            if (   lstat(szPath, &Stat) < 0
    422443                || S_ISLNK(Stat.st_mode))
    423444                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)
    432449                break;
    433450        }
     451        RTDirClose(pDir);
     452    }
    434453    else
    435454    {
    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
     462RTDECL(ssize_t) RTLinuxFindDevicePathV(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf,
    446463                                       const char *pszSuggestion, va_list va)
    447464{
    448465    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,
    451468                     errno = EINVAL, -1);
    452469
    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))
    487486        {
    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;
    489491            return -1;
    490492        }
    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
     513RTDECL(ssize_t) RTLinuxFindDevicePath(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf,
    503514                                      const char *pszSuggestion, ...)
    504515{
    505516    va_list va;
    506517    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);
    509519    va_end(va);
    510520    return rc;
    511521}
     522
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