sysfile.inc 12 KB

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