From 0c77536f11a75d737878da941c178c29c85b7541 Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 31 Jan 2021 16:24:47 +0000 Subject: [PATCH] + linux.fputimensat which properly uses the _tim64 version if needed and available + test git-svn-id: trunk@48470 - --- .gitattributes | 1 + rtl/linux/linux.pp | 32 +++++++++++ tests/test/units/linux/tutimensat.pp | 83 ++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 tests/test/units/linux/tutimensat.pp diff --git a/.gitattributes b/.gitattributes index aaddeb36e4..5d5a884d15 100644 --- a/.gitattributes +++ b/.gitattributes @@ -16111,6 +16111,7 @@ tests/test/units/fpwidestring/twide7fpwidestring.pp svneol=native#text/pascal tests/test/units/lineinfo/tlininfo.pp svneol=native#text/plain tests/test/units/linux/tepoll1.pp svneol=native#text/pascal tests/test/units/linux/tstatx.pp svneol=native#text/pascal +tests/test/units/linux/tutimensat.pp svneol=native#text/pascal tests/test/units/math/tcmpnan.pp svneol=native#text/plain tests/test/units/math/tdivmod.pp svneol=native#text/plain tests/test/units/math/tmask.inc svneol=native#text/plain diff --git a/rtl/linux/linux.pp b/rtl/linux/linux.pp index 7a31fdf8f1..72c2c9ad36 100644 --- a/rtl/linux/linux.pp +++ b/rtl/linux/linux.pp @@ -544,6 +544,19 @@ Type function Fpstatx(dfd: cint; filename: pchar; flags,mask: cuint; var buf: statx):cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'statx'; {$ENDIF} +Type + kernel_time64_t = clonglong; + + kernel_timespec = record + tv_sec : kernel_time64_t; + tv_nsec : clonglong; + end; + pkernel_timespec = ^kernel_timespec; + + tkernel_timespecs = array[0..1] of kernel_timespec; + + Function fputimensat(dfd: cint; path:pchar;const times:tkernel_timespecs;flags:cint):cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'statx'; {$ENDIF} + implementation @@ -861,4 +874,23 @@ end; {$endif} +Function fputimensat(dfd: cint; path:pchar;const times:tkernel_timespecs;flags:cint):cint; +var + tsa: Array[0..1] of timespec; +begin +{$if sizeof(clong)<=4} + fputimensat:=do_syscall(syscall_nr_utimensat_time64,dfd,TSysParam(path),TSysParam(@times),0); + if (fputimensat>=0) or (fpgeterrno<>ESysENOSYS) then + exit; + { try 32 bit fall back } + tsa[0].tv_sec := times[0].tv_sec; + tsa[0].tv_nsec := times[0].tv_nsec; + tsa[1].tv_sec := times[1].tv_sec; + tsa[1].tv_nsec := times[1].tv_nsec; + fputimensat:=do_syscall(syscall_nr_utimensat,dfd,TSysParam(path),TSysParam(@tsa),0); +{$else sizeof(clong)<=4} + fputimensat:=do_syscall(syscall_nr_utimensat,dfd,TSysParam(path),TSysParam(@times),0); +{$endif sizeof(clong)<=4} +end; + end. diff --git a/tests/test/units/linux/tutimensat.pp b/tests/test/units/linux/tutimensat.pp new file mode 100644 index 0000000000..3d72e068bd --- /dev/null +++ b/tests/test/units/linux/tutimensat.pp @@ -0,0 +1,83 @@ +{ %target=linux } +uses + ctypes,baseunix,linux; + +var + un : utsname; + res : cint; + f1,f2 : text; + err : word; + mystatx1,mystatx2 : statx; + times : tkernel_timespecs; + st,major,minor : string; + i,p,e : longint; + major_release, minor_release : longint; +begin + fpuname(un); + st:=un.release; + for i:=1 to UTSNAME_LENGTH do + if st[i]='.' then + begin + p:=i; + major:=system.copy(st,1,p-1); + system.val(major,major_release,err); + if err<>0 then + begin + writeln('Unable to parse first part of linux version ',st,'(',major,') correctly'); + halt(2); + end; + break; + end; + + for i:=p+1 to UTSNAME_LENGTH do + if st[i]='.' then + begin + e:=i; + minor:=system.copy(st,p+1,e-p-1); + system.val(minor,minor_release,err); + if err<>0 then + begin + writeln('Unable to second part of parse linux version ',st,'i(',minor,') correctly'); + halt(2); + end; + break; + end; + if (major_release<4) or ((major_release=4) and (minor_release<11)) then + begin + writeln('This version of Linux: ',st,' does not have fstatx syscall'); + halt(0); + end + else + writeln('This linux version ',st,' should support statx syscall'); + + assign(f1,'tutimensat1.txt'); + rewrite(f1); + write(f1,'ccccc'); + close(f1); + assign(f2,'tutimensat2.txt'); + rewrite(f2); + write(f2,'ccccc'); + close(f2); + + res:=fpstatx(AT_FDCWD,'tutimensat1.txt',AT_SYMLINK_NOFOLLOW,STATX_ALL,mystatx1); + if res<>0 then + halt(1); + times[0].tv_sec:=mystatx1.stx_atime.tv_sec; + times[0].tv_nsec:=mystatx1.stx_atime.tv_nsec; + times[1].tv_sec:=mystatx1.stx_mtime.tv_sec; + times[1].tv_nsec:=mystatx1.stx_mtime.tv_nsec; + res:=fputimensat(AT_FDCWD,'tutimensat2.txt',times,0); + if res<>0 then + halt(1); + res:=fpstatx(AT_FDCWD,'tutimensat2.txt',AT_SYMLINK_NOFOLLOW,STATX_ALL,mystatx2); + if res<>0 then + halt(1); + + erase(f1); + erase(f2); + + if (mystatx1.stx_atime.tv_sec<>mystatx2.stx_atime.tv_sec) or (mystatx1.stx_atime.tv_nsec<>mystatx2.stx_atime.tv_nsec) or + (mystatx1.stx_mtime.tv_sec<>mystatx2.stx_mtime.tv_sec) or (mystatx1.stx_mtime.tv_nsec<>mystatx2.stx_mtime.tv_nsec) then + halt(1); + writeln('ok'); +end.