filutil.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  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. {This is the correct way to call external assembler procedures.}
  13. procedure syscall;external name '___SYSCALL';
  14. const
  15. ofRead = $0000; {Open for reading}
  16. ofWrite = $0001; {Open for writing}
  17. ofReadWrite = $0002; {Open for reading/writing}
  18. faCreateNew = $00010000; {Create if file does not exist}
  19. faOpenReplace = $00040000; {Truncate if file exists}
  20. faCreate = $00050000; {Create if file does not exist, truncate otherwise}
  21. {$ASMMODE INTEL}
  22. function FileOpen (const FileName: string; Mode: integer): longint;
  23. {$IFOPT H+}
  24. assembler;
  25. {$ELSE}
  26. var FN: string;
  27. begin
  28. FN := FileName + #0;
  29. (* DenyAll if sharing not specified. *)
  30. if Mode and 112 = 0 then
  31. Mode := Mode or 16;
  32. {$ENDIF}
  33. asm
  34. mov eax, 7F2Bh
  35. mov ecx, Mode
  36. {$IFOPT H+}
  37. mov edx, FileName
  38. {$ELSE}
  39. lea edx, FN
  40. inc edx
  41. {$ENDIF}
  42. call syscall
  43. {$IFOPT H-}
  44. mov [ebp - 4], eax
  45. end;
  46. {$ENDIF}
  47. end;
  48. function FileCreate (const FileName: string): longint;
  49. {$IFOPT H+}
  50. assembler;
  51. {$ELSE}
  52. var FN: string;
  53. begin
  54. FN := FileName + #0;
  55. (* DenyAll if sharing not specified. *)
  56. if Mode and 112 = 0 then
  57. Mode := Mode or 16;
  58. {$ENDIF}
  59. asm
  60. mov eax, 7F2Bh
  61. mov ecx, ofReadWrite or faCreate
  62. {$IFOPT H+}
  63. mov edx, FileName
  64. {$ELSE}
  65. lea edx, FN
  66. inc edx
  67. {$ENDIF}
  68. call syscall
  69. {$IFOPT H-}
  70. mov [ebp - 4], eax
  71. end;
  72. {$ENDIF}
  73. end;
  74. function FileRead (Handle: longint; var Buffer; Count: longint): longint;
  75. assembler;
  76. asm
  77. mov eax, 3F00h
  78. mov ebx, Handle
  79. mov ecx, Count
  80. mov edx, Buffer
  81. call syscall
  82. jnc @FReadEnd
  83. mov eax, -1
  84. @FReadEnd:
  85. end;
  86. function FileWrite (Handle: longint; const Buffer; Count: longint): longint;
  87. assembler;
  88. asm
  89. mov eax, 4000h
  90. mov ebx, Handle
  91. mov ecx, Count
  92. mov edx, Buffer
  93. call syscall
  94. jnc @FWriteEnd
  95. mov eax, -1
  96. @FWriteEnd:
  97. end;
  98. function FileSeek (Handle, FOffset, Origin: longint): longint; assembler;
  99. asm
  100. mov eax, Origin
  101. mov ah, 42h
  102. mov ebx, Handle
  103. mov edx, FOffset
  104. call syscall
  105. jnc @FSeekEnd
  106. mov eax, -1
  107. @FSeekEnd:
  108. end;
  109. procedure FileClose (Handle: longint);
  110. begin
  111. if (Handle <= 4) or (os_mode = osOS2) and (Handle <= 2) then
  112. asm
  113. mov eax, 3E00h
  114. mov ebx, Handle
  115. call syscall
  116. end;
  117. end;
  118. function FileTruncate (Handle, Size: longint): boolean; assembler;
  119. asm
  120. mov eax, 7F25h
  121. mov ebx, Handle
  122. mov edx, Size
  123. call syscall
  124. jc @FTruncEnd
  125. mov eax, 4202h
  126. mov ebx, Handle
  127. mov edx, 0
  128. call syscall
  129. mov eax, 0
  130. jnc @FTruncEnd
  131. dec eax
  132. @FTruncEnd:
  133. end;
  134. function FileAge (const FileName: string): longint;
  135. var Handle: longint;
  136. begin
  137. Handle := FileOpen (FileName, 0);
  138. if Handle <> -1 then
  139. begin
  140. Result := FileGetDate (Handle);
  141. FileClose (Handle);
  142. end
  143. else
  144. Result := -1;
  145. end;
  146. function FileExists (const FileName: string): boolean;
  147. {$IFOPT H+}
  148. assembler;
  149. {$ELSE}
  150. var FN: string;
  151. begin
  152. FN := FileName + #0;
  153. {$ENDIF}
  154. asm
  155. mov ax, 4300h
  156. {$IFOPT H+}
  157. mov edx, FileName
  158. {$ELSE}
  159. lea edx, FN
  160. inc edx
  161. {$ENDIF}
  162. call syscall
  163. mov eax, 0
  164. jc @FExistsEnd
  165. test cx, 18h
  166. jnz @FExistsEnd
  167. inc eax
  168. @FExistsEnd:
  169. {$IFOPT H-}
  170. end;
  171. {$ENDIF}
  172. end;
  173. type TRec = record
  174. T, D: word;
  175. end;
  176. PSearchRec = ^SearchRec;
  177. function FindFirst (const Path: string; Attr: longint; var Rslt: TSearchRec): longint;
  178. var SR: PSearchRec;
  179. FStat: PFileFindBuf3;
  180. Count: longint;
  181. Err: longint;
  182. begin
  183. if os_mode = osOS2 then
  184. begin
  185. New (FStat);
  186. Rslt.FindHandle := $FFFFFFFF;
  187. Count := 1;
  188. Err := DosFindFirst (Path, Rslt.FindHandle, Attr, FStat,
  189. SizeOf (FStat^), Count, ilStandard);
  190. if (Err = 0) and (Count = 0) then Err := 18;
  191. FindFirst := -Err;
  192. if Err = 0 then
  193. begin
  194. Rslt.Name := FStat^.Name;
  195. Rslt.Size := FStat^.FileSize;
  196. Rslt.Attr := FStat^.AttrFile;
  197. Rslt.ExcludeAttr := 0;
  198. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  199. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  200. end;
  201. Dispose (FStat);
  202. end
  203. else
  204. begin
  205. GetMem (SR, SizeOf (SearchRec));
  206. Rslt.FindHandle := longint(SR);
  207. DOS.FindFirst (Path, Attr, SR^);
  208. FindFirst := -DosError;
  209. if DosError = 0 then
  210. begin
  211. Rslt.Time := SR^.Time;
  212. Rslt.Size := SR^.Size;
  213. Rslt.Attr := SR^.Attr;
  214. Rslt.ExcludeAttr := 0;
  215. Rslt.Name := SR^.Name;
  216. end;
  217. end;
  218. end;
  219. function FindNext (var Rslt: TSearchRec): longint;
  220. var SR: PSearchRec;
  221. FStat: PFileFindBuf3;
  222. Count: longint;
  223. Err: longint;
  224. begin
  225. if os_mode = osOS2 then
  226. begin
  227. New (FStat);
  228. Count := 1;
  229. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat), Count);
  230. if (Err = 0) and (Count = 0) then Err := 18;
  231. FindNext := -Err;
  232. if Err = 0 then
  233. begin
  234. Rslt.Name := FStat^.Name;
  235. Rslt.Size := FStat^.FileSize;
  236. Rslt.Attr := FStat^.AttrFile;
  237. Rslt.ExcludeAttr := 0;
  238. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  239. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  240. end;
  241. Dispose (FStat);
  242. end
  243. else
  244. begin
  245. SR := PSearchRec (Rslt.FindHandle);
  246. if SR <> nil then
  247. begin
  248. DOS.FindNext (SR^);
  249. FindNext := -DosError;
  250. if DosError = 0 then
  251. begin
  252. Rslt.Time := SR^.Time;
  253. Rslt.Size := SR^.Size;
  254. Rslt.Attr := SR^.Attr;
  255. Rslt.ExcludeAttr := 0;
  256. Rslt.Name := SR^.Name;
  257. end;
  258. end;
  259. end;
  260. end;
  261. procedure FindClose (var F: TSearchrec);
  262. var SR: PSearchRec;
  263. begin
  264. if os_mode = osOS2 then
  265. begin
  266. DosFindClose (F.FindHandle);
  267. end
  268. else
  269. begin
  270. DOS.FindClose (SR^);
  271. FreeMem (SR, SizeOf (SearchRec));
  272. end;
  273. F.FindHandle := 0;
  274. end;
  275. function FileGetDate (Handle: longint): longint; assembler;
  276. asm
  277. mov ax, 5700h
  278. mov ebx, Handle
  279. call syscall
  280. mov eax, -1
  281. jc @FGetDateEnd
  282. mov ax, dx
  283. shld eax, ecx, 16
  284. @FGetDateEnd:
  285. end;
  286. function FileSetDate (Handle, Age: longint): longint;
  287. var FStat: PFileStatus0;
  288. RC: longint;
  289. begin
  290. if os_mode = osOS2 then
  291. begin
  292. New (FStat);
  293. RC := DosQueryFileInfo (Handle, ilStandard, FStat,
  294. SizeOf (FStat^));
  295. if RC <> 0 then
  296. FileSetDate := -1
  297. else
  298. begin
  299. FStat^.DateLastAccess := Hi (Age);
  300. FStat^.DateLastWrite := Hi (Age);
  301. FStat^.TimeLastAccess := Lo (Age);
  302. FStat^.TimeLastWrite := Lo (Age);
  303. RC := DosSetFileInfo (Handle, ilStandard, FStat,
  304. SizeOf (FStat^));
  305. if RC <> 0 then
  306. FileSetDate := -1
  307. else
  308. FileSetDate := 0;
  309. end;
  310. Dispose (FStat);
  311. end
  312. else
  313. asm
  314. mov ax, 5701h
  315. mov ebx, Handle
  316. mov cx, word ptr [Age]
  317. mov dx, word ptr [Age + 2]
  318. call syscall
  319. jnc @FSetDateEnd
  320. mov eax, -1
  321. @FSetDateEnd:
  322. mov [ebp - 4], eax
  323. end;
  324. end;
  325. function FileGetAttr (const FileName: string): longint;
  326. {$IFOPT H+}
  327. assembler;
  328. {$ELSE}
  329. var FN: string;
  330. begin
  331. FN := FileName + #0;
  332. {$ENDIF}
  333. asm
  334. mov ax, 4300h
  335. {$IFOPT H+}
  336. mov edx, FileName
  337. {$ELSE}
  338. lea edx, FN
  339. inc edx
  340. {$ENDIF}
  341. call syscall
  342. jnc @FGetAttrEnd
  343. mov eax, -1
  344. @FGetAttrEnd:
  345. {$IFOPT H-}
  346. mov [ebp - 4], eax
  347. end;
  348. {$ENDIF}
  349. end;
  350. function FileSetAttr (const Filename: string; Attr: longint): longint;
  351. {$IFOPT H+}
  352. assembler;
  353. {$ELSE}
  354. var FN: string;
  355. begin
  356. FN := FileName + #0;
  357. {$ENDIF}
  358. asm
  359. mov ax, 4301h
  360. mov ecx, Attr
  361. {$IFOPT H+}
  362. mov edx, FileName
  363. {$ELSE}
  364. lea edx, FN
  365. inc edx
  366. {$ENDIF}
  367. call syscall
  368. mov eax, 0
  369. jnc @FSetAttrEnd
  370. mov eax, -1
  371. @FSetAttrEnd:
  372. {$IFOPT H-}
  373. mov [ebp - 4], eax
  374. end;
  375. {$ENDIF}
  376. end;
  377. function DeleteFile (const FileName: string): boolean;
  378. {$IFOPT H+}
  379. assembler;
  380. {$ELSE}
  381. var FN: string;
  382. begin
  383. FN := FileName + #0;
  384. {$ENDIF}
  385. asm
  386. mov ax, 4100h
  387. {$IFOPT H+}
  388. mov edx, FileName
  389. {$ELSE}
  390. lea edx, FN
  391. inc edx
  392. {$ENDIF}
  393. call syscall
  394. mov eax, 0
  395. jc @FDeleteEnd
  396. inc eax
  397. @FDeleteEnd:
  398. {$IFOPT H-}
  399. mov [ebp - 4], eax
  400. end;
  401. {$ENDIF}
  402. end;
  403. function RenameFile (const OldName, NewName: string): boolean;
  404. {$IFOPT H+}
  405. assembler;
  406. {$ELSE}
  407. var FN1, FN2: string;
  408. begin
  409. FN1 := OldName + #0;
  410. FN2 := NewName + #0;
  411. {$ENDIF}
  412. asm
  413. mov ax, 5600h
  414. {$IFOPT H+}
  415. mov edx, OldName
  416. mov edi, NewName
  417. {$ELSE}
  418. lea edx, FN1
  419. inc edx
  420. lea edi, FN2
  421. inc edi
  422. {$ENDIF}
  423. call syscall
  424. mov eax, 0
  425. jc @FRenameEnd
  426. inc eax
  427. @FRenameEnd:
  428. {$IFOPT H-}
  429. mov [ebp - 4], eax
  430. end;
  431. {$ENDIF}
  432. end;
  433. function FileSearch (const Name, DirList: string): string;
  434. begin
  435. Result := Dos.FSearch (Name, DirList);
  436. end;
  437. procedure GetLocalTime (var SystemTime: TSystemTime); assembler;
  438. asm
  439. (* Expects the default record alignment (DWord)!!! *)
  440. mov ah, 2Ah
  441. call syscall
  442. mov edi, SystemTime
  443. xor eax, eax
  444. mov ax, cx
  445. stosd
  446. xor eax, eax
  447. mov al, dh
  448. stosd
  449. mov al, dl
  450. stosd
  451. push edi
  452. mov ah, 2Ch
  453. call syscall
  454. pop edi
  455. xor eax, eax
  456. mov al, ch
  457. stosd
  458. mov al, cl
  459. stosd
  460. mov al, dh
  461. stosd
  462. mov al, dl
  463. stosd
  464. end;
  465. procedure InitAnsi;
  466. var I: byte;
  467. Country: TCountryCode;
  468. begin
  469. for I := 0 to 255 do
  470. UpperCaseTable [I] := Chr (I);
  471. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  472. if os_mode = osOS2 then
  473. begin
  474. FillChar (Country, SizeOf (Country), 0);
  475. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  476. end
  477. else
  478. begin
  479. (* !!! TODO: DOS/DPMI mode support!!! *)
  480. end;
  481. for I := 0 to 255 do
  482. if UpperCaseTable [I] <> Chr (I) then
  483. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  484. end;
  485. procedure InitInternational;
  486. var Country: TCountryCode;
  487. CtryInfo: TCountryInfo;
  488. Size: cardinal;
  489. RC: longint;
  490. begin
  491. Size := 0;
  492. FillChar (Country, SizeOf (Country), 0);
  493. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  494. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  495. if RC = 0 then
  496. begin
  497. DateSeparator := CtryInfo.DateSeparator;
  498. case CtryInfo.DateFormat of
  499. 1: begin
  500. ShortDateFormat := 'd/m/y';
  501. LongDateFormat := 'dd" "mmmm" "yyyy';
  502. end;
  503. 2: begin
  504. ShortDateFormat := 'y/m/d';
  505. LongDateFormat := 'yyyy" "mmmm" "dd';
  506. end;
  507. 3: begin
  508. ShortDateFormat := 'm/d/y';
  509. LongDateFormat := 'mmmm" "dd" "yyyy';
  510. end;
  511. end;
  512. TimeSeparator := CtryInfo.TimeSeparator;
  513. DecimalSeparator := CtryInfo.DecimalSeparator;
  514. ThousandSeparator := CtryInfo.ThousandSeparator;
  515. CurrencyFormat := CtryInfo.CurrencyFormat;
  516. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  517. end;
  518. InitAnsi;
  519. end;
  520. {
  521. $Log$
  522. Revision 1.13 2000-07-06 19:03:40 hajny
  523. * filutil.inc implementation (almost) finished
  524. Revision 1.12 2000/06/05 18:57:38 hajny
  525. * handle number check added to FileClose
  526. Revision 1.11 2000/06/04 15:04:22 hajny
  527. * another bunch of corrections
  528. Revision 1.10 2000/06/04 14:22:02 hajny
  529. * minor corrections
  530. Revision 1.9 2000/06/01 18:36:50 hajny
  531. * FileGetDate added
  532. Revision 1.8 2000/05/29 17:59:58 hajny
  533. * FindClose implemented
  534. Revision 1.7 2000/05/28 18:22:58 hajny
  535. + implementation started
  536. Revision 1.6 2000/02/17 22:16:05 sg
  537. * Changed the second argument of FileWrite from "var buffer" to
  538. "const buffer", like in Delphi.
  539. Revision 1.5 2000/02/09 16:59:33 peter
  540. * truncated log
  541. Revision 1.4 2000/01/07 16:41:47 daniel
  542. * copyright 2000
  543. Revision 1.3 1999/11/08 22:45:55 peter
  544. * updated
  545. }