sysfile.inc 7.3 KB

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