sysfile.inc 11 KB

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