sysutils.pp 26 KB

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