sysutils.pp 16 KB

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