VirtualBox

Changeset 77231 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Feb 8, 2019 11:18:13 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
128738
Message:

IPRT: Return VERR_FILE_TOO_BIG if we exceed the FAT file limit while writing or when calling RTFileSetSize. (The previous IsBeyondLimit() code never ever worked AFAIK.)

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/include/internal/fs.h

    r76585 r77231  
    5151void    rtFsObjInfoAttrSetUnixOwner(PRTFSOBJINFO pObjInfo, RTUID uid);
    5252void    rtFsObjInfoAttrSetUnixGroup(PRTFSOBJINFO pObjInfo, RTUID gid);
    53 #endif
     53#else  /* RT_OS_WINDOWS */
     54# ifdef DECLARE_HANDLE
     55int     rtNtQueryFsType(HANDLE hHandle, PRTFSTYPE penmType);
     56# endif
     57#endif /* RT_OS_WINDOWS */
    5458
    5559#ifdef RT_OS_LINUX
  • trunk/src/VBox/Runtime/r3/nt/fs-nt.cpp

    r76553 r77231  
    196196
    197197
     198int rtNtQueryFsType(HANDLE hHandle, PRTFSTYPE penmType)
     199{
     200    /*
     201     * Get the file system name.
     202     */
     203    union
     204    {
     205        FILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
     206        uint8_t abBuf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 4096];
     207    } u;
     208    IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     209    NTSTATUS rcNt = NtQueryVolumeInformationFile(hHandle, &Ios, &u, sizeof(u), FileFsAttributeInformation);
     210    if (NT_SUCCESS(rcNt))
     211    {
     212#define IS_FS(a_szName) rtNtCompWideStrAndAscii(u.FsAttrInfo.FileSystemName, u.FsAttrInfo.FileSystemNameLength, RT_STR_TUPLE(a_szName))
     213        if (IS_FS("NTFS"))
     214            *penmType = RTFSTYPE_NTFS;
     215        else if (IS_FS("FAT"))
     216            *penmType = RTFSTYPE_FAT;
     217        else if (IS_FS("FAT32"))
     218            *penmType = RTFSTYPE_FAT;
     219        else if (IS_FS("exFAT"))
     220            *penmType = RTFSTYPE_EXFAT;
     221        else if (IS_FS("UDF"))
     222            *penmType = RTFSTYPE_UDF;
     223        else if (IS_FS("CDFS"))
     224            *penmType = RTFSTYPE_ISO9660;
     225        else if (IS_FS("HPFS"))
     226            *penmType = RTFSTYPE_HPFS;
     227        else if (IS_FS("VBoxSharedFolderFS"))
     228            *penmType = RTFSTYPE_VBOXSHF;
     229#undef IS_FS
     230        return VINF_SUCCESS;
     231    }
     232
     233    *penmType = RTFSTYPE_UNKNOWN;
     234    return RTErrConvertFromNtStatus(rcNt);
     235}
     236
     237
    198238RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType)
    199239{
     
    220260    if (RT_SUCCESS(rc))
    221261    {
    222         /*
    223          * Get the file system name.
    224          */
    225         union
    226         {
    227             FILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
    228             uint8_t abBuf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 4096];
    229         } u;
    230         IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
    231         NTSTATUS rcNt = NtQueryVolumeInformationFile(hFile, &Ios, &u, sizeof(u), FileFsAttributeInformation);
    232         if (NT_SUCCESS(rcNt))
    233         {
    234 #define IS_FS(a_szName) \
    235     rtNtCompWideStrAndAscii(u.FsAttrInfo.FileSystemName, u.FsAttrInfo.FileSystemNameLength, RT_STR_TUPLE(a_szName))
    236             if (IS_FS("NTFS"))
    237                 *penmType = RTFSTYPE_NTFS;
    238             else if (IS_FS("FAT"))
    239                 *penmType = RTFSTYPE_FAT;
    240             else if (IS_FS("FAT32"))
    241                 *penmType = RTFSTYPE_FAT;
    242             else if (IS_FS("VBoxSharedFolderFS"))
    243                 *penmType = RTFSTYPE_VBOXSHF;
    244 #undef IS_FS
    245         }
    246         else
    247             rc = RTErrConvertFromNtStatus(rcNt);
    248 
    249         RTNtPathClose(hFile);
    250     }
    251     return rc;
    252 }
    253 
     262        rc = rtNtQueryFsType(hFile, penmType);
     263        RTNtPathClose(hFile);
     264    }
     265    return rc;
     266}
     267
  • trunk/src/VBox/Runtime/r3/win/fileio-win.cpp

    r77211 r77231  
    9696
    9797/**
    98  * This is a helper to check if an attempt was made to grow a file beyond the
    99  * limit of the filesystem.
    100  *
    101  * @returns true for file size limit exceeded.
    102  * @param   hFile       Filehandle.
    103  * @param   offSeek     Offset to seek.
    104  * @param   uMethod     The seek method.
     98 * Helper for checking if a VERR_DISK_FULL isn't a VERR_FILE_TOO_BIG.
     99 * @returns VERR_DISK_FULL or VERR_FILE_TOO_BIG.
    105100 */
    106 DECLINLINE(bool) IsBeyondLimit(RTFILE hFile, uint64_t offSeek, unsigned uMethod)
    107 {
    108     bool fIsBeyondLimit = false;
    109 
    110     /*
    111      * Get the current file position and try set the new one.
    112      * If it fails with a seek error it's because we hit the file system limit.
    113      */
    114 /** @todo r=bird: I'd be very interested to know on which versions of windows and on which file systems
    115  * this supposedly works. The fastfat sources in the latest WDK makes no limit checks during
    116  * file seeking, only at the time of writing (and some other odd ones we cannot make use of). */
    117     uint64_t offCurrent;
    118     if (MySetFilePointer(hFile, 0, &offCurrent, FILE_CURRENT))
    119     {
    120         if (!MySetFilePointer(hFile, offSeek, NULL, uMethod))
    121             fIsBeyondLimit = GetLastError() == ERROR_SEEK;
    122         else /* Restore file pointer on success. */
    123             MySetFilePointer(hFile, offCurrent, NULL, FILE_BEGIN);
    124     }
    125 
    126     return fIsBeyondLimit;
     101static int rtFileWinCheckIfDiskReallyFull(RTFILE hFile, uint64_t cbDesired)
     102{
     103    /*
     104     * Windows doesn't appear to have a way to query the file size limit of a
     105     * file system, so we have to deduce the limit from the file system driver name.
     106     * This means it will only work for known file systems.
     107     */
     108    if (cbDesired >= _2G - 1)
     109    {
     110        uint64_t cbMaxFile = UINT64_MAX;
     111        RTFSTYPE enmFsType;
     112        int rc = rtNtQueryFsType((HANDLE)RTFileToNative(hFile), &enmFsType);
     113        if (RT_SUCCESS(rc))
     114            switch (enmFsType)
     115            {
     116                case RTFSTYPE_NTFS:
     117                case RTFSTYPE_EXFAT:
     118                case RTFSTYPE_UDF:
     119                    cbMaxFile = UINT64_C(0xffffffffffffffff); /* (May be limited by IFS.) */
     120                    break;
     121
     122                case RTFSTYPE_ISO9660:
     123                    cbMaxFile = 8 *_1T;
     124                    break;
     125
     126                case RTFSTYPE_FAT:
     127                    cbMaxFile = _4G;
     128                    break;
     129
     130                case RTFSTYPE_HPFS:
     131                    cbMaxFile = _2G;
     132                    break;
     133
     134                default:
     135                    break;
     136            }
     137        if (cbDesired >= cbMaxFile)
     138            return VERR_FILE_TOO_BIG;
     139    }
     140    return VERR_DISK_FULL;
    127141}
    128142
     
    563577                {
    564578                    int rc = RTErrConvertFromWin32(GetLastError());
    565                     if (   rc == VERR_DISK_FULL
    566                         && IsBeyondLimit(hFile, cbToWriteAdj - cbWritten, FILE_CURRENT)
    567                        )
    568                         rc = VERR_FILE_TOO_BIG;
     579                    if (rc == VERR_DISK_FULL)
     580                        rc = rtFileWinCheckIfDiskReallyFull(hFile, RTFileTell(hFile) + cbToWriteAdj - cbWritten);
    569581                    return rc;
    570582                }
     
    607619                }
    608620                int rc = RTErrConvertFromWin32(dwErr);
    609                 if (   rc == VERR_DISK_FULL
    610                     && IsBeyondLimit(hFile, cbToWriteAdj - cbWritten, FILE_CURRENT))
    611                     rc = VERR_FILE_TOO_BIG;
     621                if (rc == VERR_DISK_FULL)
     622                    rc = rtFileWinCheckIfDiskReallyFull(hFile, RTFileTell(hFile) + cbToWrite);
    612623                return rc;
    613624            }
     
    628639
    629640    int rc = RTErrConvertFromWin32(dwErr);
    630     if (   rc == VERR_DISK_FULL
    631         && IsBeyondLimit(hFile, cbToWriteAdj - cbWritten, FILE_CURRENT))
    632         rc = VERR_FILE_TOO_BIG;
     641    if (rc == VERR_DISK_FULL)
     642        rc = rtFileWinCheckIfDiskReallyFull(hFile, RTFileTell(hFile) + cbToWriteAdj);
    633643    return rc;
    634644}
     
    669679                {
    670680                    int rc = RTErrConvertFromWin32(GetLastError());
    671                     if (   rc == VERR_DISK_FULL
    672                         && IsBeyondLimit(hFile, cbToWriteAdj - cbWritten, FILE_CURRENT)
    673                        )
    674                         rc = VERR_FILE_TOO_BIG;
     681                    if (rc == VERR_DISK_FULL)
     682                        rc = rtFileWinCheckIfDiskReallyFull(hFile, off + cbToWriteAdj);
    675683                    return rc;
    676684                }
     
    684692
    685693    int rc = RTErrConvertFromWin32(GetLastError());
    686     if (   rc == VERR_DISK_FULL
    687         && IsBeyondLimit(hFile, cbToWriteAdj - cbWritten, FILE_CURRENT))
    688         rc = VERR_FILE_TOO_BIG;
     694    if (rc == VERR_DISK_FULL)
     695        rc = rtFileWinCheckIfDiskReallyFull(hFile, off + cbToWriteAdj);
    689696    return rc;
    690697}
     
    703710
    704711
    705 RTR3DECL(int)  RTFileSetSize(RTFILE hFile, uint64_t cbSize)
     712RTR3DECL(int) RTFileSetSize(RTFILE hFile, uint64_t cbSize)
    706713{
    707714    /*
     
    734741            rc = GetLastError();
    735742            MySetFilePointer(hFile, offCurrent, NULL, FILE_BEGIN);
     743
     744            if (rc == ERROR_DISK_FULL)
     745                return rtFileWinCheckIfDiskReallyFull(hFile, cbSize);
    736746        }
    737747        else
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