sysfile.inc 9.3 KB

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