filutil.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. File utility calls
  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. {******************************************************************************}
  13. { private functions }
  14. {******************************************************************************}
  15. { some internal constants }
  16. const
  17. ofRead = $0000; { Open for reading }
  18. ofWrite = $0001; { Open for writing }
  19. ofReadWrite = $0002; { Open for reading/writing }
  20. faFail = $0000; { Fail if file does not exist }
  21. faCreate = $0010; { Create if file does not exist }
  22. faOpen = $0001; { Open if file exists }
  23. faOpenReplace = $0002; { Clear if file exists }
  24. { converts S to a pchar and copies it to the transfer-buffer. }
  25. procedure StringToTB(const S: string);
  26. var P: pchar; Len: integer;
  27. begin
  28. Len := Length(S) + 1;
  29. P := StrPCopy(StrAlloc(Len), S);
  30. SysCopyToDos(longint(P), Len);
  31. StrDispose(P);
  32. end ;
  33. { Native OpenFile function.
  34. if return value <> 0 call failed. }
  35. function OpenFile(const FileName: string; var Handle: longint; Mode, Action: word): longint;
  36. var
  37. Regs: registers;
  38. begin
  39. result := 0;
  40. Handle := 0;
  41. StringToTB(FileName);
  42. if LFNSupport then Regs.Eax:=$716c
  43. else Regs.Eax:=$6c00;
  44. Regs.Edx := Action; { Action if file exists/not exists }
  45. Regs.Ds := tb_segment;
  46. Regs.Esi := tb_offset;
  47. Regs.Ebx := $2000 + (Mode and $ff); { file open mode }
  48. Regs.Ecx := $20; { Attributes }
  49. RealIntr($21, Regs);
  50. if Regs.Flags and CarryFlag <> 0 then result := Regs.Ax
  51. else Handle := Regs.Ax;
  52. end ;
  53. {******************************************************************************}
  54. { Public functions }
  55. {******************************************************************************}
  56. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  57. var e: integer;
  58. Begin
  59. e := OpenFile(FileName, result, Mode, faOpen);
  60. if e <> 0 then result := -1;
  61. end ;
  62. Function FileCreate (Const FileName : String) : Longint;
  63. var e: integer;
  64. begin
  65. e := OpenFile(FileName, result, ofReadWrite, faCreate or faOpenReplace);
  66. if e <> 0 then result := -1;
  67. end;
  68. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  69. begin
  70. result := Do_Read(Handle, longint(@Buffer), Count);
  71. end;
  72. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  73. begin
  74. result := Do_Write(Handle, longint(@Buffer), Count);
  75. end;
  76. Function FileSeek (Handle, Offset, Origin : Longint) : Longint;
  77. var Regs: registers;
  78. begin
  79. Regs.Eax := $4200;
  80. Regs.Al := Origin;
  81. Regs.Edx := Lo(Offset);
  82. Regs.Ecx := Hi(Offset);
  83. Regs.Ebx := Handle;
  84. RealIntr($21, Regs);
  85. if Regs.Flags and CarryFlag <> 0 then
  86. result := -1
  87. else begin
  88. LongRec(result).Lo := Regs.Ax;
  89. LongRec(result).Hi := Regs.Dx;
  90. end ;
  91. end;
  92. Procedure FileClose (Handle : Longint);
  93. var Regs: registers;
  94. begin
  95. if Handle<=4 then
  96. exit;
  97. Regs.Eax := $3e00;
  98. Regs.Ebx := Handle;
  99. RealIntr($21, Regs);
  100. end;
  101. Function FileTruncate (Handle,Size: Longint) : boolean;
  102. var
  103. regs : trealregs;
  104. begin
  105. FileSeek(Handle,Size,0);
  106. Regs.realecx := 0;
  107. Regs.realedx := tb_offset;
  108. Regs.ds := tb_segment;
  109. Regs.ebx := Handle;
  110. Regs.eax:=$4000;
  111. RealIntr($21, Regs);
  112. FileTruncate:=(regs.realflags and carryflag)=0;
  113. end;
  114. Function FileAge (Const FileName : String): Longint;
  115. var Handle: longint;
  116. begin
  117. Handle := FileOpen(FileName, 0);
  118. if Handle <> -1 then begin
  119. result := FileGetDate(Handle);
  120. FileClose(Handle);
  121. end
  122. else result := -1;
  123. end;
  124. Function FileExists (Const FileName : String) : Boolean;
  125. var Handle: longint;
  126. begin
  127. //!! This can be done quicker, need to find out how
  128. Result := (OpenFile(FileName, Handle, ofRead, faOpen) = 0);
  129. if Handle <> 0 then
  130. FileClose(Handle);
  131. end;
  132. Type PSearchrec = ^Searchrec;
  133. Function FindFirst (Const Path : String; Attr : Longint; Var Rslt : TSearchRec) : Longint;
  134. Var Sr : PSearchrec;
  135. begin
  136. //!! Sr := New(PSearchRec);
  137. getmem(sr,sizeof(searchrec));
  138. Rslt.FindHandle := longint(Sr);
  139. DOS.FindFirst(Path, Attr, Sr^);
  140. result := -DosError;
  141. if result = 0 then begin
  142. Rslt.Time := Sr^.Time;
  143. Rslt.Size := Sr^.Size;
  144. Rslt.Attr := Sr^.Attr;
  145. Rslt.ExcludeAttr := 0;
  146. Rslt.Name := Sr^.Name;
  147. end ;
  148. end;
  149. Function FindNext (Var Rslt : TSearchRec) : Longint;
  150. var Sr: PSearchRec;
  151. begin
  152. Sr := PSearchRec(Rslt.FindHandle);
  153. if Sr <> nil then begin
  154. DOS.FindNext(Sr^);
  155. result := -DosError;
  156. if result = 0 then begin
  157. Rslt.Time := Sr^.Time;
  158. Rslt.Size := Sr^.Size;
  159. Rslt.Attr := Sr^.Attr;
  160. Rslt.ExcludeAttr := 0;
  161. Rslt.Name := Sr^.Name;
  162. end ;
  163. end ;
  164. end;
  165. Procedure FindClose (Var F : TSearchrec);
  166. var Sr: PSearchRec;
  167. begin
  168. Sr := PSearchRec(F.FindHandle);
  169. if Sr <> nil then
  170. begin
  171. //!! Dispose(Sr);
  172. // This call is non dummy if LFNSupport is true PM
  173. DOS.FindClose(SR^);
  174. freemem(sr,sizeof(searchrec));
  175. end;
  176. F.FindHandle := 0;
  177. end;
  178. Function FileGetDate (Handle : Longint) : Longint;
  179. var Regs: registers;
  180. begin
  181. //!! for win95 an alternative function is available.
  182. Regs.Ebx := Handle;
  183. Regs.Eax := $5700;
  184. RealIntr($21, Regs);
  185. if Regs.Flags and CarryFlag <> 0 then result := -Regs.Ax
  186. else begin
  187. LongRec(result).Lo := Regs.cx;
  188. LongRec(result).Hi := Regs.dx;
  189. end ;
  190. end;
  191. Function FileSetDate (Handle, Age : Longint) : Longint;
  192. var Regs: registers;
  193. begin
  194. Regs.Ebx := Handle;
  195. Regs.Eax := $5701;
  196. Regs.Ecx := Lo(Age);
  197. Regs.Edx := Hi(Age);
  198. RealIntr($21, Regs);
  199. if Regs.Flags and CarryFlag <> 0 then result := -Regs.Ax
  200. else result := 0;
  201. end;
  202. Function FileGetAttr (Const FileName : String) : Longint;
  203. var Regs: registers;
  204. begin
  205. StringToTB(FileName);
  206. Regs.Edx := tb_offset;
  207. Regs.Ds := tb_segment;
  208. if LFNSupport then
  209. begin
  210. Regs.Ax := $7143;
  211. Regs.Bx := 0;
  212. end
  213. else
  214. Regs.Ax := $4300;
  215. RealIntr($21, Regs);
  216. if Regs.Flags and CarryFlag <> 0 then
  217. result := -1
  218. else
  219. result := Regs.Cx;
  220. end;
  221. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  222. var Regs: registers;
  223. begin
  224. StringToTB(FileName);
  225. Regs.Edx := tb_offset;
  226. Regs.Ds := tb_segment;
  227. if LFNSupport then
  228. begin
  229. Regs.Ax := $7143;
  230. Regs.Bx := 1;
  231. end
  232. else
  233. Regs.Ax := $4301;
  234. Regs.Cx := Attr;
  235. RealIntr($21, Regs);
  236. if Regs.Flags and CarryFlag <> 0 then result := -Regs.Ax
  237. else result := 0;
  238. end;
  239. Function DeleteFile (Const FileName : String) : Boolean;
  240. var Regs: registers;
  241. begin
  242. StringToTB(FileName);
  243. Regs.Edx := tb_offset;
  244. Regs.Ds := tb_segment;
  245. if LFNSupport then
  246. Regs.Eax := $7141
  247. else
  248. Regs.Eax := $4100;
  249. Regs.Esi := 0;
  250. Regs.Ecx := 0;
  251. RealIntr($21, Regs);
  252. result := (Regs.Flags and CarryFlag = 0);
  253. end;
  254. Function RenameFile (Const OldName, NewName : String) : Boolean;
  255. var Regs: registers;
  256. begin
  257. StringToTB(OldName + #0 + NewName);
  258. Regs.Edx := tb_offset;
  259. Regs.Ds := tb_segment;
  260. Regs.Edi := tb_offset + Length(OldName) + 1;
  261. Regs.Es := tb_segment;
  262. if LFNSupport then
  263. Regs.Eax := $7156
  264. else
  265. Regs.Eax := $5600;
  266. Regs.Ecx := $ff;
  267. RealIntr($21, Regs);
  268. result := (Regs.Flags and CarryFlag = 0);
  269. end;
  270. Function FileSearch (Const Name, DirList : String) : String;
  271. begin
  272. result := DOS.FSearch(Name, DirList);
  273. end;
  274. Procedure GetLocalTime(var SystemTime: TSystemTime);
  275. var Regs: Registers;
  276. begin
  277. Regs.ah := $2C;
  278. RealIntr($21, Regs);
  279. SystemTime.Hour := Regs.Ch;
  280. SystemTime.Minute := Regs.Cl;
  281. SystemTime.Second := Regs.Dh;
  282. SystemTime.MilliSecond := Regs.Dl;
  283. Regs.ah := $2A;
  284. RealIntr($21, Regs);
  285. SystemTime.Year := Regs.Cx;
  286. SystemTime.Month := Regs.Dh;
  287. SystemTime.Day := Regs.Dl;
  288. end ;
  289. { ---------------------------------------------------------------------
  290. Internationalization settings
  291. ---------------------------------------------------------------------}
  292. { Codepage constants }
  293. const
  294. CP_US = 437;
  295. CP_MultiLingual = 850;
  296. CP_SlavicLatin2 = 852;
  297. CP_Turkish = 857;
  298. CP_Portugal = 860;
  299. CP_IceLand = 861;
  300. CP_Canada = 863;
  301. CP_NorwayDenmark = 865;
  302. { CountryInfo }
  303. type
  304. TCountryInfo = packed record
  305. InfoId: byte;
  306. case integer of
  307. 1: ( Size: word;
  308. CountryId: word;
  309. CodePage: word;
  310. CountryInfo: array[0..33] of byte );
  311. 2: ( UpperCaseTable: longint );
  312. 4: ( FilenameUpperCaseTable: longint );
  313. 5: ( FilecharacterTable: longint );
  314. 6: ( CollatingTable: longint );
  315. 7: ( DBCSLeadByteTable: longint );
  316. end ;
  317. procedure GetExtendedCountryInfo(InfoId: integer; CodePage, CountryId: word; var CountryInfo: TCountryInfo);
  318. Var Regs: Registers;
  319. begin
  320. Regs.AH := $65;
  321. Regs.AL := InfoId;
  322. Regs.BX := CodePage;
  323. Regs.DX := CountryId;
  324. Regs.ES := transfer_buffer div 16;
  325. Regs.DI := transfer_buffer and 15;
  326. Regs.CX := SizeOf(TCountryInfo);
  327. RealIntr($21, Regs);
  328. DosMemGet(transfer_buffer div 16,
  329. transfer_buffer and 15,
  330. CountryInfo, Regs.CX );
  331. end;
  332. procedure InitAnsi;
  333. var CountryInfo: TCountryInfo; i: integer;
  334. begin
  335. { Fill table entries 0 to 127 }
  336. for i := 0 to 96 do
  337. UpperCaseTable[i] := chr(i);
  338. for i := 97 to 122 do
  339. UpperCaseTable[i] := chr(i - 32);
  340. for i := 123 to 127 do
  341. UpperCaseTable[i] := chr(i);
  342. for i := 0 to 64 do
  343. LowerCaseTable[i] := chr(i);
  344. for i := 65 to 90 do
  345. LowerCaseTable[i] := chr(i + 32);
  346. for i := 91 to 255 do
  347. LowerCaseTable[i] := chr(i);
  348. { Get country and codepage info }
  349. GetExtendedCountryInfo(1, $FFFF, $FFFF, CountryInfo);
  350. if CountryInfo.CodePage = 850 then
  351. begin
  352. { Special, known case }
  353. Move(CP850UCT, UpperCaseTable[128], 128);
  354. Move(CP850LCT, LowerCaseTable[128], 128);
  355. end
  356. else
  357. begin
  358. { this needs to be checked !!
  359. this is correct only if UpperCaseTable is
  360. and Offset:Segment word record (PM) }
  361. { get the uppercase table from dosmemory }
  362. GetExtendedCountryInfo(2, $FFFF, $FFFF, CountryInfo);
  363. DosMemGet(CountryInfo.UpperCaseTable shr 16, 2 + CountryInfo.UpperCaseTable and 65535, UpperCaseTable[128], 128);
  364. for i := 128 to 255 do
  365. begin
  366. if UpperCaseTable[i] <> chr(i) then
  367. LowerCaseTable[ord(UpperCaseTable[i])] := chr(i);
  368. end;
  369. end;
  370. end;
  371. Procedure InitInternational;
  372. { This routine is called by the unit startup code. }
  373. begin
  374. { Init upper/lowercase tables }
  375. InitAnsi
  376. end;
  377. {
  378. $Log$
  379. Revision 1.14 2000-04-10 11:04:45 pierre
  380. * use 16 bit regs at return of system interrupts instead of 32
  381. * call Dos.FindClose because it is not a dummy if LFNSupport is true
  382. Revision 1.13 2000/02/17 22:16:05 sg
  383. * Changed the second argument of FileWrite from "var buffer" to
  384. "const buffer", like in Delphi.
  385. Revision 1.12 2000/02/09 16:59:28 peter
  386. * truncated log
  387. Revision 1.11 2000/01/16 22:25:38 peter
  388. * check handle for file closing
  389. Revision 1.10 2000/01/07 16:41:31 daniel
  390. * copyright 2000
  391. Revision 1.9 1999/11/25 15:55:52 pierre
  392. * web bug 716
  393. Revision 1.8 1999/08/26 11:02:50 peter
  394. * findclose freemem fixed
  395. Revision 1.7 1999/08/24 13:14:28 peter
  396. * fixed DeleteFile()
  397. Revision 1.6 1999/08/19 14:00:08 pierre
  398. * bug in country info code fixed
  399. }