sysutils.pp 15 KB

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