FIX: SyncDirs — preserve symlink timestamps on Linux (bug #3) (#2888)

(cherry picked from commit adb32099c9)
This commit is contained in:
EH 2026-05-26 11:45:53 -06:00 committed by Alexander Koblov
commit 680c9c8a93
2 changed files with 31 additions and 0 deletions

View file

@ -619,6 +619,14 @@ begin
if Assigned(Errors) then Errors^[caoCopyOwnership]:= GetLastOSError;
end;
end;
if caoCopyTime in Options then
begin
if DC_SymLinkSetTime(sDst, StatInfo.mtime, StatInfo.atime) = false then
begin
Include(Result, caoCopyTime);
if Assigned(Errors) then Errors^[caoCopyTime]:= GetLastOSError;
end;
end;
{$IF DEFINED(HAIKU)}
if caoCopyXattributes in Options then
begin

View file

@ -184,6 +184,11 @@ function DC_FileSetTime(const FileName: String;
const birthtime: TFileTimeEx;
const atime : TFileTimeEx ): Boolean;
// nanoseconds supported, does not follow symbolic links
function DC_SymLinkSetTime(const FileName: String;
const mtime : TFileTimeEx;
const atime : TFileTimeEx ): Boolean;
{en
Set the close-on-exec flag to all
@ -371,6 +376,7 @@ end;
{$ENDIF}
function fputimes( path:pchar; times:Array of UnixType.timeval ): cint; cdecl; external clib name 'utimes';
function flutimes( path:pchar; times:Array of UnixType.timeval ): cint; cdecl; external clib name 'lutimes';
function DC_FileSetTime(const FileName: String;
const mtime : TFileTimeEx;
@ -396,6 +402,23 @@ begin
{$ENDIF}
end;
// Like DC_FileSetTime but uses lutimes() instead of utimes(), so the
// timestamp is set on the symlink itself rather than its target.
function DC_SymLinkSetTime(const FileName: String;
const mtime : TFileTimeEx;
const atime : TFileTimeEx ): Boolean;
var
timevals: Array[0..1] of UnixType.timeval;
begin
// last access time
timevals[0].tv_sec:= atime.sec;
timevals[0].tv_usec:= round( Extended(atime.nanosec) / 1000.0 );
// last modification time
timevals[1].tv_sec:= mtime.sec;
timevals[1].tv_usec:= round( Extended(mtime.nanosec) / 1000.0 );
Result:= flutimes(pchar(UTF8ToSys(FileName)), timevals) = 0;
end;
{$IF DEFINED(BSD)}
type rlim_t = Int64;
{$ENDIF}