0

I'm using the file_size function from the filesystem library to get the size of a file. It seems to work fine since the number I get matches the "Size" in the file's properties, but I want the "Size on disk". How would I go about getting this?

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
  • 2
    You can't by only using standard C++ functions. – Ted Lyngmo Aug 02 '19 at 15:24
  • 2
    https://devblogs.microsoft.com/oldnewthing/20160427-00/?p=93365 – Paul Sanders Aug 02 '19 at 15:27
  • 1
    *It seems to work fine* -- `file_size` better work correctly, else you would have a very broken program if you rely on that value for things such as dynamically allocating a buffer, etc. – PaulMcKenzie Aug 02 '19 at 15:28
  • 1
    @PaulMcKenzie If you rely on `file_size`, in many cases you will have a race condition (e. g. when using the returned value to allocate a buffer for reading the whole file into memory). – zett42 Aug 02 '19 at 16:42
  • 1
    Possible duplicate of [How do I query "Size on disk" file information?](https://stackoverflow.com/questions/9903679/how-do-i-query-size-on-disk-file-information) – RbMm Aug 02 '19 at 16:57

1 Answers1

3

It's impossible with plain C++.

The actual size on the disk can be obtained by a call to GetDiskFreeSpace() to get the number of sectors/cluster and bytes/sector. Multiply these two to get bytes/cluster, then round the actual file size (obtained with C++ or with GetCompressedFileSizeW()) to the next multiple.

For example if bps is 512 and spc is 4 then bpc is 2048. If the file size is 4000, then the size on disk is 4096.

Michael Chourdakis
  • 10,345
  • 3
  • 42
  • 78
  • You want to use [`GetCompressedFileSizeW`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getcompressedfilesizew) instead of `GetFileSizeEx`. – zett42 Aug 02 '19 at 16:16
  • 2
    exist more simply and clear solution - `FILE_STANDARD_INFO.AllocationSize` - this is how many space on disk allocated for file, when `FILE_STANDARD_INFO.EndOfFile` - file size. so call `GetFileInformationByHandleEx ` with `FileStandardInfo` – RbMm Aug 02 '19 at 16:32
  • @RbMm not exactly the same, in your case you need a file handle which means that you have to open the file. – Michael Chourdakis Aug 02 '19 at 16:34
  • but file need open file any case, you think `GetCompressedFileSizeW` not open file ? – RbMm Aug 02 '19 at 16:37
  • @RbMm, no, at least not on my side. Whether Windows opens it or not is another issue. – Michael Chourdakis Aug 02 '19 at 16:50
  • of course windows open file, no another way query information about it. another task that `FILE_STANDARD_INFORMATION.AllocationSize` may be in some case not equal to `FILE_COMPRESSION_INFORMATION.CompressedFileSize` (this is from where `GetCompressedFileSizeW` take info) - [*CompressedFileSize MUST be less than or equal to AllocationSize*](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fsa/484bc722-6440-49a0-982a-9ba27cddf513) – RbMm Aug 02 '19 at 16:56
  • however i know only one case, when it not equal - when in call `NtCreateFile` we explicitly indicate `AllocationSize` parameter (this will be until we not close it handle), but agree - `FILE_COMPRESSION_INFORMATION.CompressedFileSize` more accurate – RbMm Aug 02 '19 at 17:00
  • I think this answer is still useful to calculate the size of a file on disk in advance. E. g. to calculate how much physical space is required for the files you are about to create (copy, extract, whatever). In this case, `GetFileInformationByHandleEx` will be useless, because the files do not exist yet. – zett42 Aug 02 '19 at 18:21