sysutils.pp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2004-2005 by Olle Raab
  5. Sysutils unit for Mac OS.
  6. NOTE !!! THIS FILE IS UNDER CONSTRUCTION AND DOES NOT WORK CURRENLY.
  7. THUS IT IS NOT BUILT BY THE MAKEFILES
  8. See the file COPYING.FPC, included in this distribution,
  9. for details about the copyright.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. **********************************************************************}
  14. unit sysutils;
  15. interface
  16. {$MODE objfpc}
  17. { force ansistrings }
  18. {$H+}
  19. uses
  20. MacOSTP;
  21. //{$DEFINE HAS_SLEEP} TODO
  22. //{$DEFINE HAS_OSERROR} TODO
  23. //{$DEFINE HAS_OSCONFIG} TODO
  24. type
  25. //TODO Check pad and size
  26. //TODO unify with Dos.SearchRec
  27. PMacOSFindData = ^TMacOSFindData;
  28. TMacOSFindData = record
  29. {MacOS specific params, private, do not use:}
  30. paramBlock: CInfoPBRec;
  31. searchFSSpec: FSSpec;
  32. searchAttr: Byte; {attribute we are searching for}
  33. exactMatch: Boolean;
  34. end;
  35. { Include platform independent interface part }
  36. {$i sysutilh.inc}
  37. implementation
  38. uses
  39. Dos, Sysconst; // For some included files.
  40. { Include platform independent implementation part }
  41. {$i sysutils.inc}
  42. {****************************************************************************
  43. File Functions
  44. ****************************************************************************}
  45. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  46. Var LinuxFlags : longint;
  47. BEGIN
  48. (* TODO fix
  49. LinuxFlags:=0;
  50. Case (Mode and 3) of
  51. 0 : LinuxFlags:=LinuxFlags or Open_RdOnly;
  52. 1 : LinuxFlags:=LinuxFlags or Open_WrOnly;
  53. 2 : LinuxFlags:=LinuxFlags or Open_RdWr;
  54. end;
  55. FileOpen:=fdOpen (FileName,LinuxFlags);
  56. //!! We need to set locking based on Mode !!
  57. *)
  58. end;
  59. Function FileCreate (Const FileName : String) : Longint;
  60. begin
  61. (* TODO fix
  62. FileCreate:=fdOpen(FileName,Open_RdWr or Open_Creat or Open_Trunc);
  63. *)
  64. end;
  65. Function FileCreate (Const FileName : String;Mode : Longint) : Longint;
  66. Var LinuxFlags : longint;
  67. BEGIN
  68. (* TODO fix
  69. LinuxFlags:=0;
  70. Case (Mode and 3) of
  71. 0 : LinuxFlags:=LinuxFlags or Open_RdOnly;
  72. 1 : LinuxFlags:=LinuxFlags or Open_WrOnly;
  73. 2 : LinuxFlags:=LinuxFlags or Open_RdWr;
  74. end;
  75. FileCreate:=fdOpen(FileName,LinuxFlags or Open_Creat or Open_Trunc);
  76. *)
  77. end;
  78. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  79. begin
  80. (* TODO fix
  81. FileRead:=fdRead (Handle,Buffer,Count);
  82. *)
  83. end;
  84. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  85. begin
  86. (* TODO fix
  87. FileWrite:=fdWrite (Handle,Buffer,Count);
  88. *)
  89. end;
  90. Function FileSeek (Handle,FOffset,Origin : Longint) : Longint;
  91. begin
  92. (* TODO fix
  93. FileSeek:=fdSeek (Handle,FOffset,Origin);
  94. *)
  95. end;
  96. Function FileSeek (Handle : Longint; FOffset,Origin : Int64) : Int64;
  97. begin
  98. (* TODO fix
  99. {$warning need to add 64bit call }
  100. FileSeek:=fdSeek (Handle,FOffset,Origin);
  101. *)
  102. end;
  103. Procedure FileClose (Handle : Longint);
  104. begin
  105. (* TODO fix
  106. fdclose(Handle);
  107. *)
  108. end;
  109. Function FileTruncate (Handle,Size: Longint) : boolean;
  110. begin
  111. (* TODO fix
  112. FileTruncate:=fdtruncate(Handle,Size);
  113. *)
  114. end;
  115. Function FileAge (Const FileName : String): Longint;
  116. (*
  117. Var Info : Stat;
  118. Y,M,D,hh,mm,ss : word;
  119. *)
  120. begin
  121. (* TODO fix
  122. If not fstat (FileName,Info) then
  123. exit(-1)
  124. else
  125. begin
  126. EpochToLocal(info.mtime,y,m,d,hh,mm,ss);
  127. Result:=DateTimeToFileDate(EncodeDate(y,m,d)+EncodeTime(hh,mm,ss,0));
  128. end;
  129. *)
  130. end;
  131. Function FileExists (Const FileName : String) : Boolean;
  132. (*
  133. Var Info : Stat;
  134. *)
  135. begin
  136. (* TODO fix
  137. FileExists:=fstat(filename,Info);
  138. *)
  139. end;
  140. Function DirectoryExists (Const Directory : String) : Boolean;
  141. (*
  142. Var Info : Stat;
  143. *)
  144. begin
  145. (* TODO fix
  146. DirectoryExists:=fstat(Directory,Info) and
  147. ((info.mode and STAT_IFMT)=STAT_IFDIR);
  148. *)
  149. end;
  150. (*
  151. Function LinuxToWinAttr (FN : Pchar; Const Info : Stat) : Longint;
  152. begin
  153. Result:=faArchive;
  154. If (Info.Mode and STAT_IFDIR)=STAT_IFDIR then
  155. Result:=Result or faDirectory;
  156. If (FN[0]='.') and (not (FN[1] in [#0,'.'])) then
  157. Result:=Result or faHidden;
  158. If (Info.Mode and STAT_IWUSR)=0 Then
  159. Result:=Result or faReadOnly;
  160. If (Info.Mode and
  161. (STAT_IFSOCK or STAT_IFBLK or STAT_IFCHR or STAT_IFIFO))<>0 then
  162. Result:=Result or faSysFile;
  163. end;
  164. {
  165. GlobToSearch takes a glob entry, stats the file.
  166. The glob entry is removed.
  167. If FileAttributes match, the entry is reused
  168. }
  169. Type
  170. TGlobSearchRec = Record
  171. Path : String;
  172. GlobHandle : PGlob;
  173. end;
  174. PGlobSearchRec = ^TGlobSearchRec;
  175. Function GlobToTSearchRec (Var Info : TSearchRec) : Boolean;
  176. Var SInfo : Stat;
  177. p : Pglob;
  178. GlobSearchRec : PGlobSearchrec;
  179. begin
  180. GlobSearchRec:=PGlobSearchrec(Info.FindHandle);
  181. P:=GlobSearchRec^.GlobHandle;
  182. Result:=P<>Nil;
  183. If Result then
  184. begin
  185. GlobSearchRec^.GlobHandle:=P^.Next;
  186. Result:=Fstat(GlobSearchRec^.Path+StrPas(p^.name),SInfo);
  187. If Result then
  188. begin
  189. Info.Attr:=LinuxToWinAttr(p^.name,SInfo);
  190. Result:=(Info.ExcludeAttr and Info.Attr)=0;
  191. If Result Then
  192. With Info do
  193. begin
  194. Attr:=Info.Attr;
  195. If P^.Name<>Nil then
  196. Name:=strpas(p^.name);
  197. Time:=Sinfo.mtime;
  198. Size:=Sinfo.Size;
  199. end;
  200. end;
  201. P^.Next:=Nil;
  202. GlobFree(P);
  203. end;
  204. end;
  205. *)
  206. procedure DoFind (var F: TSearchRec; firstTime: Boolean);
  207. var
  208. err: OSErr;
  209. s: Str255;
  210. begin
  211. with Rslt, findData, paramBlock do
  212. begin
  213. ioVRefNum := searchFSSpec.vRefNum;
  214. if firstTime then
  215. ioFDirIndex := 0;
  216. while true do
  217. begin
  218. s := '';
  219. ioDirID := searchFSSpec.parID;
  220. ioFDirIndex := ioFDirIndex + 1;
  221. ioNamePtr := @s;
  222. err := PBGetCatInfoSync(@paramBlock);
  223. if err <> noErr then
  224. begin
  225. if err = fnfErr then
  226. DosError := 18
  227. else
  228. DosError := MacOSErr2RTEerr(err);
  229. break;
  230. end;
  231. attr := GetFileAttrFromPB(Rslt.paramBlock);
  232. if ((Attr and not(searchAttr)) = 0) then
  233. begin
  234. name := s;
  235. UpperString(s, true);
  236. if FNMatch(Rslt.searchFSSpec.name, s) then
  237. begin
  238. size := GetFileSizeFromPB(paramBlock);
  239. time := MacTimeToDosPackedTime(ioFlMdDat);
  240. Result := 0;
  241. break;
  242. end;
  243. end;
  244. end;
  245. end;
  246. end;
  247. Function FindFirst (Const Path : String; Attr : Longint; Var Rslt : TSearchRec) : Longint;
  248. var
  249. s: Str255;
  250. begin
  251. fillchar(Rslt, sizeof(Rslt), 0);
  252. if path = '' then
  253. begin
  254. Result := 3;
  255. Exit;
  256. end;
  257. {We always also search for readonly and archive, regardless of Attr.}
  258. Rslt.searchAttr := (Attr or (archive or readonly));
  259. Result := PathArgToFSSpec(path, Rslt.searchFSSpec);
  260. with Rslt do
  261. if (Result = 0) or (Result = 2) then
  262. begin
  263. SearchSpec := path;
  264. NamePos := Length(path) - Length(searchFSSpec.name);
  265. if (Pos('?', searchFSSpec.name) = 0) and (Pos('*', searchFSSpec.name) = 0) then {No wildcards}
  266. begin {If exact match, we don't have to scan the directory}
  267. exactMatch := true;
  268. Result := DoFindOne(searchFSSpec, paramBlock);
  269. if Result = 0 then
  270. begin
  271. Attr := GetFileAttrFromPB(paramBlock);
  272. if ((Attr and not(searchAttr)) = 0) then
  273. begin
  274. name := searchFSSpec.name;
  275. size := GetFileSizeFromPB(paramBlock);
  276. time := MacTimeToDosPackedTime(paramBlock.ioFlMdDat);
  277. end
  278. else
  279. Result := 18;
  280. end
  281. else if Result = 2 then
  282. Result := 18;
  283. end
  284. else
  285. begin
  286. exactMatch := false;
  287. s := searchFSSpec.name;
  288. UpperString(s, true);
  289. Rslt.searchFSSpec.name := s;
  290. DoFind(Rslt, true);
  291. end;
  292. end;
  293. end;
  294. Function FindNext (Var Rslt : TSearchRec) : Longint;
  295. begin
  296. if F.exactMatch then
  297. Result := 18
  298. else
  299. Result:=DoFind (Rslt);
  300. end;
  301. Procedure FindClose (Var F : TSearchrec);
  302. (*
  303. Var
  304. GlobSearchRec : PGlobSearchRec;
  305. *)
  306. begin
  307. (* TODO fix
  308. GlobSearchRec:=PGlobSearchRec(F.FindHandle);
  309. GlobFree (GlobSearchRec^.GlobHandle);
  310. Dispose(GlobSearchRec);
  311. *)
  312. end;
  313. Function FileGetDate (Handle : Longint) : Longint;
  314. (*
  315. Var Info : Stat;
  316. *)
  317. begin
  318. (* TODO fix
  319. If Not(FStat(Handle,Info)) then
  320. Result:=-1
  321. else
  322. Result:=Info.Mtime;
  323. *)
  324. end;
  325. Function FileSetDate (Handle,Age : Longint) : Longint;
  326. begin
  327. // TODO fix
  328. // Impossible under Linux from FileHandle !!
  329. FileSetDate:=-1;
  330. end;
  331. Function FileGetAttr (Const FileName : String) : Longint;
  332. (*
  333. Var Info : Stat;
  334. *)
  335. begin
  336. (* TODO fix
  337. If Not FStat (FileName,Info) then
  338. Result:=-1
  339. Else
  340. Result:=LinuxToWinAttr(Pchar(FileName),Info);
  341. *)
  342. end;
  343. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  344. begin
  345. Result:=-1;
  346. end;
  347. Function DeleteFile (Const FileName : String) : Boolean;
  348. begin
  349. (* TODO fix
  350. Result:=UnLink (FileName);
  351. *)
  352. end;
  353. Function RenameFile (Const OldName, NewName : String) : Boolean;
  354. begin
  355. (* TODO fix
  356. RenameFile:=Unix.FRename(OldNAme,NewName);
  357. *)
  358. end;
  359. {****************************************************************************
  360. Disk Functions
  361. ****************************************************************************}
  362. {
  363. The Diskfree and Disksize functions need a file on the specified drive, since this
  364. is required for the statfs system call.
  365. These filenames are set in drivestr[0..26], and have been preset to :
  366. 0 - '.' (default drive - hence current dir is ok.)
  367. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  368. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  369. 3 - '/' (C: equivalent of dos is the root partition)
  370. 4..26 (can be set by you're own applications)
  371. ! Use AddDisk() to Add new drives !
  372. They both return -1 when a failure occurs.
  373. }
  374. Const
  375. FixDriveStr : array[0..3] of pchar=(
  376. '.',
  377. '/fd0/.',
  378. '/fd1/.',
  379. '/.'
  380. );
  381. var
  382. Drives : byte;
  383. DriveStr : array[4..26] of pchar;
  384. Procedure AddDisk(const path:string);
  385. begin
  386. if not (DriveStr[Drives]=nil) then
  387. FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1);
  388. GetMem(DriveStr[Drives],length(Path)+1);
  389. StrPCopy(DriveStr[Drives],path);
  390. inc(Drives);
  391. if Drives>26 then
  392. Drives:=4;
  393. end;
  394. Function DiskFree(Drive: Byte): int64;
  395. (*
  396. var
  397. fs : tstatfs;
  398. *)
  399. Begin
  400. (* TODO fix
  401. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and statfs(StrPas(fixdrivestr[drive]),fs)) or
  402. ((not (drivestr[Drive]=nil)) and statfs(StrPas(drivestr[drive]),fs)) then
  403. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  404. else
  405. Diskfree:=-1;
  406. *)
  407. End;
  408. Function DiskSize(Drive: Byte): int64;
  409. (*
  410. var
  411. fs : tstatfs;
  412. *)
  413. Begin
  414. (* TODO fix
  415. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and statfs(StrPas(fixdrivestr[drive]),fs)) or
  416. ((not (drivestr[Drive]=nil)) and statfs(StrPas(drivestr[drive]),fs)) then
  417. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  418. else
  419. DiskSize:=-1;
  420. *)
  421. End;
  422. Function GetCurrentDir : String;
  423. begin
  424. GetDir (0,Result);
  425. end;
  426. Function SetCurrentDir (Const NewDir : String) : Boolean;
  427. begin
  428. {$I-}
  429. ChDir(NewDir);
  430. {$I+}
  431. result := (IOResult = 0);
  432. end;
  433. Function CreateDir (Const NewDir : String) : Boolean;
  434. begin
  435. {$I-}
  436. MkDir(NewDir);
  437. {$I+}
  438. result := (IOResult = 0);
  439. end;
  440. Function RemoveDir (Const Dir : String) : Boolean;
  441. begin
  442. {$I-}
  443. RmDir(Dir);
  444. {$I+}
  445. result := (IOResult = 0);
  446. end;
  447. {****************************************************************************
  448. Misc Functions
  449. ****************************************************************************}
  450. procedure Beep;
  451. begin
  452. //TODO fix
  453. end;
  454. {****************************************************************************
  455. Locale Functions
  456. ****************************************************************************}
  457. Procedure GetLocalTime(var SystemTime: TSystemTime);
  458. begin
  459. (* TODO fix
  460. Unix.GetTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second);
  461. Unix.GetDate(SystemTime.Year, SystemTime.Month, SystemTime.Day);
  462. SystemTime.MilliSecond := 0;
  463. *)
  464. end ;
  465. Procedure InitAnsi;
  466. Var
  467. i : longint;
  468. begin
  469. { Fill table entries 0 to 127 }
  470. for i := 0 to 96 do
  471. UpperCaseTable[i] := chr(i);
  472. for i := 97 to 122 do
  473. UpperCaseTable[i] := chr(i - 32);
  474. for i := 123 to 191 do
  475. UpperCaseTable[i] := chr(i);
  476. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  477. for i := 0 to 64 do
  478. LowerCaseTable[i] := chr(i);
  479. for i := 65 to 90 do
  480. LowerCaseTable[i] := chr(i + 32);
  481. for i := 91 to 191 do
  482. LowerCaseTable[i] := chr(i);
  483. Move (CPISO88591LCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  484. end;
  485. Procedure InitInternational;
  486. begin
  487. InitAnsi;
  488. end;
  489. function SysErrorMessage(ErrorCode: Integer): String;
  490. begin
  491. (* TODO fix
  492. Result:=StrError(ErrorCode);
  493. *)
  494. end;
  495. {****************************************************************************
  496. OS utility functions
  497. ****************************************************************************}
  498. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  499. begin
  500. (* TODO fix
  501. Result:=StrPas(Unix.Getenv(PChar(EnvVar)));
  502. *)
  503. end;
  504. Function GetEnvironmentVariableCount : Integer;
  505. begin
  506. // Result:=FPCCountEnvVar(EnvP);
  507. Result:=0;
  508. end;
  509. Function GetEnvironmentString(Index : Integer) : String;
  510. begin
  511. // Result:=FPCGetEnvStrFromP(Envp,Index);
  512. Result:='';
  513. end;
  514. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString):integer;
  515. var
  516. s: AnsiString;
  517. wdpath: AnsiString;
  518. laststatuscode : longint;
  519. Begin
  520. {Make ToolServers working directory in sync with our working directory}
  521. PathArgToFullPath(':', wdpath);
  522. wdpath:= 'Directory ' + wdpath;
  523. Result := ExecuteToolserverScript(PChar(wdpath), laststatuscode);
  524. {TODO Only change path when actually needed. But this requires some
  525. change counter to be incremented each time wd is changed. }
  526. s:= path + ' ' + comline;
  527. Result := ExecuteToolserverScript(PChar(s), laststatuscode);
  528. if Result = afpItemNotFound then
  529. Result := 900
  530. else
  531. Result := MacOSErr2RTEerr(Result);
  532. if Result <> 0
  533. then
  534. raise EOSErr;
  535. //TODO Better dos error codes
  536. if laststatuscode <> 0 then
  537. begin
  538. {MPW status might be 24 bits}
  539. Result := laststatuscode and $ffff;
  540. if Result = 0 then
  541. Result := 1;
  542. end
  543. else
  544. Result := 0;
  545. End;
  546. function ExecuteProcess(Const Path: AnsiString; Const ComLine: Array Of AnsiString):integer;
  547. begin
  548. end;
  549. procedure Sleep(milliseconds: Cardinal);
  550. begin
  551. end;
  552. (*
  553. Function GetLastOSError : Integer;
  554. begin
  555. end;
  556. *)
  557. {****************************************************************************
  558. Initialization code
  559. ****************************************************************************}
  560. Initialization
  561. InitExceptions; { Initialize exceptions. OS independent }
  562. InitInternational; { Initialize internationalization settings }
  563. Finalization
  564. DoneExceptions;
  565. end.
  566. {
  567. $Log$
  568. Revision 1.5 2005-01-24 18:28:58 olle
  569. + a tiny bit of support for macos
  570. + warning that this is under construction
  571. Revision 1.4 2004/12/11 11:32:44 michael
  572. + Added GetEnvironmentVariableCount and GetEnvironmentString calls
  573. Revision 1.3 2004/10/14 16:27:11 mazen
  574. * First implementation of ExecuteProcess
  575. Revision 1.2 2004/09/30 10:42:05 mazen
  576. * implement Find[First,Next,Close] according to Dos unit code
  577. Revision 1.1 2004/09/28 15:39:29 olle
  578. + added skeleton version
  579. }