sysfile.inc 11 KB

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