sysutils.pp 26 KB

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