sysfile.inc 9.5 KB

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