sysutils.pp 28 KB

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