Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



Share:
Notifications
Clear all

[Solved] Lazarus Pascal - macOS -How to read or write extended attributes of files or directories

1 Posts
1 Users
0 Reactions
6 Views
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 3007
Topic starter  

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 ....

 

 

 



   
ReplyQuote
Share: