From 1f328cf362768d56dfe6101661209e6aeffdded5 Mon Sep 17 00:00:00 2001
From: Jonas Maebe <jonas@freepascal.org>
Date: Sat, 25 Jun 2022 17:29:48 +0200
Subject: [PATCH] Darwin: use recent versions of stat(fs) records when
 available

When the RTL is built for Mac OS X 10.6 or newer, use the new versions
and the corresponding alternate system library functions.

Also extracted the Darwin stat record definition to reduce the
ifdef hell.
---
 rtl/bsd/ostypes.inc   | 45 +++++++++++++++++++++++++++++++------------
 rtl/darwin/ptypes.inc | 11 ++++++++---
 rtl/unix/oscdeclh.inc | 17 ++++++++++------
 rtl/unix/unxdeclh.inc |  8 ++++++--
 4 files changed, 58 insertions(+), 23 deletions(-)

diff --git a/rtl/bsd/ostypes.inc b/rtl/bsd/ostypes.inc
index 230a648826..e634e25ddd 100644
--- a/rtl/bsd/ostypes.inc
+++ b/rtl/bsd/ostypes.inc
@@ -30,7 +30,7 @@
   {$endif}
 {$endif}
 
-{$if (defined(darwin) and (defined(cpuarm) or defined(cpuaarch64))) or defined(iphonesim)}
+{$if defined(darwin) and (defined(cpuarm) or defined(cpuaarch64) or defined(iphonesim) or (defined(MAC_OS_X_VERSION_MIN_REQUIRED) and (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060))) }
   {$define darwin_new_iostructs}
 {$endif}
 
@@ -63,7 +63,38 @@ TYPE
 
   { file characteristics services }
    stat    = record { the types are real}
-{$if defined(dragonfly)}
+{$if defined(darwin)}
+        st_dev        : dev_t;             // inode's device
+{$ifdef darwin_new_iostructs}
+        st_mode       : mode_t;            // inode protection mode
+        st_nlink      : nlink_t;           // number of hard links
+        st_ino        : ino_t;             // inode's number
+{$else not darwin_new_iostructs}
+        st_ino        : ino_t;             // inode's number
+        st_mode       : mode_t;            // inode protection mode
+        st_nlink      : nlink_t;           // number of hard links
+{$endif not darwin_new_iostructs}
+        st_uid        : uid_t;             // user ID of the file's owner
+        st_gid        : gid_t;             // group ID of the file's group
+        st_rdev       : dev_t;             // device type
+        st_atime      : time_t;            // time of last access
+        st_atimensec  : clong;             // nsec of last access
+        st_mtime      : time_t;            // time of last data modification
+        st_mtimensec  : clong;             // nsec of last data modification
+        st_ctime      : time_t;            // time of last file status change
+        st_ctimensec  : clong;             // nsec of last file status change
+{$ifdef darwin_new_iostructs}
+        st_birthtime  : time_t;            // File creation time
+        st_birthtimensec : clong;          // nsec of file creation time
+{$endif}
+        st_size       : off_t;             // file size, in bytes
+        st_blocks     : cint64;            // blocks allocated for file
+        st_blksize    : cuint32;           // optimal blocksize for I/O
+        st_flags      : cuint32;           // user defined flags for file
+        st_gen        : cuint32;           // file generation number
+        st_lspare     : cuint32;           // RESERVED: DO NOT USE!
+        st_qspare     : array[0..1] Of cint64;
+{$elseif defined(dragonfly)}
         st_ino        : ino_t;             // inode's number
         st_nlink      : nlink_t;           // number of hard links
         st_dev        : dev_t;             // inode's device
@@ -148,11 +179,6 @@ TYPE
 	st_spare      : array [0..10-1] of cuint64;
 {$else}
         st_dev        : dev_t;             // inode's device
-{$ifdef darwin_new_iostructs}
-        st_mode       : mode_t;            // inode protection mode
-        st_nlink      : nlink_t;           // number of hard links
-        st_ino        : ino_t;             // inode's number
-{$else not darwin_new_iostructs}
 {$ifdef netbsd_use_stat30}
      { order is inverted for better alignment probably }
         st_mode       : mode_t;            // inode protection mode
@@ -162,7 +188,6 @@ TYPE
         st_mode       : mode_t;            // inode protection mode
 {$endif not netbsd}
         st_nlink      : nlink_t;           // number of hard links
-{$endif not darwin_new_iostructs}
         st_uid        : uid_t;             // user ID of the file's owner
         st_gid        : gid_t;             // group ID of the file's group
         st_rdev       : dev_t;             // device type
@@ -172,10 +197,6 @@ TYPE
         st_mtimensec  : clong;             // nsec of last data modification
         st_ctime      : time_t;            // time of last file status change
         st_ctimensec  : clong;             // nsec of last file status change
-{$ifdef darwin_new_iostructs}
-        st_birthtime  : time_t;            // File creation time
-        st_birthtimensec : clong;          // nsec of file creation time
-{$endif}
 {$ifdef netbsdPowerpc}
         st_padd1              : cint;
 {$endif}
diff --git a/rtl/darwin/ptypes.inc b/rtl/darwin/ptypes.inc
index aa12ebcb89..2df932230c 100644
--- a/rtl/darwin/ptypes.inc
+++ b/rtl/darwin/ptypes.inc
@@ -22,6 +22,11 @@
 {$i ctypes.inc}
 {$packrecords c}
 
+
+{$if defined(darwin) and (defined(cpuarm) or defined(cpuaarch64) or defined(iphonesim) or (defined(MAC_OS_X_VERSION_MIN_REQUIRED) and (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)))}
+  {$define darwin_new_iostructs}
+{$endif}
+
 type
     { the following type definitions are compiler dependant }
     { and system dependant                                  }
@@ -35,10 +40,10 @@ type
     pGid     = ^gid_t;
     TIOCtlRequest = cuLong;
 
-{$if not defined(cpuarm) and not defined(aarch64) and not defined(iphonesim)}
-    ino_t    = cuint32;         { used for file serial numbers }
-{$else}
+{$ifdef darwin_new_iostructs}
     ino_t    = cuint64;
+{$else}
+    ino_t    = cuint32;         { used for file serial numbers }
 {$endif}
     TIno     = ino_t;
     pIno     = ^ino_t;
diff --git a/rtl/unix/oscdeclh.inc b/rtl/unix/oscdeclh.inc
index 363014e31c..b683334370 100644
--- a/rtl/unix/oscdeclh.inc
+++ b/rtl/unix/oscdeclh.inc
@@ -33,9 +33,14 @@ Type TGrpArr = Array [0..0] of TGid;            { C style array workarounds}
 const
 {$if (defined(linux) and defined(cpu32) and not defined(fs32bit)) or defined(aix)}
     suffix64bit = '64';
-{$else}    
+    darwinsuffix64bit = '';
+{$elseif defined(darwin_new_iostructs)}
     suffix64bit = '';
-{$endif}    
+    darwinsuffix64bit = '$INODE64';
+{$else}
+    suffix64bit = '';
+    darwinsuffix64bit = '';
+{$endif}
 
     function  FPSigProcMask(how:cint;nset : psigset;oset : psigset):cint;cdecl; external clib name 'sigprocmask';
     function  FPSigProcMask(how:cint;const nset : sigset;var oset : sigset):cint;cdecl; external clib name 'sigprocmask';
@@ -88,7 +93,7 @@ const
     Function  FpKill       (pid : TPid; sig: cInt): cInt; cdecl; external clib name 'kill';
     function  FpUname   (var name: utsname): cint; cdecl; external clib name 'uname';
     function  FpOpendir (dirname : pchar): pdir; cdecl; external clib name 'opendir'{$ifdef aix}+suffix64bit{$endif};
-    Function  FpReaddir (var dirp : Dir) : pDirent;cdecl; external clib name 'readdir'+suffix64bit;
+    Function  FpReaddir (var dirp : Dir) : pDirent;cdecl; external clib name 'readdir'+suffix64bit+darwinsuffix64bit;
     Function  FpClosedir (var dirp : Dir): cInt; cdecl; external clib name 'closedir'{$ifdef aix}+suffix64bit{$endif};
     function  FpChdir   (path : pchar): cint; cdecl; external clib name 'chdir';
     { emulate the bunxovl version that automatically passes
@@ -106,9 +111,9 @@ const
     function  FpStat      (path: pchar; var buf : stat): cint;inline;
 {$endif FPC_IS_SYSTEM}
 {$else linux}
-    function  FpFstat   (fd : cint; var sb : stat): cint; cdecl; external clib name 'fstat'+suffix64bit;
-    Function  fpLstat   (path:pchar;Info:pstat):cint;     cdecl; external clib name 'lstat'+suffix64bit;
-    function  FpStat    (path: pchar; var buf : stat): cint; cdecl; external clib name 'stat'+suffix64bit;
+    function  FpFstat   (fd : cint; var sb : stat): cint; cdecl; external clib name 'fstat'+suffix64bit+darwinsuffix64bit;
+    Function  fpLstat   (path:pchar;Info:pstat):cint;     cdecl; external clib name 'lstat'+suffix64bit+darwinsuffix64bit;
+    function  FpStat    (path: pchar; var buf : stat): cint; cdecl; external clib name 'stat'+suffix64bit+darwinsuffix64bit;
 {$endif linux}
     function  FpAccess  (pathname : pchar; amode : cint): cint; cdecl; external clib name 'access';
     function  FpClose   (fd : cint): cint; cdecl; external clib name 'close';
diff --git a/rtl/unix/unxdeclh.inc b/rtl/unix/unxdeclh.inc
index f8aecfc0a2..b104c40fb3 100644
--- a/rtl/unix/unxdeclh.inc
+++ b/rtl/unix/unxdeclh.inc
@@ -15,6 +15,10 @@
 
 type filedesarray=array[0..1] of cint;
 
+{$if defined(darwin) and (defined(cpuarm) or defined(cpuaarch64) or defined(iphonesim) or (defined(MAC_OS_X_VERSION_MIN_REQUIRED) and (MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)))}
+  {$define darwin_new_iostructs}
+{$endif}
+
 {$if defined(solaris) or defined(aix)}
 Function fpFlock (fd,mode : longint) : cint;{$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
 {$else solaris or aix}
@@ -26,7 +30,7 @@ Function fpFlock (fd,mode : longint) : cint; cdecl; external clib name 'flock';
 {$if defined(beos) or defined(solaris) }
 Function fpfStatFS(Fd:Longint; Info:pstatfs):cint; cdecl; external clib name 'fstatvfs';
 {$else beos or solaris }
-Function fpfStatFS(Fd:Longint; Info:pstatfs):cint; cdecl; external clib name 'fstatfs';
+Function fpfStatFS(Fd:Longint; Info:pstatfs):cint; cdecl; external clib name 'fstatfs'{$ifdef darwin_new_iostructs}+'$INODE64'{$endif};
 {$endif beos or solaris }
 
 Function fpfsync (fd : cint) : cint; cdecl; external clib name 'fsync';
@@ -34,7 +38,7 @@ Function fpfsync (fd : cint) : cint; cdecl; external clib name 'fsync';
 {$if defined(beos) or defined(solaris) }
 Function fpStatFS  (Path:pchar; Info:pstatfs):cint; cdecl; external clib name 'statvfs';
 {$else beos or solaris }
-Function fpStatFS  (Path:pchar; Info:pstatfs):cint; cdecl; external clib name 'statfs';
+Function fpStatFS  (Path:pchar; Info:pstatfs):cint; cdecl; external clib name 'statfs'{$ifdef darwin_new_iostructs}+'$INODE64'{$endif};
 {$endif beos or solaris }
 
 function pipe (var fildes: filedesarray):cint;  cdecl; external clib name 'pipe';