VirtualBox

Changeset 15644 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Dec 18, 2008 11:16:58 AM (16 years ago)
Author:
vboxsync
Message:

IPRT: sysfs review, fixes and cleanup.

File:
1 edited

Legend:

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

    r15399 r15644  
    3434*******************************************************************************/
    3535#define LOG_GROUP RTLOGGROUP_SYSTEM
     36#include <iprt/linux/sysfs.h>
     37#include <iprt/assert.h>
     38#include <iprt/param.h>
     39#include <iprt/path.h>
     40#include <iprt/string.h>
     41
    3642#include <unistd.h>
    3743#include <stdio.h>
     
    4147#include <errno.h>
    4248
    43 #include <iprt/linux/sysfs.h>
    44 #include <iprt/assert.h>
    45 #include <iprt/param.h>
    46 #include <iprt/string.h>
    47 
    4849
    4950/**
     
    5152 * prepending "/sys/" if the path is relative.
    5253 *
    53  * @returns The number of characters written, or -1 and errno on failure.
     54 * @returns The number of characters returned, or -1 and errno set to ERANGE on
     55 *        failure.
     56 *
    5457 * @param   pszBuf     Where to write the path.  Must be at least
    5558 *                     sizeof("/sys/") characters long
    56  * @param   cchBuf     The size of the buffer pointed to by @a pszBuf
     59 * @param   cchBuf     The size of the buffer pointed to by @a pszBuf.
    5760 * @param   pszFormat  The name format, either absolute or relative to "/sys/".
    5861 * @param   va         The format args.
    5962 */
    60 static ssize_t rtLinuxSysFsConstructPath(char *pszBuf, size_t cchBuf,
    61                                          const char *pszFormat, va_list va)
    62 {
     63static ssize_t rtLinuxSysFsConstructPath(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va)
     64{
     65    static const char s_szPrefix[] = "/sys/";
     66    AssertReturnStmt(cchBuf > sizeof(s_szPrefix), errno = ERANGE, -1);
     67
     68    size_t cch = RTStrPrintfV(pszBuf, cchBuf, pszFormat, va);
     69    if (*pszBuf != '/')
     70    {
     71        AssertReturnStmt(cchBuf >= cch + sizeof(s_szPrefix), errno = ERANGE, -1);
     72        memmove(pszBuf + sizeof(s_szPrefix) - 1, pszBuf, cch + 1);
     73        memcpy(pszBuf, s_szPrefix, sizeof(s_szPrefix) - 1);
     74        cch += sizeof(s_szPrefix) - 1;
     75    }
     76    return cch;
     77}
     78
     79
     80RTDECL(bool) RTLinuxSysFsExistsV(const char *pszFormat, va_list va)
     81{
     82    int iSavedErrno = errno;
     83
     84    /*
     85     * Construct the filename and call stat.
     86     */
     87    bool fRet = false;
    6388    char szFilename[RTPATH_MAX];
    64     const char szPrefix[] = "/sys/";
    65     if (cchBuf < sizeof(szPrefix))
    66         AssertFailedReturnStmt(errno = EINVAL, -1);
    67     size_t cch = RTStrPrintfV(szFilename, sizeof(szFilename), pszFormat, va);
    68     if (szFilename[0] == '/')
    69         *pszBuf = '\0';
    70     else
    71         strcpy(pszBuf, szPrefix);
    72     strncat(pszBuf, szFilename, cchBuf);
    73     return strlen(pszBuf);
    74 }
    75 
    76 /**
    77  * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
    78  *
    79  * @returns true / false, errno is preserved.
    80  * @param   pszFormat   The name format, either absolute or relative to "/sys/".
    81  * @param   va          The format args.
    82  */
    83 bool RTLinuxSysFsExistsV(const char *pszFormat, va_list va)
    84 {
    85     int iSavedErrno = errno;
    86 
    87     /*
    88      * Construct the filename and call stat.
    89      */
    90     char szFilename[RTPATH_MAX];
    91     bool fRet = false;
    92     ssize_t rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename),
    93                                            pszFormat, va);
    94     if (rc > 0 && static_cast<size_t>(rc) < sizeof(szFilename))
     89    ssize_t rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va);
     90    if (rc != -1)
    9591    {
    9692        struct stat st;
     
    10298}
    10399
    104 /**
    105  * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
    106  *
    107  * @returns true / false, errno is preserved.
    108  * @param   pszFormat   The name format, either absolute or relative to "/sys/".
    109  * @param   ...         The format args.
    110  */
    111 bool RTLinuxSysFsExists(const char *pszFormat, ...)
     100
     101RTDECL(bool) RTLinuxSysFsExists(const char *pszFormat, ...)
    112102{
    113103    va_list va;
     
    119109
    120110
    121 /**
    122  * Opens a sysfs file.
    123  *
    124  * @returns The file descriptor. -1 and errno on failure.
    125  * @param   pszFormat   The name format, either absolute or relative to "/sys/".
    126  * @param   va          The format args.
    127  */
    128 int RTLinuxSysFsOpenV(const char *pszFormat, va_list va)
     111RTDECL(int) RTLinuxSysFsOpenV(const char *pszFormat, va_list va)
    129112{
    130113    /*
     
    132115     */
    133116    char szFilename[RTPATH_MAX];
    134     ssize_t rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename),
    135                                            pszFormat, va);
    136     if (rc > 0 && static_cast<size_t>(rc) < sizeof(szFilename))
     117    ssize_t rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va);
     118    if (rc != -1)
    137119        rc = open(szFilename, O_RDONLY, 0);
    138120    return rc;
     
    140122
    141123
    142 /**
    143  * Opens a sysfs file.
    144  *
    145  * @returns The file descriptor. -1 and errno on failure.
    146  * @param   pszFormat   The name format, either absolute or relative to "/sys/".
    147  * @param   ...         The format args.
    148  */
    149 int RTLinuxSysFsOpen(const char *pszFormat, ...)
     124RTDECL(int) RTLinuxSysFsOpen(const char *pszFormat, ...)
    150125{
    151126    va_list va;
     
    157132
    158133
    159 /**
    160  * Closes a file opened with RTLinuxSysFsOpen or RTLinuxSysFsOpenV.
    161  *
    162  * @param   fd
    163  */
    164 void RTLinuxSysFsClose(int fd)
     134RTDECL(void) RTLinuxSysFsClose(int fd)
    165135{
    166136    int iSavedErrno = errno;
     
    170140
    171141
    172 /**
    173  * Reads a string from a file opened with RTLinuxSysFsOpen or RTLinuxSysFsOpenV.
    174  *
    175  * @returns The number of bytes read. -1 and errno on failure.
    176  * @param   fd          The file descriptor returned by RTLinuxSysFsOpen or RTLinuxSysFsOpenV.
    177  * @param   pszBuf      Where to store the string.
    178  * @param   cchBuf      The size of the buffer. Must be at least 2 bytes.
    179  */
    180 ssize_t RTLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf)
     142RTDECL(ssize_t) RTLinuxSysFsReadStr(int fd, char *pszBuf, size_t cchBuf)
    181143{
    182144    Assert(cchBuf > 1);
     
    187149
    188150
    189 /**
    190  * Reads a number from a sysfs file.
    191  *
    192  * @returns 64-bit signed value on success, -1 and errno on failure.
    193  * @param   uBase       The number base, 0 for autodetect.
    194  * @param   pszFormat   The filename format, either absolute or relative to "/sys/".
    195  * @param   va          Format args.
    196  */
    197 int64_t RTLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va)
     151RTDECL(int64_t) RTLinuxSysFsReadIntFileV(unsigned uBase, const char *pszFormat, va_list va)
    198152{
    199153    int fd = RTLinuxSysFsOpenV(pszFormat, va);
     
    221175
    222176
    223 /**
    224  * Reads a number from a sysfs file.
    225  *
    226  * @returns 64-bit signed value on success, -1 and errno on failure.
    227  * @param   uBase       The number base, 0 for autodetect.
    228  * @param   pszFormat   The filename format, either absolute or relative to "/sys/".
    229  * @param   ...         Format args.
    230  */
    231 int64_t RTLinuxSysFsReadIntFile(unsigned uBase, const char *pszFormat, ...)
     177RTDECL(int64_t) RTLinuxSysFsReadIntFile(unsigned uBase, const char *pszFormat, ...)
    232178{
    233179    va_list va;
     
    239185
    240186
    241 /**
    242  * Reads a string from a sysfs file.  If the file contains a newline, we only
    243  * return the text up until there.
    244  *
    245  * @returns number of characters read on success, -1 and errno on failure.
    246  * @param   pszBuf      Where to store the path element.  Must be at least two
    247  *                      characters, but a longer buffer would be advisable.
    248  * @param   cchBuf      The size of the buffer pointed to by @a pszBuf.
    249  * @param   pszFormat   The filename format, either absolute or relative to "/sys/".
    250  * @param   va          Format args.
    251  */
    252 ssize_t RTLinuxSysFsReadStrFileV(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va)
     187RTDECL(ssize_t) RTLinuxSysFsReadStrFileV(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va)
    253188{
    254189    int fd = RTLinuxSysFsOpenV(pszFormat, va);
     
    258193    ssize_t cchRet = RTLinuxSysFsReadStr(fd, pszBuf, cchBuf);
    259194    RTLinuxSysFsClose(fd);
    260     char *pchNewLine = NULL;
    261195    if (cchRet > 0)
    262         pchNewLine = reinterpret_cast<char *>(memchr(pszBuf, '\n', cchRet));
    263     if (pchNewLine != NULL)
    264         *pchNewLine = '\0';
     196    {
     197        char *pchNewLine = (char *)memchr(pszBuf, '\n', cchRet);
     198        if (pchNewLine)
     199            *pchNewLine = '\0';
     200    }
    265201    return cchRet;
    266202}
    267203
    268204
    269 /**
    270  * Reads a string from a sysfs file.  If the file contains a newline, we only
    271  * return the text up until there.
    272  *
    273  * @returns number of characters read on success, -1 and errno on failure.
    274  * @param   pszBuf      Where to store the path element.  Must be at least two
    275  *                      characters, but a longer buffer would be advisable.
    276  * @param   cchBuf      The size of the buffer pointed to by @a pszBuf.
    277  * @param   pszFormat   The filename format, either absolute or relative to "/sys/".
    278  * @param   ...         Format args.
    279  */
    280 ssize_t RTLinuxSysFsReadStrFile(char *pszBuf, size_t cchBuf, const char *pszFormat, ...)
     205RTDECL(ssize_t) RTLinuxSysFsReadStrFile(char *pszBuf, size_t cchBuf, const char *pszFormat, ...)
    281206{
    282207    va_list va;
     
    288213
    289214
    290 /**
    291  * Reads the last element of the path of the file pointed to by the symbolic
    292  * link specified.  This is needed at least to get the name of the driver
    293  * associated with a device, where pszFormat should be the "driver" link in the
    294  * devices sysfs directory.
    295  *
    296  * @returns The number of characters written on success, -1 and errno on failure.
    297  * @param   pszBuf      Where to store the path element.  Must be at least two
    298  *                      characters, but a longer buffer would be advisable.
    299  * @param   cchBuf      The size of the buffer pointed to by @a pszBuf.
    300  * @param   pszFormat   The filename format, either absolute or relative to "/sys/".
    301  * @param   ...         Format args.
    302  */
    303 int RTLinuxSysFsGetLinkDest(char *pszBuf, size_t cchBuf, const char *pszFormat, ...)
    304 {
    305     if (cchBuf < 2)
    306         AssertFailedReturnStmt(errno = EINVAL, -1);
    307     va_list va;
    308     va_start(va, pszFormat);
    309     char szFilename[RTPATH_MAX], szLink[RTPATH_MAX];
     215RTDECL(ssize_t) RTLinuxSysFsGetLinkDestV(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va)
     216{
     217    AssertReturnStmt(cchBuf >= 2, errno = EINVAL, -1);
     218
     219    /*
     220     * Construct the filename and read the link.
     221     */
     222    char szFilename[RTPATH_MAX];
    310223    int rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va);
    311     va_end(va);
    312     if (rc == sizeof(szFilename))
    313     {
    314         rc = -1;
    315         errno = EINVAL;  /* Bad format arguements */
    316     }
    317     if (rc > 0)
    318         rc = readlink(szFilename, szLink, sizeof(szLink));
    319     if (rc > 0 && static_cast<size_t>(rc) > sizeof(szLink) - 1)
    320     {
    321         rc = -1;
    322         errno = EIO;  /* The path name can't be this big. */
    323     }
    324     if (rc >= 0)
    325     {
    326         szLink[rc] = '\0';
    327         char *lastPart = strrchr(szLink, '/');
    328         Assert(lastPart != NULL);  /* rtLinuxSysFsConstructPath guarantees a path
    329                                     * starting with '/'. */
     224    if (rc == -1)
     225        return -1;
     226
     227    char szLink[RTPATH_MAX];
     228    rc = readlink(szFilename, szLink, sizeof(szLink));
     229    if (rc == -1)
     230        return -1;
     231    if ((size_t)rc > sizeof(szLink) - 1)
     232    {
     233        errno = ERANGE;
     234        return -1;
     235    }
     236    szLink[rc] = '\0'; /* readlink fun. */
     237
     238    /*
     239     * Extract the file name component and copy it into the return buffer.
     240     */
     241    size_t cchName;
     242    const char *pszName = RTPathFilename(szLink);
     243    if (pszName)
     244    {
     245        cchName = strlen(pszName);
     246        if (cchName >= cchBuf)
     247        {
     248            errno = ERANGE;
     249            return -1;
     250        }
     251        memcpy(pszBuf, pszName, cchName);
     252    }
     253    else
     254    {
    330255        *pszBuf = '\0';
    331         strncat(pszBuf, lastPart + 1, cchBuf);
    332         rc = strlen(pszBuf);
    333     }
     256        cchName = 0;
     257    }
     258    return cchName;
     259}
     260
     261
     262RTDECL(ssize_t) RTLinuxSysFsGetLinkDest(char *pszBuf, size_t cchBuf, const char *pszFormat, ...)
     263{
     264    va_list va;
     265    va_start(va, pszFormat);
     266    int rc = RTLinuxSysFsGetLinkDestV(pszBuf, cchBuf, pszFormat, va);
     267    va_end(va);
    334268    return rc;
    335269}
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