sysfile.inc 7.3 KB

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