2

According to Apple's document, we can set lots of attributes for a file

A dictionary containing as keys the attributes to set for path and as values the corresponding value for the attribute. You can set the following attributes: busy, creationDate, extensionHidden, groupOwnerAccountID, groupOwnerAccountName, hfsCreatorCode, hfsTypeCode, immutable, modificationDate, ownerAccountID, ownerAccountName, posixPermissions. You can change single attributes or any combination of attributes; you need not specify keys for all attributes.

I want to set an extra parameter for a file. The parameter is a String, I can't find any attribute that I can set String. For example, I tried

try FileManager.default.setAttributes([FileAttributeKey.ownerAccountName: NSString(string: "0B2TwsHM7lBpSMU1tNXVfSEp0RGs"), FileAttributeKey.creationDate: date], ofItemAtPath: filePath.path)

But when I load keys

let keys = try FileManager.default.attributesOfItem(atPath: filePath.path)
print(keys)

I only get .creationDate changed

[__C.FileAttributeKey(_rawValue: NSFileType): NSFileTypeRegular,
__C.FileAttributeKey(_rawValue: NSFilePosixPermissions): 420,
__C.FileAttributeKey(_rawValue: NSFileSystemNumber): 16777220,
__C.FileAttributeKey(_rawValue: NSFileReferenceCount): 1,
__C.FileAttributeKey(_rawValue: NSFileGroupOwnerAccountName): staff,
__C.FileAttributeKey(_rawValue: NSFileSystemFileNumber): 8423614,
__C.FileAttributeKey(_rawValue: NSFileGroupOwnerAccountID): 20,
__C.FileAttributeKey(_rawValue: NSFileModificationDate): 2017-08-16 06:03:57 +0000, 
__C.FileAttributeKey(_rawValue: NSFileCreationDate): 1970-01-01 00:33:20 +0000, 
__C.FileAttributeKey(_rawValue: NSFileSize): 9795,
__C.FileAttributeKey(_rawValue: NSFileExtensionHidden): 0,
__C.FileAttributeKey(_rawValue: NSFileOwnerAccountID): 501]

Is there any way that I can set string value to FileAttribute?

Alex
  • 135
  • 1
  • 15

1 Answers1

3

The documentation says "You can set the following attributes". That means you can only set those specific attributes via those API's.

What you are really looking for are Extended Attributes, and these use a separate set of (C-style) API's.

Something like:

let directory = NSTemporaryDirectory()
let someExampleText = "some sample text goes here"
do {
    try someExampleText.write(toFile: "\(directory)/test.txt", atomically: true, encoding: .utf8)
} catch let error {
    print("error while writing is \(error.localizedDescription)")
}
let valueString = "setting some value here"
let result = setxattr("\(directory)/test.txt", "com.stackoverflow.test", valueString, valueString.characters.count, 0, 0)

print("result is \(result) ; errno is \(errno)")
if errno != 0
{
    perror("could not save")
}

let sizeOfRetrievedValue = getxattr("\(directory)/test.txt", "com.stackoverflow.test", nil, 0, 0, 0)

var data = Data(count: sizeOfRetrievedValue)

let newResult = data.withUnsafeMutableBytes({
    getxattr("\(directory)/test.txt", "com.stackoverflow.test", $0, data.count, 0, 0)
})

if let resultString = String(data: data, encoding: .utf8)
{
    print("retrieved string is \(resultString)")
}
Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
  • Sorry, I advertently deleted my last comment. – Yes, that could be an invalid owner, or a permission problem. – Martin R Aug 16 '17 at 06:53
  • yep... I deleted my comment after you deleted yours. I was saying that the wacky userid string being passed in for `FileAttributeKey.ownerAccountName` does not look like a valid user id and so I'm thinking the OS is doing some validation and not allowing the change to happen to that attribute. – Michael Dautermann Aug 16 '17 at 06:54
  • Yeah, I found one solution eventually. https://stackoverflow.com/questions/38343186/write-extend-file-attributes-swift-example – Alex Aug 16 '17 at 06:57
  • Yep. I was trying to come up with a `getxattr` example and ended up googling up that same related answer as well. – Michael Dautermann Aug 16 '17 at 07:13