Took me some time to do this in Lazarus Pascal, but here an example how to add an attribute to the extended attributes of a file or directory under macOS (most likely works under Linux as well). It uses the Lib C functions getxattr and setxattr. There is also removeattr for those interested.
A simple unit I created for my own purposes, but maybe someone can use it as well:
unit t4a_macOS_XAttr;
{$mode ObjFPC}{$H+}
interface
uses
SysUtils, ctypes, unixtype;
const
// macOS extended attribute functions are in libc
libc = 'c';
function ReadXAttrInt(const FileName, AttrName: String): Integer;
function WriteXAttrInt(const FileName, AttrName: String; const Value: Integer): Boolean;
function getxattr(path: PChar; name: PChar; value: Pointer; size: size_t; position: cuint; options: cint): ssize_t; cdecl; external libc name 'getxattr';
function setxattr(path: PChar; name: PChar; value: Pointer; size: size_t; position: cuint; options: cint): cint; cdecl; external libc name 'setxattr';
implementation
// Reads an integer extended attribute. Returns 0 if not found.
function ReadXAttrInt(const FileName, AttrName: String): Integer;
var
Value: Integer;
BytesRead: ssize_t;
begin
FillChar(Value, SizeOf(Value), 0);
BytesRead := getxattr(PChar(FileName), PChar(AttrName), @Value, SizeOf(Value), 0, 0);
if BytesRead = -1 then
Result := 0 // Attribute missing or error
else
Result := Value;
end;
// Writes an integer extended attribute.
function WriteXAttrInt(const FileName, AttrName: String; const Value: Integer): Boolean;
var
Ret: cint;
begin
Ret := setxattr(PChar(FileName), PChar(AttrName), @Value, SizeOf(Value), 0, 0);
Result := (Ret = 0);
end;
end.
Example on how to use this:
procedure TForm1.Button1Click(Sender: TObject);
var
AttributeName: string;
AttributeNumber, ReadBack: integer;
Filename: string;
begin
AttributeName := 'user.myattributename'; // usually starts with "user."
AttributeNumber := 100;
Filename := '/path/to/mydirectory'; // can be a directory or a file
if WriteXAttrInt(Filename, AttributeName, AttributeNumber) then
ShowMessage('Wrote attribute '+ AttributeName+ ' = '+ IntToStr(AttributeNumber))
else
ShowMessage('Failed to write attribute');
ReadBack := ReadXAttrInt(Filename, AttributeName);
ShowMessage('Read attribute '+ AttributeName+ ' = '+ IntToStr(ReadBack));
end;
Enjoy ....