2
0

sysutils.pp 16 KB

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