sysfile.inc 8.8 KB

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