sysutils.pp 25 KB

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