Changeset 3007 for trunk/src


Ignore:
Timestamp:
Nov 6, 2016, 5:46:43 PM (9 years ago)
Author:
bird
Message:

lib/nt: Deal better with NTFS mount points.

Location:
trunk/src/lib/nt
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/lib/nt/kFsCache.c

    r3005 r3007  
    15691569#ifdef KFSCACHE_CFG_SHORT_NAMES
    15701570                if (enmInfoClass == enmInfoClassWithId)
    1571                     birdStatFillFromFileIdBothDirInfo(&pCur->Stats, uPtr.pWithId, pCur->pszName);
     1571                    birdStatFillFromFileIdBothDirInfo(&pCur->Stats, uPtr.pWithId);
    15721572                else
    1573                     birdStatFillFromFileBothDirInfo(&pCur->Stats, uPtr.pNoId, pCur->pszName);
     1573                    birdStatFillFromFileBothDirInfo(&pCur->Stats, uPtr.pNoId);
    15741574#else
    15751575                if (enmInfoClass == enmInfoClassWithId)
    1576                     birdStatFillFromFileIdFullDirInfo(&pCur->Stats, uPtr.pWithId, pCur->pszName);
     1576                    birdStatFillFromFileIdFullDirInfo(&pCur->Stats, uPtr.pWithId);
    15771577                else
    1578                     birdStatFillFromFileFullDirInfo(&pCur->Stats, uPtr.pNoId, pCur->pszName);
     1578                    birdStatFillFromFileFullDirInfo(&pCur->Stats, uPtr.pNoId);
    15791579#endif
    15801580                pCur->Stats.st_dev = pDir->uDevNo;
     
    16021602#ifdef KFSCACHE_CFG_SHORT_NAMES
    16031603                if (enmInfoClass == enmInfoClassWithId)
    1604                     birdStatFillFromFileIdBothDirInfo(&pDir->Obj.Stats, uPtr.pWithId, pDir->Obj.pszName);
     1604                    birdStatFillFromFileIdBothDirInfo(&pDir->Obj.Stats, uPtr.pWithId);
    16051605                else
    1606                     birdStatFillFromFileBothDirInfo(&pDir->Obj.Stats, uPtr.pNoId, pDir->Obj.pszName);
     1606                    birdStatFillFromFileBothDirInfo(&pDir->Obj.Stats, uPtr.pNoId);
    16071607#else
    16081608                if (enmInfoClass == enmInfoClassWithId)
    1609                     birdStatFillFromFileIdFullDirInfo(&pDir->Obj.Stats, uPtr.pWithId, pDir->Obj.pszName);
     1609                    birdStatFillFromFileIdFullDirInfo(&pDir->Obj.Stats, uPtr.pWithId);
    16101610                else
    1611                     birdStatFillFromFileFullDirInfo(&pDir->Obj.Stats, uPtr.pNoId, pDir->Obj.pszName);
     1611                    birdStatFillFromFileFullDirInfo(&pDir->Obj.Stats, uPtr.pNoId);
    16121612#endif
    16131613            }
  • trunk/src/lib/nt/ntdir.c

    r3005 r3007  
    293293
    294294
     295/**
     296 * Deals with mount points.
     297 *
     298 * @param   pDir        The directory handle.
     299 * @param   pInfo       The NT entry information.
     300 * @param   pEntryStat  The stats for the mount point directory that needs
     301 *                      updating (a d_stat member).
     302 */
     303static void birdDirUpdateMountPointInfo(BirdDir_T *pDir, MY_FILE_ID_FULL_DIR_INFORMATION *pInfo,
     304                                        BirdStat_T *pEntryStat)
     305{
     306    /*
     307     * Try open the root directory of the mount.
     308     * (Can't use birdStatAtW here because the name isn't terminated.)
     309     */
     310    HANDLE              hRoot = INVALID_HANDLE_VALUE;
     311    MY_NTSTATUS         rcNt;
     312    MY_UNICODE_STRING   Name;
     313    Name.Buffer = pInfo->FileName;
     314    Name.Length = Name.MaximumLength = (USHORT)pInfo->FileNameLength;
     315
     316    rcNt = birdOpenFileUniStr((HANDLE)pDir->pvHandle, &Name,
     317                              FILE_READ_ATTRIBUTES,
     318                              FILE_ATTRIBUTE_NORMAL,
     319                              FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     320                              FILE_OPEN,
     321                              FILE_OPEN_FOR_BACKUP_INTENT,
     322                              OBJ_CASE_INSENSITIVE,
     323                              &hRoot);
     324    if (MY_NT_SUCCESS(rcNt))
     325    {
     326        int         iSavedErrno = errno;
     327        BirdStat_T  RootStat;
     328        if (birdStatHandle(hRoot, &RootStat, NULL) == 0)
     329        {
     330            RootStat.st_ismountpoint = 2;
     331            *pEntryStat = RootStat;
     332        }
     333        birdCloseFile(hRoot);
     334        errno = iSavedErrno;
     335    }
     336    /* else: don't mind failures, we've got some info. */
     337}
     338
    295339
    296340/**
     
    372416                if (birdDirCopyNameToEntry(pInfo->FileName, pInfo->FileNameLength, pEntry) != 0)
    373417                    fSkipEntry = 1;
    374                 birdStatFillFromFileIdFullDirInfo(&pEntry->d_stat, pInfo, pEntry->d_name);
     418                birdStatFillFromFileIdFullDirInfo(&pEntry->d_stat, pInfo);
    375419                pEntry->d_stat.st_dev   = pDir->uDev;
    376420                switch (pEntry->d_stat.st_mode & S_IFMT)
     
    389433                }
    390434
     435                if (pEntry->d_stat.st_ismountpoint != 1)
     436                { /* likely. */ }
     437                else
     438                    birdDirUpdateMountPointInfo(pDir, pInfo, &pEntry->d_stat);
     439
    391440                cbMinCur = MIN_SIZEOF_MY_FILE_ID_FULL_DIR_INFORMATION + pInfo->FileNameLength;
    392441                offNext  = pInfo->NextEntryOffset;
     
    526575                if (birdDirCopyNameToEntryW(pInfo->FileName, pInfo->FileNameLength, pEntry) != 0)
    527576                    fSkipEntry = 1;
    528                 birdStatFillFromFileIdFullDirInfo(&pEntry->d_stat, pInfo, NULL);
     577                birdStatFillFromFileIdFullDirInfo(&pEntry->d_stat, pInfo);
    529578                pEntry->d_stat.st_dev   = pDir->uDev;
    530579                switch (pEntry->d_stat.st_mode & S_IFMT)
     
    543592                }
    544593
     594                if (pEntry->d_stat.st_ismountpoint != 1)
     595                { /* likely. */ }
     596                else
     597                    birdDirUpdateMountPointInfo(pDir, pInfo, &pEntry->d_stat);
     598
    545599                cbMinCur = MIN_SIZEOF_MY_FILE_ID_FULL_DIR_INFORMATION + pInfo->FileNameLength;
    546600                offNext  = pInfo->NextEntryOffset;
  • trunk/src/lib/nt/ntstat.c

    r3003 r3007  
    148148
    149149
    150 static unsigned short birdFileInfoToMode(HANDLE hFile, ULONG fAttribs, const char *pszName,
    151                                          const wchar_t *pwszName, size_t cbNameW, __int16 *pfIsDirSymlink)
     150static unsigned short birdFileInfoToMode(ULONG fAttribs, ULONG uReparseTag,
     151                                         const char *pszName, const wchar_t *pwszName, size_t cbNameW,
     152                                         unsigned __int8 *pfIsDirSymlink, unsigned __int8 *pfIsMountPoint)
    152153{
    153154    unsigned short fMode;
    154155
    155156    /* File type. */
    156     if (  (fAttribs & FILE_ATTRIBUTE_REPARSE_POINT)
    157         && hFile != INVALID_HANDLE_VALUE)
    158     {
    159         MY_FILE_ATTRIBUTE_TAG_INFORMATION   TagInfo;
    160         MY_IO_STATUS_BLOCK                  Ios;
    161         MY_NTSTATUS                         rcNt;
    162         Ios.Information = 0;
    163         Ios.u.Status    = -1;
    164         rcNt = g_pfnNtQueryInformationFile(hFile, &Ios, &TagInfo, sizeof(TagInfo), MyFileAttributeTagInformation);
    165         if (   !MY_NT_SUCCESS(rcNt)
    166             || !MY_NT_SUCCESS(Ios.u.Status)
    167             || TagInfo.ReparseTag != IO_REPARSE_TAG_SYMLINK)
    168             fAttribs &= ~FILE_ATTRIBUTE_REPARSE_POINT;
    169     }
    170 
    171     if (fAttribs & FILE_ATTRIBUTE_REPARSE_POINT)
    172     {
    173         *pfIsDirSymlink = !!(fAttribs & FILE_ATTRIBUTE_DIRECTORY);
    174         fMode = S_IFLNK;
    175     }
    176     else
    177     {
    178         *pfIsDirSymlink = 0;
     157    *pfIsDirSymlink = 0;
     158    *pfIsMountPoint = 0;
     159    if (!(fAttribs & FILE_ATTRIBUTE_REPARSE_POINT))
     160    {
    179161        if (fAttribs & FILE_ATTRIBUTE_DIRECTORY)
    180162            fMode = S_IFDIR;
    181163        else
    182164            fMode = S_IFREG;
     165    }
     166    else
     167    {
     168        switch (uReparseTag)
     169        {
     170            case IO_REPARSE_TAG_SYMLINK:
     171                *pfIsDirSymlink = !!(fAttribs & FILE_ATTRIBUTE_DIRECTORY);
     172                fMode = S_IFLNK;
     173                break;
     174
     175            case IO_REPARSE_TAG_MOUNT_POINT:
     176                *pfIsMountPoint = 1;
     177            default:
     178                if (fAttribs & FILE_ATTRIBUTE_DIRECTORY)
     179                    fMode = S_IFDIR;
     180                else
     181                    fMode = S_IFREG;
     182                break;
     183        }
    183184    }
    184185
     
    202203 * @param   pStat               The stat structure.
    203204 * @param   pBuf                The MY_FILE_ID_FULL_DIR_INFORMATION entry.
    204  * @param   pszPath             Optionally, the path for X bit checks.
    205205 * @remarks Caller sets st_dev.
    206206 */
    207 void birdStatFillFromFileIdFullDirInfo(BirdStat_T *pStat, MY_FILE_ID_FULL_DIR_INFORMATION const *pBuf, const char *pszPath)
    208 {
    209     pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes,
    210                                                  pszPath, pBuf->FileName, pBuf->FileNameLength, &pStat->st_dirsymlink);
     207void birdStatFillFromFileIdFullDirInfo(BirdStat_T *pStat, MY_FILE_ID_FULL_DIR_INFORMATION const *pBuf)
     208{
     209    pStat->st_mode          = birdFileInfoToMode(pBuf->FileAttributes, pBuf->EaSize, NULL /*pszPath*/, pBuf->FileName,
     210                                                 pBuf->FileNameLength, &pStat->st_isdirsymlink, &pStat->st_ismountpoint);
    211211    pStat->st_padding0[0]   = 0;
    212212    pStat->st_padding0[1]   = 0;
     
    234234 * @param   pStat               The stat structure.
    235235 * @param   pBuf                The MY_FILE_ID_BOTH_DIR_INFORMATION entry.
    236  * @param   pszPath             Optionally, the path for X bit checks.
    237236 * @remarks Caller sets st_dev.
    238237 */
    239 void birdStatFillFromFileIdBothDirInfo(BirdStat_T *pStat, MY_FILE_ID_BOTH_DIR_INFORMATION const *pBuf, const char *pszPath)
    240 {
    241     pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes,
    242                                                  pszPath, pBuf->FileName, pBuf->FileNameLength, &pStat->st_dirsymlink);
     238void birdStatFillFromFileIdBothDirInfo(BirdStat_T *pStat, MY_FILE_ID_BOTH_DIR_INFORMATION const *pBuf)
     239{
     240    pStat->st_mode          = birdFileInfoToMode(pBuf->FileAttributes, pBuf->EaSize, NULL /*pszPath*/, pBuf->FileName,
     241                                                 pBuf->FileNameLength, &pStat->st_isdirsymlink, &pStat->st_ismountpoint);
    243242    pStat->st_padding0[0]   = 0;
    244243    pStat->st_padding0[1]   = 0;
     
    266265 * @param   pStat               The stat structure.
    267266 * @param   pBuf                The MY_FILE_BOTH_DIR_INFORMATION entry.
    268  * @param   pszPath             Optionally, the path for X bit checks.
    269267 * @remarks Caller sets st_dev.
    270268 */
    271 void birdStatFillFromFileBothDirInfo(BirdStat_T *pStat, MY_FILE_BOTH_DIR_INFORMATION const *pBuf, const char *pszPath)
    272 {
    273     pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes,
    274                                                  pszPath, pBuf->FileName, pBuf->FileNameLength, &pStat->st_dirsymlink);
     269void birdStatFillFromFileBothDirInfo(BirdStat_T *pStat, MY_FILE_BOTH_DIR_INFORMATION const *pBuf)
     270{
     271    pStat->st_mode          = birdFileInfoToMode(pBuf->FileAttributes, pBuf->EaSize, NULL /*pszPath*/, pBuf->FileName,
     272                                                 pBuf->FileNameLength, &pStat->st_isdirsymlink, &pStat->st_ismountpoint);
    275273    pStat->st_padding0[0]   = 0;
    276274    pStat->st_padding0[1]   = 0;
     
    310308        if (MY_NT_SUCCESS(rcNt))
    311309        {
    312             pStat->st_mode          = birdFileInfoToMode(hFile, pAll->BasicInformation.FileAttributes, pszPath,
     310            pStat->st_mode          = birdFileInfoToMode(pAll->BasicInformation.FileAttributes, pszPath,
    313311                                                         pAll->NameInformation.FileNamepAll->NameInformation.FileNameLength,
    314                                                          &pStat->st_dirsymlink);
     312                                                         hFile, &pStat->st_isdirsymlink, &pStat->st_ismountpoint);
    315313            pStat->st_padding0[0]   = 0;
    316314            pStat->st_padding0[1]   = 0;
     
    354352        rc = birdSetErrnoToNoMem();
    355353#else
    356     ULONG                           cbNameInfo = 0;
    357     MY_FILE_NAME_INFORMATION       *pNameInfo  = NULL;
    358     MY_FILE_STANDARD_INFORMATION    StdInfo;
    359     MY_FILE_BASIC_INFORMATION       BasicInfo;
    360     MY_FILE_INTERNAL_INFORMATION    InternalInfo;
    361     MY_IO_STATUS_BLOCK              Ios;
     354    ULONG                               cbNameInfo = 0;
     355    MY_FILE_NAME_INFORMATION           *pNameInfo  = NULL;
     356    MY_FILE_STANDARD_INFORMATION        StdInfo;
     357    MY_FILE_BASIC_INFORMATION           BasicInfo;
     358    MY_FILE_INTERNAL_INFORMATION        InternalInfo;
     359    MY_FILE_ATTRIBUTE_TAG_INFORMATION   TagInfo;
     360    MY_IO_STATUS_BLOCK                  Ios;
    362361
    363362    Ios.Information = 0;
     
    366365    if (MY_NT_SUCCESS(rcNt))
    367366        rcNt = Ios.u.Status;
     367
    368368    if (MY_NT_SUCCESS(rcNt))
    369369        rcNt = g_pfnNtQueryInformationFile(hFile, &Ios, &BasicInfo, sizeof(BasicInfo), MyFileBasicInformation);
    370370    if (MY_NT_SUCCESS(rcNt))
    371371        rcNt = Ios.u.Status;
     372
    372373    if (MY_NT_SUCCESS(rcNt))
    373374        rcNt = g_pfnNtQueryInformationFile(hFile, &Ios, &InternalInfo, sizeof(InternalInfo), MyFileInternalInformation);
    374375    if (MY_NT_SUCCESS(rcNt))
    375376        rcNt = Ios.u.Status;
     377
     378    if (MY_NT_SUCCESS(rcNt))
     379    {
     380        if (!(BasicInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
     381            TagInfo.ReparseTag = 0;
     382        else
     383        {
     384            MY_NTSTATUS rcNt2 = g_pfnNtQueryInformationFile(hFile, &Ios, &TagInfo, sizeof(TagInfo), MyFileAttributeTagInformation);
     385            if (   !MY_NT_SUCCESS(rcNt2)
     386                || !MY_NT_SUCCESS(Ios.u.Status))
     387                TagInfo.ReparseTag = 0;
     388        }
     389    }
     390
    376391    if (MY_NT_SUCCESS(rcNt) && !pszPath && !pwszPath)
    377392    {
     
    385400    if (MY_NT_SUCCESS(rcNt))
    386401    {
    387         pStat->st_mode          = birdFileInfoToMode(hFile, BasicInfo.FileAttributes, pszPath,
     402        pStat->st_mode          = birdFileInfoToMode(BasicInfo.FileAttributes, TagInfo.ReparseTag, pszPath,
    388403                                                     pNameInfo ? pNameInfo->FileName : pwszPath,
    389404                                                     pNameInfo ? pNameInfo->FileNameLength
    390405                                                     : pwszPath ? wcslen(pwszPath) * sizeof(wchar_t) : 0,
    391                                                      &pStat->st_dirsymlink);
     406                                                     &pStat->st_isdirsymlink, &pStat->st_ismountpoint);
    392407        pStat->st_padding0[0]   = 0;
    393408        pStat->st_padding0[1]   = 0;
     
    506521        birdCloseFile(hFile);
    507522
     523        if (rc || !pStat->st_ismountpoint)
     524        { /* very likely */ }
     525        else
     526        {
     527            /*
     528             * If we hit a mount point (NTFS volume mounted under an empty NTFS directory),
     529             * we should return information about what's mounted there rather than the
     530             * directory it is mounted at as this is what UNIX does.
     531             */
     532            hFile = birdOpenFileEx(hRoot, pszPath,
     533                                   FILE_READ_ATTRIBUTES,
     534                                   FILE_ATTRIBUTE_NORMAL,
     535                                   FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     536                                   FILE_OPEN,
     537                                   FILE_OPEN_FOR_BACKUP_INTENT,
     538                                   OBJ_CASE_INSENSITIVE);
     539            if (hFile != INVALID_HANDLE_VALUE)
     540            {
     541                rc = birdStatHandle2(hFile, pStat, pszPath, NULL);
     542                pStat->st_ismountpoint = 2;
     543                birdCloseFile(hFile);
     544            }
     545        }
     546
    508547#if 0
    509548        {
     
    558597                     * Convert the data.
    559598                     */
    560                     birdStatFillFromFileIdFullDirInfo(pStat, pBuf, pszPath);
     599                    birdStatFillFromFileIdFullDirInfo(pStat, pBuf);
    561600
    562601                    /* Get the serial number, reusing the buffer from above. */
     
    597636        rc = birdStatHandle2(hFile, pStat, NULL, pwszPath);
    598637        birdCloseFile(hFile);
     638
     639        /*
     640         * If we hit a mount point (NTFS volume mounted under an empty NTFS directory),
     641         * we should return information about what's mounted there rather than the
     642         * directory it is mounted at as this is what UNIX does.
     643         */
     644        hFile = birdOpenFileExW(hRoot, pwszPath,
     645                                FILE_READ_ATTRIBUTES,
     646                                FILE_ATTRIBUTE_NORMAL,
     647                                FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     648                                FILE_OPEN,
     649                                FILE_OPEN_FOR_BACKUP_INTENT,
     650                                OBJ_CASE_INSENSITIVE);
     651        if (hFile != INVALID_HANDLE_VALUE)
     652        {
     653            rc = birdStatHandle2(hFile, pStat, NULL, pwszPath);
     654            pStat->st_ismountpoint = 2;
     655            birdCloseFile(hFile);
     656        }
    599657    }
    600658    else
     
    636694                     * Convert the data.
    637695                     */
    638                     birdStatFillFromFileIdFullDirInfo(pStat, pBuf, NULL);
     696                    birdStatFillFromFileIdFullDirInfo(pStat, pBuf);
    639697
    640698                    /* Get the serial number, reusing the buffer from above. */
  • trunk/src/lib/nt/ntstat.h

    r2985 r3007  
    5050{
    5151    unsigned __int16    st_mode;
    52     unsigned __int16    st_dirsymlink;
     52    unsigned __int8     st_isdirsymlink; /**< Set if directory symlink. */
     53    unsigned __int8     st_ismountpoint; /**< Set if mount point; 1 if not followed, 2 if followed (lstat & readdir only). */
    5354    unsigned __int16    st_padding0[2];
    5455    __int64             st_size;
     
    8788#ifdef ___nt_ntstuff_h
    8889int  birdStatHandle(HANDLE hFile, BirdStat_T *pStat, const char *pszPath);
    89 void birdStatFillFromFileIdFullDirInfo(BirdStat_T *pStat, MY_FILE_ID_FULL_DIR_INFORMATION const *pBuf, const char *pszPath);
    90 void birdStatFillFromFileIdBothDirInfo(BirdStat_T *pStat, MY_FILE_ID_BOTH_DIR_INFORMATION const *pBuf, const char *pszPath);
    91 void birdStatFillFromFileBothDirInfo(BirdStat_T *pStat, MY_FILE_BOTH_DIR_INFORMATION const *pBuf, const char *pszPath);
     90void birdStatFillFromFileIdFullDirInfo(BirdStat_T *pStat, MY_FILE_ID_FULL_DIR_INFORMATION const *pBuf);
     91void birdStatFillFromFileIdBothDirInfo(BirdStat_T *pStat, MY_FILE_ID_BOTH_DIR_INFORMATION const *pBuf);
     92void birdStatFillFromFileBothDirInfo(BirdStat_T *pStat, MY_FILE_BOTH_DIR_INFORMATION const *pBuf);
    9293MY_NTSTATUS birdQueryVolumeDeviceNumber(HANDLE hFile, MY_FILE_FS_VOLUME_INFORMATION *pVolInfo, size_t cbVolInfo,
    9394                                        unsigned __int64 *puDevNo);
  • trunk/src/lib/nt/tstNtStat.c

    r2702 r3007  
    131131            printf("%s:\n", argv[i]);
    132132            printf("  st_mode:          %o\n", st.st_mode);
    133             printf("  st_dirsymlink:    %d\n", st.st_dirsymlink);
     133            printf("  st_isdirsymlink:  %d\n", st.st_isdirsymlink);
     134            printf("  st_ismountpoint:  %d\n", st.st_ismountpoint);
    134135            printf("  st_size:          %I64u (%#I64x)\n", st.st_size, st.st_size);
    135136            printf("  st_atim:          %s\n", FormatTimeSpec(szBuf, &st.st_atim));
Note: See TracChangeset for help on using the changeset viewer.