VirtualBox

Changeset 23291 in vbox for trunk/src


Ignore:
Timestamp:
Sep 24, 2009 4:08:19 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
52784
Message:

IPRT: RTPathQueryInfo and RTPathSetTimes should work on symbolic links when specified. Introduced Ex versions of these to work around this issue. Should also address the lack of symlinks in the RTDirReadEx output as well VWRN_NO_DIRENT_INFO on broken links.

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

Legend:

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

    r20819 r23291  
    463463RTR3DECL(int) RTPathQueryInfo(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
    464464{
     465    return RTPathQueryInfoEx(pszPath, pObjInfo, enmAdditionalAttribs, RTPATH_F_ON_LINK);
     466}
     467
     468
     469RTR3DECL(int) RTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
     470{
    465471    /*
    466472     * Validate input.
    467473     */
    468     AssertMsgReturn(VALID_PTR(pszPath), ("%p\n", pszPath), VERR_INVALID_POINTER);
     474    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    469475    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
    470     AssertMsgReturn(VALID_PTR(pObjInfo), ("%p\n", pszPath), VERR_INVALID_POINTER);
     476    AssertPtrReturn(pObjInfo, VERR_INVALID_POINTER);
    471477    AssertMsgReturn(    enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING
    472478                    &&  enmAdditionalAttribs <= RTFSOBJATTRADD_LAST,
    473479                    ("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs),
    474480                    VERR_INVALID_PARAMETER);
     481    AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    475482
    476483    /*
     
    482489    {
    483490        struct stat Stat;
    484         if (!stat(pszNativePath, &Stat))
     491        if (fFlags & RTPATH_F_FOLLOW_LINK)
     492            rc = stat(pszNativePath, &Stat);
     493        else
     494            rc = lstat(pszNativePath, &Stat); /** @todo how doesn't have lstat again? */
     495        if (!rc)
    485496        {
    486497            rtFsConvertStatToObjInfo(pObjInfo, &Stat, pszPath, 0);
     
    517528                             PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
    518529{
     530    return RTPathSetTimesEx(pszPath, pAccessTime, pModificationTime, pChangeTime, pBirthTime, RTPATH_F_ON_LINK);
     531}
     532
     533
     534RTR3DECL(int) RTPathSetTimesEx(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
     535                               PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags)
     536{
    519537    /*
    520538     * Validate input.
    521539     */
    522     AssertMsgReturn(VALID_PTR(pszPath), ("%p\n", pszPath), VERR_INVALID_POINTER);
    523     AssertMsgReturn(*pszPath, ("%p\n", pszPath), VERR_INVALID_PARAMETER);
    524     AssertMsgReturn(!pAccessTime || VALID_PTR(pAccessTime), ("%p\n", pAccessTime), VERR_INVALID_POINTER);
    525     AssertMsgReturn(!pModificationTime || VALID_PTR(pModificationTime), ("%p\n", pModificationTime), VERR_INVALID_POINTER);
    526     AssertMsgReturn(!pChangeTime || VALID_PTR(pChangeTime), ("%p\n", pChangeTime), VERR_INVALID_POINTER);
    527     AssertMsgReturn(!pBirthTime || VALID_PTR(pBirthTime), ("%p\n", pBirthTime), VERR_INVALID_POINTER);
     540    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     541    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
     542    AssertPtrNullReturn(pAccessTime, VERR_INVALID_POINTER);
     543    AssertPtrNullReturn(pModificationTime, VERR_INVALID_POINTER);
     544    AssertPtrNullReturn(pChangeTime, VERR_INVALID_POINTER);
     545    AssertPtrNullReturn(pBirthTime, VERR_INVALID_POINTER);
     546    AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    528547
    529548    /*
     
    534553    if (RT_SUCCESS(rc))
    535554    {
     555        RTFSOBJINFO ObjInfo;
     556
    536557        /*
    537558         * If it's a no-op, we'll only verify the existance of the file.
    538559         */
    539560        if (!pAccessTime && !pModificationTime)
    540         {
    541             struct stat Stat;
    542             if (!stat(pszNativePath, &Stat))
    543                 rc = VINF_SUCCESS;
    544             else
    545             {
    546                 rc = RTErrConvertFromErrno(errno);
    547                 Log(("RTPathSetTimes('%s',,,,): failed with %Rrc and errno=%d\n", pszPath, rc, errno));
    548             }
    549         }
     561            rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, fFlags);
    550562        else
    551563        {
     
    562574            else
    563575            {
    564                 RTFSOBJINFO ObjInfo;
    565                 int rc = RTPathQueryInfo(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX);
     576                rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, fFlags);
    566577                if (RT_SUCCESS(rc))
    567578                {
     
    575586            if (RT_SUCCESS(rc))
    576587            {
    577                 if (utimes(pszNativePath, aTimevals))
     588                if (fFlags & RTPATH_F_FOLLOW_LINK)
    578589                {
    579                     rc = RTErrConvertFromErrno(errno);
     590                    if (utimes(pszNativePath, aTimevals))
     591                        rc = RTErrConvertFromErrno(errno);
     592                }
     593#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX) || defined(RT_OS_OS2) /** @todo who really has lutimes? */
     594                else
     595                {
     596                    if (lutimes(pszNativePath, aTimevals))
     597                        rc = RTErrConvertFromErrno(errno);
     598                }
     599#else
     600                else
     601                {
     602                    if (pAccessTime && pModificationTime)
     603                        rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, fFlags);
     604                    if (RT_SUCCESS(rc) && RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
     605                        rc = VERR_NS_SYMLINK_SET_TIME;
     606                    else if (RT_SUCCESS(rc))
     607                    {
     608                        if (utimes(pszNativePath, aTimevals))
     609                            rc = RTErrConvertFromErrno(errno);
     610                    }
     611                }
     612#endif
     613                if (RT_FAILURE(rc))
    580614                    Log(("RTPathSetTimes('%s',%p,%p,,): failed with %Rrc and errno=%d\n",
    581615                         pszPath, pAccessTime, pModificationTime, rc, errno));
    582                 }
    583616            }
    584617        }
     
    788821RTDECL(bool) RTPathExists(const char *pszPath)
    789822{
     823    return RTPathExistsEx(pszPath, RTPATH_F_FOLLOW_LINK);
     824}
     825
     826
     827RTDECL(bool) RTPathExistsEx(const char *pszPath, uint32_t fFlags)
     828{
    790829    /*
    791830     * Validate input.
     
    793832    AssertPtrReturn(pszPath, false);
    794833    AssertReturn(*pszPath, false);
     834    Assert(RTPATH_F_IS_VALID(fFlags, 0));
    795835
    796836    /*
     
    802842    {
    803843        struct stat Stat;
    804         if (!stat(pszNativePath, &Stat))
     844        if (fFlags & RTPATH_F_FOLLOW_LINK)
     845            rc = stat(pszNativePath, &Stat);
     846        else
     847            rc = lstat(pszNativePath, &Stat);
     848        if (!rc)
    805849            rc = VINF_SUCCESS;
    806850        else
  • trunk/src/VBox/Runtime/r3/win/path-win.cpp

    r21619 r23291  
    188188RTR3DECL(int) RTPathQueryInfo(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
    189189{
     190    return RTPathQueryInfoEx(pszPath, pObjInfo, enmAdditionalAttribs, RTPATH_F_ON_LINK);
     191}
     192
     193
     194RTR3DECL(int) RTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
     195{
    190196    /*
    191197     * Validate input.
    192198     */
    193     if (!pszPath)
    194     {
    195         AssertMsgFailed(("Invalid pszPath=%p\n", pszPath));
    196         return VERR_INVALID_PARAMETER;
    197     }
    198     if (!pObjInfo)
    199     {
    200         AssertMsgFailed(("Invalid pObjInfo=%p\n", pObjInfo));
    201         return VERR_INVALID_PARAMETER;
    202     }
    203     if (    enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING
    204         ||  enmAdditionalAttribs > RTFSOBJATTRADD_LAST)
    205     {
    206         AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs));
    207         return VERR_INVALID_PARAMETER;
    208     }
     199    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     200    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
     201    AssertPtrReturn(pObjInfo, VERR_INVALID_POINTER);
     202    AssertMsgReturn(    enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING
     203                    &&  enmAdditionalAttribs <= RTFSOBJATTRADD_LAST,
     204                    ("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs),
     205                    VERR_INVALID_PARAMETER);
     206    AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    209207
    210208    /*
     
    250248    {
    251249        /* Fallback to FindFileFirst in case of sharing violation. */
    252         if (GetLastError() == ERROR_SHARING_VIOLATION)
    253         {
    254             WIN32_FIND_DATAA FindData;
    255             HANDLE hDir = FindFirstFileA(pszPath, &FindData);
    256             if (hDir == INVALID_HANDLE_VALUE)
    257                 return RTErrConvertFromWin32(GetLastError());
    258             FindClose(hDir);
    259             Data.dwFileAttributes = FindData.dwFileAttributes;
    260             Data.ftCreationTime = FindData.ftCreationTime;
    261             Data.ftLastAccessTime = FindData.ftLastAccessTime;
    262             Data.ftLastWriteTime = FindData.ftLastWriteTime;
    263             Data.nFileSizeHigh = FindData.nFileSizeHigh;
    264             Data.nFileSizeLow = FindData.nFileSizeLow;
    265         }
    266         else
     250        if (GetLastError() != ERROR_SHARING_VIOLATION)
    267251            return RTErrConvertFromWin32(GetLastError());
     252        WIN32_FIND_DATAA FindData;
     253        HANDLE hDir = FindFirstFileA(pszPath, &FindData);
     254        if (hDir == INVALID_HANDLE_VALUE)
     255            return RTErrConvertFromWin32(GetLastError());
     256        FindClose(hDir);
     257        Data.dwFileAttributes = FindData.dwFileAttributes;
     258        Data.ftCreationTime = FindData.ftCreationTime;
     259        Data.ftLastAccessTime = FindData.ftLastAccessTime;
     260        Data.ftLastWriteTime = FindData.ftLastWriteTime;
     261        Data.nFileSizeHigh = FindData.nFileSizeHigh;
     262        Data.nFileSizeLow = FindData.nFileSizeLow;
    268263    }
    269264#endif
     265    if (   (fFlags & RTPATH_F_FOLLOW_LINK)
     266        && (Data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
     267    {
     268        AssertFailed();
     269        /** @todo Symlinks: RTPathQueryInfoEx is not handling symbolic links
     270         *        correctly on Windows.  (Both GetFileAttributesEx and FileFindFirst
     271         *        will return info about the symlink.) */
     272    }
    270273
    271274    /*
     
    323326                             PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
    324327{
     328    return RTPathSetTimesEx(pszPath, pAccessTime, pModificationTime, pChangeTime, pBirthTime, RTPATH_F_ON_LINK);
     329}
     330
     331
     332RTR3DECL(int) RTPathSetTimesEx(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
     333                               PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags)
     334{
    325335    /*
    326336     * Validate input.
    327337     */
    328     AssertMsgReturn(VALID_PTR(pszPath), ("%p\n", pszPath), VERR_INVALID_POINTER);
    329     AssertMsgReturn(*pszPath, ("%p\n", pszPath), VERR_INVALID_PARAMETER);
    330     AssertMsgReturn(!pAccessTime || VALID_PTR(pAccessTime), ("%p\n", pAccessTime), VERR_INVALID_POINTER);
    331     AssertMsgReturn(!pModificationTime || VALID_PTR(pModificationTime), ("%p\n", pModificationTime), VERR_INVALID_POINTER);
    332     AssertMsgReturn(!pChangeTime || VALID_PTR(pChangeTime), ("%p\n", pChangeTime), VERR_INVALID_POINTER);
    333     AssertMsgReturn(!pBirthTime || VALID_PTR(pBirthTime), ("%p\n", pBirthTime), VERR_INVALID_POINTER);
     338    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     339    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
     340    AssertPtrNullReturn(pAccessTime, VERR_INVALID_POINTER);
     341    AssertPtrNullReturn(pModificationTime, VERR_INVALID_POINTER);
     342    AssertPtrNullReturn(pChangeTime, VERR_INVALID_POINTER);
     343    AssertPtrNullReturn(pBirthTime, VERR_INVALID_POINTER);
     344    AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    334345
    335346    /*
     
    340351    if (RT_SUCCESS(rc))
    341352    {
    342         HANDLE hFile = CreateFileW(pwszPath,
    343                                    FILE_WRITE_ATTRIBUTES,   /* dwDesiredAccess */
    344                                    FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, /* dwShareMode */
    345                                    NULL,                    /* security attribs */
    346                                    OPEN_EXISTING,           /* dwCreationDisposition */
    347                                    FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL,
    348                                    NULL);
     353        HANDLE hFile;
     354        if (fOpen & RTPATH_F_FOLLOW_LINK)
     355            hFile = CreateFileW(pwszPath,
     356                                FILE_WRITE_ATTRIBUTES,   /* dwDesiredAccess */
     357                                FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, /* dwShareMode */
     358                                NULL,                    /* security attribs */
     359                                OPEN_EXISTING,           /* dwCreationDisposition */
     360                                FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL,
     361                                NULL);
     362        else
     363        {
     364/** @todo Symlink: Test RTPathSetTimesEx on Windows. (The code is disabled
     365 *        because it's not tested yet.) */
     366#if 0 //def FILE_FLAG_OPEN_REPARSE_POINT
     367            hFile = CreateFileW(pwszPath,
     368                                FILE_WRITE_ATTRIBUTES,   /* dwDesiredAccess */
     369                                FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, /* dwShareMode */
     370                                NULL,                    /* security attribs */
     371                                OPEN_EXISTING,           /* dwCreationDisposition */
     372                                FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT,
     373                                NULL);
     374
     375            if (hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_INVALID_PARAMETER)
     376#endif
     377                hFile = CreateFileW(pwszPath,
     378                                    FILE_WRITE_ATTRIBUTES,   /* dwDesiredAccess */
     379                                    FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, /* dwShareMode */
     380                                    NULL,                    /* security attribs */
     381                                    OPEN_EXISTING,           /* dwCreationDisposition */
     382                                    FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL,
     383                                    NULL);
     384        }
    349385        if (hFile != INVALID_HANDLE_VALUE)
    350386        {
     
    485521
    486522
    487 /**
    488  * Checks if the path exists.
    489  *
    490  * Symbolic links will all be attempted resolved.
    491  *
    492  * @returns true if it exists and false if it doesn't
    493  * @param   pszPath     The path to check.
    494  */
    495523RTDECL(bool) RTPathExists(const char *pszPath)
     524{
     525    return RTPathExistsEx(pszPath, RTPATH_F_FOLLOW_LINK);
     526}
     527
     528
     529RTDECL(bool) RTPathExistsEx(const char *pszPath, uint32_t fFlags)
    496530{
    497531    /*
     
    500534    AssertPtrReturn(pszPath, false);
    501535    AssertReturn(*pszPath, false);
     536    Assert(RTPATH_F_IS_VALID(fFlags, 0));
    502537
    503538    /*
    504539     * Try query file info.
    505540     */
     541    DWORD dwAttr;
    506542#ifndef RT_DONT_CONVERT_FILENAMES
    507543    PRTUTF16 pwszPath;
     
    509545    if (RT_SUCCESS(rc))
    510546    {
    511         if (GetFileAttributesW(pwszPath) == INVALID_FILE_ATTRIBUTES)
    512             rc = VERR_GENERAL_FAILURE;
     547        dwAttr = GetFileAttributesW(pwszPath);
    513548        RTUtf16Free(pwszPath);
    514549    }
     550    else
     551        dwAttr = INVALID_FILE_ATTRIBUTES;
    515552#else
    516     int rc = VINF_SUCCESS;
    517     if (GetFileAttributesExA(pszPath) == INVALID_FILE_ATTRIBUTES)
    518         rc = VERR_GENERAL_FAILURE;
     553    dwAttr = GetFileAttributesA(pszPath);
    519554#endif
    520555
    521     return RT_SUCCESS(rc);
     556    if (dwAttr == INVALID_FILE_ATTRIBUTES)
     557        return false;
     558
     559#ifdef FILE_ATTRIBUTE_REPARSE_POINT
     560    if (   (fFlags & RTPATH_F_FOLLOW_LINK)
     561        && (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT))
     562    {
     563        AssertFailed();
     564        /** @todo Symlinks: RTPathExists+RTPathExistsEx is misbehaving on symbolic
     565         *        links on Windows. */
     566    }
     567#endif
     568
     569    return true;
    522570}
    523571
Note: See TracChangeset for help on using the changeset viewer.

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