sysfile.inc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2001 by Free Pascal development team
  4. Low leve file functions
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { Keep Track of open files }
  12. const
  13. max_files = 50;
  14. var
  15. openfiles : array [0..max_files-1] of boolean;
  16. {$ifdef SYSTEMDEBUG}
  17. opennames : array [0..max_files-1] of pchar;
  18. const
  19. free_closed_names : boolean = true;
  20. verbose_files : boolean = true;
  21. { we cannot allocate memory using SysGetMem, as we use tinyheap code,
  22. but tinyheap.inc source in inserted later, so we need a forward declaration }
  23. {$endif SYSTEMDEBUG}
  24. {****************************************************************************
  25. Low level File Routines
  26. ****************************************************************************}
  27. procedure do_close(handle : thandle);
  28. var
  29. regs : Registers;
  30. begin
  31. if Handle<=4 then
  32. exit;
  33. regs.BX:=handle;
  34. if handle<max_files then
  35. begin
  36. {$ifdef SYSTEMDEBUG}
  37. if not openfiles[handle] then
  38. Writeln(stderr,'Trying to close file h=',handle,' marked as closed');
  39. if assigned(opennames[handle]) and free_closed_names then
  40. begin
  41. if verbose_files then
  42. Writeln(stderr,'file ',opennames[handle],' closed');
  43. systinyfreememsize(opennames[handle],strlen(opennames[handle])+1);
  44. opennames[handle]:=nil;
  45. end;
  46. {$endif SYSTEMDEBUG}
  47. openfiles[handle]:=false;
  48. end;
  49. regs.AX:=$3e00;
  50. MsDos(regs);
  51. if (regs.Flags and fCarry) <> 0 then
  52. begin
  53. GetInOutRes(regs.AX);
  54. {$ifdef SYSTEMDEBUG}
  55. if verbose_files then
  56. Writeln(stderr,'file close failed AX= ',regs.AX);
  57. {$endif SYSTEMDEBUG}
  58. end;
  59. end;
  60. procedure do_erase(p : pchar; pchangeable: boolean);
  61. var
  62. regs : Registers;
  63. oldp : pchar;
  64. begin
  65. oldp:=p;
  66. DoDirSeparators(p,pchangeable);
  67. regs.DX:=Ofs(p^);
  68. regs.DS:=Seg(p^);
  69. {$ifndef RTLLITE}
  70. if LFNSupport then
  71. regs.AX:=$7141
  72. else
  73. {$endif ndef RTLLITE}
  74. regs.AX:=$4100;
  75. regs.SI:=0;
  76. regs.CX:=0;
  77. MsDos(regs);
  78. if (regs.Flags and fCarry) <> 0 then
  79. GetInOutRes(regs.AX);
  80. if p<>oldp then
  81. freemem(p);
  82. end;
  83. procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
  84. var
  85. regs : Registers;
  86. oldp1, oldp2 : pchar;
  87. begin
  88. oldp1:=p1;
  89. oldp2:=p2;
  90. DoDirSeparators(p1,p1changeable);
  91. DoDirSeparators(p2,p2changeable);
  92. regs.DS:=Seg(p1^);
  93. regs.DX:=Ofs(p1^);
  94. regs.ES:=Seg(p2^);
  95. regs.DI:=Ofs(p2^);
  96. {$ifndef RTLLITE}
  97. if LFNSupport then
  98. regs.AX:=$7156
  99. else
  100. {$endif ndef RTLLITE}
  101. regs.AX:=$5600;
  102. regs.CX:=$ff; { attribute problem here ! }
  103. MsDos(regs);
  104. if (regs.Flags and fCarry) <> 0 then
  105. GetInOutRes(regs.AX);
  106. if p1<>oldp1 then
  107. freemem(p1);
  108. if p2<>oldp2 then
  109. freemem(p2);
  110. end;
  111. function do_write(h:thandle;addr:pointer;len : longint) : longint;
  112. var
  113. regs: Registers;
  114. begin
  115. regs.AH := $40;
  116. regs.BX := h;
  117. regs.CX := len;
  118. regs.DS := Seg(addr^);
  119. regs.DX := Ofs(addr^);
  120. MsDos(regs);
  121. if (regs.Flags and fCarry) <> 0 then
  122. begin
  123. GetInOutRes(regs.AX);
  124. exit(0);
  125. end;
  126. do_write := regs.AX;
  127. end;
  128. function do_read(h:thandle;addr:pointer;len : longint) : longint;
  129. var
  130. regs: Registers;
  131. begin
  132. regs.AH := $3F;
  133. regs.BX := h;
  134. regs.CX := len;
  135. regs.DS := Seg(addr^);
  136. regs.DX := Ofs(addr^);
  137. MsDos(regs);
  138. if (regs.Flags and fCarry) <> 0 then
  139. begin
  140. GetInOutRes(regs.AX);
  141. exit(0);
  142. end;
  143. do_read := regs.AX;
  144. end;
  145. function do_filepos(handle : thandle) : longint;
  146. var
  147. regs : Registers;
  148. begin
  149. regs.BX:=handle;
  150. regs.CX:=0;
  151. regs.DX:=0;
  152. regs.AX:=$4201;
  153. MsDos(regs);
  154. if (regs.Flags and fCarry) <> 0 then
  155. Begin
  156. GetInOutRes(regs.AX);
  157. do_filepos:=0;
  158. end
  159. else
  160. do_filepos:=(longint(regs.DX) shl 16) + regs.AX;
  161. end;
  162. procedure do_seek(handle:thandle;pos : longint);
  163. var
  164. regs : Registers;
  165. begin
  166. regs.BX:=handle;
  167. regs.CX:=pos shr 16;
  168. regs.DX:=pos and $ffff;
  169. regs.AX:=$4200;
  170. MsDos(regs);
  171. if (regs.Flags and fCarry) <> 0 then
  172. GetInOutRes(regs.AX);
  173. end;
  174. function do_seekend(handle:thandle):longint;
  175. var
  176. regs : Registers;
  177. begin
  178. regs.BX:=handle;
  179. regs.CX:=0;
  180. regs.DX:=0;
  181. regs.AX:=$4202;
  182. MsDos(regs);
  183. if (regs.Flags and fCarry) <> 0 then
  184. Begin
  185. GetInOutRes(regs.AX);
  186. do_seekend:=0;
  187. end
  188. else
  189. do_seekend:=(longint(regs.DX) shl 16) + regs.AX;
  190. end;
  191. function do_filesize(handle : thandle) : longint;
  192. var
  193. aktfilepos : longint;
  194. begin
  195. aktfilepos:=do_filepos(handle);
  196. do_filesize:=do_seekend(handle);
  197. do_seek(handle,aktfilepos);
  198. end;
  199. { truncate at a given position }
  200. procedure do_truncate (handle:thandle;pos:longint);
  201. var
  202. regs : Registers;
  203. begin
  204. do_seek(handle,pos);
  205. regs.CX:=0;
  206. regs.BX:=handle;
  207. regs.AX:=$4000;
  208. MsDos(regs);
  209. if (regs.Flags and fCarry) <> 0 then
  210. GetInOutRes(regs.AX);
  211. end;
  212. const
  213. FileHandleCount : word = 20;
  214. function Increase_file_handle_count : boolean;
  215. var
  216. regs : Registers;
  217. begin
  218. Inc(FileHandleCount,10);
  219. regs.BX:=FileHandleCount;
  220. regs.AX:=$6700;
  221. MsDos(regs);
  222. if (regs.Flags and fCarry) <> 0 then
  223. begin
  224. Increase_file_handle_count:=false;
  225. Dec (FileHandleCount, 10);
  226. end
  227. else
  228. Increase_file_handle_count:=true;
  229. end;
  230. procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
  231. {
  232. filerec and textrec have both handle and mode as the first items so
  233. they could use the same routine for opening/creating.
  234. when (flags and $100) the file will be append
  235. when (flags and $1000) the file will be truncate/rewritten
  236. when (flags and $10000) there is no check for close (needed for textfiles)
  237. }
  238. var
  239. regs : Registers;
  240. action : word;
  241. oldp : pchar;
  242. begin
  243. {$ifdef SYSTEMDEBUG}
  244. if verbose_files then
  245. Writeln(stderr,'do_open for file "',p,'" called');
  246. {$endif SYSTEMDEBUG}
  247. { close first if opened }
  248. if ((flags and $10000)=0) then
  249. begin
  250. case filerec(f).mode of
  251. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  252. fmclosed : ;
  253. else
  254. begin
  255. inoutres:=102; {not assigned}
  256. exit;
  257. end;
  258. end;
  259. end;
  260. { reset file handle }
  261. filerec(f).handle:=UnusedHandle;
  262. action:=$1;
  263. { convert filemode to filerec modes }
  264. case (flags and 3) of
  265. 0 : filerec(f).mode:=fminput;
  266. 1 : filerec(f).mode:=fmoutput;
  267. 2 : filerec(f).mode:=fminout;
  268. end;
  269. if (flags and $1000)<>0 then
  270. action:=$12; {create file function}
  271. { empty name is special }
  272. if p[0]=#0 then
  273. begin
  274. case FileRec(f).mode of
  275. fminput :
  276. FileRec(f).Handle:=StdInputHandle;
  277. fminout, { this is set by rewrite }
  278. fmoutput :
  279. FileRec(f).Handle:=StdOutputHandle;
  280. fmappend :
  281. begin
  282. FileRec(f).Handle:=StdOutputHandle;
  283. FileRec(f).mode:=fmoutput; {fool fmappend}
  284. end;
  285. end;
  286. exit;
  287. end;
  288. oldp:=p;
  289. DoDirSeparators(p,pchangeable);
  290. {$ifndef RTLLITE}
  291. if LFNSupport then
  292. begin
  293. regs.AX := $716c; { Use LFN Open/Create API }
  294. regs.DX := action; { action if file does/doesn't exist }
  295. regs.SI := Ofs(p^);
  296. regs.BX := $2000 + (flags and $ff); { file open mode }
  297. end
  298. else
  299. {$endif RTLLITE}
  300. begin
  301. if (action and $00f0) <> 0 then
  302. regs.AX := $3c00 { Map to Create/Replace API }
  303. else
  304. regs.AX := $3d00 + (flags and $ff); { Map to Open_Existing API }
  305. regs.DX := Ofs(p^);
  306. end;
  307. regs.DS := Seg(p^);
  308. regs.CX := $20; { file attributes }
  309. MsDos(regs);
  310. {$ifndef RTLLITE}
  311. if (regs.Flags and fCarry) <> 0 then
  312. if regs.AX=4 then
  313. if Increase_file_handle_count then
  314. begin
  315. { Try again }
  316. if LFNSupport then
  317. begin
  318. regs.AX := $716c; {Use LFN Open/Create API}
  319. regs.DX := action; {action if file does/doesn't exist}
  320. regs.SI := Ofs(p^);
  321. regs.BX := $2000 + (flags and $ff); {file open mode}
  322. end
  323. else
  324. begin
  325. if (action and $00f0) <> 0 then
  326. regs.AX := $3c00 {Map to Create/Replace API}
  327. else
  328. regs.AX := $3d00 + (flags and $ff); {Map to Open API}
  329. regs.DX := Ofs(p^);
  330. end;
  331. regs.DS := Seg(p^);
  332. regs.CX := $20; {file attributes}
  333. MsDos(regs);
  334. end;
  335. {$endif RTLLITE}
  336. if (regs.Flags and fCarry) <> 0 then
  337. begin
  338. FileRec(f).mode:=fmclosed;
  339. GetInOutRes(regs.AX);
  340. if oldp<>p then
  341. freemem(p);
  342. {$ifdef SYSTEMDEBUG}
  343. if verbose_files then
  344. Writeln(stderr,'MSDOS INT open for file "',p,'" failed err=',regs.AX);
  345. {$endif SYSTEMDEBUG}
  346. exit;
  347. end
  348. else
  349. begin
  350. filerec(f).handle:=regs.AX;
  351. {$ifndef RTLLITE}
  352. { for systems that have more then 20 by default ! }
  353. if regs.AX>FileHandleCount then
  354. FileHandleCount:=regs.AX;
  355. {$endif RTLLITE}
  356. end;
  357. {$ifdef SYSTEMDEBUG}
  358. if verbose_files then
  359. Writeln(stderr,'MSDOS INT open for file "',p,'" returned ',regs.AX);
  360. {$endif SYSTEMDEBUG}
  361. if regs.AX<max_files then
  362. begin
  363. {$ifdef SYSTEMDEBUG}
  364. if openfiles[regs.AX] and
  365. assigned(opennames[regs.AX]) then
  366. begin
  367. Writeln(stderr,'file ',opennames[regs.AX],'(',regs.AX,') not closed but handle reused!');
  368. systinyfreememsize(opennames[regs.AX],strlen(opennames[regs.AX])+1);
  369. end;
  370. {$endif SYSTEMDEBUG}
  371. openfiles[regs.AX]:=true;
  372. {$ifdef SYSTEMDEBUG}
  373. opennames[regs.AX] := systinygetmem(strlen(p)+1);
  374. move(p^,opennames[regs.AX]^,strlen(p)+1);
  375. if verbose_files then
  376. Writeln(stderr,'file ',opennames[regs.AX],' opened');
  377. {$endif SYSTEMDEBUG}
  378. end;
  379. { append mode }
  380. if ((flags and $100) <> 0) and
  381. (FileRec (F).Handle <> UnusedHandle) then
  382. begin
  383. do_seekend(filerec(f).handle);
  384. filerec(f).mode:=fmoutput; {fool fmappend}
  385. end;
  386. if oldp<>p then
  387. freemem(p);
  388. end;
  389. function do_isdevice(handle:THandle):boolean;
  390. var
  391. regs: Registers;
  392. begin
  393. regs.AX := $4400;
  394. regs.BX := handle;
  395. MsDos(regs);
  396. do_isdevice := (regs.DL and $80) <> 0;
  397. if (regs.Flags and fCarry) <> 0 then
  398. GetInOutRes(regs.AX);
  399. end;