filutil.inc 12 KB

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