sysutils.pp 26 KB

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