VirtualBox

Changeset 23291 in vbox


Ignore:
Timestamp:
Sep 24, 2009 4:08:19 PM (16 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
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/err.h

    r22722 r23291  
    710710/** Too many symbolic links. */
    711711#define VERR_TOO_MANY_SYMLINKS              (-156)
     712/** The OS does not support setting the time stamps on a symbolic link. */
     713#define VERR_NS_SYMLINK_SET_TIME            (-157)
    712714/** @} */
    713715
  • trunk/include/iprt/path.h

    r22109 r23291  
    118118
    119119
     120/** @name Generic RTPath flags
     121 * @{ */
     122/** Last component: Work on the link. */
     123#define RTPATH_F_ON_LINK          RT_BIT_32(0)
     124/** Last component: Follow if link. */
     125#define RTPATH_F_FOLLOW_LINK      RT_BIT_32(1)
     126/** @} */
     127
     128
     129/** Validates a flags parameter containing RTPATH_F_*.
     130 * @remarks The parameters will be referneced multiple times. */
     131#define RTPATH_F_IS_VALID(fFlags, fIgnore) \
     132    (    ((fFlags) & ~(uint32_t)(fIgnore)) == RTPATH_F_ON_LINK \
     133      || ((fFlags) & ~(uint32_t)(fIgnore)) == RTPATH_F_FOLLOW_LINK )
     134
     135
    120136/**
    121137 * Checks if the path exists.
    122138 *
    123  * Symbolic links will all be attempted resolved.
     139 * Symbolic links will all be attempted resolved and broken links means false.
    124140 *
    125141 * @returns true if it exists and false if it doesn't.
     
    127143 */
    128144RTDECL(bool) RTPathExists(const char *pszPath);
     145
     146/**
     147 * Checks if the path exists.
     148 *
     149 * @returns true if it exists and false if it doesn't.
     150 * @param   pszPath     The path to check.
     151 * @param   fFlags      RTPATH_F_ON_LINK or RPATH_F_FOLLOW_LINK.
     152 */
     153RTDECL(bool) RTPathExistsEx(const char *pszPath, uint32_t fFlags);
    129154
    130155/**
     
    500525 * Query information about a file system object.
    501526 *
    502  * This API will not resolve symbolic links in the last component (just
    503  * like unix lstat()).
    504  *
    505  * @returns VINF_SUCCESS if the object exists, information returned.
    506  * @returns VERR_PATH_NOT_FOUND if any but the last component in the specified
     527 * This API will resolve NOT symbolic links in the last component (just like
     528 * unix lstat()).
     529 *
     530 * @returns IPRT status code.
     531 * @retval  VINF_SUCCESS if the object exists, information returned.
     532 * @retval  VERR_PATH_NOT_FOUND if any but the last component in the specified
    507533 *          path was not found or was not a directory.
    508  * @returns VERR_FILE_NOT_FOUND if the object does not exist (but path to the
     534 * @retval VERR_FILE_NOT_FOUND if the object does not exist (but path to the
    509535 *          parent directory exists).
    510  * @returns some other iprt status code.
    511536 *
    512537 * @param   pszPath     Path to the file system object.
     
    519544
    520545/**
     546 * Query information about a file system object.
     547 *
     548 * @returns IPRT status code.
     549 * @retval  VINF_SUCCESS if the object exists, information returned.
     550 * @retval  VERR_PATH_NOT_FOUND if any but the last component in the specified
     551 *          path was not found or was not a directory.
     552 * @retval  VERR_FILE_NOT_FOUND if the object does not exist (but path to the
     553 *          parent directory exists).
     554 *
     555 * @param   pszPath     Path to the file system object.
     556 * @param   pObjInfo    Object information structure to be filled on successful return.
     557 * @param   enmAdditionalAttribs
     558 *                      Which set of additional attributes to request.
     559 *                      Use RTFSOBJATTRADD_NOTHING if this doesn't matter.
     560 * @param   fFlags      RTPATH_F_ON_LINK or RPATH_F_FOLLOW_LINK.
     561 */
     562RTR3DECL(int) RTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags);
     563
     564/**
    521565 * Changes the mode flags of a file system object.
    522566 *
     
    573617
    574618/**
     619 * Changes one or more of the timestamps associated of file system object.
     620 *
     621 * @returns iprt status code.
     622 * @param   pszPath             Path to the file system object.
     623 * @param   pAccessTime         Pointer to the new access time.
     624 * @param   pModificationTime   Pointer to the new modification time.
     625 * @param   pChangeTime         Pointer to the new change time. NULL if not to be changed.
     626 * @param   pBirthTime          Pointer to the new time of birth. NULL if not to be changed.
     627 * @param   fFlags              RTPATH_F_ON_LINK or RPATH_F_FOLLOW_LINK.
     628 *
     629 * @remark  The file system might not implement all these time attributes,
     630 *          the API will ignore the ones which aren't supported.
     631 *
     632 * @remark  The file system might not implement the time resolution
     633 *          employed by this interface, the time will be chopped to fit.
     634 *
     635 * @remark  The file system may update the change time even if it's
     636 *          not specified.
     637 *
     638 * @remark  POSIX can only set Access & Modification and will always set both.
     639 */
     640RTR3DECL(int) RTPathSetTimesEx(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
     641                               PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags);
     642
     643/**
    575644 * Gets one or more of the timestamps associated of file system object.
    576645 *
     
    582651 * @param   pBirthTime          Where to store the creation time. NULL is ok.
    583652 *
    584  * @remark  This is wrapper around RTPathQueryInfo() and exists to complement RTPathSetTimes().
     653 * @remark  This is wrapper around RTPathQueryInfo() and exists to complement
     654 *          RTPathSetTimes().  If the last component is a symbolic link, it will
     655 *          not be resolved.
    585656 */
    586657RTR3DECL(int) RTPathGetTimes(const char *pszPath, PRTTIMESPEC pAccessTime, PRTTIMESPEC pModificationTime,
     
    601672
    602673/**
     674 * Changes the owner and/or group of a file system object.
     675 *
     676 * @returns iprt status code.
     677 * @param   pszPath     Path to the file system object.
     678 * @param   uid         The new file owner user id. Use -1 (or ~0) to leave this unchanged.
     679 * @param   gid         The new group id. Use -1 (or ~0) to leave this unchanged.
     680 * @param   fFlags      RTPATH_F_ON_LINK or RPATH_F_FOLLOW_LINK.
     681 */
     682RTR3DECL(int) RTPathSetOwnerEx(const char *pszPath, uint32_t uid, uint32_t gid, uint32_t fFlags);
     683
     684/**
    603685 * Gets the owner and/or group of a file system object.
    604686 *
     
    608690 * @param   pGid        Where to store the group id. NULL is ok.
    609691 *
    610  * @remark  This is wrapper around RTPathQueryInfo() and exists to complement RTPathGetOwner().
     692 * @remark  This is wrapper around RTPathQueryInfo() and exists to complement
     693 *          RTPathGetOwner().  If the last component is a symbolic link, it will
     694 *          not be resolved.
    611695 */
    612696RTR3DECL(int) RTPathGetOwner(const char *pszPath, uint32_t *pUid, uint32_t *pGid);
     
    622706 * Renames a path within a filesystem.
    623707 *
     708 * This will rename symbolic links.  If RTPATHRENAME_FLAGS_REPLACE is used and
     709 * pszDst is a symbolic link, it will be replaced and not its target.
     710 *
    624711 * @returns IPRT status code.
    625712 * @param   pszSrc      The source path.
  • 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