Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@dreness
Created May 1, 2019 06:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dreness/08213395aef006720bd1fd9022d2a86e to your computer and use it in GitHub Desktop.
Save dreness/08213395aef006720bd1fd9022d2a86e to your computer and use it in GitHub Desktop.
Show something mumble mumble APFS cloned files mumble?
import Cocoa
// https://cocoa-dev.apple.narkive.com/Ciy40e20/is-cloning-the-same-as-copying-in-apfs#post8
func unclonedSize(of url: URL) throws -> off_t {
var list = attrlist(bitmapcount: UInt16(ATTR_BIT_MAP_COUNT),
reserved: 0,
commonattr: 0,
volattr: 0,
dirattr: 0,
fileattr: 0,
forkattr: attrgroup_t(ATTR_CMNEXT_PRIVATESIZE))
let bufsize = 4 + MemoryLayout<off_t>.size
let buf = UnsafeMutablePointer<UInt8>.allocate(capacity: bufsize)
defer { buf.deallocate() }
let err = url.withUnsafeFileSystemRepresentation { getattrlist($0, &list, buf, bufsize, UInt32(FSOPT_ATTR_CMN_EXTENDED)) }
if err != 0 { throw POSIXError.Code(rawValue: errno).map { POSIXError($0) } ?? CocoaError(.fileReadUnknown) }
let attrsize = buf.withMemoryRebound(to: UInt32.self, capacity: 1) { $0.pointee }
if attrsize < bufsize { throw CocoaError(.fileReadUnknown) }
var unclonedSize: off_t = 0
_ = withUnsafeMutableBytes(of: &unclonedSize) { memcpy($0.baseAddress!, buf + 4, MemoryLayout<off_t>.size) }
return unclonedSize
}
do {
let regular = URL(fileURLWithPath: "/Users/andre/borkens/regular.dmg")
let clone = URL(fileURLWithPath: "/Users/andre/borkens/clone.dmg")
let cpRegular = URL(fileURLWithPath: "/Users/andre/borkens/cp-regular.dmg")
let cloneAppended = URL(fileURLWithPath: "/Users/andre/borkens/clone-appended.dmg")
print("Uncloned size of regular.dmg : \(try unclonedSize(of: regular))")
print("Uncloned size of clone.dmg : \(try unclonedSize(of: clone))")
print("Uncloned size of cpRegular.dmg : \(try unclonedSize(of: cpRegular))")
print("Uncloned size of cloneAppended.dmg: \(try unclonedSize(of: cloneAppended))")
} catch {
print("Error occurred: \(error.localizedDescription)")
}
@dreness
Copy link
Author

dreness commented May 1, 2019

Let's try it. In Xcode, make a new macOS playground and use the above Swift code. The test files are described as follows:

  • regular.dmg is a file of zeroes made with dd
  • cp-regular.dmg is a copy of that file made with cp, no arguments. standard copy.
  • clone.dmg was made with clonefile (cp -c).
  • clone-appended.dmg is a clone of regular.dmg, but with 10 bytes appended to it with echo and >>.
xomg% /bin/ls -le@ *.dmg
-rw-r--r--  1 andre  staff  104857610 Apr 30 21:35 clone-appended.dmg
-rw-r--r--  1 andre  staff  104857600 Apr 30 21:32 clone.dmg
-rw-r--r--  1 andre  staff  104857600 Apr 30 21:32 cp-regular.dmg
-rw-r--r--  1 andre  staff  104857600 Apr 30 21:32 regular.dmg

The playground output is:

Uncloned size of regular.dmg      : 0
Uncloned size of clone.dmg        : 0
Uncloned size of cpRegular.dmg    : 104857600
Uncloned size of cloneAppended.dmg: 14921728

Because this is a gist, conclusions are left as an exercise for the reader. I'll even tell you where the answer is: in the man page for getattrlist(2).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment