sysfile.inc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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. {****************************************************************************
  12. Low Level File Routines
  13. ****************************************************************************}
  14. procedure do_close (H: THandle);
  15. begin
  16. { Only three standard handles under real OS/2 }
  17. if (h > 4) or
  18. ((os_MODE = osOS2) and (h > 2)) then
  19. begin
  20. asm
  21. pushl %ebx
  22. movb $0x3e,%ah
  23. movl h,%ebx
  24. call syscall
  25. jnc .Lnoerror { error code? }
  26. movw %ax, InOutRes { yes, then set InOutRes }
  27. .Lnoerror:
  28. popl %ebx
  29. end ['eax'];
  30. end;
  31. end;
  32. procedure do_erase(p:Pchar; pchangeable: boolean);
  33. var
  34. oldp: pchar;
  35. begin
  36. oldp:=p;
  37. DoDirSeparators(p,pchangeable);
  38. asm
  39. movl P,%edx
  40. movb $0x41,%ah
  41. call syscall
  42. jnc .LERASE1
  43. movw %ax,inoutres
  44. .LERASE1:
  45. end ['eax', 'edx'];
  46. if p<>oldp then
  47. freemem(p);
  48. end;
  49. procedure do_rename(p1,p2:Pchar; p1changeable, p2changeable: boolean);
  50. var
  51. oldp1, oldp2 : pchar;
  52. begin
  53. oldp1:=p1;
  54. oldp2:=p2;
  55. DoDirSeparators(p1,p1changeable);
  56. DoDirSeparators(p2,p2changeable);
  57. asm
  58. movl P1, %edx
  59. movl P2, %edi
  60. movb $0x56,%ah
  61. call syscall
  62. jnc .LRENAME1
  63. movw %ax,inoutres
  64. .LRENAME1:
  65. end ['eax', 'edx', 'edi'];
  66. if p1<>oldp1 then
  67. freemem(p1);
  68. if p2<>oldp2 then
  69. freemem(p2);
  70. end;
  71. function do_read (H: THandle; Addr: pointer; Len: longint): longint; assembler;
  72. asm
  73. pushl %ebx
  74. {$IFNDEF REGCALL}
  75. movl len,%ecx
  76. movl addr,%edx
  77. movl %eax,%ebx
  78. {$ELSE REGCALL}
  79. movl h,%ebx
  80. {$ENDIF REGCALL}
  81. movb $0x3f,%ah
  82. call syscall
  83. jnc .LDOSREAD1
  84. movw %ax,inoutres
  85. xorl %eax,%eax
  86. .LDOSREAD1:
  87. popl %ebx
  88. end {['eax', 'ebx', 'ecx', 'edx']};
  89. function do_write (H: THandle; Addr: pointer; Len: longint): longint;
  90. assembler;
  91. asm
  92. pushl %ebx
  93. {$IFDEF REGCALL}
  94. movl %eax,%ebx
  95. {$ENDIF REGCALL}
  96. xorl %eax,%eax
  97. cmpl $0,len { 0 bytes to write is undefined behavior }
  98. jz .LDOSWRITE1
  99. {$IFNDEF REGCALL}
  100. movl len,%ecx
  101. movl addr,%edx
  102. movl h,%ebx
  103. {$ENDIF REGCALL}
  104. movb $0x40,%ah
  105. call syscall
  106. jnc .LDOSWRITE1
  107. movw %ax,inoutres
  108. .LDOSWRITE1:
  109. popl %ebx
  110. end {['eax', 'ebx', 'ecx', 'edx']};
  111. function do_filepos (Handle: THandle): longint; assembler;
  112. asm
  113. pushl %ebx
  114. {$IFDEF REGCALL}
  115. movl %eax,%ebx
  116. {$ELSE REGCALL}
  117. movl handle,%ebx
  118. {$ENDIF REGCALL}
  119. movw $0x4201,%ax
  120. xorl %edx,%edx
  121. call syscall
  122. jnc .LDOSFILEPOS
  123. movw %ax,inoutres
  124. xorl %eax,%eax
  125. .LDOSFILEPOS:
  126. popl %ebx
  127. end {['eax', 'ebx', 'ecx', 'edx']};
  128. procedure do_seek (Handle: THandle; Pos: longint); assembler;
  129. asm
  130. pushl %ebx
  131. {$IFDEF REGCALL}
  132. movl %eax,%ebx
  133. {$ELSE REGCALL}
  134. movl handle,%ebx
  135. movl pos,%edx
  136. {$ENDIF REGCALL}
  137. movw $0x4200,%ax
  138. call syscall
  139. jnc .LDOSSEEK1
  140. movw %ax,inoutres
  141. .LDOSSEEK1:
  142. popl %ebx
  143. end {['eax', 'ebx', 'ecx', 'edx']};
  144. function do_seekend (Handle: THandle): longint; assembler;
  145. asm
  146. pushl %ebx
  147. {$IFDEF REGCALL}
  148. movl %eax,%ebx
  149. {$ELSE REGCALL}
  150. movl handle,%ebx
  151. {$ENDIF REGCALL}
  152. movw $0x4202,%ax
  153. xorl %edx,%edx
  154. call syscall
  155. jnc .Lset_at_end1
  156. movw %ax,inoutres;
  157. xorl %eax,%eax
  158. .Lset_at_end1:
  159. popl %ebx
  160. end {['eax', 'ebx', 'ecx', 'edx']};
  161. function do_filesize (Handle: THandle): longint;
  162. var aktfilepos:longint;
  163. begin
  164. aktfilepos:=do_filepos(handle);
  165. do_filesize:=do_seekend(handle);
  166. do_seek(handle,aktfilepos);
  167. end;
  168. procedure do_truncate (Handle: THandle; Pos: longint); assembler;
  169. asm
  170. pushl %ebx
  171. (* DOS function 40h isn't safe for this according to EMX documentation *)
  172. {$IFDEF REGCALL}
  173. movl %eax,%ebx
  174. pushl %eax
  175. {$ELSE REGCALL}
  176. movl Handle,%ebx
  177. movl Pos,%edx
  178. {$ENDIF REGCALL}
  179. movl $0x7F25,%eax
  180. call syscall
  181. incl %eax
  182. movl %ecx, %eax
  183. {$IFDEF REGCALL}
  184. popl %ebx
  185. {$ENDIF REGCALL}
  186. jnz .LTruncate1 { compare the value of EAX to verify error }
  187. (* File position is undefined after truncation, move to the end. *)
  188. movl $0x4202,%eax
  189. {$IFNDEF REGCALL}
  190. movl Handle,%ebx
  191. {$ENDIF REGCALL}
  192. movl $0,%edx
  193. call syscall
  194. jnc .LTruncate2
  195. .LTruncate1:
  196. movw %ax,inoutres
  197. .LTruncate2:
  198. popl %ebx
  199. end {['eax', 'ebx', 'ecx', 'edx']};
  200. const
  201. FileHandleCount: cardinal = 20;
  202. function Increase_File_Handle_Count: boolean;
  203. var Err: word;
  204. L1: longint;
  205. L2: cardinal;
  206. begin
  207. if os_mode = osOS2 then
  208. begin
  209. L1 := 10;
  210. if DosSetRelMaxFH (L1, L2) <> 0 then
  211. Increase_File_Handle_Count := false
  212. else
  213. if L2 > FileHandleCount then
  214. begin
  215. FileHandleCount := L2;
  216. Increase_File_Handle_Count := true;
  217. end
  218. else
  219. Increase_File_Handle_Count := false;
  220. end
  221. else
  222. begin
  223. Inc (FileHandleCount, 10);
  224. Err := 0;
  225. asm
  226. pushl %ebx
  227. movl $0x6700, %eax
  228. movl FileHandleCount, %ebx
  229. call syscall
  230. jnc .LIncFHandles
  231. movw %ax, Err
  232. .LIncFHandles:
  233. popl %ebx
  234. end ['eax'];
  235. if Err <> 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. end;
  244. procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
  245. {
  246. filerec and textrec have both handle and mode as the first items so
  247. they could use the same routine for opening/creating.
  248. when (flags and $100) the file will be append
  249. when (flags and $1000) the file will be truncate/rewritten
  250. when (flags and $10000) there is no check for close (needed for textfiles)
  251. }
  252. var
  253. Action: cardinal;
  254. oldp : pchar;
  255. begin
  256. { close first if opened }
  257. if ((flags and $10000)=0) then
  258. begin
  259. case filerec(f).mode of
  260. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  261. fmclosed:;
  262. else
  263. begin
  264. inoutres:=102; {not assigned}
  265. exit;
  266. end;
  267. end;
  268. end;
  269. { reset file handle }
  270. filerec(f).handle := UnusedHandle;
  271. Action := 0;
  272. { convert filemode to filerec modes }
  273. case (flags and 3) of
  274. 0 : filerec(f).mode:=fminput;
  275. 1 : filerec(f).mode:=fmoutput;
  276. 2 : filerec(f).mode:=fminout;
  277. end;
  278. if (flags and $1000)<>0 then
  279. Action := $50000; (* Create / replace *)
  280. { empty name is special }
  281. if p[0]=#0 then
  282. begin
  283. case FileRec(f).mode of
  284. fminput :
  285. FileRec(f).Handle:=StdInputHandle;
  286. fminout, { this is set by rewrite }
  287. fmoutput :
  288. FileRec(f).Handle:=StdOutputHandle;
  289. fmappend :
  290. begin
  291. FileRec(f).Handle:=StdOutputHandle;
  292. FileRec(f).mode:=fmoutput; {fool fmappend}
  293. end;
  294. end;
  295. exit;
  296. end;
  297. oldp:=p;
  298. DoDirSeparators(p,pchangeable);
  299. Action := Action or (Flags and $FF);
  300. (* DenyNone if sharing not specified. *)
  301. if Flags and 112 = 0 then
  302. Action := Action or 64;
  303. asm
  304. pushl %ebx
  305. movl $0x7f2b, %eax
  306. movl Action, %ecx
  307. movl p, %edx
  308. call syscall
  309. cmpl $0xffffffff, %eax
  310. jnz .LOPEN1
  311. movw %cx, InOutRes
  312. movl UnusedHandle, %eax
  313. .LOPEN1:
  314. movl f,%edx { Warning : This assumes Handle is first }
  315. movl %eax,(%edx) { field of FileRec }
  316. popl %ebx
  317. end ['eax', 'ecx', 'edx'];
  318. if (InOutRes = 4) and Increase_File_Handle_Count then
  319. (* Trying again after increasing amount of file handles *)
  320. asm
  321. pushl %ebx
  322. movl $0x7f2b, %eax
  323. movl Action, %ecx
  324. movl p, %edx
  325. call syscall
  326. cmpl $0xffffffff, %eax
  327. jnz .LOPEN2
  328. movw %cx, InOutRes
  329. movl UnusedHandle, %eax
  330. .LOPEN2:
  331. movl f,%edx
  332. movl %eax,(%edx)
  333. popl %ebx
  334. end ['eax', 'ecx', 'edx'];
  335. { for systems that have more handles }
  336. if (FileRec (F).Handle <> UnusedHandle) then
  337. begin
  338. if (FileRec (F).Handle > FileHandleCount) then
  339. FileHandleCount := FileRec (F).Handle;
  340. if ((Flags and $100) <> 0) then
  341. begin
  342. do_seekend (FileRec (F).Handle);
  343. FileRec (F).Mode := fmOutput; {fool fmappend}
  344. end;
  345. end
  346. else
  347. FileRec(f).mode:=fmclosed;
  348. if oldp<>p then
  349. freemem(p);
  350. end;
  351. {$ASMMODE INTEL}
  352. function do_isdevice (Handle: THandle): boolean; assembler;
  353. (*
  354. var HT, Attr: longint;
  355. begin
  356. if os_mode = osOS2 then
  357. begin
  358. if DosQueryHType (Handle, HT, Attr) <> 0 then HT := 1;
  359. end
  360. else
  361. *)
  362. asm
  363. push ebx
  364. {$IFDEF REGCALL}
  365. mov ebx, eax
  366. {$ELSE REGCALL}
  367. mov ebx, Handle
  368. {$ENDIF REGCALL}
  369. mov eax, 4400h
  370. call syscall
  371. mov eax, 1
  372. jc @IsDevEnd
  373. test edx, 80h { verify if it is a file }
  374. jnz @IsDevEnd
  375. dec eax { nope, so result is zero }
  376. @IsDevEnd:
  377. pop ebx
  378. end {['eax', 'ebx', 'edx']};
  379. {$ASMMODE ATT}