2
0

sysutils.pp 16 KB

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