sysutils.pp 28 KB

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