sysutils.pp 25 KB

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