sysfile.inc 10 KB

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