sysfile.inc 7.8 KB

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