sysfile.inc 9.8 KB

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