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!
[Solved] Lazarus Pascal - macOS - getmntinfo() returns empty array under Apple Silicon
Delphi, Lazarus, Free Pascal
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2854
Topic starter
September 10, 2022 11:05 AM
To determine what kind of drives have been mounted on a Mac, I prefer to use the old school C-library function (BSD) getmntinfo().
Worked great on Intel Mac's but recent experiments with ARM/Apple Silicon Macs only returned an empty array.
After a lot of tinkering around I found the issue ...
Intel Macs seem to prefer "MFSNAMELEN = 15" (the max length of filesystem type).
However ARM based Macs this appear to prefer "MFSNAMELEN = 16".
In short:
unit ...
{$LINKLIB c} // used for getmntinfo, seems to work without this as well
interface
uses
..., unixtype,... ;
type
{$IF defined(cpuaarch64)}
My_tstatfs = record
bsize : cuint32;
iosize : cint32;
blocks : cuint64;
bfree : cuint64;
bavail : cuint64;
files : cuint64;
ffree : cuint64;
fsid : fsid_t;
owner : uid_t;
ftype : cuint32;
fflags : cuint32;
fssubtype : cuint32;
fstypename : array[0..(MFSNAMELEN)] of char; // <-- was MFSNAMELEN-1 => fails => bug?
mountpoint : array[0..(PATH_MAX)-1] of char;
mntfromname : array[0..(PATH_MAX)-1] of char;
reserved: array[0..7] of cuint32;
end;
{$ELSE}
My_tstatfs = record
otype : cint16;
oflags : cint16;
bsize : clong;
iosize : clong;
blocks : clong;
bfree : clong;
bavail : clong;
files : clong;
ffree : clong;
fsid : array[0..1] of cint32;//fsid_t;
fowner : cuint32; //uid_t;
reserved1 : cint16;
ftype : cint16;
fflags : clong;
reserved2 : array[0..1] of clong;
fstypename : array[0..(MFSNAMELEN)-1] of char;
mountpoint : array[0..(MNAMELEN)-1] of char;
mntfromname : array[0..(MNAMELEN)-1] of char;
f_reserved3 : char;
reserved4 : array[0..3] of clong;
end;
{$ENDIF}
My_pstatfs = ^My_tstatfs;
{ clib import to get mount info }
function getmntinfo( buf: My_pstatfs; flasg: integer):integer; cdecl; external 'clib' name 'getmntinfo';
const
{ constants for getmntinfo }
MNT_NOWAIT = 2; // No waiting
MNT_LOCAL = $1000; // filesystem is stored locally -> eg. NOT a network share
....
procedure TForm1.Button1Click(Sender: TObject);
var
Counter : integer;
MountCount : integer;
pStatfsBuffer : My_pstatfs;
begin
Memo1.Clear;
MountCount := getmntinfo(@pStatfsBuffer, MNT_NOWAIT);
for Counter :=0 to MountCount - 1 do
begin
Memo1.Lines.Add('fstypename : '+ pStatfsBuffer[Counter].fstypename);
Memo1.Lines.Add('mountpoint : '+ pStatfsBuffer[Counter].mountpoint);
Memo1.Lines.Add('mntfromname : '+ pStatfsBuffer[Counter].mntfromname + LineEnding);
end;
end;
Â
Hope this is useful someone struggling with this like I did ... 😊