Post

Replies

Boosts

Views

Activity

Reply to Resolve bookmark created in iOS app in Share Extension
Sorry, I didn't know that clicking on the checkmark would mark your answer as the correct one (it looks more like a badge to show that your account is verified, so I was wondering where the link would bring me). Is it possible to revert this action? Anyway, what you suggest is exactly what I'm doing (except that I cannot use withSecurityScope since I'm on iOS), and it's not working.
Aug ’20
Reply to Getting inode number from URL
I'm building an app that makes periodic backups and would like to know what files have changed between two backups (in particular when a file has been renamed so that I can rename it as well on the backup drive instead of removing the old file and copying the new one over again), which as far as I understand is only possible by comparing the inode numbers.
Aug ’20
Reply to Getting inode number from URL
Thank you, I already filed FB8308273. The problem even when only using stat is that FileManager will already have been its own call to get the other attributes, so it's always approximately double the scan time. What is the difference between getdirentriesattr and getattrlistbulk? Are there any examples in Swift? I already tried using getattrlistbulk in the past, but could only find examples written in Objective-C which were quite difficult to translate to Swift.
Aug ’20
Reply to Getting inode number from URL
Thank you so much! Although I don't understand why you use a while loop inside getattrlistbulk2. Shouldn't it be like this:     func getattrlistbulk2(_ dirFD: CInt, _ attrListPtr: UnsafeMutablePointer<attrlist>, _ attrBuf: UnsafeMutableRawBufferPointer, _ options: UInt64) throws -> Int {         let result = getattrlistbulk(dirFD, attrListPtr, attrBuf.baseAddress!, attrBuf.count, 0)         if result >= 0 {             return Int(result)         }         let err = errno         if err != EINTR {             throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno), userInfo: nil)         }         return 0     }
Aug ’20
Reply to Getting inode number from URL
I kept wondering why your code is slightly slower than enumeration done with FileManager. It turns out that using let attrBuf = UnsafeMutableRawBufferPointer.allocate(byteCount: 1024, alignment: 16) instead of let attrBuf = UnsafeMutableRawBufferPointer.allocate(byteCount: 256, alignment: 16) is about 25% faster when scanning my Documents directory.
Aug ’20
Reply to Getting inode number from URL
In order to get the inode I use var fileId: UInt32 = 0 if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_FILEID)) != 0 {     fileId = field.load(as: UInt32.self)     field += MemoryLayout<UInt32>.size } which seems to work fine (at least for all files in my Documents directory it's equal to FileManager.attributesOfItem(atPath: url.path)[.systemFileNumber]). Is UInt32 the right type? (The documentation says it should be u_int64_t, but using UInt64 crashes at runtime at the line fileId = field.load(as: UInt64.self) with an error Fatal error: load from misaligned raw pointer.) I'm also having difficulties reading the modification date. With this code attrList.commonattr =     attrgroup_t(ATTR_CMN_RETURNED_ATTRS) | 		attrgroup_t(bitPattern: ATTR_CMN_NAME) | 		attrgroup_t(bitPattern: ATTR_CMN_ERROR) | 		attrgroup_t(bitPattern: ATTR_CMN_OBJTYPE) | 		attrgroup_t(bitPattern: ATTR_CMN_MODTIME) | 		attrgroup_t(bitPattern: ATTR_CMN_FILEID) and this code appended to the end of printAttrs var modtime: timespec if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_MODTIME)) != 0 {     modtime = field.load(as: timespec.self)     field += MemoryLayout<timespec>.size } var fileId: UInt32 = 0 if (returned.commonattr & attrgroup_t(bitPattern: ATTR_CMN_FILEID)) != 0 {     fileId = field.load(as: UInt32.self)     field += MemoryLayout<UInt32>.size } I get again the same error Fatal error: load from misaligned raw pointer at the line modtime = field.load(as: timespec.self). Any idea what the problem could be?
Aug ’20
Reply to Getting inode number from URL
Thanks Kevin, for apps targeting macOS 11+ fileContentIdentifierKey will be useful, but for my existing apps that still run on older systems I will probably have to use getattrlistbulk. Does that key effectively return the inode, or what kind of identifier is it? It would be helpful to mention it in the documentation. Thanks also Quinn, I didn't know the meaning of EINTR. If someone could have a look at the issues with ATTR_CMN_MODTIME and ATTR_CMN_FILEID I mentioned in my previous post, that would be great.
Aug ’20
Reply to Getting inode number from URL
Thank you, that was it. I hope I'm now facing the last issue with this solution: thanks to your code we have name = String(cString: (base + Int(nameInfo.attr_dataoffset)).assumingMemoryBound(to: CChar.self)). I need the absolute path so I did let path = "\(dirPath)/\(name)", but this produces some kind of string that is not "fast": using the Instruments app I found out that when using path as a key for a Swift dictionary with some custom object as the value, the scan is more than double the time than if I use let path = String(format: "%@/%@", directoryPath, name) or even let path = URL(fileURLWithPath: "\(dirPath)/\(name)").path. Is there an easy explanation for this? I would have thought that string interpolation should produce the same kind of string as when using String(format:), only more efficiently.
Aug ’20
Reply to getattrlistbulk lists files with underscore prefix on exFAT
Thanks, that seems to be the case. Is there a more efficient way of checking that a file is an AppleDouble file other than testing if a file exists with the same name but without the ._ prefix or check the first bytes against that magic number? During my test I noticed that the dot underscore file seems to be enumerated by getattrlistbulk immediately after the original file: is this always guaranteed and is there a documentation somewhere that explains this in more detail? Any idea how FileManager does it?
Aug ’20