sysfile.inc 8.7 KB

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