sysutils.pp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  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. { used OS file system APIs use ansistring }
  36. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  37. { OS has an ansistring/single byte environment variable API }
  38. {$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
  39. { Include platform independent interface part }
  40. {$i sysutilh.inc}
  41. implementation
  42. uses
  43. Dos, Sysconst; // For some included files.
  44. {$DEFINE FPC_FEXPAND_VOLUMES}
  45. {$DEFINE FPC_FEXPAND_NO_DEFAULT_PATHS}
  46. {$DEFINE FPC_FEXPAND_DRIVESEP_IS_ROOT}
  47. {$DEFINE FPC_FEXPAND_NO_DOTS_UPDIR}
  48. {$DEFINE FPC_FEXPAND_NO_CURDIR}
  49. { Include platform independent implementation part }
  50. {$i sysutils.inc}
  51. {****************************************************************************
  52. File Functions
  53. ****************************************************************************}
  54. Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : Longint;
  55. Var LinuxFlags : longint;
  56. SystemFileName: RawByteString;
  57. begin
  58. (* TODO fix
  59. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  60. LinuxFlags:=0;
  61. Case (Mode and 3) of
  62. 0 : LinuxFlags:=LinuxFlags or Open_RdOnly;
  63. 1 : LinuxFlags:=LinuxFlags or Open_WrOnly;
  64. 2 : LinuxFlags:=LinuxFlags or Open_RdWr;
  65. end;
  66. FileOpen:=fdOpen (FileName,LinuxFlags);
  67. //!! We need to set locking based on Mode !!
  68. *)
  69. end;
  70. Function FileCreate (Const FileName : RawByteString) : Longint;
  71. begin
  72. (* TODO fix
  73. FileCreate:=fdOpen(FileName,Open_RdWr or Open_Creat or Open_Trunc);
  74. *)
  75. end;
  76. Function FileCreate (Const FileName : RawByteString;Rights : Longint) : Longint;
  77. Var LinuxFlags : longint;
  78. BEGIN
  79. (* TODO fix
  80. LinuxFlags:=0;
  81. Case (Mode and 3) of
  82. 0 : LinuxFlags:=LinuxFlags or Open_RdOnly;
  83. 1 : LinuxFlags:=LinuxFlags or Open_WrOnly;
  84. 2 : LinuxFlags:=LinuxFlags or Open_RdWr;
  85. end;
  86. FileCreate:=fdOpen(FileName,LinuxFlags or Open_Creat or Open_Trunc);
  87. *)
  88. end;
  89. Function FileCreate (Const FileName : RawByteString;ShareMode : Longint; Rights : Longint) : Longint;
  90. Var LinuxFlags : longint;
  91. BEGIN
  92. (* TODO fix
  93. LinuxFlags:=0;
  94. Case (Mode and 3) of
  95. 0 : LinuxFlags:=LinuxFlags or Open_RdOnly;
  96. 1 : LinuxFlags:=LinuxFlags or Open_WrOnly;
  97. 2 : LinuxFlags:=LinuxFlags or Open_RdWr;
  98. end;
  99. FileCreate:=fdOpen(FileName,LinuxFlags or Open_Creat or Open_Trunc);
  100. *)
  101. end;
  102. Function FileRead (Handle : Longint; out Buffer; Count : longint) : Longint;
  103. begin
  104. (* TODO fix
  105. FileRead:=fdRead (Handle,Buffer,Count);
  106. *)
  107. end;
  108. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  109. begin
  110. (* TODO fix
  111. FileWrite:=fdWrite (Handle,Buffer,Count);
  112. *)
  113. end;
  114. Function FileSeek (Handle,FOffset,Origin : Longint) : Longint;
  115. begin
  116. (* TODO fix
  117. FileSeek:=fdSeek (Handle,FOffset,Origin);
  118. *)
  119. end;
  120. Function FileSeek (Handle : Longint; FOffset: Int64; Origin : Longint) : Int64;
  121. begin
  122. (* TODO fix
  123. {$warning need to add 64bit call }
  124. FileSeek:=fdSeek (Handle,FOffset,Origin);
  125. *)
  126. end;
  127. Procedure FileClose (Handle : Longint);
  128. begin
  129. (* TODO fix
  130. fdclose(Handle);
  131. *)
  132. end;
  133. Function FileTruncate (Handle: THandle; Size: Int64) : boolean;
  134. begin
  135. (* TODO fix
  136. FileTruncate:=fdtruncate(Handle,Size);
  137. *)
  138. end;
  139. Function FileAge (Const FileName : String): Longint;
  140. (*
  141. Var Info : Stat;
  142. Y,M,D,hh,mm,ss : word;
  143. *)
  144. begin
  145. (* TODO fix
  146. If not fstat (FileName,Info) then
  147. exit(-1)
  148. else
  149. begin
  150. EpochToLocal(info.mtime,y,m,d,hh,mm,ss);
  151. Result:=DateTimeToFileDate(EncodeDate(y,m,d)+EncodeTime(hh,mm,ss,0));
  152. end;
  153. *)
  154. end;
  155. Function FileExists (Const FileName : RawByteString) : Boolean;
  156. (*
  157. Var Info : Stat;
  158. *)
  159. begin
  160. (* TODO fix
  161. FileExists:=fstat(filename,Info);
  162. *)
  163. end;
  164. Function DirectoryExists (Const Directory : RawByteString) : Boolean;
  165. (*
  166. Var Info : Stat;
  167. *)
  168. begin
  169. (* TODO fix
  170. DirectoryExists:=fstat(Directory,Info) and
  171. ((info.mode and STAT_IFMT)=STAT_IFDIR);
  172. *)
  173. end;
  174. (*
  175. Function LinuxToWinAttr (FN : Pchar; Const Info : Stat) : Longint;
  176. begin
  177. Result:=faArchive;
  178. If (Info.Mode and STAT_IFDIR)=STAT_IFDIR then
  179. Result:=Result or faDirectory;
  180. If (FN[0]='.') and (not (FN[1] in [#0,'.'])) then
  181. Result:=Result or faHidden;
  182. If (Info.Mode and STAT_IWUSR)=0 Then
  183. Result:=Result or faReadOnly;
  184. If (Info.Mode and
  185. (STAT_IFSOCK or STAT_IFBLK or STAT_IFCHR or STAT_IFIFO))<>0 then
  186. Result:=Result or faSysFile;
  187. end;
  188. {
  189. GlobToSearch takes a glob entry, stats the file.
  190. The glob entry is removed.
  191. If FileAttributes match, the entry is reused
  192. }
  193. Type
  194. TGlobSearchRec = Record
  195. Path : String;
  196. GlobHandle : PGlob;
  197. end;
  198. PGlobSearchRec = ^TGlobSearchRec;
  199. Function GlobToTSearchRec (Var Info : TSearchRec) : Boolean;
  200. Var SInfo : Stat;
  201. p : Pglob;
  202. GlobSearchRec : PGlobSearchrec;
  203. begin
  204. GlobSearchRec:=PGlobSearchrec(Info.FindHandle);
  205. P:=GlobSearchRec^.GlobHandle;
  206. Result:=P<>Nil;
  207. If Result then
  208. begin
  209. GlobSearchRec^.GlobHandle:=P^.Next;
  210. Result:=Fstat(GlobSearchRec^.Path+StrPas(p^.name),SInfo);
  211. If Result then
  212. begin
  213. Info.Attr:=LinuxToWinAttr(p^.name,SInfo);
  214. Result:=(Info.ExcludeAttr and Info.Attr)=0;
  215. If Result Then
  216. With Info do
  217. begin
  218. Attr:=Info.Attr;
  219. If P^.Name<>Nil then
  220. Name:=strpas(p^.name);
  221. Time:=Sinfo.mtime;
  222. Size:=Sinfo.Size;
  223. end;
  224. end;
  225. P^.Next:=Nil;
  226. GlobFree(P);
  227. end;
  228. end;
  229. *)
  230. procedure DoFind (var F: TSearchRec; firstTime: Boolean);
  231. var
  232. err: OSErr;
  233. s: Str255;
  234. begin
  235. with Rslt, findData, paramBlock do
  236. begin
  237. ioVRefNum := searchFSSpec.vRefNum;
  238. if firstTime then
  239. ioFDirIndex := 0;
  240. while true do
  241. begin
  242. s := '';
  243. ioDirID := searchFSSpec.parID;
  244. ioFDirIndex := ioFDirIndex + 1;
  245. ioNamePtr := @s;
  246. err := PBGetCatInfoSync(@paramBlock);
  247. if err <> noErr then
  248. begin
  249. if err = fnfErr then
  250. DosError := 18
  251. else
  252. DosError := MacOSErr2RTEerr(err);
  253. break;
  254. end;
  255. attr := GetFileAttrFromPB(Rslt.paramBlock);
  256. if ((Attr and not(searchAttr)) = 0) then
  257. begin
  258. name := s;
  259. UpperString(s, true);
  260. if FNMatch(Rslt.searchFSSpec.name, s) then
  261. begin
  262. size := GetFileSizeFromPB(paramBlock);
  263. time := MacTimeToDosPackedTime(ioFlMdDat);
  264. Result := 0;
  265. break;
  266. end;
  267. end;
  268. end;
  269. end;
  270. end;
  271. Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
  272. var
  273. s: Str255;
  274. begin
  275. fillchar(Rslt, sizeof(Rslt), 0);
  276. if path = '' then
  277. begin
  278. Result := 3;
  279. Exit;
  280. end;
  281. {We always also search for readonly and archive, regardless of Attr.}
  282. Rslt.searchAttr := (Attr or (archive or readonly));
  283. Result := PathArgToFSSpec(path, Rslt.searchFSSpec);
  284. with Rslt do
  285. if (Result = 0) or (Result = 2) then
  286. begin
  287. SearchSpec := path;
  288. NamePos := Length(path) - Length(searchFSSpec.name);
  289. if (Pos('?', searchFSSpec.name) = 0) and (Pos('*', searchFSSpec.name) = 0) then {No wildcards}
  290. begin {If exact match, we don't have to scan the directory}
  291. exactMatch := true;
  292. Result := DoFindOne(searchFSSpec, paramBlock);
  293. if Result = 0 then
  294. begin
  295. Attr := GetFileAttrFromPB(paramBlock);
  296. if ((Attr and not(searchAttr)) = 0) then
  297. begin
  298. name := searchFSSpec.name;
  299. size := GetFileSizeFromPB(paramBlock);
  300. time := MacTimeToDosPackedTime(paramBlock.ioFlMdDat);
  301. end
  302. else
  303. Result := 18;
  304. end
  305. else if Result = 2 then
  306. Result := 18;
  307. end
  308. else
  309. begin
  310. exactMatch := false;
  311. s := searchFSSpec.name;
  312. UpperString(s, true);
  313. Rslt.searchFSSpec.name := s;
  314. DoFind(Rslt, true);
  315. end;
  316. end;
  317. end;
  318. Function FindNext (Var Rslt : TSearchRec) : Longint;
  319. begin
  320. if F.exactMatch then
  321. Result := 18
  322. else
  323. Result:=DoFind (Rslt);
  324. end;
  325. Procedure FindClose (Var F : TSearchrec);
  326. (*
  327. Var
  328. GlobSearchRec : PGlobSearchRec;
  329. *)
  330. begin
  331. (* TODO fix
  332. GlobSearchRec:=PGlobSearchRec(F.FindHandle);
  333. GlobFree (GlobSearchRec^.GlobHandle);
  334. Dispose(GlobSearchRec);
  335. *)
  336. end;
  337. Function FileGetDate (Handle : Longint) : Longint;
  338. (*
  339. Var Info : Stat;
  340. *)
  341. begin
  342. (* TODO fix
  343. If Not(FStat(Handle,Info)) then
  344. Result:=-1
  345. else
  346. Result:=Info.Mtime;
  347. *)
  348. end;
  349. Function FileSetDate (Handle,Age : Longint) : Longint;
  350. begin
  351. // TODO fix
  352. // Impossible under Linux from FileHandle !!
  353. FileSetDate:=-1;
  354. end;
  355. Function FileGetAttr (Const FileName : RawByteString) : Longint;
  356. (*
  357. Var Info : Stat;
  358. *)
  359. begin
  360. (* TODO fix
  361. If Not FStat (FileName,Info) then
  362. Result:=-1
  363. Else
  364. Result:=LinuxToWinAttr(Pchar(FileName),Info);
  365. *)
  366. end;
  367. Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
  368. begin
  369. Result:=-1;
  370. end;
  371. Function DeleteFile (Const FileName : RawByteString) : Boolean;
  372. begin
  373. (* TODO fix
  374. Result:=UnLink (FileName);
  375. *)
  376. end;
  377. Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
  378. begin
  379. (* TODO fix
  380. RenameFile:=Unix.FRename(OldNAme,NewName);
  381. *)
  382. end;
  383. {****************************************************************************
  384. Disk Functions
  385. ****************************************************************************}
  386. {
  387. The Diskfree and Disksize functions need a file on the specified drive, since this
  388. is required for the statfs system call.
  389. These filenames are set in drivestr[0..26], and have been preset to :
  390. 0 - '.' (default drive - hence current dir is ok.)
  391. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  392. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  393. 3 - '/' (C: equivalent of dos is the root partition)
  394. 4..26 (can be set by you're own applications)
  395. ! Use AddDisk() to Add new drives !
  396. They both return -1 when a failure occurs.
  397. }
  398. Const
  399. FixDriveStr : array[0..3] of pchar=(
  400. '.',
  401. '/fd0/.',
  402. '/fd1/.',
  403. '/.'
  404. );
  405. var
  406. Drives : byte;
  407. DriveStr : array[4..26] of pchar;
  408. Procedure AddDisk(const path:string);
  409. begin
  410. if not (DriveStr[Drives]=nil) then
  411. FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1);
  412. GetMem(DriveStr[Drives],length(Path)+1);
  413. StrPCopy(DriveStr[Drives],path);
  414. inc(Drives);
  415. if Drives>26 then
  416. Drives:=4;
  417. end;
  418. Function DiskFree(Drive: Byte): int64;
  419. (*
  420. var
  421. fs : tstatfs;
  422. *)
  423. Begin
  424. (* TODO fix
  425. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and statfs(StrPas(fixdrivestr[drive]),fs)) or
  426. ((not (drivestr[Drive]=nil)) and statfs(StrPas(drivestr[drive]),fs)) then
  427. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  428. else
  429. Diskfree:=-1;
  430. *)
  431. End;
  432. Function DiskSize(Drive: Byte): int64;
  433. (*
  434. var
  435. fs : tstatfs;
  436. *)
  437. Begin
  438. (* TODO fix
  439. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and statfs(StrPas(fixdrivestr[drive]),fs)) or
  440. ((not (drivestr[Drive]=nil)) and statfs(StrPas(drivestr[drive]),fs)) then
  441. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  442. else
  443. DiskSize:=-1;
  444. *)
  445. End;
  446. {****************************************************************************
  447. Misc Functions
  448. ****************************************************************************}
  449. procedure Beep;
  450. begin
  451. //TODO fix
  452. end;
  453. {****************************************************************************
  454. Locale Functions
  455. ****************************************************************************}
  456. Procedure GetLocalTime(var SystemTime: TSystemTime);
  457. begin
  458. (* TODO fix
  459. Unix.GetTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second);
  460. Unix.GetDate(SystemTime.Year, SystemTime.Month, SystemTime.Day);
  461. SystemTime.MilliSecond := 0;
  462. *)
  463. end ;
  464. Procedure InitAnsi;
  465. Var
  466. i : longint;
  467. begin
  468. { Fill table entries 0 to 127 }
  469. for i := 0 to 96 do
  470. UpperCaseTable[i] := chr(i);
  471. for i := 97 to 122 do
  472. UpperCaseTable[i] := chr(i - 32);
  473. for i := 123 to 191 do
  474. UpperCaseTable[i] := chr(i);
  475. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  476. for i := 0 to 64 do
  477. LowerCaseTable[i] := chr(i);
  478. for i := 65 to 90 do
  479. LowerCaseTable[i] := chr(i + 32);
  480. for i := 91 to 191 do
  481. LowerCaseTable[i] := chr(i);
  482. Move (CPISO88591LCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  483. end;
  484. Procedure InitInternational;
  485. begin
  486. InitInternationalGeneric;
  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:=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) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
  510. begin
  511. // Result:=FPCGetEnvStrFromP(Envp,Index);
  512. Result:='';
  513. end;
  514. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString;Flags:TExecuteFlags=[]):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;Flags:TExecuteFlags=[]):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.