sysfile.inc 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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. function do_isdevice(handle:thandle):boolean;
  15. {$IFNDEF WINCE}
  16. var
  17. HT: dword;
  18. {$ENDIF WINCE}
  19. begin
  20. {$IFDEF WINCE}
  21. Do_IsDevice := false;
  22. {$ELSE WINCE}
  23. HT := GetFileType (Handle);
  24. Do_IsDevice := (HT = FILE_TYPE_CHAR) or (HT = FILE_TYPE_PIPE);
  25. {$ENDIF WINCE}
  26. end;
  27. procedure do_close(h : thandle);
  28. begin
  29. if (h=StdInputHandle) or (h=StdOutputHandle) or (h=StdErrorHandle) then
  30. exit;
  31. if CloseHandle(h)=0 then
  32. Errno2InOutRes(GetLastError);
  33. end;
  34. procedure do_erase(p: pwidechar; pchangeable: boolean);
  35. var
  36. oldp: pwidechar;
  37. err: longword;
  38. begin
  39. oldp:=p;
  40. DoDirSeparators(p,pchangeable);
  41. if DeleteFileW(p)=0 then
  42. Begin
  43. err:=GetLastError;
  44. if err=5 then
  45. begin
  46. if ((GetFileAttributesW(p) and FILE_ATTRIBUTE_DIRECTORY)=FILE_ATTRIBUTE_DIRECTORY) then
  47. err:=2;
  48. end;
  49. Errno2InoutRes(err);
  50. end;
  51. if p<>oldp then
  52. freemem(p);
  53. end;
  54. procedure do_rename(p1,p2: pwidechar; p1changeable, p2changeable: boolean);
  55. var
  56. oldp1,oldp2: pwidechar;
  57. begin
  58. oldp1:=p1;
  59. oldp2:=p2;
  60. DoDirSeparators(p1,p1changeable);
  61. DoDirSeparators(p2,p2changeable);
  62. if MoveFileW(p1,p2)=0 then
  63. Begin
  64. Errno2InoutRes(GetLastError);
  65. end;
  66. if p1<>oldp1 then
  67. freemem(p1);
  68. if p2<>oldp2 then
  69. freemem(p2);
  70. end;
  71. function do_write(h:thandle;addr:pointer;len : longint) : longint;
  72. var
  73. size:longint;
  74. {$ifndef WINCE}
  75. ConsoleMode : dword;
  76. CodePage : UInt;
  77. accept_smaller_size : boolean;
  78. {$endif ndef WINCE}
  79. begin
  80. if writefile(h,addr,len,size,nil)=0 then
  81. Begin
  82. Errno2InoutRes(GetLastError);
  83. {$ifndef WINCE}
  84. end
  85. else if (size<len) then
  86. Begin
  87. if GetConsoleMode (h, @ConsoleMode) then
  88. Begin
  89. accept_smaller_size:=false;
  90. { GetConsoleMode success means that we do have a
  91. console handle that might return less than
  92. LEN because a UTF-8 with length LEN input was
  93. transformed into a shorter string of size SIZE }
  94. CodePage:=GetConsoleOutputCP;
  95. Case CodePage of
  96. 1200, {utf-16}
  97. 1201, {unicodeFFFE}
  98. 12000, {utf-32}
  99. 12001, {utf-32BE}
  100. 65000, {utf-7}
  101. 65001: {utf-8}
  102. accept_smaller_size:=true;
  103. end;
  104. if accept_smaller_size then
  105. size:=len;
  106. end;
  107. {$endif ndef WINCE}
  108. end;
  109. do_write:=size;
  110. end;
  111. function do_read(h:thandle;addr:pointer;len : longint) : longint;
  112. var
  113. _result:longint;
  114. err: longword;
  115. begin
  116. if readfile(h,addr,len,_result,nil)=0 then
  117. Begin
  118. err:=GetLastError;
  119. if err<>ERROR_BROKEN_PIPE then
  120. Errno2InoutRes(err);
  121. end;
  122. do_read:=_result;
  123. end;
  124. type
  125. tint64rec = record
  126. low, high: dword;
  127. end;
  128. function do_filepos(handle : thandle) : Int64;
  129. var
  130. rslt: tint64rec;
  131. begin
  132. rslt.high := 0;
  133. rslt.low := SetFilePointer(handle, 0, @rslt.high, FILE_CURRENT);
  134. if (rslt.low = $FFFFFFFF) and (GetLastError <> 0) then
  135. begin
  136. Errno2InoutRes(GetLastError);
  137. end;
  138. do_filepos := int64(rslt);
  139. end;
  140. procedure do_seek(handle: thandle; pos: Int64);
  141. var
  142. posHigh: LongInt;
  143. begin
  144. posHigh := tint64rec(pos).high;
  145. if (SetFilePointer(handle, pos, @posHigh, FILE_BEGIN)=-1) and
  146. { return value of -1 is valid unless GetLastError is non-zero }
  147. (GetLastError <> 0) then
  148. begin
  149. Errno2InoutRes(GetLastError);
  150. end;
  151. end;
  152. function do_seekend(handle:thandle):Int64;
  153. var
  154. rslt: tint64rec;
  155. begin
  156. rslt.high := 0;
  157. rslt.low := SetFilePointer(handle, 0, @rslt.high, FILE_END);
  158. if (rslt.low = $FFFFFFFF) and (GetLastError <> 0) then
  159. begin
  160. Errno2InoutRes(GetLastError);
  161. end;
  162. do_seekend := int64(rslt);
  163. end;
  164. function do_filesize(handle : thandle) : Int64;
  165. var
  166. aktfilepos : Int64;
  167. begin
  168. aktfilepos:=do_filepos(handle);
  169. do_filesize:=do_seekend(handle);
  170. do_seek(handle,aktfilepos);
  171. end;
  172. procedure do_truncate (handle:thandle;pos:Int64);
  173. begin
  174. do_seek(handle,pos);
  175. if not(SetEndOfFile(handle)) then
  176. begin
  177. Errno2InoutRes(GetLastError);
  178. end;
  179. end;
  180. procedure do_open(var f; p: pwidechar; flags: longint; pchangeable: boolean);
  181. {
  182. filerec and textrec have both handle and mode as the first items so
  183. they could use the same routine for opening/creating.
  184. when (flags and $100) the file will be append
  185. when (flags and $1000) the file will be truncate/rewritten
  186. when (flags and $10000) there is no check for close (needed for textfiles)
  187. }
  188. Const
  189. file_Share_Read = $00000001;
  190. file_Share_Write = $00000002;
  191. file_Share_Delete = $00000004;
  192. Var
  193. shflags,
  194. oflags,cd : longint;
  195. security : TSecurityAttributes;
  196. oldp : pwidechar;
  197. begin
  198. { close first if opened }
  199. if ((flags and $10000)=0) then
  200. begin
  201. case filerec(f).mode of
  202. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  203. fmclosed : ;
  204. else
  205. begin
  206. {not assigned}
  207. inoutres:=102;
  208. exit;
  209. end;
  210. end;
  211. end;
  212. oldp:=p;
  213. DoDirSeparators(p,pchangeable);
  214. { reset file handle }
  215. filerec(f).handle:=UnusedHandle;
  216. { convert filesharing }
  217. shflags:=0;
  218. if ((filemode and fmshareExclusive) = fmshareExclusive) then
  219. { no sharing }
  220. else
  221. if ((filemode and $f0) = fmShareCompat) or ((filemode and fmshareDenyWrite) = fmshareDenyWrite) then
  222. shflags := file_Share_Read
  223. else
  224. if ((filemode and fmshareDenyRead) = fmshareDenyRead) then
  225. shflags := file_Share_Write
  226. else
  227. if ((filemode and fmshareDenyNone) = fmshareDenyNone) then
  228. shflags :=
  229. {$ifdef WINCE}
  230. { WinCE does not know file_share_delete }
  231. file_Share_Read or file_Share_Write;
  232. {$else WINCE}
  233. fmShareDenyNoneFlags;
  234. {$endif WINCE}
  235. { convert filemode to filerec modes }
  236. case (flags and 3) of
  237. 0 : begin
  238. filerec(f).mode:=fminput;
  239. oflags:=longint(GENERIC_READ);
  240. end;
  241. 1 : begin
  242. filerec(f).mode:=fmoutput;
  243. oflags:=longint(GENERIC_WRITE);
  244. end;
  245. 2 : begin
  246. filerec(f).mode:=fminout;
  247. oflags:=longint(GENERIC_WRITE or GENERIC_READ);
  248. end;
  249. end;
  250. { create it ? }
  251. if (flags and $1000)<>0 then
  252. cd:=CREATE_ALWAYS
  253. { or Append/Open ? }
  254. else
  255. cd:=OPEN_EXISTING;
  256. { empty name is special }
  257. if p[0]=#0 then
  258. begin
  259. case FileRec(f).mode of
  260. fminput :
  261. FileRec(f).Handle:=StdInputHandle;
  262. fminout, { this is set by rewrite }
  263. fmoutput :
  264. FileRec(f).Handle:=StdOutputHandle;
  265. fmappend :
  266. begin
  267. FileRec(f).Handle:=StdOutputHandle;
  268. FileRec(f).mode:=fmoutput; {fool fmappend}
  269. end;
  270. end;
  271. { no dirseparators can have been replaced in the empty string -> no need
  272. to check whether we have to free p }
  273. exit;
  274. end;
  275. security.nLength := Sizeof(TSecurityAttributes);
  276. security.bInheritHandle:=true;
  277. security.lpSecurityDescriptor:=nil;
  278. filerec(f).handle:=CreateFileW(p,oflags,shflags,@security,cd,FILE_ATTRIBUTE_NORMAL,0);
  279. { append mode }
  280. if ((flags and $100)<>0) and
  281. (filerec(f).handle<>0) and
  282. (filerec(f).handle<>UnusedHandle) then
  283. begin
  284. do_seekend(filerec(f).handle);
  285. filerec(f).mode:=fmoutput; {fool fmappend}
  286. end;
  287. { get errors }
  288. { handle -1 is returned sometimes !! (PM) }
  289. if (filerec(f).handle=0) or (filerec(f).handle=UnusedHandle) then
  290. begin
  291. Errno2InoutRes(GetLastError);
  292. FileRec(f).mode:=fmclosed;
  293. end;
  294. if oldp<>p then
  295. freemem(p);
  296. end;