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 - getmntinfo() returns empty array under Apple Silicon

1 Posts
1 Users
0 Reactions
1,113 Views
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
Topic starter  

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


   
ReplyQuote
Share: