sysutils.pp 29 KB

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