mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-27 00:20:36 +00:00
+
This commit is contained in:
parent
683f552d55
commit
4fbb608639
@ -11,6 +11,7 @@ uses
|
||||
sys_fd,
|
||||
sys_file,
|
||||
sys_dev,
|
||||
sys_dir,
|
||||
Classes,
|
||||
SysUtils;
|
||||
|
||||
@ -1036,7 +1037,7 @@ begin
|
||||
PT_FILE:;
|
||||
PT_DEV :Exit(_set_sce_errno(0));
|
||||
else
|
||||
Exit(_set_sce_errno(px2sce(EACCES)));
|
||||
Exit(_set_sce_errno(SCE_KERNEL_ERROR_EACCES));
|
||||
end;
|
||||
|
||||
if FileExists(fn) or DirectoryExists(fn) then
|
||||
|
@ -10,7 +10,6 @@ uses
|
||||
SysUtils,
|
||||
RWLock,
|
||||
sys_kernel,
|
||||
sys_time,
|
||||
sys_fd;
|
||||
|
||||
function _sys_dev_open(const path:RawByteString;flags,mode:Integer):Integer;
|
||||
@ -33,8 +32,10 @@ type
|
||||
end;
|
||||
|
||||
TDevStd=class(TDevFile)
|
||||
Text:PText;
|
||||
cache:TMemoryStream;
|
||||
var
|
||||
Text:PText;
|
||||
lock:TRWLock;
|
||||
cache:RawByteString;
|
||||
Constructor Create(t:PText);
|
||||
Destructor Destroy; override;
|
||||
function read (data:Pointer;size:Int64):Int64; override;
|
||||
@ -155,38 +156,101 @@ type
|
||||
begin
|
||||
Handle:=PTextRec(t)^.Handle;
|
||||
Text:=t;
|
||||
cache:=TMemoryStream.Create
|
||||
rwlock_init(lock);
|
||||
cache:='';
|
||||
end;
|
||||
|
||||
Destructor TDevStd.Destroy;
|
||||
begin
|
||||
FreeAndNil(cache);
|
||||
rwlock_destroy(lock);
|
||||
cache:='';
|
||||
end;
|
||||
|
||||
function TDevStd.read (data:Pointer;size:Int64):Int64;
|
||||
var
|
||||
S:RawByteString;
|
||||
begin
|
||||
//
|
||||
rwlock_wrlock(lock);
|
||||
if (Length(cache)<>0) then
|
||||
begin
|
||||
if (size>Length(cache)) then
|
||||
begin
|
||||
size:=Length(cache);
|
||||
end;
|
||||
|
||||
Move(PChar(cache)^,data^,size);
|
||||
Delete(cache,1,size);
|
||||
|
||||
rwlock_unlock(lock);
|
||||
Exit(size);
|
||||
end;
|
||||
rwlock_unlock(lock);
|
||||
|
||||
S:='';
|
||||
System.ReadLn(Text^,S);
|
||||
S:=S+#10;
|
||||
|
||||
if (Length(S)>size) then
|
||||
begin
|
||||
Move(PChar(S)^,data^,size);
|
||||
Result:=size;
|
||||
|
||||
Delete(S,1,size);
|
||||
|
||||
rwlock_wrlock(lock);
|
||||
cache:=cache+S;
|
||||
rwlock_unlock(lock);
|
||||
end else
|
||||
begin
|
||||
size:=Length(S);
|
||||
Move(PChar(S)^,data^,size);
|
||||
Result:=size;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDevStd.pread (data:Pointer;size,offset:Int64):Int64;
|
||||
begin
|
||||
//
|
||||
Result:=read(data,size);
|
||||
end;
|
||||
|
||||
function TDevStd.readv (vector:p_iovec;count:Integer):Int64;
|
||||
var
|
||||
i,n:Integer;
|
||||
begin
|
||||
//
|
||||
Result:=0;
|
||||
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
n:=read(vector[i].iov_base,vector[i].iov_len);
|
||||
|
||||
if (n>0) then
|
||||
begin
|
||||
Result:=Result+n;
|
||||
if (n<vector[i].iov_len) then Exit;
|
||||
end else
|
||||
begin
|
||||
Exit(-EIO);
|
||||
Break;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDevStd.write (data:Pointer;size:Int64):Int64;
|
||||
var
|
||||
S:RawByteString;
|
||||
begin
|
||||
//
|
||||
SetString(S,data,size);
|
||||
System.Write(Text^,S);
|
||||
Result:=size;
|
||||
end;
|
||||
|
||||
function TDevStd.pwrite(data:Pointer;size,offset:Int64):Int64;
|
||||
begin
|
||||
//
|
||||
Result:=write(data,size);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
end.
|
||||
|
||||
|
369
sys/sys_dir.pas
Normal file
369
sys/sys_dir.pas
Normal file
@ -0,0 +1,369 @@
|
||||
unit sys_dir;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows,
|
||||
Classes,
|
||||
SysUtils,
|
||||
RWLock,
|
||||
sys_kernel,
|
||||
sys_time,
|
||||
sys_fd;
|
||||
|
||||
const
|
||||
// File types
|
||||
DT_UNKNOWN= 0; //The type is unknown.
|
||||
DT_FIFO = 1; //A named pipe, or FIFO.
|
||||
DT_CHR = 2; //A character device.
|
||||
DT_DIR = 4; //A directory.
|
||||
DT_BLK = 6; //A block device.
|
||||
DT_REG = 8; //A regular file.
|
||||
DT_LNK =10; //A symbolic link.
|
||||
DT_SOCK =12; //A local-domain socket.
|
||||
DT_WHT =14; //
|
||||
|
||||
type
|
||||
p_dirent=^dirent;
|
||||
dirent=packed object
|
||||
Const
|
||||
MAXNAMLEN=255;
|
||||
Var
|
||||
d_fileno:DWORD; // file number of entry
|
||||
d_reclen:WORD; // length of this record
|
||||
d_type :BYTE; // file type, see below
|
||||
d_namlen:BYTE; // length of string in d_name
|
||||
d_name :array[0..MAXNAMLEN] of AnsiChar; //name must be no longer than this
|
||||
end;
|
||||
|
||||
function _sys_dir_open(const path:RawByteString;flags,mode:Integer):Integer;
|
||||
function _sys_dir_stat(Const path:RawByteString;stat:PSceKernelStat):Integer;
|
||||
|
||||
implementation
|
||||
|
||||
type
|
||||
a_dirent=array of dirent;
|
||||
|
||||
TDirFile=class(TCustomFile)
|
||||
var
|
||||
lock:TRWLock;
|
||||
path:RawByteString;
|
||||
dirs:a_dirent;
|
||||
pos:DWORD;
|
||||
Constructor Create;
|
||||
Destructor Destroy; override;
|
||||
function read (data:Pointer;size:Int64):Int64; override;
|
||||
function pread (data:Pointer;size,offset:Int64):Int64; override;
|
||||
function readv (vector:p_iovec;count:Integer):Int64; override;
|
||||
function write (data:Pointer;size:Int64):Int64; override;
|
||||
function pwrite(data:Pointer;size,offset:Int64):Int64; override;
|
||||
function fstat (stat:PSceKernelStat):Integer; override;
|
||||
function lseek (offset:Int64;whence:Integer):Int64; override;
|
||||
function getdirentries(buf:Pointer;nbytes:Int64;basep:PInt64):Int64; override;
|
||||
end;
|
||||
|
||||
function get_d_type(dwFileAttributes:DWORD):BYTE;
|
||||
begin
|
||||
if (dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)<>0 then
|
||||
begin
|
||||
Result:=DT_DIR;
|
||||
end else
|
||||
begin
|
||||
Result:=DT_REG;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure move_dirent(id:DWORD;src:PWIN32FindDataW;buf:Pointer);
|
||||
var
|
||||
p:p_dirent;
|
||||
f:RawByteString;
|
||||
len:ptruint;
|
||||
begin
|
||||
f:=UTF8Encode(WideString(src^.cFileName));
|
||||
len:=Length(f);
|
||||
if (len>dirent.MAXNAMLEN) then len:=dirent.MAXNAMLEN;
|
||||
|
||||
Inc(len);
|
||||
SetLength(f,len);
|
||||
f[len]:=#0;
|
||||
|
||||
p:=buf;
|
||||
p^.d_fileno:=id;
|
||||
p^.d_reclen:=SizeOf(dirent);
|
||||
p^.d_type :=get_d_type(src^.dwFileAttributes);
|
||||
p^.d_namlen:=BYTE(len-1);
|
||||
|
||||
Move(PChar(f)^,p^.d_name,len);
|
||||
end;
|
||||
|
||||
function get_dir_wp(const path:RawByteString):WideString;
|
||||
begin
|
||||
Result:=UTF8Decode(IncludeTrailingPathDelimiter(path)+'*');
|
||||
end;
|
||||
|
||||
function _sys_dir_open(const path:RawByteString;flags,mode:Integer):Integer;
|
||||
var
|
||||
f:TDirFile;
|
||||
h:THandle;
|
||||
err:DWORD;
|
||||
wp:WideString;
|
||||
data:TWIN32FindDataW;
|
||||
tmp:dirent;
|
||||
i:Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
|
||||
wp:=get_dir_wp(path);
|
||||
|
||||
data:=Default(TWIN32FindDataW);
|
||||
h:=FindFirstFileW(PWideChar(wp),data);
|
||||
|
||||
err:=0;
|
||||
if (h=INVALID_HANDLE_VALUE) then
|
||||
begin
|
||||
err:=GetLastError;
|
||||
Case err of
|
||||
ERROR_INVALID_DRIVE,
|
||||
ERROR_PATH_NOT_FOUND :Exit(-ENOENT);
|
||||
ERROR_ACCESS_DENIED :Exit(-EACCES);
|
||||
ERROR_BUFFER_OVERFLOW :Exit(-ENAMETOOLONG);
|
||||
ERROR_NOT_ENOUGH_MEMORY:Exit(-ENOMEM);
|
||||
ERROR_DISK_FULL :Exit(-ENOSPC);
|
||||
ERROR_FILE_NOT_FOUND :;
|
||||
else
|
||||
Exit(-EIO);
|
||||
end;
|
||||
end;
|
||||
|
||||
f:=TDirFile.Create;
|
||||
f.path:=path;
|
||||
|
||||
if (err<>ERROR_FILE_NOT_FOUND) then
|
||||
begin
|
||||
tmp:=Default(dirent);
|
||||
move_dirent(0,@data,@tmp);
|
||||
|
||||
SetLength(f.dirs,1);
|
||||
f.dirs[0]:=tmp;
|
||||
|
||||
repeat
|
||||
if FindNextFileW(h,data) then
|
||||
begin
|
||||
tmp:=Default(dirent);
|
||||
move_dirent(0,@data,@tmp);
|
||||
|
||||
i:=Length(f.dirs);
|
||||
SetLength(f.dirs,i+1);
|
||||
f.dirs[i]:=tmp;
|
||||
end else
|
||||
begin
|
||||
err:=GetLastError;
|
||||
Case err of
|
||||
ERROR_FILE_NOT_FOUND:
|
||||
begin
|
||||
Break;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
Windows.FindClose(h);
|
||||
f.Destroy;
|
||||
Exit(-EIO);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
until false;
|
||||
end;
|
||||
|
||||
Result:=_sys_open_fd(f);
|
||||
|
||||
if (Result<0) then
|
||||
begin
|
||||
f.Release;
|
||||
end else
|
||||
begin
|
||||
f.Destroy;
|
||||
end;
|
||||
end;
|
||||
|
||||
function _sys_dir_stat(Const path:RawByteString;stat:PSceKernelStat):Integer;
|
||||
var
|
||||
hfi:WIN32_FILE_ATTRIBUTE_DATA;
|
||||
err:DWORD;
|
||||
begin
|
||||
stat^:=Default(SceKernelStat);
|
||||
|
||||
hfi:=Default(WIN32_FILE_ATTRIBUTE_DATA);
|
||||
err:=SwGetFileAttributes(path,@hfi);
|
||||
if (err<>0) then
|
||||
begin
|
||||
Case err of
|
||||
ERROR_ACCESS_DENIED,
|
||||
ERROR_SHARING_VIOLATION,
|
||||
ERROR_LOCK_VIOLATION,
|
||||
ERROR_SHARING_BUFFER_EXCEEDED:
|
||||
Exit(EACCES);
|
||||
|
||||
ERROR_BUFFER_OVERFLOW:
|
||||
Exit(ENAMETOOLONG);
|
||||
|
||||
ERROR_NOT_ENOUGH_MEMORY:
|
||||
Exit(ENOMEM);
|
||||
|
||||
else
|
||||
Exit(ENOENT);
|
||||
end;
|
||||
end;
|
||||
|
||||
stat^.st_mode :=S_IFDIR;
|
||||
stat^.st_size :=hfi.nFileSizeLow or (QWORD(hfi.nFileSizeHigh) shl 32);
|
||||
stat^.st_nlink :=1;
|
||||
|
||||
stat^.st_atim :=filetime_to_timespec(hfi.ftLastAccessTime);
|
||||
stat^.st_mtim :=filetime_to_timespec(hfi.ftLastWriteTime);
|
||||
stat^.st_ctim :=stat^.st_mtim;
|
||||
stat^.st_birthtim:=filetime_to_timespec(hfi.ftCreationTime);
|
||||
|
||||
stat^.st_blocks :=0;
|
||||
stat^.st_blksize :=SizeOf(dirent);
|
||||
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Constructor TDirFile.Create;
|
||||
begin
|
||||
pos:=0;
|
||||
Handle:=INVALID_HANDLE_VALUE;
|
||||
rwlock_init(lock);
|
||||
dirs:=Default(a_dirent);
|
||||
end;
|
||||
|
||||
Destructor TDirFile.Destroy;
|
||||
begin
|
||||
dirs:=Default(a_dirent);
|
||||
rwlock_destroy(lock);
|
||||
end;
|
||||
|
||||
function TDirFile.read (data:Pointer;size:Int64):Int64;
|
||||
begin
|
||||
Result:=-EISDIR;
|
||||
end;
|
||||
|
||||
function TDirFile.pread (data:Pointer;size,offset:Int64):Int64;
|
||||
begin
|
||||
Result:=-EISDIR;
|
||||
end;
|
||||
|
||||
function TDirFile.readv (vector:p_iovec;count:Integer):Int64;
|
||||
begin
|
||||
Result:=-EISDIR;
|
||||
end;
|
||||
|
||||
function TDirFile.write (data:Pointer;size:Int64):Int64;
|
||||
begin
|
||||
Result:=-EISDIR;
|
||||
end;
|
||||
|
||||
function TDirFile.pwrite(data:Pointer;size,offset:Int64):Int64;
|
||||
begin
|
||||
Result:=-EISDIR;
|
||||
end;
|
||||
|
||||
function TDirFile.fstat (stat:PSceKernelStat):Integer;
|
||||
begin
|
||||
Result:=_sys_dir_stat(path,stat);
|
||||
if (Result=0) then
|
||||
begin
|
||||
stat^.st_dev :=fd;
|
||||
stat^.st_rdev:=fd;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDirFile.lseek (offset:Int64;whence:Integer):Int64;
|
||||
begin
|
||||
rwlock_wrlock(lock);
|
||||
case whence of
|
||||
SEEK_SET:
|
||||
begin
|
||||
if (offset>=0) then
|
||||
begin
|
||||
pos:=offset;
|
||||
Result:=offset;
|
||||
end else
|
||||
begin
|
||||
Result:=-EINVAL;
|
||||
end;
|
||||
end;
|
||||
SEEK_CUR:
|
||||
begin
|
||||
offset:=offset+pos;
|
||||
if (offset>=0) then
|
||||
begin
|
||||
pos:=offset;
|
||||
Result:=offset;
|
||||
end else
|
||||
begin
|
||||
Result:=-EINVAL;
|
||||
end;
|
||||
end;
|
||||
SEEK_END:
|
||||
begin
|
||||
offset:=offset+Length(dirs);
|
||||
if (offset>=0) then
|
||||
begin
|
||||
pos:=offset;
|
||||
Result:=offset;
|
||||
end else
|
||||
begin
|
||||
Result:=-EINVAL;
|
||||
end;
|
||||
end;
|
||||
else
|
||||
Result:=-EINVAL;
|
||||
end;
|
||||
rwlock_unlock(lock);
|
||||
end;
|
||||
|
||||
function TDirFile.getdirentries(buf:Pointer;nbytes:Int64;basep:PInt64):Int64;
|
||||
var
|
||||
i,count:DWORD;
|
||||
begin
|
||||
count:=nbytes div SizeOf(dirent);
|
||||
|
||||
rwlock_wrlock(lock);
|
||||
i:=pos+count;
|
||||
if (i>Length(dirs)) then
|
||||
begin
|
||||
i:=Length(dirs);
|
||||
if (pos>i) then
|
||||
begin
|
||||
count:=0;
|
||||
end else
|
||||
begin
|
||||
count:=(i-pos);
|
||||
end;
|
||||
end;
|
||||
|
||||
if (count<>0) then
|
||||
begin
|
||||
Move(dirs[pos],buf^,count);
|
||||
end;
|
||||
|
||||
pos:=i;
|
||||
rwlock_unlock(lock);
|
||||
|
||||
if (basep<>nil) then
|
||||
begin
|
||||
basep^:=i;
|
||||
end;
|
||||
|
||||
Result:=count*SizeOf(dirent);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
end.
|
||||
|
@ -196,13 +196,14 @@ type
|
||||
var
|
||||
fd:Integer;
|
||||
Handle:THandle;
|
||||
function lseek (offset:Int64;whence:Integer):Int64; virtual;
|
||||
function read (data:Pointer;size:Int64):Int64; virtual;
|
||||
function pread (data:Pointer;size,offset:Int64):Int64; virtual;
|
||||
function readv (vector:p_iovec;count:Integer):Int64; virtual;
|
||||
function write (data:Pointer;size:Int64):Int64; virtual;
|
||||
function pwrite(data:Pointer;size,offset:Int64):Int64; virtual;
|
||||
function fstat (stat:PSceKernelStat):Integer; virtual;
|
||||
function lseek (offset:Int64;whence:Integer):Int64; virtual;
|
||||
function read (data:Pointer;size:Int64):Int64; virtual;
|
||||
function pread (data:Pointer;size,offset:Int64):Int64; virtual;
|
||||
function readv (vector:p_iovec;count:Integer):Int64; virtual;
|
||||
function write (data:Pointer;size:Int64):Int64; virtual;
|
||||
function pwrite(data:Pointer;size,offset:Int64):Int64; virtual;
|
||||
function fstat (stat:PSceKernelStat):Integer; virtual;
|
||||
function getdirentries(buf:Pointer;nbytes:Int64;basep:PInt64):Int64; virtual;
|
||||
end;
|
||||
|
||||
function _sys_get_osfhandle(fd:Integer):THandle;
|
||||
@ -251,6 +252,11 @@ begin
|
||||
Result:=-ENOTSUP;
|
||||
end;
|
||||
|
||||
function TCustomFile.getdirentries(buf:Pointer;nbytes:Int64;basep:PInt64):Int64;
|
||||
begin
|
||||
Result:=-EINVAL;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function _sys_get_osfhandle(fd:Integer):THandle;
|
||||
|
@ -379,6 +379,9 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
stat^.st_dev :=fd;
|
||||
stat^.st_rdev :=fd;
|
||||
|
||||
stat^.st_mode :=file_attr_to_st_mode(hfi.dwFileAttributes);
|
||||
stat^.st_size :=hfi.nFileSizeLow or (QWORD(hfi.nFileSizeHigh) shl 32);
|
||||
stat^.st_nlink :=Word(hfi.nNumberOfLinks);
|
||||
|
Loading…
Reference in New Issue
Block a user