VirtualBox

Changeset 77231 in vbox for trunk/src/VBox/Runtime/r3/win


Ignore:
Timestamp:
Feb 8, 2019 11:18:13 PM (6 years ago)
Author:
vboxsync
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.)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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.

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