sysutils.pp 16 KB

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