How can GetFreeDiskSpaceEx return (apparently) the wrong amount of disk space?

Therefore, I am working on a device that displays large images (from 30 MB to 2 GB +). Before we start creating one of these images, we will check to see if there is sufficient disk space through GetDiskFreeSpaceEx . Usually (and in this case) we write to a shared folder on the same network. There are no user quotas on disk.

Last night, in preparation for the demonstration, we started a test run. During the run, we failed. We needed 327391776 bytes, and we were told that we only have 186580992 . The numbers from GetDiskFreeSpaceEx were:

Available Free Space: 186580992

Total free space: 186580992

They correspond to the QuadPart variables in the two (output) arguments lpFreeBytesAvailable and lpTotalNumberOfFreeBytes - GetDiskFreeSpaceAvailable .

This code has been used for many years, and I have never seen a false negative result. Here is the full function:

 long IsDiskSpaceAvailable( const char* inDirectory, const _int64& inRequestedSize, _int64& outUserFree, _int64& outTotalFree, _int64& outCalcRequest ) { ULARGE_INTEGER fba; ULARGE_INTEGER tnb; ULARGE_INTEGER tnfba; ULARGE_INTEGER reqsize; string dir; size_t len; dir = inDirectory; len = strlen( inDirectory ); outUserFree = 0; outTotalFree = 0; outCalcRequest = 0; if( inDirectory[len-1] != '\\' ) dir += "\\"; // this is the value of inRequestSize that was passed in // inRequestedSize = 3273917760; if( GetDiskFreeSpaceEx( dir.c_str(), &fba, &tnb, &tnfba ) ) { outUserFree = fba.QuadPart; outTotalFree = tnfba.QuadPart; // this is computed dynamically given a specific compression // type, but for simplicity I had hard-coded the value that was used float compressionRatio = 10.0; reqsize.QuadPart = (ULONGLONG) (inRequestedSize / compressionRatio); outCalcRequest = reqsize.QuadPart; // this is what was triggered to cause the failure, // ie, user free space was < the request size if( fba.QuadPart < reqsize.QuadPart ) return( RetCode_OutOfSpace ); } else { return( RetCode_Failure ); } return( RetCode_OK ); } 

So, the value 3273917760 was passed to the function, which is the total amount of disk space required before compression. The function divides this by a compression ratio of 10 to obtain the required actual size.

When I checked the disk on which this resource was located, it was free from 177 GB, much more than was reported. After restarting the test, without changing anything, it worked.

So my question is here; what could lead to something like that? As far as I can tell, this is not a programming error, and, as I mentioned earlier, this code has been used for a very long time without problems.

I checked the event log on the remote computer and did not find anything interesting during the crash. I hope someone out there saw something similar before, thanks in advance.

+4
source share
1 answer

It may not be of any use, but it is "strange" that:

177GB ~ = 186580992 * 1000.

This may be due to stack corruption (since you are not initializing your local variable), occurring elsewhere in the code.

In the "inRequestedSize / compressionRatio" code, it is not necessary to use float for division, and since you were shading the "lose accuracy" warning with the application, you can actually cause an error too (but the number given in the example should work). You can just do "inRequestedSize / 10".

Last but not least, you don’t say where the code works. On a mobile device, the GetDiskFreeSpaceEx documentation states:

When mobile encryption is enabled, the message behavior for this function changes. Each encrypted file has at least one 4 KB associated service information. This function takes into account this overhead when it reports the amount of available space. That is, if a 128 KB disk contains one 60 KB file, this function reports that there is 64 KB, subtracting the space occupied by both the file and the associated service message.

Although this function reports the total available space, consider the space requirements for encrypted files when evaluating whether several new files will be included in the remaining space. Include the amount of space required for overhead when Mobile Encryption is enabled. Each file requires at least 4 KB. For example, 64 KB is required for a single 60 KB file, but 68 KB is required for two 30 KB files.

+3
source

Source: https://habr.com/ru/post/1392770/


All Articles