sysutils.pp 28 KB

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