VirtualBox

Changeset 86239 in vbox


Ignore:
Timestamp:
Sep 23, 2020 2:23:22 PM (4 years ago)
Author:
vboxsync
Message:

IPRT: Some fixes to RTTimeZoneGetCurrent-posix.cpp and a basic testcase: ':' prefix in TZ value shouldn't be returned if we want. Don't read the /etc/localtime symlink, just pass it directly to RTPathReal (the symlink is often self-relative, i.e. ../usr/share/zoneinfo/x/y). Must terminate line buffer when reading /etc/timezone before using it. Share buffers to save stack space.

Location:
trunk/src/VBox/Runtime
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/RTTimeZoneGetCurrent-posix.cpp

    r86220 r86239  
    4242#include <iprt/stream.h>
    4343
    44 #if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD)
    45  #define TZDIR                   "/usr/share/zoneinfo"
    46  #define TZ_MAGIC                "TZif"
     44#if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)
     45# include <tzfile.h>
    4746#else
    48  #include <tzfile.h>
     47# define TZDIR                   "/usr/share/zoneinfo"
     48# define TZ_MAGIC                "TZif"
    4949#endif
    5050
     51
     52/*********************************************************************************************************************************
     53*   Defined Constants And Macros                                                                                                 *
     54*********************************************************************************************************************************/
    5155#define PATH_LOCALTIME           "/etc/localtime"
    5256#if defined(RT_OS_FREEBSD)
    53  #define PATH_TIMEZONE           "/var/db/zoneinfo"
     57# define PATH_TIMEZONE           "/var/db/zoneinfo"
    5458#else
    55  #define PATH_TIMEZONE           "/etc/timezone"
     59# define PATH_TIMEZONE           "/etc/timezone"
    5660#endif
    5761#define PATH_SYSCONFIG_CLOCK     "/etc/sysconfig/clock"
     
    6973static int rtIsValidTimeZoneFile(const char *pszTimeZone)
    7074{
    71     int rc;
    72 
    7375    if (pszTimeZone == NULL || *pszTimeZone == '\0' || *pszTimeZone == '/')
    7476        return VERR_INVALID_PARAMETER;
    7577
    76     /* POSIX allows $TZ to begin with a colon (:) so we allow for that here */
    77     if (*pszTimeZone == ':')
    78         pszTimeZone++;
    79 
    8078    /* construct full pathname of the time zone file */
    8179    char szTZPath[RTPATH_MAX];
    82     ssize_t cchStr = RTStrPrintf2(szTZPath, sizeof(szTZPath), "%s/%s", TZDIR, pszTimeZone);
    83     if (cchStr <= 0)
    84         return VERR_BUFFER_OVERFLOW;
    85 
    86     /* open the time zone file and check that it begins with the correct magic number */
    87     RTFILE hFile = NIL_RTFILE;
    88     rc = RTFileOpen(&hFile, szTZPath, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     80    int rc = RTPathJoin(szTZPath, sizeof(szTZPath), TZDIR, pszTimeZone);
    8981    if (RT_SUCCESS(rc))
    9082    {
    91         char achTZBuf[sizeof(TZ_MAGIC)];
    92 
    93         rc = RTFileRead(hFile, achTZBuf, sizeof(achTZBuf), NULL);
    94         if (RT_SUCCESS(rc))
    95         {
    96             if (RTStrNCmp(achTZBuf, RT_STR_TUPLE(TZ_MAGIC)))
    97             {
    98                 (void) RTFileClose(hFile);
    99                 return VERR_INVALID_MAGIC;
    100             }
    101         }
    102         (void) RTFileClose(hFile);
     83        /* open the time zone file and check that it begins with the correct magic number */
     84        RTFILE hFile = NIL_RTFILE;
     85        rc = RTFileOpen(&hFile, szTZPath, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     86        if (RT_SUCCESS(rc))
     87        {
     88            char achTZBuf[sizeof(TZ_MAGIC)];
     89            rc = RTFileRead(hFile, achTZBuf, sizeof(achTZBuf), NULL);
     90            RTFileClose(hFile);
     91            if (RT_SUCCESS(rc))
     92            {
     93                if (memcmp(achTZBuf, RT_STR_TUPLE(TZ_MAGIC)) == 0)
     94                    rc = VINF_SUCCESS;
     95                else
     96                    rc = VERR_INVALID_MAGIC;
     97            }
     98        }
    10399    }
    104100
     
    126122         * to the other mechanisms to return the system's current time zone.
    127123         */
     124        if (*pszName == ':') /* POSIX allows $TZ to begin with a colon (:) so we allow for that here */
     125            memmove(pszName, pszName + 1, strlen(pszName));
     126        /** @todo this isn't perfect for absolute paths... Should probably try treat
     127         *        it like /etc/localtime. */
    128128        rc = rtIsValidTimeZoneFile(pszName);
    129129        if (RT_SUCCESS(rc))
     
    144144     * specifying the system-wide time zone for the sake of simplicity.
    145145     */
     146    char szBuf[RTPATH_MAX];
    146147    const char *pszPath = PATH_LOCALTIME;
    147148    if (RTSymlinkExists(pszPath))
    148149    {
    149         char szLinkPath[RTPATH_MAX];
    150 
    151         rc = RTSymlinkRead(pszPath, szLinkPath, sizeof(szLinkPath), 0);
    152         if (RT_SUCCESS(rc))
    153         {
    154             char szLinkPathReal[RTPATH_MAX];
    155 
    156             /* the contents of the symink may contain '..' or other links */
    157             rc = RTPathReal(szLinkPath, szLinkPathReal, sizeof(szLinkPathReal));
     150        /* the contents of the symink may contain '..' or other links */
     151        char szLinkPathReal[RTPATH_MAX];
     152        rc = RTPathReal(pszPath, szLinkPathReal, sizeof(szLinkPathReal));
     153        if (RT_SUCCESS(rc))
     154        {
     155            rc = RTPathReal(TZDIR, szBuf, sizeof(szBuf));
     156            AssertRC(rc);
    158157            if (RT_SUCCESS(rc))
    159158            {
    160                 char szTZDirPathReal[RTPATH_MAX];
    161 
    162                 rc = RTPathReal(TZDIR, szTZDirPathReal, sizeof(szTZDirPathReal));
    163                 if (RT_SUCCESS(rc)) {
     159                Assert(RTPathStartsWith(szLinkPathReal, szBuf));
     160                if (RTPathStartsWith(szLinkPathReal, szBuf))
     161                {
    164162                    /* <tzfile.h>:TZDIR doesn't include a trailing slash */
    165                     rc = rtIsValidTimeZoneFile(szLinkPathReal + strlen(szTZDirPathReal) + 1);
     163                    const char *pszTimeZone = &szLinkPathReal[strlen(szBuf) + 1];
     164                    rc = rtIsValidTimeZoneFile(pszTimeZone);
    166165                    if (RT_SUCCESS(rc))
    167                         return RTStrCopy(pszName, cbName, szLinkPathReal + strlen(szTZDirPathReal) + 1);
     166                        return RTStrCopy(pszName, cbName, pszTimeZone);
    168167                }
    169168            }
    170169        }
    171         return rc;
    172170    }
    173171
     
    185183        if (RT_SUCCESS(rc))
    186184        {
    187             char achBuf[_1K];
    188185            size_t cbRead = 0;
    189 
    190             rc = RTFileRead(hFile, achBuf, sizeof(achBuf), &cbRead);
     186            rc = RTFileRead(hFile, szBuf, sizeof(szBuf), &cbRead);
     187            RTFileClose(hFile);
    191188            if (RT_SUCCESS(rc) && cbRead > 0)
    192189            {
    193                 size_t offNewLine = RTStrOffCharOrTerm(achBuf, '\n');
    194                 /* in case no newline or terminating NULL is found */
    195                 offNewLine = RT_MIN(offNewLine, sizeof(achBuf) - 1);
    196                 achBuf[offNewLine] = '\0';
    197 
    198                 rc = rtIsValidTimeZoneFile(achBuf);
     190                /* Get the first line and strip it. */
     191                szBuf[RT_MIN(sizeof(szBuf) - 1, cbRead)] = '\0';
     192                size_t const offNewLine = RTStrOffCharOrTerm(szBuf, '\n');
     193                szBuf[offNewLine] = '\0';
     194                const char *pszTimeZone = RTStrStrip(szBuf);
     195
     196                rc = rtIsValidTimeZoneFile(pszTimeZone);
     197                /** @todo UTF-8 encoding. */
    199198                if (RT_SUCCESS(rc))
    200                 {
    201                     (void) RTFileClose(hFile);
    202                     return RTStrCopy(pszName, cbName, achBuf);
    203                 }
    204             }
    205             (void) RTFileClose(hFile);
    206         }
    207         return rc;
     199                    return RTStrCopy(pszName, cbName, pszTimeZone);
     200            }
     201        }
    208202    }
    209203
     
    217211    {
    218212        PRTSTREAM pStrm;
    219 
    220213        rc = RTStrmOpen(pszPath, "r", &pStrm);
    221214        if (RT_SUCCESS(rc))
    222215        {
    223             char szLine[_1K];
    224 
    225             while (RT_SUCCESS(rc = RTStrmGetLine(pStrm, szLine, sizeof(szLine))))
    226             {
    227                 if (RTStrNCmp(szLine, RT_STR_TUPLE("ZONE=")))
    228                     continue;
    229 
    230                 rc = rtIsValidTimeZoneFile(szLine + strlen("ZONE="));
    231                 if (RT_SUCCESS(rc))
     216            while (RT_SUCCESS(rc = RTStrmGetLine(pStrm, szBuf, sizeof(szBuf))))
     217            {
     218                static char const s_szVarEq[] = "ZONE=";
     219                if (memcmp(szBuf, RT_STR_TUPLE(s_szVarEq)) == 0)
    232220                {
    233                     RTStrmClose(pStrm);
    234                     return RTStrCopy(pszName, cbName, szLine + strlen("ZONE="));
     221                    const char *pszTimeZone = &szBuf[sizeof(s_szVarEq) - 1];
     222                    rc = rtIsValidTimeZoneFile(pszTimeZone);
     223                    if (RT_SUCCESS(rc))
     224                    {
     225                        RTStrmClose(pStrm);
     226                        /** @todo UTF-8 encoding. */
     227                        return RTStrCopy(pszName, cbName, pszTimeZone);
     228                    }
    235229                }
    236230            }
    237231            RTStrmClose(pStrm);
    238232        }
    239         return rc;
    240233    }
    241234
  • trunk/src/VBox/Runtime/testcase/tstRTTimeSpec.cpp

    r82968 r86239  
    707707    RTTESTI_CHECK_FROM(RTTimeFromRfc2822(&T2, " 00006 Sep 2018 04:09:08 GMT "));
    708708
     709    /*
     710     * Check that RTTimeZoneGetCurrent works (not really timespec, but whatever).
     711     */
     712    RTTestSub(hTest, "RTTimeZoneGetCurrent");
     713    szValue[0] = '\0';
     714    RTTESTI_CHECK_RC(RTTimeZoneGetCurrent(szValue, sizeof(szValue)), VINF_SUCCESS);
     715    RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "TimeZone: %s", szValue);
    709716
    710717    /*
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