sysutils.pp 26 KB

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