sysfile.inc 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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 PAnsiChar;
  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.A := 0;
  32. regs.B := Byte(handle);
  33. if handle < max_files then
  34. begin
  35. {$ifdef SYSTEMDEBUG}
  36. if not openfiles[handle] then
  37. Writeln(stderr,'Trying to close file h=',handle,' marked as closed');
  38. if assigned(opennames[handle]) and free_closed_names then
  39. begin
  40. if verbose_files then
  41. Writeln(stderr,'file ',opennames[handle],' closed');
  42. sysfreememsize(opennames[handle],strlen(opennames[handle])+1);
  43. opennames[handle]:=nil;
  44. end;
  45. {$endif SYSTEMDEBUG}
  46. openfiles[handle]:=false;
  47. end;
  48. regs.C := $45;
  49. MsxDos(regs);
  50. if regs.A <> 0 then
  51. begin
  52. GetInOutRes(regs.A);
  53. {$ifdef SYSTEMDEBUG}
  54. if verbose_files then
  55. Writeln(stderr,'file close failed A = ',regs.A);
  56. {$endif SYSTEMDEBUG}
  57. end;
  58. end;
  59. procedure do_erase(p : PAnsiChar; pchangeable: boolean);
  60. var
  61. regs: Registers;
  62. oldp: PAnsiChar;
  63. begin
  64. oldp := p;
  65. DoDirSeparators(p, pchangeable);
  66. regs.A := 0;
  67. regs.C := $4D;
  68. regs.DE := PtrUInt(p);
  69. MsxDos(regs);
  70. if regs.A <> 0 then
  71. GetInOutRes(regs.A);
  72. if p <> oldp then
  73. freemem(p);
  74. end;
  75. procedure do_rename(p1,p2 : PAnsiChar; p1changeable, p2changeable: boolean);
  76. var
  77. regs: Registers;
  78. oldp1, oldp2: PAnsiChar;
  79. begin
  80. oldp1 := p1;
  81. oldp2 := p2;
  82. DoDirSeparators(p1, p1changeable);
  83. DoDirSeparators(p2, p2changeable);
  84. regs.A := 0;
  85. regs.C := $4E;
  86. { ToDo: check for same directory? }
  87. regs.DE := PtrUInt(p1);
  88. regs.HL := PtrUInt(p2);
  89. MsxDos(regs);
  90. if regs.A <> 0 then
  91. GetInOutRes(regs.A);
  92. if p1 <> oldp1 then
  93. freemem(p1);
  94. if p2 <> oldp2 then
  95. freemem(p2);
  96. end;
  97. function do_write(h:thandle;addr:pointer;len : longint) : longint;
  98. var
  99. regs: Registers;
  100. begin
  101. regs.C := $49;
  102. regs.A := 0;
  103. regs.B := h;
  104. regs.DE := PtrUInt(addr);
  105. regs.HL := len;
  106. MsxDos(regs);
  107. if regs.A <> 0 then
  108. begin
  109. GetInOutRes(regs.A);
  110. exit(0);
  111. end;
  112. do_write := regs.HL;
  113. end;
  114. function do_read(h:thandle;addr:pointer;len : longint) : longint;
  115. var
  116. regs: Registers;
  117. begin
  118. regs.C := $48;
  119. regs.A := 0;
  120. regs.B := h;
  121. regs.DE := PtrUInt(addr);
  122. regs.HL := len;
  123. MsxDos(regs);
  124. if regs.A <> 0 then
  125. begin
  126. GetInOutRes(regs.A);
  127. exit(0);
  128. end;
  129. do_read := regs.HL;
  130. end;
  131. function do_filepos(handle : thandle) : longint;
  132. var
  133. regs : Registers;
  134. begin
  135. regs.C := $4A;
  136. regs.B := handle;
  137. regs.A := 1;
  138. regs.DE := 0;
  139. regs.HL := 0;
  140. MsxDos(regs);
  141. if regs.A <> 0 then
  142. begin
  143. GetInOutRes(regs.A);
  144. do_filepos := 0;
  145. end
  146. else
  147. do_filepos := (longint(regs.DE) shl 16) + regs.HL;
  148. end;
  149. procedure do_seek(handle:thandle;pos : longint);
  150. var
  151. regs: Registers;
  152. begin
  153. regs.C := $4A;
  154. regs.B := handle;
  155. regs.A := 0;
  156. regs.DE := pos shr 16;
  157. regs.HL := pos and $ffff;
  158. MsxDos(regs);
  159. if regs.A <> 0 then
  160. GetInOutRes(regs.A);
  161. end;
  162. function do_seekend(handle:thandle):longint;
  163. var
  164. regs : Registers;
  165. begin
  166. regs.C := $4A;
  167. regs.B := handle;
  168. regs.A := 2;
  169. regs.DE := 0;
  170. regs.HL := 0;
  171. MsxDos(regs);
  172. if regs.A <> 0 then
  173. begin
  174. GetInOutRes(regs.A);
  175. do_seekend := 0;
  176. end
  177. else
  178. do_seekend := (longint(regs.DE) shl 16) + regs.HL;
  179. end;
  180. function do_filesize(handle : thandle) : longint;
  181. var
  182. aktfilepos : longint;
  183. begin
  184. aktfilepos:=do_filepos(handle);
  185. do_filesize:=do_seekend(handle);
  186. do_seek(handle,aktfilepos);
  187. end;
  188. { truncate at a given position }
  189. procedure do_truncate (handle:thandle;pos:longint);
  190. {var
  191. regs : Registers;}
  192. begin
  193. GetInOutRes(153);
  194. {do_seek(handle,pos);
  195. regs.C:=??;
  196. regs.B:=handle;
  197. MsxDos(regs);
  198. if regs.A <> 0 then
  199. GetInOutRes(regs.A);}
  200. end;
  201. procedure do_open(var f;p:PAnsiChar;flags:longint; pchangeable: boolean);
  202. {
  203. filerec and textrec have both handle and mode as the first items so
  204. they could use the same routine for opening/creating.
  205. when (flags and $100) the file will be append
  206. when (flags and $1000) the file will be truncate/rewritten
  207. when (flags and $10000) there is no check for close (needed for textfiles)
  208. }
  209. var
  210. regs : Registers;
  211. action : word;
  212. oldp : PAnsiChar;
  213. begin
  214. {$ifdef SYSTEMDEBUG}
  215. if verbose_files then
  216. Writeln(stderr,'do_open for file "',p,'" called');
  217. {$endif SYSTEMDEBUG}
  218. { close first if opened }
  219. if ((flags and $10000)=0) then
  220. begin
  221. case filerec(f).mode of
  222. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  223. fmclosed : ;
  224. else
  225. begin
  226. inoutres:=102; {not assigned}
  227. exit;
  228. end;
  229. end;
  230. end;
  231. { reset file handle }
  232. filerec(f).handle:=UnusedHandle;
  233. action:=$1;
  234. { convert filemode to filerec modes }
  235. regs.A:=0;
  236. case (flags and 3) of
  237. 0 : begin
  238. filerec(f).mode:=fminput;
  239. { b1 -> no write }
  240. regs.A := 1;
  241. end;
  242. 1 : begin
  243. filerec(f).mode:=fmoutput;
  244. { b2 -> no read }
  245. regs.A := 2;
  246. end;
  247. 2 : filerec(f).mode:=fminout;
  248. end;
  249. if (flags and $1000)<>0 then
  250. action:=$12; {create file function}
  251. { empty name is special }
  252. if p[0]=#0 then
  253. begin
  254. case FileRec(f).mode of
  255. fminput :
  256. FileRec(f).Handle:=StdInputHandle;
  257. fminout, { this is set by rewrite }
  258. fmoutput :
  259. FileRec(f).Handle:=StdOutputHandle;
  260. fmappend :
  261. begin
  262. FileRec(f).Handle:=StdOutputHandle;
  263. FileRec(f).mode:=fmoutput; {fool fmappend}
  264. end;
  265. end;
  266. exit;
  267. end;
  268. oldp:=p;
  269. DoDirSeparators(p,pchangeable);
  270. if (action and $00f0) <> 0 then
  271. regs.C := $44 { Map to Create/Replace API }
  272. else
  273. regs.C := $43; { Map to Open_Existing API }
  274. regs.B := 0;
  275. MsxDos(regs);
  276. if regs.A <> 0 then
  277. begin
  278. FileRec(f).mode:=fmclosed;
  279. GetInOutRes(regs.A);
  280. if oldp<>p then
  281. freemem(p);
  282. {$ifdef SYSTEMDEBUG}
  283. if verbose_files then
  284. Writeln(stderr,'MSXDOS INT open for file "',p,'" failed err=',regs.A);
  285. {$endif SYSTEMDEBUG}
  286. exit;
  287. end
  288. else
  289. begin
  290. filerec(f).handle:=regs.B;
  291. end;
  292. {$ifdef SYSTEMDEBUG}
  293. if verbose_files then
  294. Writeln(stderr,'MSXDOS INT open for file "',p,'" returned ',regs.B);
  295. {$endif SYSTEMDEBUG}
  296. if regs.B<max_files then
  297. begin
  298. {$ifdef SYSTEMDEBUG}
  299. if openfiles[regs.B] and
  300. assigned(opennames[regs.B]) then
  301. begin
  302. Writeln(stderr,'file ',opennames[regs.B],'(',regs.B,') not closed but handle reused!');
  303. sysfreememsize(opennames[regs.B],strlen(opennames[regs.B])+1);
  304. end;
  305. {$endif SYSTEMDEBUG}
  306. openfiles[regs.B]:=true;
  307. {$ifdef SYSTEMDEBUG}
  308. opennames[regs.B] := sysgetmem(strlen(p)+1);
  309. move(p^,opennames[regs.B]^,strlen(p)+1);
  310. if verbose_files then
  311. Writeln(stderr,'file ',opennames[regs.B],' opened');
  312. {$endif SYSTEMDEBUG}
  313. end;
  314. { append mode }
  315. if ((flags and $100) <> 0) and
  316. (FileRec (F).Handle <> UnusedHandle) then
  317. begin
  318. do_seekend(filerec(f).handle);
  319. filerec(f).mode:=fmoutput; {fool fmappend}
  320. end;
  321. if oldp<>p then
  322. freemem(p);
  323. end;
  324. function do_isdevice(handle:THandle):boolean;
  325. var
  326. regs: Registers;
  327. begin
  328. regs.C := $4B;
  329. regs.B := handle;
  330. regs.A := $00;
  331. MsxDos(regs);
  332. do_isdevice := (regs.D and $80) <> 0;
  333. if regs.A <> 0 then
  334. GetInOutRes(regs.A);
  335. end;