sysfile.inc 11 KB

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