sysfile.inc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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 Err: word;
  183. L1: longint;
  184. L2: cardinal;
  185. RC: cardinal;
  186. begin
  187. L1 := 10;
  188. RC := DosSetRelMaxFH (L1, L2);
  189. if RC <> 0 then
  190. begin
  191. Increase_File_Handle_Count := false;
  192. OSErrorWatch (RC);
  193. end
  194. else
  195. if L2 > FileHandleCount then
  196. begin
  197. FileHandleCount := L2;
  198. Increase_File_Handle_Count := true;
  199. end
  200. else
  201. Increase_File_Handle_Count := false;
  202. end;
  203. procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
  204. {
  205. filerec and textrec have both handle and mode as the first items so
  206. they could use the same routine for opening/creating.
  207. when (flags and $100) the file will be append
  208. when (flags and $1000) the file will be truncate/rewritten
  209. when (flags and $10000) there is no check for close (needed for textfiles)
  210. }
  211. var
  212. Action, Attrib, OpenFlags, FM: Cardinal;
  213. oldp : pchar;
  214. RC: cardinal;
  215. begin
  216. // close first if opened
  217. if ((flags and $10000)=0) then
  218. begin
  219. case filerec(f).mode of
  220. fminput,fmoutput,fminout : Do_Close (FileRec (F).Handle);
  221. fmclosed:;
  222. else
  223. begin
  224. inoutres:=102; {not assigned}
  225. exit;
  226. end;
  227. end;
  228. end;
  229. // reset file handle
  230. filerec(f).handle := UnusedHandle;
  231. Attrib:=0;
  232. OpenFlags:=0;
  233. // convert filesharing
  234. FM := Flags and $FF and not (8);
  235. (* DenyNone if sharing not specified. *)
  236. if FM and 112 = 0 then
  237. FM := FM or 64;
  238. // convert filemode to filerec modes and access mode
  239. case (FM and 3) of
  240. 0: filerec(f).mode:=fminput;
  241. 1: filerec(f).mode:=fmoutput;
  242. 2: filerec(f).mode:=fminout;
  243. end;
  244. if (flags and $1000)<>0 then
  245. OpenFlags:=OpenFlags or 2 {doOverwrite} or 16 {doCreate} // Create/overwrite
  246. else
  247. OpenFlags:=OpenFlags or 1 {doOpen}; // Open existing
  248. // Handle Std I/O
  249. if p[0]=#0 then
  250. begin
  251. case FileRec(f).mode of
  252. fminput :
  253. FileRec(f).Handle:=StdInputHandle;
  254. fminout, // this is set by rewrite
  255. fmoutput :
  256. FileRec(f).Handle:=StdOutputHandle;
  257. fmappend :
  258. begin
  259. FileRec(f).Handle:=StdOutputHandle;
  260. FileRec(f).mode:=fmoutput; // fool fmappend
  261. end;
  262. end;
  263. exit;
  264. end;
  265. oldp:=p;
  266. // convert unix slashes to normal slashes
  267. DoDirSeparators(p,pchangeable);
  268. Attrib:=32 {faArchive};
  269. RC := Sys_DosOpenL(p, FileRec(F).Handle, Action, 0, Attrib, OpenFlags, FM, nil);
  270. if RC <> 0 then
  271. begin
  272. InOutRes := longint (RC);
  273. OSErrorWatch (RC);
  274. end;
  275. // If too many open files try to set more file handles and open again
  276. if (InOutRes = 4) then
  277. if Increase_File_Handle_Count then
  278. begin
  279. RC := Sys_DosOpenL(p, FileRec(F).Handle, Action, 0, Attrib, OpenFlags, FM, nil);
  280. if RC <> 0 then
  281. begin
  282. InOutRes := longint (RC);
  283. OSErrorWatch (RC);
  284. end;
  285. end;
  286. if RC <> 0 then
  287. FileRec(F).Handle:=UnusedHandle;
  288. // If Handle created -> make some things
  289. if (FileRec(F).Handle <> UnusedHandle) then
  290. begin
  291. // Move to end of file for Append command
  292. if ((Flags and $100) <> 0) then
  293. begin
  294. do_seekend(FileRec(F).Handle);
  295. FileRec(F).Mode := fmOutput;
  296. end;
  297. end;
  298. if oldp<>p then
  299. freemem(p);
  300. {$ifdef IODEBUG}
  301. writeln('do_open,', filerec(f).handle, ',', filerec(f).name, ',', filerec(f).mode, ', InOutRes=', InOutRes);
  302. {$endif}
  303. end;
  304. function do_isdevice (Handle: THandle): boolean;
  305. var
  306. HT, Attr: cardinal;
  307. RC: cardinal;
  308. begin
  309. do_isdevice:=false;
  310. RC := DosQueryHType(Handle, HT, Attr);
  311. if RC <> 0 then
  312. begin
  313. OSErrorWatch (RC);
  314. Exit;
  315. end;
  316. if ht=1 then
  317. do_isdevice:=true;
  318. end;
  319. {$ASMMODE ATT}