sysfile.inc 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2001 by Free Pascal development team
  4. Low level 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. var
  16. RC: cardinal;
  17. begin
  18. { Only three standard handles under real OS/2 }
  19. if h>2 then
  20. begin
  21. RC := DosClose (H);
  22. if RC <> 0 then
  23. begin
  24. InOutRes := longint (RC);
  25. OSErrorWatch (RC);
  26. end;
  27. end;
  28. {$ifdef IODEBUG}
  29. writeln('do_close: handle=', H, ', InOutRes=', InOutRes);
  30. {$endif}
  31. end;
  32. procedure do_erase(p:Pchar; pchangeable: boolean);
  33. var
  34. oldp: pchar;
  35. RC: cardinal;
  36. begin
  37. oldp:=p;
  38. DoDirSeparators(p,pchangeable);
  39. RC := DosDelete (P);
  40. if RC <> 0 then
  41. begin
  42. InOutRes := longint (RC);
  43. OSErrorWatch (RC);
  44. end;
  45. if p<>oldp then
  46. freemem(p);
  47. end;
  48. procedure do_rename(p1,p2:Pchar; p1changeable, p2changeable: boolean);
  49. var
  50. oldp1, oldp2 : pchar;
  51. RC: cardinal;
  52. begin
  53. oldp1:=p1;
  54. oldp2:=p2;
  55. DoDirSeparators(p1,p1changeable);
  56. DoDirSeparators(p2,p2changeable);
  57. RC := DosMove (p1, p2);
  58. if RC <> 0 then
  59. begin
  60. InOutRes := longint (RC);
  61. OSErrorWatch (RC);
  62. end;
  63. if p1<>oldp1 then
  64. freemem(p1);
  65. if p2<>oldp2 then
  66. freemem(p2);
  67. end;
  68. function do_read(h:thandle;addr:pointer;len:longint):longint;
  69. Var
  70. T: cardinal;
  71. RC: cardinal;
  72. begin
  73. {$ifdef IODEBUG}
  74. write('do_read: handle=', h, ', addr=', ptrint(addr), ', length=', len);
  75. {$endif}
  76. RC := DosRead(H, Addr, Len, T);
  77. if RC <> 0 then
  78. begin
  79. InOutRes := longint (RC);
  80. OSErrorWatch (RC);
  81. end;
  82. do_read:= longint (T);
  83. {$ifdef IODEBUG}
  84. writeln(', actual_len=', t, ', InOutRes=', InOutRes);
  85. {$endif}
  86. end;
  87. function do_write(h:thandle;addr:pointer;len:longint) : longint;
  88. Var
  89. T: cardinal;
  90. RC: cardinal;
  91. begin
  92. {$ifdef IODEBUG}
  93. write('do_write: handle=', h, ', addr=', ptrint(addr), ', length=', len);
  94. {$endif}
  95. RC := DosWrite(H, Addr, Len, T);
  96. if RC <> 0 then
  97. begin
  98. InOutRes := longint (RC);
  99. OSErrorWatch (RC);
  100. end;
  101. do_write:= longint (T);
  102. {$ifdef IODEBUG}
  103. writeln(', actual_len=', t, ', InOutRes=', InOutRes);
  104. {$endif}
  105. end;
  106. function Do_FilePos (Handle: THandle): int64;
  107. var
  108. PosActual: int64;
  109. RC: cardinal;
  110. begin
  111. RC := Sys_DosSetFilePtrL (Handle, 0, 1, PosActual);
  112. if RC <> 0 then
  113. begin
  114. InOutRes := longint (RC);
  115. OSErrorWatch (RC);
  116. end;
  117. Do_FilePos := PosActual;
  118. {$ifdef IODEBUG}
  119. writeln('do_filepos: handle=', Handle, ', actual_pos=', PosActual, ', InOutRes=', InOutRes);
  120. {$endif}
  121. end;
  122. procedure Do_Seek (Handle: THandle; Pos: int64);
  123. var
  124. PosActual: int64;
  125. RC: cardinal;
  126. begin
  127. RC := Sys_DosSetFilePtrL(Handle, Pos, 0 {ZeroBased}, PosActual);
  128. if RC <> 0 then
  129. begin
  130. InOutRes := longint (RC);
  131. OSErrorWatch (RC);
  132. end;
  133. {$ifdef IODEBUG}
  134. writeln('do_seek: handle=', Handle, ', pos=', pos, ', actual_pos=', PosActual, ', InOutRes=', InOutRes);
  135. {$endif}
  136. end;
  137. function Do_SeekEnd (Handle: THandle): int64;
  138. var
  139. PosActual: int64;
  140. RC: cardinal;
  141. begin
  142. RC := Sys_DosSetFilePtrL (Handle, 0, 2 {EndBased}, PosActual);
  143. if RC <> 0 then
  144. begin
  145. InOutRes := longint (RC);
  146. OSErrorWatch (RC);
  147. Do_SeekEnd := -1;
  148. end
  149. else
  150. Do_SeekEnd := PosActual;
  151. {$ifdef IODEBUG}
  152. writeln('do_seekend: handle=', Handle, ', actual_pos=', PosActual, ', InOutRes=', InOutRes);
  153. {$endif}
  154. end;
  155. function Do_FileSize (Handle: THandle): int64;
  156. var
  157. AktFilePos: int64;
  158. begin
  159. AktFilePos := Do_FilePos (Handle);
  160. if InOutRes = 0 then
  161. begin
  162. Do_FileSize := Do_SeekEnd (Handle);
  163. Do_Seek (Handle, AktFilePos);
  164. end;
  165. end;
  166. procedure Do_Truncate (Handle: THandle; Pos: int64);
  167. var
  168. RC: cardinal;
  169. begin
  170. RC := Sys_DosSetFileSizeL (Handle, Pos);
  171. if RC <> 0 then
  172. begin
  173. InOutRes := longint (RC);
  174. OSErrorWatch (RC);
  175. end
  176. else
  177. Do_SeekEnd (Handle);
  178. end;
  179. const
  180. FileHandleCount: cardinal = 20;
  181. function Increase_File_Handle_Count: boolean;
  182. var L1: longint;
  183. L2: cardinal;
  184. RC: cardinal;
  185. begin
  186. L1 := 10;
  187. RC := DosSetRelMaxFH (L1, L2);
  188. if RC <> 0 then
  189. begin
  190. Increase_File_Handle_Count := false;
  191. OSErrorWatch (RC);
  192. end
  193. else
  194. if L2 > FileHandleCount then
  195. begin
  196. FileHandleCount := L2;
  197. Increase_File_Handle_Count := true;
  198. end
  199. else
  200. Increase_File_Handle_Count := false;
  201. end;
  202. procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
  203. {
  204. filerec and textrec have both handle and mode as the first items so
  205. they could use the same routine for opening/creating.
  206. when (flags and $100) the file will be append
  207. when (flags and $1000) the file will be truncate/rewritten
  208. when (flags and $10000) there is no check for close (needed for textfiles)
  209. }
  210. var
  211. Action, Attrib, OpenFlags, FM: Cardinal;
  212. oldp : pchar;
  213. RC: cardinal;
  214. begin
  215. // close first if opened
  216. if ((flags and $10000)=0) then
  217. begin
  218. case filerec(f).mode of
  219. fminput,fmoutput,fminout : Do_Close (FileRec (F).Handle);
  220. fmclosed:;
  221. else
  222. begin
  223. inoutres:=102; {not assigned}
  224. exit;
  225. end;
  226. end;
  227. end;
  228. // reset file handle
  229. filerec(f).handle := UnusedHandle;
  230. Attrib:=0;
  231. OpenFlags:=0;
  232. // convert filesharing
  233. FM := Flags and $FF and not (8);
  234. (* DenyNone if sharing not specified. *)
  235. if FM and 112 = 0 then
  236. FM := FM or 64;
  237. // convert filemode to filerec modes and access mode
  238. case (FM and 3) of
  239. 0: filerec(f).mode:=fminput;
  240. 1: filerec(f).mode:=fmoutput;
  241. 2: filerec(f).mode:=fminout;
  242. end;
  243. if (flags and $1000)<>0 then
  244. OpenFlags:=OpenFlags or 2 {doOverwrite} or 16 {doCreate} // Create/overwrite
  245. else
  246. OpenFlags:=OpenFlags or 1 {doOpen}; // Open existing
  247. // Handle Std I/O
  248. if p[0]=#0 then
  249. begin
  250. case FileRec(f).mode of
  251. fminput :
  252. FileRec(f).Handle:=StdInputHandle;
  253. fminout, // this is set by rewrite
  254. fmoutput :
  255. FileRec(f).Handle:=StdOutputHandle;
  256. fmappend :
  257. begin
  258. FileRec(f).Handle:=StdOutputHandle;
  259. FileRec(f).mode:=fmoutput; // fool fmappend
  260. end;
  261. end;
  262. exit;
  263. end;
  264. oldp:=p;
  265. // convert unix slashes to normal slashes
  266. DoDirSeparators(p,pchangeable);
  267. Attrib:=32 {faArchive};
  268. RC := Sys_DosOpenL(p, FileRec(F).Handle, Action, 0, Attrib, OpenFlags, FM, nil);
  269. if RC <> 0 then
  270. begin
  271. InOutRes := longint (RC);
  272. OSErrorWatch (RC);
  273. end;
  274. // If too many open files try to set more file handles and open again
  275. if (InOutRes = 4) then
  276. if Increase_File_Handle_Count then
  277. begin
  278. RC := Sys_DosOpenL(p, FileRec(F).Handle, Action, 0, Attrib, OpenFlags, FM, nil);
  279. if RC <> 0 then
  280. begin
  281. InOutRes := longint (RC);
  282. OSErrorWatch (RC);
  283. end;
  284. end;
  285. if RC <> 0 then
  286. FileRec(F).Handle:=UnusedHandle;
  287. // If Handle created -> make some things
  288. if (FileRec(F).Handle <> UnusedHandle) then
  289. begin
  290. // Move to end of file for Append command
  291. if ((Flags and $100) <> 0) then
  292. begin
  293. if not (Do_IsDevice (FileRec (F).Handle)) then
  294. Do_SeekEnd (FileRec (F).Handle);
  295. FileRec(F).Mode := fmOutput;
  296. end;
  297. end
  298. else
  299. FileRec(f).mode:=fmclosed;
  300. if oldp<>p then
  301. freemem(p);
  302. {$ifdef IODEBUG}
  303. writeln('do_open,', filerec(f).handle, ',', filerec(f).name, ',', filerec(f).mode, ', InOutRes=', InOutRes);
  304. {$endif}
  305. end;
  306. function do_isdevice (Handle: THandle): boolean;
  307. var
  308. HT, Attr: cardinal;
  309. RC: cardinal;
  310. begin
  311. do_isdevice:=false;
  312. RC := DosQueryHType(Handle, HT, Attr);
  313. if RC <> 0 then
  314. begin
  315. OSErrorWatch (RC);
  316. Exit;
  317. end;
  318. if ht=1 then
  319. do_isdevice:=true;
  320. end;
  321. {$ASMMODE ATT}