diff --git a/kernel/ps4_kernel_file.pas b/kernel/ps4_kernel_file.pas index 6d56991..7fe7d9e 100644 --- a/kernel/ps4_kernel_file.pas +++ b/kernel/ps4_kernel_file.pas @@ -8,189 +8,12 @@ uses windows, sys_types, sys_path, + sys_fd, + sys_file, + sys_dev, Classes, SysUtils; -const - NAME_MAX =255; // max bytes in a file name - PATH_MAX =1024; // max bytes in pathname - IOV_MAX =1024; // max elements in i/o vector - MAXNAMLEN =255; - - O_RDONLY =$0000; // open for reading only - O_WRONLY =$0001; // open for writing only - O_RDWR =$0002; // open for reading and writing - O_ACCMODE =$0003; // mask for above modes - - O_NONBLOCK =$0004; // no delay - O_APPEND =$0008; // set append mode - O_SYNC =$0080; // POSIX synonym for O_FSYNC - O_CREAT =$0200; // create if nonexistent - O_TRUNC =$0400; // truncate to zero length - O_EXCL =$0800; // error if already exists - O_DSYNC =$1000; // synchronous data writes(omit inode writes) - - O_DIRECT =$00010000; - O_FSYNC =$0080; // synchronous writes - - O_DIRECTORY =$00020000; // Fail if not directory - O_EXEC =$00040000; // Open for execute only - - S_IRWXU =&0000700; // RWX mask for owner - S_IRUSR =&0000400; // R for owner - S_IWUSR =&0000200; // W for owner - S_IXUSR =&0000100; // X for owner - - S_IRWXG =&0000070; // RWX mask for group - S_IRGRP =&0000040; // R for group - S_IWGRP =&0000020; // W for group - S_IXGRP =&0000010; // X for group - - S_IRWXO =&0000007; // RWX mask for other - S_IROTH =&0000004; // R for other - S_IWOTH =&0000002; // W for other - S_IXOTH =&0000001; // X for other - - S_IFMT =&0170000; // type of file mask - S_IFIFO =&0010000; // named pipe (fifo) - S_IFCHR =&0020000; // character special - S_IFDIR =&0040000; // directory - S_IFBLK =&0060000; // block special - S_IFREG =&0100000; // regular - S_IFLNK =&0120000; // symbolic link - S_IFSOCK =&0140000; // socket - S_ISVTX =&0001000; // save swapped text even after use - - F_GETFL =3; // get file status flags - F_SETFL =4; // set file status flags - - SEEK_SET =0; // set file offset to offset - SEEK_CUR =1; // set file offset to current plus offset - SEEK_END =2; // set file offset to EOF plus offset - - MAP_SHARED =$0001; // share changes - MAP_PRIVATE =$0002; // changes are private - - MAP_FILE =$0000; // map from file (default) - MAP_ANON =$1000; // allocated from memory, swap space - MAP_SYSTEM =$2000; - - MAP_NOCORE =$00020000; // dont include these pages in a coredump - MAP_NOSYNC =$0800; // page to but do not sync underlying file - MAP_PREFAULT_READ =$00040000; // prefault mapping for reading - - DT_UNKNOWN =0; - DT_DIR =4; - DT_REG =8; - - SCE_KERNEL_NAME_MAX =NAME_MAX; - SCE_KERNEL_PATH_MAX =PATH_MAX; - SCE_KERNEL_IOV_MAX =IOV_MAX; - SCE_KERNEL_MAXNAMLEN =MAXNAMLEN; - - SCE_KERNEL_O_RDONLY =O_RDONLY; - SCE_KERNEL_O_WRONLY =O_WRONLY; - SCE_KERNEL_O_RDWR =O_RDWR ; - SCE_KERNEL_O_NONBLOCK =O_NONBLOCK; - SCE_KERNEL_O_APPEND =O_APPEND; - SCE_KERNEL_O_CREAT =O_CREAT; - SCE_KERNEL_O_TRUNC =O_TRUNC; - SCE_KERNEL_O_EXCL =O_EXCL; - SCE_KERNEL_O_DIRECT =O_DIRECT; - SCE_KERNEL_O_FSYNC =O_FSYNC; - SCE_KERNEL_O_SYNC =O_SYNC; - SCE_KERNEL_O_DSYNC =O_DSYNC; - SCE_KERNEL_O_DIRECTORY =O_DIRECTORY; - - SCE_KERNEL_S_IFMT =S_IFMT; - SCE_KERNEL_S_IFDIR =S_IFDIR; - SCE_KERNEL_S_IFREG =S_IFREG; - - SCE_KERNEL_S_IRUSR =(S_IRUSR or S_IRGRP or S_IROTH or S_IXUSR or S_IXGRP or S_IXOTH); - SCE_KERNEL_S_IWUSR =(S_IWUSR or S_IWGRP or S_IWOTH or S_IXUSR or S_IXGRP or S_IXOTH); - SCE_KERNEL_S_IXUSR =(S_IXUSR or S_IXGRP or S_IXOTH); - SCE_KERNEL_S_IRWXU =(SCE_KERNEL_S_IRUSR or SCE_KERNEL_S_IWUSR); - - SCE_KERNEL_S_IRWU =(SCE_KERNEL_S_IRUSR or SCE_KERNEL_S_IWUSR); -// 00777, R/W - SCE_KERNEL_S_IRU =(SCE_KERNEL_S_IRUSR); -// 00555, R - - SCE_KERNEL_S_INONE =&0000000; - - //SCE_KERNEL_S_ISDIR(m) =S_ISDIR(m); - //SCE_KERNEL_S_ISREG(m) =S_ISREG(m); - -// for sceKernelFcntl() - SCE_KERNEL_F_GETFL =F_GETFL; - SCE_KERNEL_F_SETFL =F_SETFL; - -// for sceKernelLseek() - SCE_KERNEL_SEEK_SET =SEEK_SET; - SCE_KERNEL_SEEK_CUR =SEEK_CUR; - SCE_KERNEL_SEEK_END =SEEK_END; - -// for sceKernelMmap() - SCE_KERNEL_MAP_NOCORE =MAP_NOCORE; - SCE_KERNEL_MAP_NOSYNC =MAP_NOSYNC; - SCE_KERNEL_MAP_PREFAULT_READ=MAP_PREFAULT_READ; - SCE_KERNEL_MAP_PRIVATE =MAP_PRIVATE; - SCE_KERNEL_MAP_SHARED =MAP_SHARED; - -// for SceKernelDirent - SCE_KERNEL_DT_UNKNOWN =DT_UNKNOWN; - SCE_KERNEL_DT_DIR =DT_DIR; - SCE_KERNEL_DT_REG =DT_REG; - -// for sceKernelSetCompress - SCE_KERNEL_COMPRESS_FILE_MAGIC =($43534650); - SCE_KERNEL_SET_COMPRESS_FILE =(1); - SCE_KERNEL_SET_REGULAR_FILE =(0); - -// for sceKernelLwfsSetAttribute - SCE_KERNEL_LWFS_DISABLE =(0); - SCE_KERNEL_LWFS_ENABLE =(1); - -type - p_iovec=^iovec; - iovec=packed record - iov_base:Pointer; //Base address. - iov_len :Int64; //Length. - end; - - PSceKernelStat=^SceKernelStat; - SceKernelStat=packed object - type - __dev_t =DWORD; - ino_t =DWORD; - mode_t =Word; - nlink_t =Word; - uid_t =DWORD; - gid_t =DWORD; - off_t =Int64; - blkcnt_t =Int64; - blksize_t=DWORD; - fflags_t =DWORD; - var - st_dev :__dev_t ; // inode's device - st_ino :ino_t ; // inode's number - st_mode :mode_t ; // inode protection mode S_IFMT..... - st_nlink :nlink_t ; // number of hard links - st_uid :uid_t ; // user ID of the file's owner S_IRWXU.... - st_gid :gid_t ; // group ID of the file's group S_IRWXG.... - st_rdev :__dev_t ; // device type - st_atim :timespec ; // time of last access - st_mtim :timespec ; // time of last data modification - st_ctim :timespec ; // time of last file status change - st_size :off_t ; // file size, in bytes - st_blocks :blkcnt_t ; // blocks allocated for file - st_blksize :blksize_t ; // optimal blocksize for I/O - st_flags :fflags_t ; // user defined flags for file - st_gen :DWORD ; // file generation number - st_lspare :DWORD ; - st_birthtim:timespec ; // time of file creation - end; - function ps4_open(path:PChar;flags,mode:Integer):Integer; SysV_ABI_CDecl; function ps4_sceKernelOpen(path:PChar;flags,mode:Integer):Integer; SysV_ABI_CDecl; diff --git a/sys/sys_dev.pas b/sys/sys_dev.pas new file mode 100644 index 0000000..3c44a72 --- /dev/null +++ b/sys/sys_dev.pas @@ -0,0 +1,192 @@ +unit sys_dev; + +{$mode ObjFPC}{$H+} + +interface + +uses + Windows, + Classes, + SysUtils, + RWLock, + sys_kernel, + sys_time, + sys_fd; + +function _sys_dev_open(const path:RawByteString;flags,mode:Integer):Integer; + +implementation + +type + TDevFile=class(TCustomFile) + Constructor Create; + function lseek (offset:Int64;whence:Integer):Int64; override; + function fstat (stat:PSceKernelStat):Integer; override; + end; + + TDevRandom=class(TDevFile) + 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; + end; + + TDevStd=class(TDevFile) + Text:PText; + cache:TMemoryStream; + Constructor Create(t:PText); + 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; + end; + +function _sys_dev_open(const path:RawByteString;flags,mode:Integer):Integer; +var + f:TCustomFile; +begin + + Case path of + 'stdin' :f:=TDevStd.Create(@Input); + 'stdout':f:=TDevStd.Create(@StdOut); + 'stderr':f:=TDevStd.Create(@StdErr); + + 'random', + 'urandom': + begin + f:=TDevRandom.Create; + end; + else + Exit(-ENOENT); + end; + + Result:=_sys_open_fd(f); + + if (Result<0) then + begin + f.Release; + end else + begin + f.Destroy; + end; +end; + +// + +Constructor TDevFile.Create; +begin + Handle:=INVALID_HANDLE_VALUE; +end; + +function TDevFile.lseek (offset:Int64;whence:Integer):Int64; +begin + Result:=-ESPIPE; +end; + +function TDevFile.fstat (stat:PSceKernelStat):Integer; +begin + Result:=0; + stat^:=Default(SceKernelStat); + stat^.st_dev :=fd; + stat^.st_rdev :=fd; + stat^.st_mode :=S_IFCHR; + stat^.st_nlink:=1; +end; + +// + +const + BCRYPT_USE_SYSTEM_PREFERRED_RNG=2; + +function BCryptGenRandom(hAlgorithm:Pointer; + pbBuffer:PByte; + cbBuffer:DWORD; + dwFlags:DWORD):DWORD; stdcall; external 'Bcrypt'; + +function TDevRandom.read (data:Pointer;size:Int64):Int64; +begin + Assert(sizenil) then + begin + Result:=f.Handle; + f.Release; + end; +end; + +function _sys_open_fd(f:TCustomFile):Integer; +begin + if (f=nil) then Exit(-EINVAL); + if FileHandles.New(f,Result) then + begin + f.fd:=Result; + end else + begin + Result:=-EMFILE; + end; +end; + +function _sys_close(fd:Integer):Integer; +begin + Result:=0; + if (fd<0) then Exit(EINVAL); + if not FileHandles.Delete(fd) then Exit(EBADF); +end; + +// + +initialization + FileHandles:=TIntegerHandles.Create; + FileHandles.min_key:=0; + +end. + diff --git a/sys/sys_file.pas b/sys/sys_file.pas new file mode 100644 index 0000000..49595ed --- /dev/null +++ b/sys/sys_file.pas @@ -0,0 +1,408 @@ +unit sys_file; + +{$mode ObjFPC}{$H+} + +interface + +uses + Windows, + Classes, + SysUtils, + RWLock, + sys_kernel, + sys_time, + sys_fd; + +function _sys_file_open(const path:RawByteString;flags,mode:Integer):Integer; + +implementation + +type + TFile=class(TCustomFile) + var + lock:TRWLock; + Constructor Create; + Destructor Destroy; override; + function lseek (offset:Int64;whence:Integer):Int64; 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; + end; + +Function get_DesiredAccess(flags:Integer):DWORD; +begin + Result:=0; + if (flags and SCE_KERNEL_O_RDWR)<>0 then + begin + Result:=GENERIC_READ or GENERIC_WRITE; + end else + if (flags and SCE_KERNEL_O_WRONLY)<>0 then + begin + Result:=GENERIC_WRITE; + end else + begin + Result:=GENERIC_READ; + end; + + if (flags and SCE_KERNEL_O_APPEND)<>0 then + begin + Result:=Result or FILE_APPEND_DATA; + end; +end; + +Function get_CreationDisposition(flags:Integer):DWORD; +const + CREAT_EXCL=SCE_KERNEL_O_CREAT or SCE_KERNEL_O_EXCL; +begin + Result:=0; + if (flags and CREAT_EXCL)=CREAT_EXCL then + begin + Result:=CREATE_NEW; + end else + if (flags and SCE_KERNEL_O_CREAT)<>0 then + begin + Result:=CREATE_ALWAYS; + end else + if (flags and SCE_KERNEL_O_TRUNC)<>0 then + begin + Result:=TRUNCATE_EXISTING; + end else + begin + Result:=OPEN_EXISTING; + end; +end; + +function _sys_file_open(const path:RawByteString;flags,mode:Integer):Integer; +var + f:TFile; + h:THandle; + + err:DWORD; + dwDesiredAccess:DWORD; + dwCreationDisposition:DWORD; + + wp:WideString; +begin + Result:=0; + + wp:=UTF8Decode(path); + + dwDesiredAccess:=get_DesiredAccess(flags); + dwCreationDisposition:=get_CreationDisposition(flags); + + h:=CreateFileW( + PWideChar(wp), + dwDesiredAccess, + FILE_SHARE_READ, + nil, + dwCreationDisposition, + FILE_ATTRIBUTE_NORMAL, + 0 + ); + + if (h=INVALID_HANDLE_VALUE) then + begin + err:=GetLastError; + //Writeln('GetLastError:',err{,' ',ps4_pthread_self^.sig._lock}); + Case err of + ERROR_INVALID_DRIVE, + ERROR_PATH_NOT_FOUND, + ERROR_FILE_NOT_FOUND :Exit(-ENOENT); + ERROR_ACCESS_DENIED :Exit(-EACCES); + ERROR_BUFFER_OVERFLOW :Exit(-ENAMETOOLONG); + ERROR_NOT_ENOUGH_MEMORY:Exit(-ENOMEM); + ERROR_ALREADY_EXISTS :Exit(-EEXIST); + ERROR_FILE_EXISTS :Exit(-EEXIST); + ERROR_DISK_FULL :Exit(-ENOSPC); + else + Exit(-EIO); + end; + end; + + f:=TFile.Create; + f.Handle:=h; + + Result:=_sys_open_fd(f); + + if (Result<0) then + begin + f.Release; + end else + begin + f.Destroy; + end; +end; + +// + +Constructor TFile.Create; +begin + rwlock_init(lock); +end; + +Destructor TFile.Destroy; +begin + rwlock_destroy(lock); + CloseHandle(Handle); +end; + +function SetFilePointerEx(hFile:HANDLE; + liDistanceToMove:LARGE_INTEGER; + lpNewFilePointer:PLARGE_INTEGER; + dwMoveMethod:DWORD):BOOL; external 'kernel32'; + +function TFile.lseek (offset:Int64;whence:Integer):Int64; +var + err:DWORD; + R:BOOL; +begin + Result:=0; + + rwlock_wrlock(lock); + R:=SetFilePointerEx(Handle,LARGE_INTEGER(offset),@Result,whence); + rwlock_unlock(lock); + + if not R then + begin + err:=GetLastError; + Case err of + ERROR_HANDLE_EOF :Exit(-EOVERFLOW); + ERROR_INVALID_PARAMETER:Exit(-EINVAL); + else + Exit(-EOVERFLOW); + end; + end; +end; + +function TFile.read (data:Pointer;size:Int64):Int64; +var + N:DWORD; + R:BOOL; +begin + Assert(size0) then + Result:=Result or S_IFDIR + else + Result:=Result or S_IFREG; + + if ((attr and FILE_ATTRIBUTE_READONLY)=0) then + Result:=Result or S_IWUSR; +end; + +function TFile.fstat (stat:PSceKernelStat):Integer; +var + hfi:TByHandleFileInformation; + err:DWORD; +begin + stat^:=Default(SceKernelStat); + + Case SwGetFileType(Handle) of + FILE_TYPE_PIPE: + begin + stat^.st_dev :=fd; + stat^.st_rdev :=fd; + stat^.st_mode :=S_IFIFO; + stat^.st_nlink:=1; + end; + FILE_TYPE_CHAR: + begin + stat^.st_dev :=fd; + stat^.st_rdev :=fd; + stat^.st_mode :=S_IFCHR; + stat^.st_nlink:=1; + end; + FILE_TYPE_DISK: + begin + err:=SwGetFileInformationByHandle(Handle,@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 :=file_attr_to_st_mode(hfi.dwFileAttributes); + stat^.st_size :=hfi.nFileSizeLow or (QWORD(hfi.nFileSizeHigh) shl 32); + stat^.st_nlink :=Word(hfi.nNumberOfLinks); + stat^.st_gen :=hfi.nFileIndexLow; + + 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 :=((stat^.st_size+511) div 512); + stat^.st_blksize :=512; + end; + + else + Exit(EBADF); + end; + + Result:=0; +end; + +// + +end. + + +