sysutils.pp 16 KB

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