filutil.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  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.Eax;
  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; Var 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.Eax;
  89. LongRec(result).Hi := Regs.Edx;
  90. end ;
  91. end;
  92. Procedure FileClose (Handle : Longint);
  93. var Regs: registers;
  94. begin
  95. Regs.Eax := $3e00;
  96. Regs.Ebx := Handle;
  97. RealIntr($21, Regs);
  98. end;
  99. Function FileTruncate (Handle,Size: Longint) : boolean;
  100. var
  101. regs : trealregs;
  102. begin
  103. FileSeek(Handle,Size,0);
  104. Regs.realecx := 0;
  105. Regs.realedx := tb_offset;
  106. Regs.ds := tb_segment;
  107. Regs.ebx := Handle;
  108. Regs.eax:=$4000;
  109. RealIntr($21, Regs);
  110. FileTruncate:=(regs.realflags and carryflag)=0;
  111. end;
  112. Function FileAge (Const FileName : String): Longint;
  113. var Handle: longint;
  114. begin
  115. Handle := FileOpen(FileName, 0);
  116. if Handle <> -1 then begin
  117. result := FileGetDate(Handle);
  118. FileClose(Handle);
  119. end
  120. else result := -1;
  121. end;
  122. Function FileExists (Const FileName : String) : Boolean;
  123. var Handle: longint;
  124. begin
  125. //!! This can be done quicker, need to find out how
  126. Result := (OpenFile(FileName, Handle, ofRead, faOpen) = 0);
  127. if Handle <> 0 then
  128. FileClose(Handle);
  129. end;
  130. Type PSearchrec = ^Searchrec;
  131. Function FindFirst (Const Path : String; Attr : Longint; Var Rslt : TSearchRec) : Longint;
  132. Var Sr : PSearchrec;
  133. begin
  134. //!! Sr := New(PSearchRec);
  135. getmem(sr,sizeof(searchrec));
  136. Rslt.FindHandle := longint(Sr);
  137. DOS.FindFirst(Path, Attr, Sr^);
  138. result := -DosError;
  139. if result = 0 then begin
  140. Rslt.Time := Sr^.Time;
  141. Rslt.Size := Sr^.Size;
  142. Rslt.Attr := Sr^.Attr;
  143. Rslt.ExcludeAttr := 0;
  144. Rslt.Name := Sr^.Name;
  145. end ;
  146. end;
  147. Function FindNext (Var Rslt : TSearchRec) : Longint;
  148. var Sr: PSearchRec;
  149. begin
  150. Sr := PSearchRec(Rslt.FindHandle);
  151. if Sr <> nil then begin
  152. DOS.FindNext(Sr^);
  153. result := -DosError;
  154. if result = 0 then begin
  155. Rslt.Time := Sr^.Time;
  156. Rslt.Size := Sr^.Size;
  157. Rslt.Attr := Sr^.Attr;
  158. Rslt.ExcludeAttr := 0;
  159. Rslt.Name := Sr^.Name;
  160. end ;
  161. end ;
  162. end;
  163. Procedure FindClose (Var F : TSearchrec);
  164. var Sr: PSearchRec;
  165. begin
  166. Sr := PSearchRec(F.FindHandle);
  167. if Sr <> nil then
  168. //!! Dispose(Sr);
  169. freemem(sr,sizeof(searchrec));
  170. F.FindHandle := 0;
  171. end;
  172. Function FileGetDate (Handle : Longint) : Longint;
  173. var Regs: registers;
  174. begin
  175. //!! for win95 an alternative function is available.
  176. Regs.Ebx := Handle;
  177. Regs.Eax := $5700;
  178. RealIntr($21, Regs);
  179. if Regs.Flags and CarryFlag <> 0 then result := -Regs.Ax
  180. else begin
  181. LongRec(result).Lo := Regs.cx;
  182. LongRec(result).Hi := Regs.dx;
  183. end ;
  184. end;
  185. Function FileSetDate (Handle, Age : Longint) : Longint;
  186. var Regs: registers;
  187. begin
  188. Regs.Ebx := Handle;
  189. Regs.Eax := $5701;
  190. Regs.Ecx := Lo(Age);
  191. Regs.Edx := Hi(Age);
  192. RealIntr($21, Regs);
  193. if Regs.Flags and CarryFlag <> 0 then result := -Regs.Ax
  194. else result := 0;
  195. end;
  196. Function FileGetAttr (Const FileName : String) : Longint;
  197. var Regs: registers;
  198. begin
  199. StringToTB(FileName);
  200. Regs.Edx := tb_offset;
  201. Regs.Ds := tb_segment;
  202. if LFNSupport then
  203. begin
  204. Regs.Ax := $7143;
  205. Regs.Bx := 0;
  206. end
  207. else
  208. Regs.Ax := $4300;
  209. RealIntr($21, Regs);
  210. if Regs.Flags and CarryFlag <> 0 then
  211. result := -1
  212. else
  213. result := Regs.Cx;
  214. end;
  215. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  216. var Regs: registers;
  217. begin
  218. StringToTB(FileName);
  219. Regs.Edx := tb_offset;
  220. Regs.Ds := tb_segment;
  221. if LFNSupport then
  222. begin
  223. Regs.Ax := $7143;
  224. Regs.Bx := 1;
  225. end
  226. else
  227. Regs.Ax := $4301;
  228. Regs.Cx := Attr;
  229. RealIntr($21, Regs);
  230. if Regs.Flags and CarryFlag <> 0 then result := -Regs.Ax
  231. else result := 0;
  232. end;
  233. Function DeleteFile (Const FileName : String) : Boolean;
  234. var Regs: registers;
  235. begin
  236. StringToTB(FileName);
  237. Regs.Edx := tb_offset;
  238. Regs.Ds := tb_segment;
  239. if LFNSupport then
  240. Regs.Eax := $7141
  241. else
  242. Regs.Eax := $4100;
  243. Regs.Esi := 0;
  244. Regs.Ecx := 0;
  245. RealIntr($21, Regs);
  246. result := (Regs.Flags and CarryFlag = 0);
  247. end;
  248. Function RenameFile (Const OldName, NewName : String) : Boolean;
  249. var Regs: registers;
  250. begin
  251. StringToTB(OldName + #0 + NewName);
  252. Regs.Edx := tb_offset;
  253. Regs.Ds := tb_segment;
  254. Regs.Edi := tb_offset + Length(OldName) + 1;
  255. Regs.Es := tb_segment;
  256. if LFNSupport then
  257. Regs.Eax := $7156
  258. else
  259. Regs.Eax := $5600;
  260. Regs.Ecx := $ff;
  261. RealIntr($21, Regs);
  262. result := (Regs.Flags and CarryFlag = 0);
  263. end;
  264. Function FileSearch (Const Name, DirList : String) : String;
  265. begin
  266. result := DOS.FSearch(Name, DirList);
  267. end;
  268. Procedure GetLocalTime(var SystemTime: TSystemTime);
  269. var Regs: Registers;
  270. begin
  271. Regs.ah := $2C;
  272. RealIntr($21, Regs);
  273. SystemTime.Hour := Regs.Ch;
  274. SystemTime.Minute := Regs.Cl;
  275. SystemTime.Second := Regs.Dh;
  276. SystemTime.MilliSecond := Regs.Dl;
  277. Regs.ah := $2A;
  278. RealIntr($21, Regs);
  279. SystemTime.Year := Regs.Cx;
  280. SystemTime.Month := Regs.Dh;
  281. SystemTime.Day := Regs.Dl;
  282. end ;
  283. { ---------------------------------------------------------------------
  284. Internationalization settings
  285. ---------------------------------------------------------------------}
  286. { Codepage constants }
  287. const
  288. CP_US = 437;
  289. CP_MultiLingual = 850;
  290. CP_SlavicLatin2 = 852;
  291. CP_Turkish = 857;
  292. CP_Portugal = 860;
  293. CP_IceLand = 861;
  294. CP_Canada = 863;
  295. CP_NorwayDenmark = 865;
  296. { CountryInfo }
  297. type
  298. TCountryInfo = packed record
  299. InfoId: byte;
  300. case integer of
  301. 1: ( Size: word;
  302. CountryId: word;
  303. CodePage: word;
  304. CountryInfo: array[0..33] of byte );
  305. 2: ( UpperCaseTable: longint );
  306. 4: ( FilenameUpperCaseTable: longint );
  307. 5: ( FilecharacterTable: longint );
  308. 6: ( CollatingTable: longint );
  309. 7: ( DBCSLeadByteTable: longint );
  310. end ;
  311. procedure GetExtendedCountryInfo(InfoId: integer; CodePage, CountryId: word; var CountryInfo: TCountryInfo);
  312. Var Regs: Registers;
  313. begin
  314. Regs.AH := $65;
  315. Regs.AL := InfoId;
  316. Regs.BX := CodePage;
  317. Regs.DX := CountryId;
  318. Regs.ES := transfer_buffer div 16;
  319. Regs.DI := transfer_buffer and 15;
  320. Regs.CX := SizeOf(TCountryInfo);
  321. RealIntr($21, Regs);
  322. DosMemGet(transfer_buffer div 16,
  323. transfer_buffer and 15,
  324. CountryInfo, Regs.CX );
  325. end;
  326. procedure InitAnsi;
  327. var CountryInfo: TCountryInfo; i: integer;
  328. begin
  329. { Fill table entries 0 to 127 }
  330. for i := 0 to 96 do
  331. UpperCaseTable[i] := chr(i);
  332. for i := 97 to 122 do
  333. UpperCaseTable[i] := chr(i - 32);
  334. for i := 123 to 127 do
  335. UpperCaseTable[i] := chr(i);
  336. for i := 0 to 64 do
  337. LowerCaseTable[i] := chr(i);
  338. for i := 65 to 90 do
  339. LowerCaseTable[i] := chr(i + 32);
  340. for i := 91 to 255 do
  341. LowerCaseTable[i] := chr(i);
  342. { Get country and codepage info }
  343. GetExtendedCountryInfo(1, $FFFF, $FFFF, CountryInfo);
  344. if CountryInfo.CodePage = 850 then
  345. begin
  346. { Special, known case }
  347. Move(CP850UCT, UpperCaseTable[128], 128);
  348. Move(CP850LCT, LowerCaseTable[128], 128);
  349. end
  350. else
  351. begin
  352. { this needs to be checked !!
  353. this is correct only if UpperCaseTable is
  354. and Offset:Segment word record (PM) }
  355. { get the uppercase table from dosmemory }
  356. GetExtendedCountryInfo(2, $FFFF, $FFFF, CountryInfo);
  357. DosMemGet(CountryInfo.UpperCaseTable shr 16, 2 + CountryInfo.UpperCaseTable and 65535, UpperCaseTable[128], 128);
  358. for i := 128 to 255 do
  359. begin
  360. if UpperCaseTable[i] <> chr(i) then
  361. LowerCaseTable[ord(UpperCaseTable[i])] := chr(i);
  362. end;
  363. end;
  364. end;
  365. Procedure InitInternational;
  366. { This routine is called by the unit startup code. }
  367. begin
  368. { Init upper/lowercase tables }
  369. InitAnsi
  370. end;
  371. {
  372. $Log$
  373. Revision 1.10 2000-01-07 16:41:31 daniel
  374. * copyright 2000
  375. Revision 1.9 1999/11/25 15:55:52 pierre
  376. * web bug 716
  377. Revision 1.8 1999/08/26 11:02:50 peter
  378. * findclose freemem fixed
  379. Revision 1.7 1999/08/24 13:14:28 peter
  380. * fixed DeleteFile()
  381. Revision 1.6 1999/08/19 14:00:08 pierre
  382. * bug in country info code fixed
  383. Revision 1.5 1999/02/28 13:18:12 michael
  384. + Added internationalization support
  385. Revision 1.4 1999/02/24 15:57:28 michael
  386. + Moved getlocaltime to system-dependent files
  387. Revision 1.3 1999/02/09 17:16:59 florian
  388. + typinfo is now also in the makefile for go32v2
  389. + sysutils.filetruncate for go32v2
  390. Revision 1.2 1999/02/03 11:42:31 michael
  391. + Added filetruncate
  392. Revision 1.1 1998/12/21 13:07:02 peter
  393. * use -FE
  394. Revision 1.4 1998/10/29 13:16:19 michael
  395. * Fix for fileseek by gertjan schouten
  396. Revision 1.3 1998/10/15 09:39:13 michael
  397. Changes from Gretjan Schouten
  398. Revision 1.2 1998/10/12 08:02:16 michael
  399. wrong file committed
  400. Revision 1.1 1998/10/11 12:21:01 michael
  401. Added file calls. Implemented for linux only
  402. }