sysutils.pp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for linux
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. { force ansistrings }
  16. {$H+}
  17. {$if (defined(BSD) or defined(SUNOS)) and defined(FPC_USE_LIBC)}
  18. {$define USE_VFORK}
  19. {$endif}
  20. {$DEFINE OS_FILESETDATEBYNAME}
  21. {$DEFINE HAS_SLEEP}
  22. {$DEFINE HAS_OSERROR}
  23. {$DEFINE HAS_OSCONFIG}
  24. {$DEFINE HAS_TEMPDIR}
  25. {$DEFINE HASUNIX}
  26. {$DEFINE HASCREATEGUID}
  27. {$DEFINE HAS_OSUSERDIR}
  28. uses
  29. Unix,errors,sysconst,Unixtype;
  30. { Include platform independent interface part }
  31. {$i sysutilh.inc}
  32. Function AddDisk(const path:string) : Byte;
  33. { the following is Kylix compatibility stuff, it should be moved to a
  34. special compatibilty unit (FK) }
  35. const
  36. RTL_SIGINT = 0;
  37. RTL_SIGFPE = 1;
  38. RTL_SIGSEGV = 2;
  39. RTL_SIGILL = 3;
  40. RTL_SIGBUS = 4;
  41. RTL_SIGQUIT = 5;
  42. RTL_SIGLAST = RTL_SIGQUIT;
  43. RTL_SIGDEFAULT = -1;
  44. type
  45. TSignalState = (ssNotHooked, ssHooked, ssOverridden);
  46. function InquireSignal(RtlSigNum: Integer): TSignalState;
  47. procedure AbandonSignalHandler(RtlSigNum: Integer);
  48. procedure HookSignal(RtlSigNum: Integer);
  49. procedure UnhookSignal(RtlSigNum: Integer; OnlyIfHooked: Boolean = True);
  50. implementation
  51. Uses
  52. {$ifdef FPC_USE_LIBC}initc{$ELSE}Syscall{$ENDIF}, Baseunix, unixutil;
  53. function InquireSignal(RtlSigNum: Integer): TSignalState;
  54. begin
  55. end;
  56. procedure AbandonSignalHandler(RtlSigNum: Integer);
  57. begin
  58. end;
  59. procedure HookSignal(RtlSigNum: Integer);
  60. begin
  61. end;
  62. procedure UnhookSignal(RtlSigNum: Integer; OnlyIfHooked: Boolean = True);
  63. begin
  64. end;
  65. {$Define OS_FILEISREADONLY} // Specific implementation for Unix.
  66. {$DEFINE FPC_FEXPAND_TILDE} { Tilde is expanded to home }
  67. {$DEFINE FPC_FEXPAND_GETENVPCHAR} { GetEnv result is a PChar }
  68. { Include platform independent implementation part }
  69. {$i sysutils.inc}
  70. { Include SysCreateGUID function }
  71. {$i suuid.inc}
  72. Const
  73. {Date Translation}
  74. C1970=2440588;
  75. D0 = 1461;
  76. D1 = 146097;
  77. D2 =1721119;
  78. Procedure JulianToGregorian(JulianDN:LongInt;Var Year,Month,Day:Word);
  79. Var
  80. YYear,XYear,Temp,TempMonth : LongInt;
  81. Begin
  82. Temp:=((JulianDN-D2) shl 2)-1;
  83. JulianDN:=Temp Div D1;
  84. XYear:=(Temp Mod D1) or 3;
  85. YYear:=(XYear Div D0);
  86. Temp:=((((XYear mod D0)+4) shr 2)*5)-3;
  87. Day:=((Temp Mod 153)+5) Div 5;
  88. TempMonth:=Temp Div 153;
  89. If TempMonth>=10 Then
  90. Begin
  91. inc(YYear);
  92. dec(TempMonth,12);
  93. End;
  94. inc(TempMonth,3);
  95. Month := TempMonth;
  96. Year:=YYear+(JulianDN*100);
  97. end;
  98. Procedure EpochToLocal(epoch:longint;var year,month,day,hour,minute,second:Word);
  99. {
  100. Transforms Epoch time into local time (hour, minute,seconds)
  101. }
  102. Var
  103. DateNum: LongInt;
  104. Begin
  105. inc(Epoch,TZSeconds);
  106. Datenum:=(Epoch Div 86400) + c1970;
  107. JulianToGregorian(DateNum,Year,Month,day);
  108. Epoch:=Abs(Epoch Mod 86400);
  109. Hour:=Epoch Div 3600;
  110. Epoch:=Epoch Mod 3600;
  111. Minute:=Epoch Div 60;
  112. Second:=Epoch Mod 60;
  113. End;
  114. {****************************************************************************
  115. File Functions
  116. ****************************************************************************}
  117. Procedure FSplit(const Path:PathStr;Var Dir:DirStr;Var Name:NameStr;Var Ext:ExtStr);
  118. Var
  119. DotPos,SlashPos,i : longint;
  120. Begin
  121. SlashPos:=0;
  122. DotPos:=256;
  123. i:=Length(Path);
  124. While (i>0) and (SlashPos=0) Do
  125. Begin
  126. If (DotPos=256) and (Path[i]='.') Then
  127. begin
  128. DotPos:=i;
  129. end;
  130. If (Path[i]='/') Then
  131. SlashPos:=i;
  132. Dec(i);
  133. End;
  134. Ext:=Copy(Path,DotPos,255);
  135. Dir:=Copy(Path,1,SlashPos);
  136. Name:=Copy(Path,SlashPos + 1,DotPos - SlashPos - 1);
  137. End;
  138. Function DoFileLocking(Handle: Longint; Mode: Integer) : Longint;
  139. var
  140. lockop: cint;
  141. lockres: cint;
  142. begin
  143. DoFileLocking:=Handle;
  144. {$ifndef beos}
  145. if (Handle>=0) then
  146. begin
  147. {$ifdef solaris}
  148. { Solaris' flock is based on top of fcntl, which does not allow
  149. exclusive locks for files only opened for reading nor shared
  150. locks for files opened only for writing
  151. }
  152. if ((mode and (fmShareCompat or fmShareExclusive or fmShareDenyWrite or fmShareDenyRead)) = fmShareCompat) then
  153. begin
  154. mode := mode and not(fmShareCompat);
  155. if ((mode and (fmOpenRead or fmOpenWrite or fmOpenReadWrite)) = fmOpenRead) then
  156. mode := mode or fmShareDenyWrite
  157. else
  158. mode := mode or fmShareExclusive;
  159. end;
  160. {$endif solaris}
  161. case (mode and (fmShareCompat or fmShareExclusive or fmShareDenyWrite or fmShareDenyRead)) of
  162. fmShareCompat,
  163. fmShareExclusive:
  164. lockop:=LOCK_EX or LOCK_NB;
  165. fmShareDenyWrite:
  166. lockop:=LOCK_SH or LOCK_NB;
  167. fmShareDenyNone:
  168. exit;
  169. else
  170. begin
  171. { fmShareDenyRead does not exit under *nix, only shared access
  172. (similar to fmShareDenyWrite) and exclusive access (same as
  173. fmShareExclusive)
  174. }
  175. FpClose(Handle);
  176. DoFileLocking:=-1;
  177. exit;
  178. end;
  179. end;
  180. repeat
  181. lockres:=fpflock(Handle,lockop);
  182. until lockres<>ESysEIntr;
  183. if (lockres<>0) then
  184. begin
  185. FpClose(Handle);
  186. DoFileLocking:=-1;
  187. exit;
  188. end;
  189. end;
  190. {$endif not beos}
  191. end;
  192. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  193. Var
  194. LinuxFlags : longint;
  195. begin
  196. LinuxFlags:=0;
  197. case (Mode and (fmOpenRead or fmOpenWrite or fmOpenReadWrite)) of
  198. fmOpenRead : LinuxFlags:=LinuxFlags or O_RdOnly;
  199. fmOpenWrite : LinuxFlags:=LinuxFlags or O_WrOnly;
  200. fmOpenReadWrite : LinuxFlags:=LinuxFlags or O_RdWr;
  201. end;
  202. FileOpen:=fpOpen (pointer(FileName),LinuxFlags);
  203. FileOpen:=DoFileLocking(FileOpen, Mode);
  204. end;
  205. Function FileCreate (Const FileName : String) : Longint;
  206. begin
  207. FileCreate:=fpOpen(pointer(FileName),O_RdWr or O_Creat or O_Trunc);
  208. end;
  209. Function FileCreate (Const FileName : String;Mode : Longint) : Longint;
  210. begin
  211. FileCreate:=fpOpen(pointer(FileName),O_RdWr or O_Creat or O_Trunc,Mode);
  212. end;
  213. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  214. begin
  215. FileRead:=fpRead (Handle,Buffer,Count);
  216. end;
  217. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  218. begin
  219. FileWrite:=fpWrite (Handle,Buffer,Count);
  220. end;
  221. Function FileSeek (Handle,FOffset,Origin : Longint) : Longint;
  222. begin
  223. result:=longint(FileSeek(Handle,int64(FOffset),Origin));
  224. end;
  225. Function FileSeek (Handle : Longint; FOffset : Int64; Origin : Longint) : Int64;
  226. begin
  227. FileSeek:=fplSeek (Handle,FOffset,Origin);
  228. end;
  229. Procedure FileClose (Handle : Longint);
  230. begin
  231. fpclose(Handle);
  232. end;
  233. Function FileTruncate (Handle: THandle; Size: Int64) : boolean;
  234. begin
  235. if (SizeOf (TOff) < 8) (* fpFTruncate only supporting signed 32-bit size *)
  236. and (Size > high (longint)) then
  237. FileTruncate := false
  238. else
  239. FileTruncate:=fpftruncate(Handle,Size)>=0;
  240. end;
  241. {$ifndef FPUNONE}
  242. Function UnixToWinAge(UnixAge : time_t): Longint;
  243. Var
  244. Y,M,D,hh,mm,ss : word;
  245. begin
  246. EpochToLocal(UnixAge,y,m,d,hh,mm,ss);
  247. Result:=DateTimeToFileDate(EncodeDate(y,m,d)+EncodeTime(hh,mm,ss,0));
  248. end;
  249. Function FileAge (Const FileName : String): Longint;
  250. Var Info : Stat;
  251. begin
  252. If fpstat (pointer(FileName),Info)<0 then
  253. exit(-1)
  254. else
  255. Result:=UnixToWinAge(info.st_mtime);
  256. end;
  257. {$endif}
  258. Function FileExists (Const FileName : String) : Boolean;
  259. begin
  260. // Don't use stat. It fails on files >2 GB.
  261. // Access obeys the same access rules, so the result should be the same.
  262. FileExists:=fpAccess(pointer(filename),F_OK)=0;
  263. end;
  264. Function DirectoryExists (Const Directory : String) : Boolean;
  265. Var Info : Stat;
  266. begin
  267. DirectoryExists:=(fpstat(pointer(Directory),Info)>=0) and fpS_ISDIR(Info.st_mode);
  268. end;
  269. Function LinuxToWinAttr (FN : Pchar; Const Info : Stat) : Longint;
  270. Var
  271. FNL : String;
  272. LinkInfo : Stat;
  273. begin
  274. Result:=faArchive;
  275. If fpS_ISDIR(Info.st_mode) then
  276. Result:=Result or faDirectory;
  277. If (FN[0]='.') and (not (FN[1] in [#0,'.'])) then
  278. Result:=Result or faHidden;
  279. If (Info.st_Mode and S_IWUSR)=0 Then
  280. Result:=Result or faReadOnly;
  281. If fpS_ISSOCK(Info.st_mode) or fpS_ISBLK(Info.st_mode) or fpS_ISCHR(Info.st_mode) or fpS_ISFIFO(Info.st_mode) Then
  282. Result:=Result or faSysFile;
  283. If fpS_ISLNK(Info.st_mode) Then
  284. begin
  285. Result:=Result or faSymLink;
  286. // Windows reports if the link points to a directory.
  287. FNL:=StrPas(FN);
  288. if (fpstat(FNL,LinkInfo)>=0) and fpS_ISDIR(LinkInfo.st_mode) then
  289. Result := Result or faDirectory;
  290. end;
  291. end;
  292. Function FNMatch(const Pattern,Name:string):Boolean;
  293. Var
  294. LenPat,LenName : longint;
  295. Function DoFNMatch(i,j:longint):Boolean;
  296. Var
  297. Found : boolean;
  298. Begin
  299. Found:=true;
  300. While Found and (i<=LenPat) Do
  301. Begin
  302. Case Pattern[i] of
  303. '?' : Found:=(j<=LenName);
  304. '*' : Begin
  305. {find the next character in pattern, different of ? and *}
  306. while Found do
  307. begin
  308. inc(i);
  309. if i>LenPat then Break;
  310. case Pattern[i] of
  311. '*' : ;
  312. '?' : begin
  313. if j>LenName then begin DoFNMatch:=false; Exit; end;
  314. inc(j);
  315. end;
  316. else
  317. Found:=false;
  318. end;
  319. end;
  320. Assert((i>LenPat) or ( (Pattern[i]<>'*') and (Pattern[i]<>'?') ));
  321. {Now, find in name the character which i points to, if the * or ?
  322. wasn't the last character in the pattern, else, use up all the
  323. chars in name}
  324. Found:=false;
  325. if (i<=LenPat) then
  326. begin
  327. repeat
  328. {find a letter (not only first !) which maches pattern[i]}
  329. while (j<=LenName) and (name[j]<>pattern[i]) do
  330. inc (j);
  331. if (j<LenName) then
  332. begin
  333. if DoFnMatch(i+1,j+1) then
  334. begin
  335. i:=LenPat;
  336. j:=LenName;{we can stop}
  337. Found:=true;
  338. Break;
  339. end else
  340. inc(j);{We didn't find one, need to look further}
  341. end else
  342. if j=LenName then
  343. begin
  344. Found:=true;
  345. Break;
  346. end;
  347. { This 'until' condition must be j>LenName, not j>=LenName.
  348. That's because when we 'need to look further' and
  349. j = LenName then loop must not terminate. }
  350. until (j>LenName);
  351. end else
  352. begin
  353. j:=LenName;{we can stop}
  354. Found:=true;
  355. end;
  356. end;
  357. else {not a wildcard character in pattern}
  358. Found:=(j<=LenName) and (pattern[i]=name[j]);
  359. end;
  360. inc(i);
  361. inc(j);
  362. end;
  363. DoFnMatch:=Found and (j>LenName);
  364. end;
  365. Begin {start FNMatch}
  366. LenPat:=Length(Pattern);
  367. LenName:=Length(Name);
  368. FNMatch:=DoFNMatch(1,1);
  369. End;
  370. Type
  371. TUnixFindData = Record
  372. NamePos : LongInt; {to track which search this is}
  373. DirPtr : Pointer; {directory pointer for reading directory}
  374. SearchSpec : String;
  375. SearchType : Byte; {0=normal, 1=open will close, 2=only 1 file}
  376. SearchAttr : Byte; {attribute we are searching for}
  377. End;
  378. PUnixFindData = ^TUnixFindData;
  379. Var
  380. CurrSearchNum : LongInt;
  381. Procedure FindClose(Var f: TSearchRec);
  382. var
  383. UnixFindData : PUnixFindData;
  384. Begin
  385. UnixFindData:=PUnixFindData(f.FindHandle);
  386. if UnixFindData=nil then
  387. exit;
  388. if UnixFindData^.SearchType=0 then
  389. begin
  390. if UnixFindData^.dirptr<>nil then
  391. fpclosedir(pdir(UnixFindData^.dirptr)^);
  392. end;
  393. Dispose(UnixFindData);
  394. f.FindHandle:=nil;
  395. End;
  396. Function FindGetFileInfo(const s:string;var f:TSearchRec):boolean;
  397. var
  398. st : baseunix.stat;
  399. WinAttr : longint;
  400. begin
  401. FindGetFileInfo:=false;
  402. If Assigned(F.FindHandle) and ((((PUnixFindData(f.FindHandle)^.searchattr)) and faSymlink) > 0) then
  403. FindGetFileInfo:=(fplstat(pointer(s),st)=0)
  404. else
  405. FindGetFileInfo:=(fpstat(pointer(s),st)=0);
  406. If not FindGetFileInfo then
  407. exit;
  408. WinAttr:=LinuxToWinAttr(PChar(pointer(s)),st);
  409. If (f.FindHandle = nil) or ((WinAttr and Not(PUnixFindData(f.FindHandle)^.searchattr))=0) Then
  410. Begin
  411. f.Name:=ExtractFileName(s);
  412. f.Attr:=WinAttr;
  413. f.Size:=st.st_Size;
  414. f.Mode:=st.st_mode;
  415. {$ifndef FPUNONE}
  416. f.Time:=UnixToWinAge(st.st_mtime);
  417. {$endif}
  418. result:=true;
  419. End;
  420. end;
  421. Function FindNext (Var Rslt : TSearchRec) : Longint;
  422. {
  423. re-opens dir if not already in array and calls FindGetFileInfo
  424. }
  425. Var
  426. DirName : String;
  427. FName,
  428. SName : string;
  429. Found,
  430. Finished : boolean;
  431. p : pdirent;
  432. UnixFindData : PUnixFindData;
  433. Begin
  434. Result:=-1;
  435. UnixFindData:=PUnixFindData(Rslt.FindHandle);
  436. if UnixFindData=nil then
  437. exit;
  438. if (UnixFindData^.SearchType=0) and
  439. (UnixFindData^.Dirptr=nil) then
  440. begin
  441. If UnixFindData^.NamePos = 0 Then
  442. DirName:='./'
  443. Else
  444. DirName:=Copy(UnixFindData^.SearchSpec,1,UnixFindData^.NamePos);
  445. UnixFindData^.DirPtr := fpopendir(Pchar(pointer(DirName)));
  446. end;
  447. SName:=Copy(UnixFindData^.SearchSpec,UnixFindData^.NamePos+1,Length(UnixFindData^.SearchSpec));
  448. Found:=False;
  449. Finished:=(UnixFindData^.dirptr=nil);
  450. While Not Finished Do
  451. Begin
  452. p:=fpreaddir(pdir(UnixFindData^.dirptr)^);
  453. if p=nil then
  454. FName:=''
  455. else
  456. FName:=p^.d_name;
  457. If FName='' Then
  458. Finished:=True
  459. Else
  460. Begin
  461. If FNMatch(SName,FName) Then
  462. Begin
  463. Found:=FindGetFileInfo(Copy(UnixFindData^.SearchSpec,1,UnixFindData^.NamePos)+FName,Rslt);
  464. if Found then
  465. begin
  466. Result:=0;
  467. exit;
  468. end;
  469. End;
  470. End;
  471. End;
  472. End;
  473. Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
  474. {
  475. opens dir and calls FindNext if needed.
  476. }
  477. var
  478. UnixFindData : PUnixFindData;
  479. Begin
  480. Result:=-1;
  481. fillchar(Rslt,sizeof(Rslt),0);
  482. if Path='' then
  483. exit;
  484. {Wildcards?}
  485. if (Pos('?',Path)=0) and (Pos('*',Path)=0) then
  486. begin
  487. if FindGetFileInfo(Path,Rslt) then
  488. Result:=0;
  489. end
  490. else
  491. begin
  492. { Allocate UnixFindData }
  493. New(UnixFindData);
  494. FillChar(UnixFindData^,sizeof(UnixFindData^),0);
  495. Rslt.FindHandle:=UnixFindData;
  496. {Create Info}
  497. UnixFindData^.SearchSpec := Path;
  498. {We always also search for readonly and archive, regardless of Attr:}
  499. UnixFindData^.SearchAttr := Attr or faarchive or fareadonly;
  500. UnixFindData^.NamePos := Length(UnixFindData^.SearchSpec);
  501. while (UnixFindData^.NamePos>0) and (UnixFindData^.SearchSpec[UnixFindData^.NamePos]<>'/') do
  502. dec(UnixFindData^.NamePos);
  503. Result:=FindNext(Rslt);
  504. end;
  505. End;
  506. Function FileGetDate (Handle : Longint) : Longint;
  507. Var Info : Stat;
  508. begin
  509. If (fpFStat(Handle,Info))<0 then
  510. Result:=-1
  511. else
  512. Result:=Info.st_Mtime;
  513. end;
  514. Function FileSetDate (Handle,Age : Longint) : Longint;
  515. begin
  516. // Impossible under Linux from FileHandle !!
  517. FileSetDate:=-1;
  518. end;
  519. Function FileGetAttr (Const FileName : String) : Longint;
  520. Var Info : Stat;
  521. begin
  522. If FpStat (pointer(FileName),Info)<0 then
  523. Result:=-1
  524. Else
  525. Result:=LinuxToWinAttr(Pchar(ExtractFileName(FileName)),Info);
  526. end;
  527. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  528. begin
  529. Result:=-1;
  530. end;
  531. Function DeleteFile (Const FileName : String) : Boolean;
  532. begin
  533. Result:=fpUnLink (pointer(FileName))>=0;
  534. end;
  535. Function RenameFile (Const OldName, NewName : String) : Boolean;
  536. begin
  537. RenameFile:=BaseUnix.FpRename(pointer(OldNAme),pointer(NewName))>=0;
  538. end;
  539. Function FileIsReadOnly(const FileName: String): Boolean;
  540. begin
  541. Result := fpAccess(PChar(pointer(FileName)),W_OK)<>0;
  542. end;
  543. Function FileSetDate (Const FileName : String;Age : Longint) : Longint;
  544. var
  545. t: TUTimBuf;
  546. begin
  547. Result := 0;
  548. t.actime := Age;
  549. t.modtime := Age;
  550. if fputime(PChar(pointer(FileName)), @t) = -1 then
  551. Result := fpgeterrno;
  552. end;
  553. {****************************************************************************
  554. Disk Functions
  555. ****************************************************************************}
  556. {
  557. The Diskfree and Disksize functions need a file on the specified drive, since this
  558. is required for the statfs system call.
  559. These filenames are set in drivestr[0..26], and have been preset to :
  560. 0 - '.' (default drive - hence current dir is ok.)
  561. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  562. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  563. 3 - '/' (C: equivalent of dos is the root partition)
  564. 4..26 (can be set by you're own applications)
  565. ! Use AddDisk() to Add new drives !
  566. They both return -1 when a failure occurs.
  567. }
  568. Const
  569. FixDriveStr : array[0..3] of pchar=(
  570. '.',
  571. '/fd0/.',
  572. '/fd1/.',
  573. '/.'
  574. );
  575. var
  576. Drives : byte;
  577. DriveStr : array[4..26] of pchar;
  578. Function AddDisk(const path:string) : Byte;
  579. begin
  580. if not (DriveStr[Drives]=nil) then
  581. FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1);
  582. GetMem(DriveStr[Drives],length(Path)+1);
  583. StrPCopy(DriveStr[Drives],path);
  584. inc(Drives);
  585. if Drives>26 then
  586. Drives:=4;
  587. Result:=Drives;
  588. end;
  589. Function DiskFree(Drive: Byte): int64;
  590. var
  591. fs : tstatfs;
  592. Begin
  593. if ((Drive in [Low(FixDriveStr)..High(FixDriveStr)]) and (not (fixdrivestr[Drive]=nil)) and (statfs(StrPas(fixdrivestr[drive]),fs)<>-1)) or
  594. ((Drive <= High(drivestr)) and (not (drivestr[Drive]=nil)) and (statfs(StrPas(drivestr[drive]),fs)<>-1)) then
  595. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  596. else
  597. Diskfree:=-1;
  598. End;
  599. Function DiskSize(Drive: Byte): int64;
  600. var
  601. fs : tstatfs;
  602. Begin
  603. if ((Drive in [Low(FixDriveStr)..High(FixDriveStr)]) and (not (fixdrivestr[Drive]=nil)) and (statfs(StrPas(fixdrivestr[drive]),fs)<>-1)) or
  604. ((drive <= High(drivestr)) and (not (drivestr[Drive]=nil)) and (statfs(StrPas(drivestr[drive]),fs)<>-1)) then
  605. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  606. else
  607. DiskSize:=-1;
  608. End;
  609. Function GetCurrentDir : String;
  610. begin
  611. GetDir (0,Result);
  612. end;
  613. Function SetCurrentDir (Const NewDir : String) : Boolean;
  614. begin
  615. {$I-}
  616. ChDir(NewDir);
  617. {$I+}
  618. result := (IOResult = 0);
  619. end;
  620. Function CreateDir (Const NewDir : String) : Boolean;
  621. begin
  622. {$I-}
  623. MkDir(NewDir);
  624. {$I+}
  625. result := (IOResult = 0);
  626. end;
  627. Function RemoveDir (Const Dir : String) : Boolean;
  628. begin
  629. {$I-}
  630. RmDir(Dir);
  631. {$I+}
  632. result := (IOResult = 0);
  633. end;
  634. {****************************************************************************
  635. Misc Functions
  636. ****************************************************************************}
  637. procedure Beep;
  638. begin
  639. end;
  640. {****************************************************************************
  641. Locale Functions
  642. ****************************************************************************}
  643. Function GetEpochTime: cint;
  644. {
  645. Get the number of seconds since 00:00, January 1 1970, GMT
  646. the time NOT corrected any way
  647. }
  648. begin
  649. GetEpochTime:=fptime;
  650. end;
  651. procedure GetTime(var hour,min,sec,msec,usec:word);
  652. {
  653. Gets the current time, adjusted to local time
  654. }
  655. var
  656. year,day,month:Word;
  657. tz:timeval;
  658. begin
  659. fpgettimeofday(@tz,nil);
  660. EpochToLocal(tz.tv_sec,year,month,day,hour,min,sec);
  661. msec:=tz.tv_usec div 1000;
  662. usec:=tz.tv_usec mod 1000;
  663. end;
  664. procedure GetTime(var hour,min,sec,sec100:word);
  665. {
  666. Gets the current time, adjusted to local time
  667. }
  668. var
  669. usec : word;
  670. begin
  671. gettime(hour,min,sec,sec100,usec);
  672. sec100:=sec100 div 10;
  673. end;
  674. Procedure GetTime(Var Hour,Min,Sec:Word);
  675. {
  676. Gets the current time, adjusted to local time
  677. }
  678. var
  679. msec,usec : Word;
  680. Begin
  681. gettime(hour,min,sec,msec,usec);
  682. End;
  683. Procedure GetDate(Var Year,Month,Day:Word);
  684. {
  685. Gets the current date, adjusted to local time
  686. }
  687. var
  688. hour,minute,second : word;
  689. Begin
  690. EpochToLocal(fptime,year,month,day,hour,minute,second);
  691. End;
  692. Procedure GetDateTime(Var Year,Month,Day,hour,minute,second:Word);
  693. {
  694. Gets the current date, adjusted to local time
  695. }
  696. Begin
  697. EpochToLocal(fptime,year,month,day,hour,minute,second);
  698. End;
  699. {$ifndef FPUNONE}
  700. Procedure GetLocalTime(var SystemTime: TSystemTime);
  701. var
  702. usecs : Word;
  703. begin
  704. GetTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second, SystemTime.MilliSecond, usecs);
  705. GetDate(SystemTime.Year, SystemTime.Month, SystemTime.Day);
  706. // SystemTime.MilliSecond := 0;
  707. end ;
  708. {$endif}
  709. Procedure InitAnsi;
  710. Var
  711. i : longint;
  712. begin
  713. { Fill table entries 0 to 127 }
  714. for i := 0 to 96 do
  715. UpperCaseTable[i] := chr(i);
  716. for i := 97 to 122 do
  717. UpperCaseTable[i] := chr(i - 32);
  718. for i := 123 to 191 do
  719. UpperCaseTable[i] := chr(i);
  720. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  721. for i := 0 to 64 do
  722. LowerCaseTable[i] := chr(i);
  723. for i := 65 to 90 do
  724. LowerCaseTable[i] := chr(i + 32);
  725. for i := 91 to 191 do
  726. LowerCaseTable[i] := chr(i);
  727. Move (CPISO88591LCT,LowerCaseTable[192],SizeOf(CPISO88591UCT));
  728. end;
  729. Procedure InitInternational;
  730. begin
  731. InitInternationalGeneric;
  732. InitAnsi;
  733. end;
  734. function SysErrorMessage(ErrorCode: Integer): String;
  735. begin
  736. Result:=StrError(ErrorCode);
  737. end;
  738. {****************************************************************************
  739. OS utility functions
  740. ****************************************************************************}
  741. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  742. begin
  743. Result:=StrPas(BaseUnix.FPGetenv(PChar(pointer(EnvVar))));
  744. end;
  745. Function GetEnvironmentVariableCount : Integer;
  746. begin
  747. Result:=FPCCountEnvVar(EnvP);
  748. end;
  749. Function GetEnvironmentString(Index : Integer) : String;
  750. begin
  751. Result:=FPCGetEnvStrFromP(Envp,Index);
  752. end;
  753. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString):integer;
  754. var
  755. pid : longint;
  756. e : EOSError;
  757. CommandLine: AnsiString;
  758. cmdline2 : ppchar;
  759. Begin
  760. { always surround the name of the application by quotes
  761. so that long filenames will always be accepted. But don't
  762. do it if there are already double quotes!
  763. }
  764. // Only place we still parse
  765. cmdline2:=nil;
  766. if Comline<>'' Then
  767. begin
  768. CommandLine:=ComLine;
  769. { Make an unique copy because stringtoppchar modifies the
  770. string }
  771. UniqueString(CommandLine);
  772. cmdline2:=StringtoPPChar(CommandLine,1);
  773. cmdline2^:=pchar(pointer(Path));
  774. end
  775. else
  776. begin
  777. getmem(cmdline2,2*sizeof(pchar));
  778. cmdline2^:=pchar(Path);
  779. cmdline2[1]:=nil;
  780. end;
  781. {$ifdef USE_VFORK}
  782. pid:=fpvFork;
  783. {$else USE_VFORK}
  784. pid:=fpFork;
  785. {$endif USE_VFORK}
  786. if pid=0 then
  787. begin
  788. {The child does the actual exec, and then exits}
  789. fpexecv(pchar(pointer(Path)),Cmdline2);
  790. { If the execve fails, we return an exitvalue of 127, to let it be known}
  791. fpExit(127);
  792. end
  793. else
  794. if pid=-1 then {Fork failed}
  795. begin
  796. e:=EOSError.CreateFmt(SExecuteProcessFailed,[Path,-1]);
  797. e.ErrorCode:=-1;
  798. raise e;
  799. end;
  800. { We're in the parent, let's wait. }
  801. result:=WaitProcess(pid); // WaitPid and result-convert
  802. if Comline<>'' Then
  803. freemem(cmdline2);
  804. if (result<0) or (result=127) then
  805. begin
  806. E:=EOSError.CreateFmt(SExecuteProcessFailed,[Path,result]);
  807. E.ErrorCode:=result;
  808. Raise E;
  809. end;
  810. End;
  811. function ExecuteProcess(Const Path: AnsiString; Const ComLine: Array Of AnsiString):integer;
  812. var
  813. pid : longint;
  814. e : EOSError;
  815. Begin
  816. pid:=fpFork;
  817. if pid=0 then
  818. begin
  819. {The child does the actual exec, and then exits}
  820. fpexecl(Path,Comline);
  821. { If the execve fails, we return an exitvalue of 127, to let it be known}
  822. fpExit(127);
  823. end
  824. else
  825. if pid=-1 then {Fork failed}
  826. begin
  827. e:=EOSError.CreateFmt(SExecuteProcessFailed,[Path,-1]);
  828. e.ErrorCode:=-1;
  829. raise e;
  830. end;
  831. { We're in the parent, let's wait. }
  832. result:=WaitProcess(pid); // WaitPid and result-convert
  833. if (result<0) or (result=127) then
  834. begin
  835. E:=EOSError.CreateFmt(SExecuteProcessFailed,[Path,result]);
  836. E.ErrorCode:=result;
  837. raise E;
  838. end;
  839. End;
  840. procedure Sleep(milliseconds: Cardinal);
  841. Var
  842. timeout,timeoutresult : TTimespec;
  843. begin
  844. timeout.tv_sec:=milliseconds div 1000;
  845. timeout.tv_nsec:=1000*1000*(milliseconds mod 1000);
  846. fpnanosleep(@timeout,@timeoutresult);
  847. end;
  848. Function GetLastOSError : Integer;
  849. begin
  850. Result:=fpgetErrNo;
  851. end;
  852. { ---------------------------------------------------------------------
  853. Application config files
  854. ---------------------------------------------------------------------}
  855. Function GetHomeDir : String;
  856. begin
  857. Result:=GetEnvironmentVariable('HOME');
  858. If (Result<>'') then
  859. Result:=IncludeTrailingPathDelimiter(Result);
  860. end;
  861. { Follows base-dir spec,
  862. see [http://freedesktop.org/Standards/basedir-spec].
  863. Always ends with PathDelim. }
  864. Function XdgConfigHome : String;
  865. begin
  866. Result:=GetEnvironmentVariable('XDG_CONFIG_HOME');
  867. if (Result='') then
  868. Result:=GetHomeDir + '.config/'
  869. else
  870. Result:=IncludeTrailingPathDelimiter(Result);
  871. end;
  872. Function GetAppConfigDir(Global : Boolean) : String;
  873. begin
  874. If Global then
  875. Result:=IncludeTrailingPathDelimiter(SysConfigDir)
  876. else
  877. Result:=IncludeTrailingPathDelimiter(XdgConfigHome);
  878. if VendorName<>'' then
  879. Result:=IncludeTrailingPathDelimiter(Result+VendorName);
  880. Result:=IncludeTrailingPathDelimiter(Result+ApplicationName);
  881. end;
  882. Function GetAppConfigFile(Global : Boolean; SubDir : Boolean) : String;
  883. begin
  884. If Global then
  885. Result:=IncludeTrailingPathDelimiter(SysConfigDir)
  886. else
  887. Result:=IncludeTrailingPathDelimiter(XdgConfigHome);
  888. if SubDir then
  889. begin
  890. if VendorName<>'' then
  891. Result:=IncludeTrailingPathDelimiter(Result+VendorName);
  892. Result:=IncludeTrailingPathDelimiter(Result+ApplicationName);
  893. end;
  894. Result:=Result+ApplicationName+ConfigExtension;
  895. end;
  896. {****************************************************************************
  897. GetTempDir
  898. ****************************************************************************}
  899. Function GetTempDir(Global : Boolean) : String;
  900. begin
  901. If Assigned(OnGetTempDir) then
  902. Result:=OnGetTempDir(Global)
  903. else
  904. begin
  905. Result:=GetEnvironmentVariable('TEMP');
  906. If (Result='') Then
  907. Result:=GetEnvironmentVariable('TMP');
  908. if (Result='') then
  909. Result:='/tmp/' // fallback.
  910. end;
  911. if (Result<>'') then
  912. Result:=IncludeTrailingPathDelimiter(Result);
  913. end;
  914. {****************************************************************************
  915. GetUserDir
  916. ****************************************************************************}
  917. Var
  918. TheUserDir : String;
  919. Function GetUserDir : String;
  920. begin
  921. If (TheUserDir='') then
  922. begin
  923. TheUserDir:=GetEnvironmentVariable('HOME');
  924. if (TheUserDir<>'') then
  925. TheUserDir:=IncludeTrailingPathDelimiter(TheUserDir)
  926. else
  927. TheUserDir:=GetTempDir(False);
  928. end;
  929. Result:=TheUserDir;
  930. end;
  931. {****************************************************************************
  932. Initialization code
  933. ****************************************************************************}
  934. Initialization
  935. InitExceptions; { Initialize exceptions. OS independent }
  936. InitInternational; { Initialize internationalization settings }
  937. SysConfigDir:='/etc'; { Initialize system config dir }
  938. Finalization
  939. DoneExceptions;
  940. end.