mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 13:28:05 +02:00
410 lines
9.3 KiB
PHP
410 lines
9.3 KiB
PHP
{
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 2001 by Free Pascal development team
|
|
|
|
Low leve file functions
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
|
|
{****************************************************************************
|
|
Low level File Routines
|
|
All these functions can set InOutRes on errors
|
|
****************************************************************************}
|
|
|
|
|
|
PROCEDURE NW2PASErr (Err : LONGINT);
|
|
BEGIN
|
|
if Err = 0 then { Else it will go through all the cases }
|
|
exit;
|
|
case Err of
|
|
Sys_ENFILE,
|
|
Sys_EMFILE : Inoutres:=4;
|
|
Sys_ENOENT : Inoutres:=2;
|
|
Sys_EBADF : Inoutres:=6;
|
|
Sys_ENOMEM,
|
|
Sys_EFAULT : Inoutres:=217;
|
|
Sys_EINVAL : Inoutres:=218;
|
|
Sys_EPIPE,
|
|
Sys_EINTR,
|
|
Sys_EIO,
|
|
Sys_EAGAIN,
|
|
Sys_ENOSPC : Inoutres:=101;
|
|
Sys_ENAMETOOLONG,
|
|
Sys_ELOOP,
|
|
Sys_ENOTDIR : Inoutres:=3;
|
|
Sys_EROFS,
|
|
Sys_EEXIST,
|
|
Sys_EACCES : Inoutres:=5;
|
|
Sys_EBUSY : Inoutres:=162
|
|
else begin
|
|
Writeln (stderr,'NW2PASErr: unknown error ',err);
|
|
libc_perror('NW2PASErr');
|
|
Inoutres := Err;
|
|
end;
|
|
end;
|
|
END;
|
|
|
|
|
|
procedure Errno2Inoutres;
|
|
begin
|
|
NW2PASErr (___errno^);
|
|
end;
|
|
|
|
procedure SetFileError (VAR Err : LONGINT);
|
|
begin
|
|
if Err >= 0 then
|
|
InOutRes := 0
|
|
else begin
|
|
// libc_perror ('SetFileError');
|
|
Err := ___errno^;
|
|
NW2PASErr (Err);
|
|
Err := 0;
|
|
end;
|
|
end;
|
|
|
|
{ close a file from the handle value }
|
|
procedure do_close(handle : thandle);
|
|
VAR res : LONGINT;
|
|
begin
|
|
{$ifdef IOpossix}
|
|
res := FpClose (handle);
|
|
{$else}
|
|
res := _fclose (_TFILE(handle));
|
|
{$endif}
|
|
IF res <> 0 THEN
|
|
SetFileError (res)
|
|
ELSE
|
|
InOutRes := 0;
|
|
end;
|
|
|
|
procedure do_erase(p : PAnsiChar; pchangeable: boolean);
|
|
VAR res : LONGINT;
|
|
begin
|
|
res := unlink (p);
|
|
IF Res < 0 THEN
|
|
SetFileError (res)
|
|
ELSE
|
|
InOutRes := 0;
|
|
end;
|
|
|
|
procedure do_rename(p1,p2 : PAnsiChar; p1changeable, p2changeable: boolean);
|
|
VAR res : LONGINT;
|
|
begin
|
|
res := rename (p1,p2);
|
|
IF Res < 0 THEN
|
|
SetFileError (res)
|
|
ELSE
|
|
InOutRes := 0
|
|
end;
|
|
|
|
function do_write(h:thandle;addr:pointer;len : longint) : longint;
|
|
var res : LONGINT;
|
|
begin
|
|
{$ifdef IOpossix}
|
|
res := Fpwrite (h,addr,len);
|
|
{$else}
|
|
res := _fwrite (addr,1,len,_TFILE(h));
|
|
{$endif}
|
|
if res > 0 then
|
|
InOutRes := 0
|
|
else
|
|
SetFileError (res);
|
|
do_write := res;
|
|
NXThreadYield;
|
|
end;
|
|
|
|
function do_read(h:thandle;addr:pointer;len : longint) : longint;
|
|
VAR res : LONGINT;
|
|
begin
|
|
{$ifdef IOpossix}
|
|
res := Fpread (h,addr,len);
|
|
{$else}
|
|
res := _fread (addr,1,len,_TFILE(h));
|
|
{$endif}
|
|
IF res > 0 THEN
|
|
InOutRes := 0
|
|
ELSE
|
|
SetFileError (res);
|
|
do_read := res;
|
|
NXThreadYield;
|
|
end;
|
|
|
|
|
|
function do_filepos(handle : thandle) : longint;
|
|
var res : LONGINT;
|
|
begin
|
|
InOutRes:=1;
|
|
{$ifdef IOpossix}
|
|
res := Fptell (handle);
|
|
{$else}
|
|
res := _ftell (_TFILE(handle));
|
|
{$endif}
|
|
if res < 0 THEN
|
|
SetFileError (res)
|
|
else
|
|
InOutRes := 0;
|
|
do_filepos := res;
|
|
end;
|
|
|
|
|
|
procedure do_seek(handle:thandle;pos : longint);
|
|
VAR res : LONGINT;
|
|
begin
|
|
{$ifdef IOpossix}
|
|
res := Fplseek (handle,pos, SEEK_SET);
|
|
{$else}
|
|
res := _fseek (_TFILE(handle),pos, SEEK_SET);
|
|
{$endif}
|
|
IF res >= 0 THEN
|
|
InOutRes := 0
|
|
ELSE
|
|
SetFileError (res);
|
|
end;
|
|
|
|
function do_seekend(handle:thandle):longint;
|
|
VAR res : LONGINT;
|
|
begin
|
|
{$ifdef IOpossix}
|
|
res := Fplseek (handle,0, SEEK_END);
|
|
{$else}
|
|
res := _fseek (_TFILE(handle),0, SEEK_END);
|
|
{$endif}
|
|
IF res >= 0 THEN
|
|
InOutRes := 0
|
|
ELSE
|
|
SetFileError (res);
|
|
do_seekend := res;
|
|
end;
|
|
|
|
|
|
function do_filesize(handle : thandle) : longint;
|
|
VAR res : LONGINT;
|
|
statbuf : TStat;
|
|
begin
|
|
{$ifdef IOpossix}
|
|
res := Fpfstat (handle, statbuf);
|
|
{$else}
|
|
res := _fstat (_fileno (_TFILE(handle)), statbuf); // was _filelength for clib
|
|
{$endif}
|
|
if res <> 0 then
|
|
begin
|
|
SetFileError (Res);
|
|
do_filesize := -1;
|
|
end else
|
|
begin
|
|
InOutRes := 0;
|
|
do_filesize := statbuf.st_size;
|
|
end;
|
|
end;
|
|
|
|
{ truncate at a given position }
|
|
procedure do_truncate (handle:thandle;pos:longint);
|
|
VAR res : LONGINT;
|
|
begin
|
|
{$ifdef IOpossix}
|
|
res := ftruncate (handle,pos);
|
|
{$else}
|
|
res := _ftruncate (_fileno (_TFILE(handle)),pos);
|
|
{$endif}
|
|
IF res <> 0 THEN
|
|
SetFileError (res)
|
|
ELSE
|
|
InOutRes := 0;
|
|
end;
|
|
|
|
{$ifdef IOpossix}
|
|
// mostly stolen from linux system unit
|
|
procedure do_open(var f;p:PAnsiChar;flags:longint; pchangeable: boolean);
|
|
{
|
|
filerec and textrec have both handle and mode as the first items so
|
|
they could use the same routine for opening/creating.
|
|
when (flags and $10) the file will be append
|
|
when (flags and $100) the file will be truncate/rewritten
|
|
when (flags and $1000) there is no check for close (needed for textfiles)
|
|
}
|
|
var
|
|
oflags : longint;
|
|
Begin
|
|
{ close first if opened }
|
|
if ((flags and $10000)=0) then
|
|
begin
|
|
case FileRec(f).mode of
|
|
fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
|
|
fmclosed : ;
|
|
else
|
|
begin
|
|
inoutres:=102; {not assigned}
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
{ reset file Handle }
|
|
FileRec(f).Handle:=UnusedHandle;
|
|
|
|
{ We do the conversion of filemodes here, concentrated on 1 place }
|
|
case (flags and 3) of
|
|
0 : begin
|
|
oflags := O_RDONLY;
|
|
filerec(f).mode := fminput;
|
|
end;
|
|
1 : begin
|
|
oflags := O_WRONLY;
|
|
filerec(f).mode := fmoutput;
|
|
end;
|
|
2 : begin
|
|
oflags := O_RDWR;
|
|
filerec(f).mode := fminout;
|
|
end;
|
|
end;
|
|
if (flags and $1000)=$1000 then
|
|
oflags:=oflags or (O_CREAT or O_TRUNC)
|
|
else
|
|
if (flags and $100)=$100 then
|
|
oflags:=oflags or (O_APPEND);
|
|
{ empty name is special }
|
|
if p[0]=#0 then
|
|
begin
|
|
case FileRec(f).mode of
|
|
fminput :
|
|
FileRec(f).Handle:=StdInputHandle;
|
|
fminout, { this is set by rewrite }
|
|
fmoutput :
|
|
FileRec(f).Handle:=StdOutputHandle;
|
|
fmappend :
|
|
begin
|
|
FileRec(f).Handle:=StdOutputHandle;
|
|
FileRec(f).mode:=fmoutput; {fool fmappend}
|
|
end;
|
|
end;
|
|
exit;
|
|
end;
|
|
{ real open call }
|
|
___errno^ := 0;
|
|
FileRec(f).Handle := open(p,oflags,438);
|
|
{ open somtimes returns > -1 but errno was set }
|
|
if (___errno^ <> 0) or (longint(FileRec(f).Handle) < 0) then
|
|
if (___errno^=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
|
|
begin // i.e. for cd-rom
|
|
Oflags:=Oflags and not(O_RDWR);
|
|
FileRec(f).Handle := open(p,oflags,438);
|
|
end;
|
|
if (___errno^ <> 0) or (longint(FileRec(f).Handle) < 0) then
|
|
begin
|
|
Errno2Inoutres;
|
|
FileRec(f).mode:=fmclosed;
|
|
end
|
|
else
|
|
InOutRes := 0;
|
|
end;
|
|
|
|
|
|
{$else}
|
|
procedure do_open(var f;p:PAnsiChar;flags:longint);
|
|
{
|
|
filerec and textrec have both handle and mode as the first items so
|
|
they could use the same routine for opening/creating.
|
|
when (flags and $10) the file will be append
|
|
when (flags and $100) the file will be truncate/rewritten
|
|
when (flags and $1000) there is no check for close (needed for textfiles)
|
|
}
|
|
var
|
|
oflags : string[10];
|
|
Begin
|
|
{ close first if opened }
|
|
if ((flags and $10000)=0) then
|
|
begin
|
|
case FileRec(f).mode of
|
|
fminput,fmoutput,fminout : Do_Close(FileRec(f).Handle);
|
|
fmclosed : ;
|
|
else
|
|
begin
|
|
inoutres:=102; {not assigned}
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
{ reset file Handle }
|
|
FileRec(f).Handle:=UnusedHandle;
|
|
|
|
{ We do the conversion of filemodes here, concentrated on 1 place }
|
|
case (flags and 3) of
|
|
0 : begin
|
|
oflags := 'rb'#0;
|
|
filerec(f).mode := fminput;
|
|
end;
|
|
1 : begin
|
|
if (flags and $1000)=$1000 then
|
|
oflags := 'w+b' else
|
|
oflags := 'wb';
|
|
filerec(f).mode := fmoutput;
|
|
end;
|
|
2 : begin
|
|
if (flags and $1000)=$1000 then
|
|
oflags := 'w+' else
|
|
oflags := 'r+';
|
|
filerec(f).mode := fminout;
|
|
end;
|
|
end;
|
|
{if (flags and $1000)=$1000 then
|
|
oflags:=oflags or (O_CREAT or O_TRUNC)
|
|
else
|
|
if (flags and $100)=$100 then
|
|
oflags:=oflags or (O_APPEND);}
|
|
{ empty name is special }
|
|
if p[0]=#0 then
|
|
begin
|
|
case FileRec(f).mode of
|
|
fminput :
|
|
FileRec(f).Handle:=StdInputHandle;
|
|
fminout, { this is set by rewrite }
|
|
fmoutput :
|
|
FileRec(f).Handle:=StdOutputHandle;
|
|
fmappend :
|
|
begin
|
|
FileRec(f).Handle:=StdOutputHandle;
|
|
FileRec(f).mode:=fmoutput; {fool fmappend}
|
|
end;
|
|
end;
|
|
exit;
|
|
end;
|
|
{ real open call }
|
|
FileRec(f).Handle := THandle (_fopen (p,@oflags[1]));//_open(p,oflags,438);
|
|
//WriteLn ('_open (',p,') returned ',ErrNo, 'Handle: ',FileRec(f).Handle);
|
|
// errno does not seem to be set on succsess ??
|
|
{IF FileRec(f).Handle < 0 THEN
|
|
if (ErrNo=Sys_EROFS) and ((OFlags and O_RDWR)<>0) then
|
|
begin // i.e. for cd-rom
|
|
Oflags:=Oflags and not(O_RDWR);
|
|
FileRec(f).Handle := _open(p,oflags,438);
|
|
end;}
|
|
if FileRec(f).Handle = 0 then
|
|
begin
|
|
Errno2Inoutres;
|
|
FileRec(f).mode:=fmclosed;
|
|
end
|
|
else
|
|
InOutRes := 0;
|
|
End;
|
|
{$endif}
|
|
|
|
function do_isdevice(handle:THandle):boolean;
|
|
begin
|
|
{$ifdef IOpossix}
|
|
do_isdevice := (Fpisatty (handle) > 0);
|
|
{$else}
|
|
do_isdevice := (isatty (_fileno(_TFILE(handle))) > 0);
|
|
{$endif}
|
|
end;
|
|
|
|
|
|
|
|
|
|
|