sysutils.pp 27 KB

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