Force Refresh Volume to Get Current Amount of Free Bytes From File System Without Any Caches

Hello,

in my app I need the current amount of free space on a certain volume.

I use the following code to the this information:

if let mountedVolumeURLs = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: nil)
{
    for volumeUrl in mountedVolumeURLs
    {
         guard let values = try? self.url.resourceValues(forKeys: [.volumeTotalCapacityKey, .volumeAvailableCapacityKey]) else { continue }
        
        let totalBytes = values.allValues[.volumeTotalCapacityKey] as? UInt64 ?? 0
        let freeBytes = values.allValues[.volumeAvailableCapacityKey] as? UInt64 ?? 0 // This is not always correct.
    }
}

When writing to a volume and then calling the code above, a wrong amount is returned. I suspect that there is still some cacheing going on.

Is there any function that I can call to get this information from the file system without any cacheing? I guess an alternative would be to get a list of all files, get their sizes, add them up and subtract that number from the total bytes of the volume. But maybe there is a more elegant solution.

I also tried something like this:

 let handle = try FileDescriptor.open(volumeUrl.path, .writeOnly, options: .create, permissions: .ownerReadWrite, retryOnInterrupt: true)

fcntl(handle.rawValue, F_FULLFSYNC)

But this did not help. I would appreciate any help.

Regards

Accepted Reply

On modern Apple devices, there's no easy answer to "How much free space is on this volume?"

Briefly, there are several general factors to consider, including:

  1. On APFS volumes, copies of files don't occupy any more space than the originals they were copied from — assuming the copies have not been modified. That means you could add up the sizes of all files on the volume, and get a number that's way higher than the number of bytes actually in use. The total could even be larger than the size of the volume.

  2. When there is actual free space on a volume, the OS is free to fill some of it up, speculatively, with information that it thinks might be used in the near future. For example, an app can download HLS (live streaming) videos for later viewing, and these are stored in a place where the system "knows" that they are somewhat temporary. If there is a demand to a large amount of storage for a new file, the system can discard some of the temporary information.

All of this means that a volume could appear to be quite full, by the old-fashioned file system metrics, but could actually have a lot of available free space.

In the end, the answer to your question depends on exactly why you're trying to get this information, and exactly what you're intending to do with it. I'd recommend you use a code-level support incident from your developer account to discuss this with DTS engineers who have expertise in this area.

Replies

On modern Apple devices, there's no easy answer to "How much free space is on this volume?"

Briefly, there are several general factors to consider, including:

  1. On APFS volumes, copies of files don't occupy any more space than the originals they were copied from — assuming the copies have not been modified. That means you could add up the sizes of all files on the volume, and get a number that's way higher than the number of bytes actually in use. The total could even be larger than the size of the volume.

  2. When there is actual free space on a volume, the OS is free to fill some of it up, speculatively, with information that it thinks might be used in the near future. For example, an app can download HLS (live streaming) videos for later viewing, and these are stored in a place where the system "knows" that they are somewhat temporary. If there is a demand to a large amount of storage for a new file, the system can discard some of the temporary information.

All of this means that a volume could appear to be quite full, by the old-fashioned file system metrics, but could actually have a lot of available free space.

In the end, the answer to your question depends on exactly why you're trying to get this information, and exactly what you're intending to do with it. I'd recommend you use a code-level support incident from your developer account to discuss this with DTS engineers who have expertise in this area.