2
0

sysutils.pp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for netware
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. {$MODESWITCH OUT}
  16. { force ansistrings }
  17. {$H+}
  18. {$modeswitch typehelpers}
  19. {$modeswitch advancedrecords}
  20. uses DOS;
  21. {$I nwsys.inc}
  22. {$I errno.inc}
  23. {$DEFINE HAS_SLEEP}
  24. {$DEFINE HAS_OSERROR}
  25. { used OS file system APIs use ansistring }
  26. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  27. { OS has an ansistring/single byte environment variable API }
  28. {$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
  29. TYPE
  30. TNetwareFindData =
  31. RECORD
  32. DirP : PNWDirEnt; { used for opendir }
  33. EntryP: PNWDirEnt; { and readdir }
  34. Magic : WORD; { to avoid abends with uninitialized TSearchRec }
  35. END;
  36. { Include platform independent interface part }
  37. {$i sysutilh.inc}
  38. { additional NetWare file flags}
  39. CONST
  40. faSHARE = $00000080; { Sharable file }
  41. faNO_SUBALLOC = $00000800; { Don't sub alloc. this file }
  42. faTRANS = $00001000; { Transactional file (TTS usable) }
  43. faREADAUD = $00004000; { Read audit }
  44. faWRITAUD = $00008000; { Write audit }
  45. faIMMPURG = $00010000; { Immediate purge }
  46. faNORENAM = $00020000; { Rename inhibit }
  47. faNODELET = $00040000; { Delete inhibit }
  48. faNOCOPY = $00080000; { Copy inhibit }
  49. faFILE_MIGRATED = $00400000; { File has been migrated }
  50. faDONT_MIGRATE = $00800000; { Don't migrate this file }
  51. faIMMEDIATE_COMPRESS = $02000000; { Compress this file immediately }
  52. faFILE_COMPRESSED = $04000000; { File is compressed }
  53. faDONT_COMPRESS = $08000000; { Don't compress this file }
  54. faCANT_COMPRESS = $20000000; { Can't compress this file }
  55. faATTR_ARCHIVE = $40000000; { Entry has had an EA modified, }
  56. { an ownerID changed, or trustee }
  57. { info changed, etc. }
  58. implementation
  59. uses
  60. sysconst;
  61. {$define FPC_FEXPAND_DRIVES}
  62. {$define FPC_FEXPAND_VOLUMES}
  63. {$define FPC_FEXPAND_NO_DEFAULT_PATHS}
  64. { Include platform independent implementation part }
  65. {$i sysutils.inc}
  66. {****************************************************************************
  67. File Functions
  68. ****************************************************************************}
  69. Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : THandle;
  70. VAR NWOpenFlags : longint;
  71. SystemFileName: RawByteString;
  72. begin
  73. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  74. NWOpenFlags:=0;
  75. Case (Mode and 3) of
  76. 0 : NWOpenFlags:=NWOpenFlags or O_RDONLY;
  77. 1 : NWOpenFlags:=NWOpenFlags or O_WRONLY;
  78. 2 : NWOpenFlags:=NWOpenFlags or O_RDWR;
  79. end;
  80. FileOpen := _open (pchar(SystemFileName),NWOpenFlags,0);
  81. //!! We need to set locking based on Mode !!
  82. end;
  83. Function FileCreate (Const FileName : RawByteString) : THandle;
  84. VAR SystemFileName: RawByteString;
  85. begin
  86. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  87. FileCreate:=_open(Pchar(SystemFileName),O_RdWr or O_Creat or O_Trunc,0);
  88. end;
  89. Function FileCreate (Const FileName : RawByteString; Rights:longint) : THandle;
  90. begin
  91. FileCreate:=FileCreate (FileName);
  92. end;
  93. Function FileCreate (Const FileName : RawByteString; ShareMode: Longint; Rights:longint) : THandle;
  94. begin
  95. FileCreate:=FileCreate (FileName);
  96. end;
  97. Function FileRead (Handle : THandle; Out Buffer; Count : longint) : longint;
  98. begin
  99. FileRead:=_read (Handle,@Buffer,Count);
  100. end;
  101. Function FileWrite (Handle : THandle; const Buffer; Count : Longint) : longint;
  102. begin
  103. FileWrite:=_write (Handle,@Buffer,Count);
  104. end;
  105. Function FileSeek (Handle : THandle; FOffset,Origin : Longint) : Longint;
  106. begin
  107. FileSeek:=_lseek (Handle,FOffset,Origin);
  108. end;
  109. Function FileSeek (Handle : THandle; FOffset: Int64; Origin: Longint) : Int64;
  110. begin
  111. {$warning need to add 64bit FileSeek }
  112. FileSeek:=FileSeek(Handle,Longint(FOffset),Longint(Origin));
  113. end;
  114. Procedure FileClose (Handle : THandle);
  115. begin
  116. _close(Handle);
  117. end;
  118. Function FileTruncate (Handle : THandle; Size: Int64) : boolean;
  119. begin
  120. if Size > high (longint) then
  121. FileTruncate := false
  122. {$WARNING Possible support for 64-bit FS to be checked!}
  123. else
  124. FileTruncate:=(_chsize(Handle,Size) = 0);
  125. end;
  126. Function FileLock (Handle,FOffset,FLen : Longint) : Longint;
  127. begin
  128. FileLock := _lock (Handle,FOffset,FLen);
  129. end;
  130. Function FileLock (Handle : Longint; FOffset,FLen : Int64) : Longint;
  131. begin
  132. {$warning need to add 64bit FileLock call }
  133. FileLock := FileLock (Handle, longint(FOffset),longint(FLen));
  134. end;
  135. Function FileUnlock (Handle,FOffset,FLen : Longint) : Longint;
  136. begin
  137. FileUnlock := _unlock (Handle,FOffset,FLen);
  138. end;
  139. Function FileUnlock (Handle : Longint; FOffset,FLen : Int64) : Longint;
  140. begin
  141. {$warning need to add 64bit FileUnlock call }
  142. FileUnlock := FileUnlock (Handle, longint(FOffset),longint(FLen));
  143. end;
  144. Function FileAge (Const FileName : String): Longint;
  145. VAR Info : NWStatBufT;
  146. PTM : PNWTM;
  147. begin
  148. If _stat (pchar(FileName),Info) <> 0 then
  149. exit(-1)
  150. else
  151. begin
  152. PTM := _localtime (Info.st_mtime);
  153. IF PTM = NIL THEN
  154. exit(-1)
  155. else
  156. WITH PTM^ DO
  157. Result:=DateTimeToFileDate(EncodeDate(tm_year+1900,tm_mon+1,tm_mday)+EncodeTime(tm_hour,tm_min,tm_sec,0));
  158. end;
  159. end;
  160. Function FileExists (Const FileName : RawByteString) : Boolean;
  161. VAR Info : NWStatBufT;
  162. SystemFileName: RawByteString;
  163. begin
  164. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  165. FileExists:=(_stat(pchar(SystemFileName),Info) = 0);
  166. end;
  167. PROCEDURE find_setfields (VAR f : TsearchRec; VAR Name : RawByteString);
  168. VAR T : Dos.DateTime;
  169. BEGIN
  170. WITH F DO
  171. BEGIN
  172. IF FindData.Magic = $AD01 THEN
  173. BEGIN
  174. {attr := FindData.EntryP^.d_attr AND $FF;} // lowest 8 bit -> same as dos
  175. attr := FindData.EntryP^.d_attr; { return complete netware attributes }
  176. UnpackTime(FindData.EntryP^.d_time + (LONGINT (FindData.EntryP^.d_date) SHL 16), T);
  177. time := DateTimeToFileDate(EncodeDate(T.Year,T.Month,T.day)+EncodeTime(T.Hour,T.Min,T.Sec,0));
  178. size := FindData.EntryP^.d_size;
  179. name := FindData.EntryP^.d_nameDOS;
  180. SetCodePage(name, DefaultFileSystemCodePage, false);
  181. END ELSE
  182. BEGIN
  183. name := '';
  184. END;
  185. END;
  186. END;
  187. Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
  188. var
  189. SystemEncodedPath: RawByteString;
  190. begin
  191. IF path = '' then
  192. exit (18);
  193. SystemEncodedPath := ToSingleByteEncodedFileName (Path);
  194. Rslt.FindData.DirP := _opendir (pchar(SystemEncodedPath));
  195. IF Rslt.FindData.DirP = NIL THEN
  196. exit (18);
  197. IF attr <> faAnyFile THEN
  198. _SetReaddirAttribute (Rslt.FindData.DirP, attr);
  199. Rslt.FindData.Magic := $AD01;
  200. Rslt.FindData.EntryP := _readdir (Rslt.FindData.DirP);
  201. if Rslt.FindData.EntryP = nil then
  202. begin
  203. _closedir (Rslt.FindData.DirP);
  204. Rslt.FindData.DirP := NIL;
  205. result := 18;
  206. end else
  207. begin
  208. find_setfields (Rslt,Name);
  209. result := 0;
  210. end;
  211. end;
  212. Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
  213. begin
  214. IF Rslt.FindData.Magic <> $AD01 THEN
  215. exit (18);
  216. Rslt.FindData.EntryP := _readdir (Rslt.FindData.DirP);
  217. IF Rslt.FindData.EntryP = NIL THEN
  218. exit (18);
  219. find_setfields (Rslt,Name);
  220. result := 0;
  221. end;
  222. Procedure InternalFindClose (var Handle: THandle; var FindData: TFindData);
  223. begin
  224. IF FindData.Magic = $AD01 THEN
  225. BEGIN
  226. IF F.FindData.DirP <> NIL THEN
  227. _closedir (F.FindData.DirP);
  228. F.FindData.Magic := 0;
  229. F.FindData.DirP := NIL;
  230. F.FindData.EntryP := NIL;
  231. END;
  232. end;
  233. Function FileGetDate (Handle : THandle) : Longint;
  234. Var Info : NWStatBufT;
  235. PTM : PNWTM;
  236. begin
  237. If _fstat(Handle,Info) <> 0 then
  238. Result:=-1
  239. else
  240. begin
  241. PTM := _localtime (Info.st_mtime);
  242. IF PTM = NIL THEN
  243. exit(-1)
  244. else
  245. WITH PTM^ DO
  246. Result:=DateTimeToFileDate(EncodeDate(tm_year+1900,tm_mon+1,tm_mday)+EncodeTime(tm_hour,tm_min,tm_sec,0));
  247. end;
  248. end;
  249. Function FileSetDate (Handle : THandle; Age : Longint) : Longint;
  250. begin
  251. { i think its impossible under netware from FileHandle. I dident found a way to get the
  252. complete pathname of a filehandle, that would be needed for ChangeDirectoryEntry }
  253. FileSetDate:=-1;
  254. ConsolePrintf ('warning: fpc sysutils.FileSetDate not implemented'#13#10,0);
  255. {$warning FileSetDate not implemented (i think is impossible) }
  256. end;
  257. Function FileGetAttr (Const FileName : RawByteString) : Longint;
  258. Var Info : NWStatBufT;
  259. SystemFileName: RawByteString;
  260. begin
  261. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  262. If _stat (pchar(SystemFileName),Info) <> 0 then
  263. Result:=-1
  264. Else
  265. Result := Info.st_attr AND $FFFF;
  266. end;
  267. Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
  268. VAR MS : NWModifyStructure;
  269. SystemFileName: RawByteString;
  270. begin
  271. { The Attr parameter is not used! }
  272. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  273. FillChar (MS, SIZEOF (MS), 0);
  274. if _ChangeDirectoryEntry (PChar (SystemFilename), MS, MFileAtrributesBit, 0) <> 0 then
  275. result := -1
  276. else
  277. result := 0;
  278. end;
  279. Function DeleteFile (Const FileName : RawByteString) : Boolean;
  280. var
  281. SystemFileName: RawByteString;
  282. begin
  283. SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
  284. Result:= (_UnLink (pchar(SystemFileName)) = 0);
  285. end;
  286. Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
  287. var
  288. OldSystemFileName, NewSystemFileName: RawByteString;
  289. begin
  290. OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
  291. NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);
  292. RenameFile:=(_rename(pchar(OldSystemFileName),pchar(NewSystemFileName)) = 0);
  293. end;
  294. {****************************************************************************
  295. Disk Functions
  296. ****************************************************************************}
  297. {
  298. The Diskfree and Disksize functions need a file on the specified drive, since this
  299. is required for the statfs system call.
  300. These filenames are set in drivestr[0..26], and have been preset to :
  301. 0 - '.' (default drive - hence current dir is ok.)
  302. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  303. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  304. 3 - '/' (C: equivalent of dos is the root partition)
  305. 4..26 (can be set by you're own applications)
  306. ! Use AddDisk() to Add new drives !
  307. They both return -1 when a failure occurs.
  308. }
  309. Const
  310. FixDriveStr : array[0..3] of pchar=(
  311. '.',
  312. 'a:.',
  313. 'b:.',
  314. 'sys:/'
  315. );
  316. var
  317. Drives : byte;
  318. DriveStr : array[4..26] of pchar;
  319. Procedure AddDisk(const path:string);
  320. begin
  321. if not (DriveStr[Drives]=nil) then
  322. FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1);
  323. GetMem(DriveStr[Drives],length(Path)+1);
  324. StrPCopy(DriveStr[Drives],path);
  325. inc(Drives);
  326. if Drives>26 then
  327. Drives:=4;
  328. end;
  329. Function DiskFree(Drive: Byte): int64;
  330. //var fs : statfs;
  331. Begin
  332. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and fsstat(StrPas(fixdrivestr[drive]),fs)) or
  333. ((not (drivestr[Drive]=nil)) and fsstat(StrPas(drivestr[drive]),fs)) then
  334. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  335. else
  336. Diskfree:=-1;}
  337. DiskFree := -1;
  338. ConsolePrintf ('warning: fpc sysutils.diskfree not implemented'#13#10,0);
  339. {$warning DiskFree not implemented (does it make sense ?) }
  340. End;
  341. Function DiskSize(Drive: Byte): int64;
  342. //var fs : statfs;
  343. Begin
  344. { if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and fsstat(StrPas(fixdrivestr[drive]),fs)) or
  345. ((not (drivestr[Drive]=nil)) and fsstat(StrPas(drivestr[drive]),fs)) then
  346. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  347. else
  348. DiskSize:=-1;}
  349. DiskSize := -1;
  350. ConsolePrintf ('warning: fpc sysutils.disksize not implemented'#13#10,0);
  351. {$warning DiskSize not implemented (does it make sense ?) }
  352. End;
  353. function DirectoryExists (const Directory: string): boolean;
  354. var
  355. Info : NWStatBufT;
  356. SystemFileName: RawByteString;
  357. begin
  358. SystemFileName:=ToSingleByteFileSystemEncodedFileName(Directory);
  359. If _stat (pchar(SystemFileName),Info) <> 0 then
  360. exit(false)
  361. else
  362. Exit ((Info.st_attr and faDirectory) <> 0);
  363. end;
  364. {****************************************************************************
  365. Misc Functions
  366. ****************************************************************************}
  367. procedure SysBeep;
  368. begin
  369. _RingTheBell;
  370. end;
  371. {****************************************************************************
  372. Locale Functions
  373. ****************************************************************************}
  374. Procedure GetLocalTime(var SystemTime: TSystemTime);
  375. var xx : word;
  376. begin
  377. Dos.GetTime(SystemTime.Hour, SystemTime.Minute, SystemTime.Second, xx);
  378. Dos.GetDate(SystemTime.Year, SystemTime.Month, SystemTime.Day, xx);
  379. SystemTime.MilliSecond := 0;
  380. end;
  381. Procedure InitAnsi;
  382. Var i : longint;
  383. begin
  384. { Fill table entries 0 to 127 }
  385. for i := 0 to 96 do
  386. UpperCaseTable[i] := chr(i);
  387. for i := 97 to 122 do
  388. UpperCaseTable[i] := chr(i - 32);
  389. for i := 123 to 191 do
  390. UpperCaseTable[i] := chr(i);
  391. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  392. for i := 0 to 64 do
  393. LowerCaseTable[i] := chr(i);
  394. for i := 65 to 90 do
  395. LowerCaseTable[i] := chr(i + 32);
  396. for i := 91 to 191 do
  397. LowerCaseTable[i] := chr(i);
  398. Move (CPISO88591LCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  399. end;
  400. Procedure InitInternational;
  401. begin
  402. InitInternationalGeneric;
  403. InitAnsi;
  404. end;
  405. function SysErrorMessage(ErrorCode: Integer): String;
  406. begin
  407. Result:=''; // StrError(ErrorCode);
  408. end;
  409. {****************************************************************************
  410. OS utility functions
  411. ****************************************************************************}
  412. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  413. begin
  414. Result:=_getenv(PChar(EnvVar));
  415. end;
  416. Function GetEnvironmentVariableCount : Integer;
  417. begin
  418. // Result:=FPCCountEnvVar(EnvP);
  419. Result:=0;
  420. end;
  421. Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
  422. begin
  423. // Result:=FPCGetEnvStrFromP(Envp,Index);
  424. Result:='';
  425. end;
  426. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString;Flags:TExecuteFlags=[]):integer;
  427. var
  428. e : EOSError;
  429. CommandLine: AnsiString;
  430. begin
  431. dos.exec(path,comline);
  432. if (Dos.DosError <> 0) then
  433. begin
  434. if ComLine <> '' then
  435. CommandLine := Path + ' ' + ComLine
  436. else
  437. CommandLine := Path;
  438. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,Dos.DosError]);
  439. e.ErrorCode:=Dos.DosError;
  440. raise e;
  441. end;
  442. Result := DosExitCode;
  443. end;
  444. function ExecuteProcess (const Path: AnsiString;
  445. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  446. var
  447. CommandLine: AnsiString;
  448. I: integer;
  449. begin
  450. Commandline := '';
  451. for I := 0 to High (ComLine) do
  452. if Pos (' ', ComLine [I]) <> 0 then
  453. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  454. else
  455. CommandLine := CommandLine + ' ' + Comline [I];
  456. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  457. end;
  458. procedure Sleep(milliseconds: Cardinal);
  459. begin
  460. _delay (milliseconds);
  461. end;
  462. Function GetLastOSError : Integer;
  463. begin
  464. Result:=Integer(__get_errno_ptr^);
  465. end;
  466. {****************************************************************************
  467. Initialization code
  468. ****************************************************************************}
  469. Initialization
  470. InitExceptions; { Initialize exceptions. OS independent }
  471. InitInternational; { Initialize internationalization settings }
  472. OnBeep:=@SysBeep;
  473. Finalization
  474. DoneExceptions;
  475. end.