sysfile.inc 11 KB

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