sysutils.pp 29 KB

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