sysfile.inc 9.8 KB

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