sysfile.inc 12 KB

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