diff --git a/kernel/ps4_kernel_file.pas b/kernel/ps4_kernel_file.pas index 7fe7d9e..db979fa 100644 --- a/kernel/ps4_kernel_file.pas +++ b/kernel/ps4_kernel_file.pas @@ -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 diff --git a/sys/sys_dev.pas b/sys/sys_dev.pas index 3c44a72..6db8753 100644 --- a/sys/sys_dev.pas +++ b/sys/sys_dev.pas @@ -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 (n0 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. + diff --git a/sys/sys_fd.pas b/sys/sys_fd.pas index 980a6d5..a84c59a 100644 --- a/sys/sys_fd.pas +++ b/sys/sys_fd.pas @@ -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; diff --git a/sys/sys_file.pas b/sys/sys_file.pas index 49595ed..d3aaba5 100644 --- a/sys/sys_file.pas +++ b/sys/sys_file.pas @@ -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);