sysfile.inc 9.6 KB

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