sysfile.inc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2001 by Free Pascal development team
  5. Low leve file functions
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {****************************************************************************
  13. Low level File Routines
  14. All these functions can set InOutRes on errors
  15. ****************************************************************************}
  16. PROCEDURE NW2PASErr (Err : LONGINT);
  17. BEGIN
  18. if Err = 0 then { Else it will go through all the cases }
  19. exit;
  20. case Err of
  21. Sys_ENFILE,
  22. Sys_EMFILE : Inoutres:=4;
  23. Sys_ENOENT : Inoutres:=2;
  24. Sys_EBADF : Inoutres:=6;
  25. Sys_ENOMEM,
  26. Sys_EFAULT : Inoutres:=217;
  27. Sys_EINVAL : Inoutres:=218;
  28. Sys_EPIPE,
  29. Sys_EINTR,
  30. Sys_EIO,
  31. Sys_EAGAIN,
  32. Sys_ENOSPC : Inoutres:=101;
  33. Sys_ENAMETOOLONG,
  34. Sys_ELOOP,
  35. Sys_ENOTDIR : Inoutres:=3;
  36. Sys_EROFS,
  37. Sys_EEXIST,
  38. Sys_EACCES : Inoutres:=5;
  39. Sys_EBUSY : Inoutres:=162
  40. else begin
  41. Writeln (stderr,'NW2PASErr: unknown error ',err);
  42. libc_perror('NW2PASErr');
  43. Inoutres := Err;
  44. end;
  45. end;
  46. END;
  47. procedure Errno2Inoutres;
  48. begin
  49. NW2PASErr (___errno^);
  50. end;
  51. procedure SetFileError (VAR Err : LONGINT);
  52. begin
  53. if Err >= 0 then
  54. InOutRes := 0
  55. else begin
  56. // libc_perror ('SetFileError');
  57. Err := ___errno^;
  58. NW2PASErr (Err);
  59. Err := 0;
  60. end;
  61. end;
  62. { close a file from the handle value }
  63. procedure do_close(handle : thandle);
  64. VAR res : LONGINT;
  65. begin
  66. {$ifdef IOpossix}
  67. res := FpClose (handle);
  68. {$else}
  69. res := _fclose (_TFILE(handle));
  70. {$endif}
  71. IF res <> 0 THEN
  72. SetFileError (res)
  73. ELSE
  74. InOutRes := 0;
  75. end;
  76. procedure do_erase(p : pchar);
  77. VAR res : LONGINT;
  78. begin
  79. res := unlink (p);
  80. IF Res < 0 THEN
  81. SetFileError (res)
  82. ELSE
  83. InOutRes := 0;
  84. end;
  85. procedure do_rename(p1,p2 : pchar);
  86. VAR res : LONGINT;
  87. begin
  88. res := rename (p1,p2);
  89. IF Res < 0 THEN
  90. SetFileError (res)
  91. ELSE
  92. InOutRes := 0
  93. end;
  94. function do_write(h:thandle;addr:pointer;len : longint) : longint;
  95. var res : LONGINT;
  96. begin
  97. {$ifdef IOpossix}
  98. res := Fpwrite (h,addr,len);
  99. {$else}
  100. res := _fwrite (addr,1,len,_TFILE(h));
  101. {$endif}
  102. if res > 0 then
  103. InOutRes := 0
  104. else
  105. SetFileError (res);
  106. do_write := res;
  107. NXThreadYield;
  108. end;
  109. function do_read(h:thandle;addr:pointer;len : longint) : longint;
  110. VAR res : LONGINT;
  111. begin
  112. {$ifdef IOpossix}
  113. res := Fpread (h,addr,len);
  114. {$else}
  115. res := _fread (addr,1,len,_TFILE(h));
  116. {$endif}
  117. IF res > 0 THEN
  118. InOutRes := 0
  119. ELSE
  120. SetFileError (res);
  121. do_read := res;
  122. NXThreadYield;
  123. end;
  124. function do_filepos(handle : thandle) : longint;
  125. var res : LONGINT;
  126. begin
  127. InOutRes:=1;
  128. {$ifdef IOpossix}
  129. res := Fptell (handle);
  130. {$else}
  131. res := _ftell (_TFILE(handle));
  132. {$endif}
  133. if res < 0 THEN
  134. SetFileError (res)
  135. else
  136. InOutRes := 0;
  137. do_filepos := res;
  138. end;
  139. procedure do_seek(handle:thandle;pos : longint);
  140. VAR res : LONGINT;
  141. begin
  142. {$ifdef IOpossix}
  143. res := Fplseek (handle,pos, SEEK_SET);
  144. {$else}
  145. res := _fseek (_TFILE(handle),pos, SEEK_SET);
  146. {$endif}
  147. IF res >= 0 THEN
  148. InOutRes := 0
  149. ELSE
  150. SetFileError (res);
  151. end;
  152. function do_seekend(handle:thandle):longint;
  153. VAR res : LONGINT;
  154. begin
  155. {$ifdef IOpossix}
  156. res := Fplseek (handle,0, SEEK_END);
  157. {$else}
  158. res := _fseek (_TFILE(handle),0, SEEK_END);
  159. {$endif}
  160. IF res >= 0 THEN
  161. InOutRes := 0
  162. ELSE
  163. SetFileError (res);
  164. do_seekend := res;
  165. end;
  166. function do_filesize(handle : thandle) : longint;
  167. VAR res : LONGINT;
  168. statbuf : TStat;
  169. begin
  170. {$ifdef IOpossix}
  171. res := Fpfstat (handle, statbuf);
  172. {$else}
  173. res := _fstat (_fileno (_TFILE(handle)), statbuf); // was _filelength for clib
  174. {$endif}
  175. if res <> 0 then
  176. begin
  177. SetFileError (Res);
  178. do_filesize := -1;
  179. end else
  180. begin
  181. InOutRes := 0;
  182. do_filesize := statbuf.st_size;
  183. end;
  184. end;
  185. { truncate at a given position }
  186. procedure do_truncate (handle:thandle;pos:longint);
  187. VAR res : LONGINT;
  188. begin
  189. {$ifdef IOpossix}
  190. res := ftruncate (handle,pos);
  191. {$else}
  192. res := _ftruncate (_fileno (_TFILE(handle)),pos);
  193. {$endif}
  194. IF res <> 0 THEN
  195. SetFileError (res)
  196. ELSE
  197. InOutRes := 0;
  198. end;
  199. {$ifdef IOpossix}
  200. // mostly stolen from syslinux
  201. procedure do_open(var f;p:pchar;flags:longint);
  202. {
  203. filerec and textrec have both handle and mode as the first items so
  204. they could use the same routine for opening/creating.
  205. when (flags and $10) the file will be append
  206. when (flags and $100) the file will be truncate/rewritten
  207. when (flags and $1000) there is no check for close (needed for textfiles)
  208. }
  209. var
  210. oflags : longint;
  211. Begin
  212. { close first if opened }
  213. if ((flags and $10000)=0) then
  214. begin
  215. case FileRec(f).mode of
  216. fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
  217. fmclosed : ;
  218. else
  219. begin
  220. inoutres:=102; {not assigned}
  221. exit;
  222. end;
  223. end;
  224. end;
  225. { reset file Handle }
  226. FileRec(f).Handle:=UnusedHandle;
  227. { We do the conversion of filemodes here, concentrated on 1 place }
  228. case (flags and 3) of
  229. 0 : begin
  230. oflags := O_RDONLY;
  231. filerec(f).mode := fminput;
  232. end;
  233. 1 : begin
  234. oflags := O_WRONLY;
  235. filerec(f).mode := fmoutput;
  236. end;
  237. 2 : begin
  238. oflags := O_RDWR;
  239. filerec(f).mode := fminout;
  240. end;
  241. end;
  242. if (flags and $1000)=$1000 then
  243. oflags:=oflags or (O_CREAT or O_TRUNC)
  244. else
  245. if (flags and $100)=$100 then
  246. oflags:=oflags or (O_APPEND);
  247. { empty name is special }
  248. if p[0]=#0 then
  249. begin
  250. case FileRec(f).mode of
  251. fminput :
  252. FileRec(f).Handle:=StdInputHandle;
  253. fminout, { this is set by rewrite }
  254. fmoutput :
  255. FileRec(f).Handle:=StdOutputHandle;
  256. fmappend :
  257. begin
  258. FileRec(f).Handle:=StdOutputHandle;
  259. FileRec(f).mode:=fmoutput; {fool fmappend}
  260. end;
  261. end;
  262. exit;
  263. end;
  264. { real open call }
  265. ___errno^ := 0;
  266. FileRec(f).Handle := open(p,oflags,438);
  267. { open somtimes returns > -1 but errno was set }
  268. if (___errno^ <> 0) or (longint(FileRec(f).Handle) < 0) then
  269. if (___errno^=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
  270. begin // i.e. for cd-rom
  271. Oflags:=Oflags and not(O_RDWR);
  272. FileRec(f).Handle := open(p,oflags,438);
  273. end;
  274. if (___errno^ <> 0) or (longint(FileRec(f).Handle) < 0) then
  275. Errno2Inoutres
  276. else
  277. InOutRes := 0;
  278. end;
  279. {$else}
  280. procedure do_open(var f;p:pchar;flags:longint);
  281. {
  282. filerec and textrec have both handle and mode as the first items so
  283. they could use the same routine for opening/creating.
  284. when (flags and $10) the file will be append
  285. when (flags and $100) the file will be truncate/rewritten
  286. when (flags and $1000) there is no check for close (needed for textfiles)
  287. }
  288. var
  289. oflags : string[10];
  290. Begin
  291. { close first if opened }
  292. if ((flags and $10000)=0) then
  293. begin
  294. case FileRec(f).mode of
  295. fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
  296. fmclosed : ;
  297. else
  298. begin
  299. inoutres:=102; {not assigned}
  300. exit;
  301. end;
  302. end;
  303. end;
  304. { reset file Handle }
  305. FileRec(f).Handle:=UnusedHandle;
  306. { We do the conversion of filemodes here, concentrated on 1 place }
  307. case (flags and 3) of
  308. 0 : begin
  309. oflags := 'rb'#0;
  310. filerec(f).mode := fminput;
  311. end;
  312. 1 : begin
  313. if (flags and $1000)=$1000 then
  314. oflags := 'w+b' else
  315. oflags := 'wb';
  316. filerec(f).mode := fmoutput;
  317. end;
  318. 2 : begin
  319. if (flags and $1000)=$1000 then
  320. oflags := 'w+' else
  321. oflags := 'r+';
  322. filerec(f).mode := fminout;
  323. end;
  324. end;
  325. {if (flags and $1000)=$1000 then
  326. oflags:=oflags or (O_CREAT or O_TRUNC)
  327. else
  328. if (flags and $100)=$100 then
  329. oflags:=oflags or (O_APPEND);}
  330. { empty name is special }
  331. if p[0]=#0 then
  332. begin
  333. case FileRec(f).mode of
  334. fminput :
  335. FileRec(f).Handle:=StdInputHandle;
  336. fminout, { this is set by rewrite }
  337. fmoutput :
  338. FileRec(f).Handle:=StdOutputHandle;
  339. fmappend :
  340. begin
  341. FileRec(f).Handle:=StdOutputHandle;
  342. FileRec(f).mode:=fmoutput; {fool fmappend}
  343. end;
  344. end;
  345. exit;
  346. end;
  347. { real open call }
  348. FileRec(f).Handle := THandle (_fopen (p,@oflags[1]));//_open(p,oflags,438);
  349. //WriteLn ('_open (',p,') returned ',ErrNo, 'Handle: ',FileRec(f).Handle);
  350. // errno does not seem to be set on succsess ??
  351. {IF FileRec(f).Handle < 0 THEN
  352. if (ErrNo=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
  353. begin // i.e. for cd-rom
  354. Oflags:=Oflags and not(O_RDWR);
  355. FileRec(f).Handle := _open(p,oflags,438);
  356. end;}
  357. if FileRec(f).Handle = 0 then
  358. Errno2Inoutres
  359. else
  360. InOutRes := 0;
  361. End;
  362. {$endif}
  363. function do_isdevice(handle:THandle):boolean;
  364. begin
  365. {$ifdef IOpossix}
  366. do_isdevice := (Fpisatty (handle) > 0);
  367. {$else}
  368. do_isdevice := (isatty (_fileno(_TFILE(handle))) > 0);
  369. {$endif}
  370. end;
  371. {
  372. $Log$
  373. Revision 1.2 2005-02-14 17:13:30 peter
  374. * truncate log
  375. Revision 1.1 2005/02/06 16:57:18 peter
  376. * threads for go32v2,os,emx,netware
  377. Revision 1.1 2005/02/06 13:06:20 peter
  378. * moved file and dir functions to sysfile/sysdir
  379. * win32 thread in systemunit
  380. }