diff --git a/sys/dev/dev_dmem.pas b/sys/dev/dev_dmem.pas
new file mode 100644
index 00000000..b9664253
--- /dev/null
+++ b/sys/dev/dev_dmem.pas
@@ -0,0 +1,82 @@
+unit dev_dmem;
+
+{$mode ObjFPC}{$H+}
+{$CALLING SysV_ABI_CDecl}
+
+interface
+
+uses
+ kern_conf;
+
+procedure dmemdev_init();
+
+implementation
+
+uses
+ errno,
+ vuio,
+ subr_uio,
+ vm,
+ kern_dmem;
+
+Const
+ SCE_KERNEL_MAIN_DMEM_SIZE=$180000000; //6GB
+
+Function dmem_ioctl(dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer;
+begin
+ Result:=0;
+
+ Writeln('dmem_ioctl("',dev^.si_name,'",0x',HexStr(cmd,8),',0x',HexStr(fflag,8),')');
+
+ case cmd of
+ $4008800A: //sceKernelGetDirectMemorySize
+ begin
+ PQWORD(data)^:=SCE_KERNEL_MAIN_DMEM_SIZE;
+ end;
+ else
+ Assert(False);
+ end;
+
+end;
+
+Function dmem_mmap(dev:p_cdev;offset:vm_ooffset_t;paddr:p_vm_paddr_t;nprot:Integer;memattr:p_vm_memattr_t):Integer;
+begin
+ Result:=0;
+
+ Writeln('dmem_mmap("',dev^.si_name,'",0x',HexStr(offset,8),',0x',HexStr(paddr),',',nprot,')');
+ Assert(False);
+end;
+
+const
+ dmem_cdevsw:t_cdevsw=(
+ d_version :D_VERSION;
+ d_flags :0;
+ d_name :'dmem';
+ d_open :nil;
+ d_fdopen :nil;
+ d_close :nil;
+ d_read :nil;
+ d_write :nil;
+ d_ioctl :@dmem_ioctl;
+ d_poll :nil;
+ d_mmap :@dmem_mmap;
+ d_strategy :nil;
+ d_dump :nil;
+ d_kqfilter :nil;
+ d_purge :nil;
+ d_mmap_single:nil;
+ );
+
+procedure dmemdev_init();
+var
+ i:Integer;
+begin
+ For i:=0 to 2 do
+ begin
+ make_dev(@dmem_cdevsw,i,0,0,&777,'dmem%d',[i]);
+ end;
+end;
+
+
+end.
+
diff --git a/sys/dev/dev_null.pas b/sys/dev/dev_null.pas
index 49b993a8..c2ac9e5e 100644
--- a/sys/dev/dev_null.pas
+++ b/sys/dev/dev_null.pas
@@ -13,9 +13,9 @@ const
var
zero_region:Pointer;
- _zero_region:array[0..ZERO_REGION_SIZE-1] of Byte;
procedure init_zero_region;
+procedure free_zero_region;
Function null_modevent(_mod,_type:Integer):Integer; //DEV_MODULE(nil, null_modevent, nil);
@@ -109,7 +109,9 @@ begin
end;
end;
else
+ begin
error:=ENOIOCTL;
+ end;
end;
Exit(error);
@@ -132,21 +134,36 @@ begin
end;
end;
else
+ begin
error:=ENOIOCTL;
+ end;
end;
Exit(error);
end;
procedure init_zero_region;
+var
+ buf:Pointer;
begin
if (zero_region=nil) then
begin
- FillChar(_zero_region,SizeOf(_zero_region),0);
- zero_region:=@_zero_region;
+ buf:=AllocMem(ZERO_REGION_SIZE);
+ if (System.InterlockedCompareExchange(zero_region,buf,nil)<>nil) then
+ begin
+ FreeMem(buf);
+ end;
end;
end;
+procedure free_zero_region;
+var
+ buf:Pointer;
+begin
+ buf:=System.InterlockedExchange(zero_region,nil);
+ FreeMem(buf);
+end;
+
{ ARGSUSED }
Function zero_read(dev:p_cdev;uio:p_uio;ioflag:Integer):Integer;
var
@@ -188,6 +205,7 @@ begin
begin
destroy_dev(null_dev);
destroy_dev(zero_dev);
+ free_zero_region;
end;
MOD_SHUTDOWN:;
diff --git a/sys/dev/dev_tty.pas b/sys/dev/dev_tty.pas
index d6e4214e..e4144259 100644
--- a/sys/dev/dev_tty.pas
+++ b/sys/dev/dev_tty.pas
@@ -33,7 +33,7 @@ var
}
Function ttydev_open(dev:p_cdev;oflags,devtype:Integer):Integer;
begin
- Writeln('ttydev_open(',dev^.si_name,',',oflags,',',devtype,')');
+ Writeln('ttydev_open("',dev^.si_name,'",',oflags,',',devtype,')');
Result:=0;
end;
@@ -110,7 +110,7 @@ begin
else;
end;
- Writeln('ttydev_ioctl(0',dev^.si_name,',0x',HexStr(cmd,8),',0x',HexStr(data),',0x',HexStr(fflag,8));
+ Writeln('ttydev_ioctl("',dev^.si_name,'",0x',HexStr(cmd,8),',0x',HexStr(data),',0x',HexStr(fflag,8),')');
//error:=tty_ioctl(tp, cmd, data, fflag, td);
//done:
@@ -343,27 +343,27 @@ const
* will be logged in the kernel message buffer.
}
- function tty_makedev(fmt:PChar;const Args:Array of const):p_cdev; register;
- var
- dev:p_cdev;
- uid:uid_t;
- gid:gid_t;
- mode:mode_t;
- begin
- // User device.
- uid :=0;
- gid :=GID_TTY;
- mode:=S_IRUSR or S_IWUSR or S_IWGRP;
+function tty_makedev(fmt:PChar;const Args:Array of const):p_cdev; register;
+var
+ dev:p_cdev;
+ uid:uid_t;
+ gid:gid_t;
+ mode:mode_t;
+begin
+ // User device.
+ uid :=0;
+ gid :=GID_TTY;
+ mode:=S_IRUSR or S_IWUSR or S_IWGRP;
- dev:=make_dev_cred(@ttydev_cdevsw, 0, uid, gid, mode, fmt, Args);
+ dev:=make_dev_cred(@ttydev_cdevsw, 0, uid, gid, mode, fmt, Args);
- Result:=dev;
- end;
+ Result:=dev;
+end;
procedure ttyconsdev_init();
begin
dev_console:=make_dev_credf(MAKEDEV_ETERNAL, @ttyconsdev_cdevsw, 0, UID_ROOT, GID_WHEEL, &600, 'console',[]);
-
+ //
tty_makedev('deci_stderr',[]);
tty_makedev('deci_stdin' ,[]);
tty_makedev('deci_stdout',[]);
diff --git a/sys/fs/devfs/devfs_vnops.pas b/sys/fs/devfs/devfs_vnops.pas
index e3447aef..8c5976c9 100644
--- a/sys/fs/devfs/devfs_vnops.pas
+++ b/sys/fs/devfs/devfs_vnops.pas
@@ -227,7 +227,9 @@ begin
if (devp^<>fp^.f_data) then
begin
if (dswp^<>nil) then
+ begin
dev_relthread(devp^, ref^);
+ end;
Exit(ENXIO);
end;
@@ -252,7 +254,9 @@ begin
error:=0;
datap^:=p^.cdpd_data;
end else
+ begin
error:=ENOENT;
+ end;
Exit(error);
end;
@@ -390,7 +394,9 @@ begin
error:=devfs_populate_vp(vp);
if (error<>0) then
+ begin
Exit(error);
+ end;
i:=buflen^;
dd:=vp^.v_data;
@@ -500,7 +506,9 @@ var
begin
not_found:=0;
if ((de^.de_flags and DE_DOOMED)<>0) then
+ begin
not_found:=1;
+ end;
if DEVFS_DE_DROP(de) then
begin
Assert(not_found=1,'DEVFS de dropped but not doomed');
@@ -632,7 +640,9 @@ loop:
VI_UNLOCK(vp);
if ((dev^.si_flags and SI_ETERNAL)<>0) then
+ begin
vp^.v_vflag:=vp^.v_vflag or VV_ETERNALDEV;
+ end;
vp^.v_op:=@devfs_specops;
end else
@@ -689,16 +699,22 @@ begin
de:=vp^.v_data;
if (vp^.v_type=VDIR) then
+ begin
de:=de^.de_dir;
+ end;
error:=vaccess(vp^.v_type, de^.de_mode, de^.de_uid, de^.de_gid, ap^.a_accmode, nil);
if (error=0) then
+ begin
Exit(0);
+ end;
if (error<>EACCES) then
Exit(error);
{ We do, however, allow access to the controlling terminal }
if ((p_proc.p_flag and P_CONTROLT)=0) then
+ begin
Exit(error);
+ end;
//if (ap^.a_td^.td_proc^.p_session^.s_ttydp=de^.de_cdp) then
// Exit(0);
Exit(error);
@@ -721,7 +737,9 @@ begin
* XXX: insmntque1() failure.
}
if (vp^.v_data=nil) then
+ begin
Exit(0);
+ end;
{
* Hack: a tty device that is a controlling terminal
@@ -750,7 +768,9 @@ begin
//end;
//sx_xunlock(@proctree_lock);
if (oldvp<>nil) then
+ begin
vrele(oldvp);
+ end;
{
* We do not want to really close the device if it
* is still in use unless we are trying to close it
@@ -865,7 +885,9 @@ begin
error:=devfs_populate_vp(vp);
if (error<>0) then
+ begin
Exit(error);
+ end;
dmp:=VFSTODEVFS(vp^.v_mount);
sx_xunlock(@dmp^.dm_lock);
@@ -958,10 +980,12 @@ begin
fgn:=data;
p:=devtoname(dev);
i:=strlen(p) + 1;
+
if (i > fgn^.len) then
error:=EINVAL
else
error:=copyout(p, fgn^.buf, i);
+
td^.td_fpop:=fpop;
dev_relthread(dev, ref);
Exit(error);
@@ -970,7 +994,9 @@ begin
td^.td_fpop:=nil;
dev_relthread(dev, ref);
if (error=ENOIOCTL) then
+ begin
error:=ENOTTY;
+ end;
if (error=0) and (com=TIOCSCTTY) then
begin
vp:=fp^.f_vnode;
@@ -995,7 +1021,9 @@ begin
{ Get rid of reference to old control tty }
if (vpold<>nil) then
+ begin
vrele(vpold);
+ end;
end;
Exit(error);
end;
@@ -1032,10 +1060,14 @@ begin
error:=0;
//error:=prison_check(td^.td_ucred, dcr);
if (error=0) then
+ begin
Exit(0);
+ end;
{ We do, however, allow access to the controlling terminal }
if ((p_proc.p_flag and P_CONTROLT)=0) then
+ begin
Exit(error);
+ end;
//if (td^.td_proc^.p_session^.s_ttydp=cdp) then
// Exit(0);
Exit(error);
@@ -1067,22 +1099,32 @@ begin
vpp^:=nil;
if ((flags and ISLASTCN)<>0) and (nameiop=RENAME) then
+ begin
Exit(EOPNOTSUPP);
+ end;
if (dvp^.v_type<>VDIR) then
+ begin
Exit(ENOTDIR);
+ end;
if (((flags and ISDOTDOT)<>0) and ((dvp^.v_vflag and VV_ROOT)<>0)) then
+ begin
Exit(EIO);
+ end;
error:=VOP_ACCESS(dvp, VEXEC);
if (error<>0) then
+ begin
Exit(error);
+ end;
if (cnp^.cn_namelen=1) and (pname^='.') then
begin
if ((flags and ISLASTCN) and nameiop<>LOOKUP) then
+ begin
Exit(EINVAL);
+ end;
vpp^:=dvp;
VREF(dvp);
Exit(0);
@@ -1091,7 +1133,9 @@ begin
if ((flags and ISDOTDOT)<>0) then
begin
if ((flags and ISLASTCN)<>0) and (nameiop<>LOOKUP) then
+ begin
Exit(EINVAL);
+ end;
de:=devfs_parent_dirent(dd);
if (de=nil) then Exit(ENOENT);
@@ -1152,7 +1196,9 @@ begin
devfs_unmount_final(dmp);
if (cdev<>nil) then
+ begin
dev_rel(cdev);
+ end;
Exit(ENOENT);
end;
@@ -1190,13 +1236,17 @@ begin
end;
if (devfs_prison_check(de)<>0) then
+ begin
Exit(ENOENT);
+ end;
if (cnp^.cn_nameiop=DELETE) and ((flags and ISLASTCN)<>0) then
begin
error:=VOP_ACCESS(dvp, VWRITE);
if (error<>0) then
+ begin
Exit(error);
+ end;
if (vpp^=dvp) then
begin
VREF(dvp);
@@ -1428,7 +1478,9 @@ var
fpop:p_file;
begin
if (uio^.uio_resid > DEVFS_IOSIZE_MAX) then
+ begin
Exit(EINVAL);
+ end;
td:=curkthread;
fpop:=td^.td_fpop;
@@ -1444,7 +1496,9 @@ begin
foffset_lock_uio(fp, uio, flags or FOF_NOLOCK);
error:=dsw^.d_read(dev, uio, ioflag);
if (uio^.uio_resid<>resid) or ((error=0) and (resid<>0)) then
+ begin
vfs_timestamp(@dev^.si_atime);
+ end;
td^.td_fpop:=fpop;
dev_relthread(dev, ref);
@@ -1466,11 +1520,15 @@ begin
tmp_ncookies:=nil;
if (ap^.a_vp^.v_type<>VDIR) then
+ begin
Exit(ENOTDIR);
+ end;
uio:=ap^.a_uio;
if (uio^.uio_offset < 0) then
+ begin
Exit(EINVAL);
+ end;
{
* XXX: This is a temporary hack to get around this filesystem not
@@ -1616,18 +1674,24 @@ begin
begin
de_cov:=devfs_find(dd, de^.de_dirent^.d_name, de^.de_dirent^.d_namlen, 0);
if (de_cov<>nil) then
+ begin
de_cov^.de_flags:=de_cov^.de_flags and (not DE_COVERED);
+ end;
end;
{ We need to unlock dvp because devfs_delete() may lock it. }
VOP_UNLOCK(vp, 0);
if (dvp<>vp) then
+ begin
VOP_UNLOCK(dvp, 0);
+ end;
devfs_delete(dmp, de, 0);
sx_xunlock(@dmp^.dm_lock);
if (dvp<>vp) then
+ begin
vn_lock(dvp, LK_EXCLUSIVE or LK_RETRY);
+ end;
vn_lock(vp, LK_EXCLUSIVE or LK_RETRY);
end else
@@ -1712,7 +1776,9 @@ begin
dev_unlock();
dev_rel(@cdp^.cdp_c);
end else
+ begin
dev_unlock();
+ end;
vn_lock(vp, LK_EXCLUSIVE or LK_RETRY);
Exit(0);
@@ -1781,7 +1847,9 @@ begin
de:=vp^.v_data;
if (vp^.v_type=VDIR) then
+ begin
de:=de^.de_dir;
+ end;
error:=0;
c:=0;
@@ -1874,12 +1942,16 @@ begin
error:=0;
//error:=priv_check(curkthread, PRIV_DEVFS_SYMLINK);
if (error<>0) then
+ begin
Exit(error);
+ end;
dmp:=VFSTODEVFS(ap^.a_dvp^.v_mount);
if (devfs_populate_vp(ap^.a_dvp)<>0) then
+ begin
Exit(ENOENT);
+ end;
dd:=ap^.a_dvp^.v_data;
de_cov:=devfs_find(dd, ap^.a_cnp^.cn_nameptr, ap^.a_cnp^.cn_namelen, 0);
@@ -1937,7 +2009,9 @@ begin
td:=curkthread;
if (uio^.uio_resid > DEVFS_IOSIZE_MAX) then
+ begin
Exit(EINVAL);
+ end;
fpop:=td^.td_fpop;
error:=devfs_fp_check(fp, @dev, @dsw, @ref);
@@ -1947,7 +2021,9 @@ begin
ioflag:=fp^.f_flag and (O_NONBLOCK or O_DIRECT or O_FSYNC);
if ((ioflag and O_DIRECT)<>0) then
+ begin
ioflag:=ioflag or IO_DIRECT;
+ end;
foffset_lock_uio(fp, uio, flags or FOF_NOLOCK);
diff --git a/sys/kern/kern_dmem.pas b/sys/kern/kern_dmem.pas
new file mode 100644
index 00000000..1d730b5a
--- /dev/null
+++ b/sys/kern/kern_dmem.pas
@@ -0,0 +1,40 @@
+unit kern_dmem;
+
+{$mode ObjFPC}{$H+}
+{$CALLING SysV_ABI_CDecl}
+
+interface
+
+function sys_dmem_container(d_pool_id:Integer):Integer;
+
+implementation
+
+uses
+ errno,
+ kern_thr;
+
+const
+ default_pool_id=1;
+
+function sys_dmem_container(d_pool_id:Integer):Integer;
+var
+ td:p_kthread;
+begin
+ td:=curkthread;
+ if (td=nil) then Exit(-1);
+
+ td^.td_retval[0]:=default_pool_id;
+ Result:=0;
+
+ if (d_pool_id<>-1) then
+ begin
+ //Result:=priv_check(td,0x2ad);
+ //(param < 3)
+ Exit(EPERM);
+ end;
+end;
+
+
+
+end.
+
diff --git a/sys/kern/kern_exec.pas b/sys/kern/kern_exec.pas
index 8f1f5de6..e7c96c76 100644
--- a/sys/kern/kern_exec.pas
+++ b/sys/kern/kern_exec.pas
@@ -56,7 +56,8 @@ uses
kern_event,
machdep,
kern_dlsym,
- kern_authinfo;
+ kern_authinfo,
+ vfs_syscalls;
function exec_alloc_args(args:p_image_args):Integer;
begin
@@ -1197,6 +1198,13 @@ begin
Exit(0);
end;
+procedure init_tty;
+begin
+ kern_openat(STDIN_FILENO ,'/dev/deci_stdin' ,UIO_SYSSPACE,O_RDWR,0);
+ kern_openat(STDOUT_FILENO,'/dev/deci_stdout',UIO_SYSSPACE,O_RDWR,0);
+ kern_openat(STDERR_FILENO,'/dev/deci_stderr',UIO_SYSSPACE,O_RDWR,0);
+end;
+
const
fexecv_proc_title='(fexecv)';
@@ -1422,6 +1430,9 @@ begin
//copy authinfo
g_authinfo:=imgp^.authinfo;
+ //init std tty
+ init_tty;
+
{
* Free any resources malloc'd earlier that we didn't use.
}
diff --git a/sys/kern/kern_sysctl.pas b/sys/kern/kern_sysctl.pas
index d6c0c5a9..90532197 100644
--- a/sys/kern/kern_sysctl.pas
+++ b/sys/kern/kern_sysctl.pas
@@ -414,6 +414,12 @@ begin
if (pid<>g_pid) then Exit(EINVAL);
+ //G_APPINFO.mmap_flags:=G_APPINFO.mmap_flags or 1;
+ if (p_proc.p_sce_replay_exec<>0) then
+ begin
+ G_APPINFO.mmap_flags:=G_APPINFO.mmap_flags or 2;
+ end;
+
//sceSblACMgrIsSystemUcred()!=0 -> any proc
//sceSblACMgrIsSystemUcred()==0 -> cur proc
@@ -425,6 +431,10 @@ begin
if (Result=0) then
begin
G_APPINFO:=APPINFO;
+ if (p_proc.p_sce_replay_exec<>0) then
+ begin
+ G_APPINFO.mmap_flags:=G_APPINFO.mmap_flags or 2;
+ end;
end;
end;
diff --git a/sys/kern/kern_thr.pas b/sys/kern/kern_thr.pas
index a062fdae..d26fadce 100644
--- a/sys/kern/kern_thr.pas
+++ b/sys/kern/kern_thr.pas
@@ -544,12 +544,16 @@ end;
procedure PROC_INIT;
+const
+ osreldate=$000DBBA0;
begin
FillChar(p_proc,SizeOf(p_proc),0);
mtx_init(p_proc.p_mtx,'process lock');
knlist_init_mtx(@p_proc.p_klist,@p_proc.p_mtx);
+ p_proc.p_osrel:=osreldate;
+
p_proc.p_randomized_path:='system';
p_proc.p_ptc:=rdtsc;
diff --git a/sys/sys_sysinit.pas b/sys/sys_sysinit.pas
index c27b6e82..68a52351 100644
--- a/sys/sys_sysinit.pas
+++ b/sys/sys_sysinit.pas
@@ -40,7 +40,8 @@ uses
vfs_mountroot,
kern_conf,
dev_null,
- dev_tty;
+ dev_tty,
+ dev_dmem;
var
daemon_thr:p_kthread;
@@ -74,6 +75,7 @@ begin
//
null_modevent(0,MOD_LOAD);
ttyconsdev_init();
+ dmemdev_init();
end;
//Manual order of lazy initialization
diff --git a/sys/syscalls.pas b/sys/syscalls.pas
index b80ffe7d..9f4f3afd 100644
--- a/sys/syscalls.pas
+++ b/sys/syscalls.pas
@@ -205,6 +205,7 @@ function budget_delete(key:Integer):Integer;
function budget_get(key:Integer;ptr:Pointer;psize:PInteger):Integer;
function budget_set(key:Integer):Integer;
function is_in_sandbox():Integer;
+function dmem_container(d_pool_id:Integer):Integer;
function get_authinfo(pid:Integer;info:Pointer):Integer;
function mname(addr:Pointer;len:QWORD;name:PChar):Integer;
function dynlib_dlsym(handle:Integer;symbol:pchar;addrp:ppointer):Integer;
@@ -1632,6 +1633,13 @@ asm
jmp cerror
end;
+function dmem_container(d_pool_id:Integer):Integer; assembler; nostackframe;
+asm
+ movq $586,%rax
+ call fast_syscall
+ jmp cerror
+end;
+
function get_authinfo(pid:Integer;info:Pointer):Integer; assembler; nostackframe;
asm
movq $587,%rax
diff --git a/sys/sysent.pas b/sys/sysent.pas
index 28f71c20..cb630622 100644
--- a/sys/sysent.pas
+++ b/sys/sysent.pas
@@ -13,6 +13,7 @@ uses
kern_evf,
kern_gpo,
kern_sig,
+ kern_dmem,
kern_exec,
kern_exit,
kern_osem,
@@ -2986,7 +2987,7 @@ const
),
(//[586]
sy_narg:1;
- sy_call:nil;
+ sy_call:@sys_dmem_container;
sy_name:'sys_dmem_container'
),
(//[587]
diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi
index 6eae88d8..cfd1755b 100644
--- a/sys/test/project1.lpi
+++ b/sys/test/project1.lpi
@@ -633,6 +633,14 @@
+
+
+
+
+
+
+
+
diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr
index 05b658d2..44f3199a 100644
--- a/sys/test/project1.lpr
+++ b/sys/test/project1.lpr
@@ -95,7 +95,8 @@ uses
kern_sysctl,
kern_budget,
kern_regmgr,
- kern_authinfo;
+ kern_authinfo,
+ kern_dmem;
const
PAGE_MAP_COUNT=(qword(VM_MAXUSER_ADDRESS) shr PAGE_SHIFT);
diff --git a/sys/vfs/vfile.pas b/sys/vfs/vfile.pas
index 7ca6c267..4dbd3838 100644
--- a/sys/vfs/vfile.pas
+++ b/sys/vfs/vfile.pas
@@ -105,6 +105,10 @@ const
DFLAG_PASSABLE=$01; { may be passed via unix sockets. }
DFLAG_SEEKABLE=$02; { seekable / nonsequential }
+ STDIN_FILENO =0; // standard input file descriptor
+ STDOUT_FILENO=1; // standard output file descriptor
+ STDERR_FILENO=2; // standard error file descriptor
+
type
mode_t=Integer;
uid_t =Integer;
diff --git a/sys/vfs/vsys_generic.pas b/sys/vfs/vsys_generic.pas
index 39024174..b0e50bcf 100644
--- a/sys/vfs/vsys_generic.pas
+++ b/sys/vfs/vsys_generic.pas
@@ -126,7 +126,9 @@ var
begin
error:=fget_read(fd, CAP_READ or CAP_SEEK, @fp);
if (error<>0) then
+ begin
Exit(error);
+ end;
error:=dofileread(fd, fp, auio, -1, 0);
fdrop(fp);
Exit(error);
@@ -139,7 +141,9 @@ var
begin
error:=fget_read(fd, CAP_READ, @fp);
if (error<>0) then
+ begin
Exit(error);
+ end;
if ((fp^.f_ops^.fo_flags and DFLAG_SEEKABLE)=0) then
error:=ESPIPE
else
@@ -147,6 +151,7 @@ begin
error:=EINVAL
else
error:=dofileread(fd, fp, auio, offset, FOF_OFFSET);
+
fdrop(fp);
Exit(error);
end;
@@ -158,7 +163,9 @@ var
begin
error:=fget_write(fd, CAP_WRITE or CAP_SEEK, @fp);
if (error<>0) then
+ begin
Exit(error);
+ end;
error:=dofilewrite(fd, fp, auio, -1, 0);
fdrop(fp);
Exit(error);
@@ -171,7 +178,9 @@ var
begin
error:=fget_write(fd, CAP_WRITE, @fp);
if (error<>0) then
+ begin
Exit(error);
+ end;
if ((fp^.f_ops^.fo_flags and DFLAG_SEEKABLE)=0) then
error:=ESPIPE
else
@@ -179,6 +188,7 @@ begin
error:=EINVAL
else
error:=dofilewrite(fd, fp, auio, offset, FOF_OFFSET);
+
fdrop(fp);
Exit(error);
end;
@@ -234,7 +244,9 @@ var
begin
error:=copyinuio(iovp, iovcnt, @auio);
if (error<>0) then
+ begin
Exit(error);
+ end;
error:=kern_readv(fd, auio);
FreeMem(auio);
Exit(error);
@@ -250,7 +262,9 @@ var
begin
error:=copyinuio(iovp, iovcnt, @auio);
if (error<>0) then
+ begin
Exit(error);
+ end;
error:=kern_preadv(fd, auio, offset);
FreeMem(auio);
Exit(error);
@@ -282,7 +296,9 @@ begin
if (error<>0) then
begin
if (auio^.uio_resid<>cnt) and ((error=ERESTART) or (error=EINTR) or (error=EWOULDBLOCK)) then
+ begin
error:=0;
+ end;
end;
Dec(cnt,auio^.uio_resid);
@@ -339,7 +355,9 @@ var
begin
error:=copyinuio(iovp, iovcnt, @auio);
if (error<>0) then
+ begin
Exit(error);
+ end;
error:=kern_writev(fd, auio);
FreeMem(auio);
Exit(error);
@@ -355,7 +373,9 @@ var
begin
error:=copyinuio(iovp, iovcnt, @auio);
if (error<>0) then
+ begin
Exit(error);
+ end;
error:=kern_pwritev(fd, auio, offset);
FreeMem(auio);
Exit(error);
@@ -385,7 +405,9 @@ begin
if (error<>0) then
begin
if (auio^.uio_resid<>cnt) and ((error=ERESTART) or (error=EINTR) or (error=EWOULDBLOCK)) then
+ begin
error:=0;
+ end;
{ Socket layer is responsible for issuing SIGPIPE. }
if (fp^.f_type<>DTYPE_SOCKET) and (error=EPIPE) then
begin
@@ -412,10 +434,14 @@ var
error:Integer;
begin
if (length < 0) then
+ begin
Exit(EINVAL);
+ end;
error:=fget(fd, CAP_FTRUNCATE, @fp);
if (error<>0) then
+ begin
Exit(error);
+ end;
if ((fp^.f_flag and FWRITE)=0) then
begin
fdrop(fp);
@@ -441,7 +467,9 @@ var
begin
error:=fget(fd, CAP_IOCTL, @fp);
if (error<>0) then
+ begin
Exit(error);
+ end;
if ((fp^.f_flag and (FREAD or FWRITE))=0) then
begin
fdrop(fp);
@@ -461,19 +489,23 @@ begin
FIONBIO:
begin
tmp:=PInteger(data)^;
+
if (tmp<>0) then
atomic_set_int(@fp^.f_flag, FNONBLOCK)
else
atomic_clear_int(@fp^.f_flag, FNONBLOCK);
+
data:=@tmp;
end;
FIOASYNC:
begin
tmp:=PInteger(data)^;
+
if (tmp<>0) then
atomic_set_int(@fp^.f_flag, FASYNC)
else
atomic_clear_int(@fp^.f_flag, FASYNC);
+
data:=@tmp;
end;
end;
@@ -490,6 +522,7 @@ var
smalldata:array[0..SYS_IOCTL_SMALL_SIZE-1] of Byte; //__aligned(SYS_IOCTL_SMALL_ALIGN)
arg,error:Integer;
size:DWORD;
+ kern_data:Pointer;
begin
if (com > $ffffffff) then
begin
@@ -506,7 +539,9 @@ begin
((com and (IOC_VOID or IOC_IN or IOC_OUT))=0) or
(((com and (IOC_IN or IOC_OUT))<>0) and (size=0)) or
(((com and IOC_VOID)<>0) and (size > 0) and (size<>sizeof(Integer))) then
+ begin
Exit(ENOTTY);
+ end;
if (size > 0) then
begin
@@ -514,22 +549,26 @@ begin
begin
{ Integer argument. }
arg:=ptrint(data);
- data:=@arg;
+ kern_data:=@arg;
size:=0;
end else
begin
if (size > SYS_IOCTL_SMALL_SIZE) then
- data:=AllocMem(size)
+ kern_data:=AllocMem(size)
else
- data:=@smalldata;
+ kern_data:=@smalldata;
end;
end else
- data:=@data;
+ begin
+ kern_data:=@curkthread^.td_frame.tf_rsi;
+ end;
if ((com and IOC_IN)<>0) then
begin
- error:=copyin(data, data, size);
+ error:=copyin(data, kern_data, size);
if (error<>0) then
+ begin
goto _out;
+ end;
end else
if ((com and IOC_OUT)<>0) then
begin
@@ -537,17 +576,21 @@ begin
* Zero the buffer so the user always
* gets back something deterministic.
}
- FillChar(data,size,0);
+ FillChar(kern_data^,size,0);
end;
- error:=kern_ioctl(fd, com, data);
+ error:=kern_ioctl(fd, com, kern_data);
if (error=0) and ((com and IOC_OUT)<>0) then
- error:=copyout(data, data, size);
+ begin
+ error:=copyout(kern_data, data, size);
+ end;
_out:
if (size > SYS_IOCTL_SMALL_SIZE) then
- FreeMem(data);
+ begin
+ FreeMem(kern_data);
+ end;
Exit(error);
end;
@@ -561,7 +604,9 @@ begin
* of specific filesystem implementations.
}
if (events and (not POLLSTANDARD))<>0 then
+ begin
Exit(POLLNVAL);
+ end;
Exit(events and (POLLIN or POLLOUT or POLLRDNORM or POLLWRNORM));
end;
@@ -585,7 +630,9 @@ begin
begin
error:=kern_sigprocmask(td, SIG_SETMASK, uset, @td^.td_oldsigmask, 0);
if (error<>0) then
+ begin
Exit(error);
+ end;
td^.td_pflags:=td^.td_pflags or TDP_OLDMASK;
{
* Make sure that ast() is called on Exitto
@@ -613,19 +660,27 @@ begin
begin
error:=copyin(uts, @ts, sizeof(ts));
if (error<>0) then
+ begin
Exit(error);
+ end;
TIMESPEC_TO_TIMEVAL(@tv, @ts);
tvp:=@tv;
end else
+ begin
tvp:=nil;
+ end;
if (sm<>nil) then
begin
error:=copyin(sm, @_set, sizeof(_set));
if (error<>0) then
+ begin
Exit(error);
+ end;
uset:=@_set;
end else
+ begin
uset:=nil;
+ end;
Exit(kern_pselect(nd, uin, uou, uex, tvp, uset, NFDBITS));
end;
@@ -639,7 +694,9 @@ begin
begin
error:=copyin(utv, @tv, sizeof(tv));
if (error<>0) then
+ begin
Exit(error);
+ end;
tvp:=@tv;
end else
tvp:=nil;
@@ -663,7 +720,9 @@ var
bits:Byte;
begin
if (nd >= ndu) or (fd_in=nil) then
+ begin
Exit(0);
+ end;
oaddr:=nil;
bits:=0; { silence gcc }
@@ -675,12 +734,16 @@ begin
begin
res:=fubyte(addr^);
if (res=-1) then
+ begin
Exit(EFAULT);
+ end;
oaddr:=addr;
bits:=res;
end;
if ((bits and (1 shl (i mod NBBY)))<>0) then
+ begin
Exit(EBADF);
+ end;
end;
Exit(0);
end;
@@ -714,7 +777,9 @@ var
begin
error2:=copyout(@obits[x], name, ncpubytes);
if (error2<>0) then
+ begin
error:=error2;
+ end;
end;
end;
@@ -731,13 +796,19 @@ begin
error:=select_check_badfd(fd_in, nd, ndu, abi_nfdbits);
if (error<>0) then
+ begin
Exit(error);
+ end;
error:=select_check_badfd(fd_ou, nd, ndu, abi_nfdbits);
if (error<>0) then
+ begin
Exit(error);
+ end;
error:=select_check_badfd(fd_ex, nd, ndu, abi_nfdbits);
if (error<>0) then
+ begin
Exit(error);
+ end;
{
* Allocate just enough bits for the non-nil fd_sets. Use the
@@ -749,11 +820,17 @@ begin
nbufbytes:=0;
if (fd_in<>nil) then
+ begin
Inc(nbufbytes,2 * ncpbytes);
+ end;
if (fd_ou<>nil) then
+ begin
Inc(nbufbytes,2 * ncpbytes);
+ end;
if (fd_ex<>nil) then
+ begin
Inc(nbufbytes,2 * ncpbytes);
+ end;
if (nbufbytes <= sizeof(s_selbits)) then
selbits:=@s_selbits[0]
@@ -789,12 +866,16 @@ begin
repeat
error:=selscan(td, @ibits, @obits, nd);
if (error<>0) or (td^.td_retval[0]<>0) then
+ begin
break;
+ end;
if (atv<>0) then
begin
rtv:=get_unit_uptime;
if (rtv>=atv) then
+ begin
break;
+ end;
ttv:=atv-rtv;
if (ttv>24*60*60*hz) then
@@ -804,19 +885,27 @@ begin
end;
error:=seltdwait(td, timo);
if (error<>0) then
+ begin
break;
+ end;
error:=selrescan(td, @ibits, @obits);
if (error<>0) or (td^.td_retval[0]<>0) then
+ begin
break;
+ end;
until false;
seltdclear(td);
done:
{ select is not restarted after signals... }
if (error=ERESTART) then
+ begin
error:=EINTR;
+ end;
if (error=EWOULDBLOCK) then
+ begin
error:=0;
+ end;
if (error=0) then
begin
@@ -826,7 +915,9 @@ done:
end;
if (selbits<>@s_selbits[0]) then
+ begin
FreeMem(selbits);
+ end;
Exit(error);
end;
@@ -902,7 +993,9 @@ var
begin
fp:=fget_unlocked(fd);
if (fp=nil) then
+ begin
Exit(EBADF);
+ end;
{
* If the file descriptor is for a capability, test rights and use
* the file descriptor references by the capability.
@@ -958,7 +1051,9 @@ begin
end;
error:=getselfd_cap(fd, @fp);
if (error<>0) then
+ begin
Exit(error);
+ end;
idx:=fd div NFDBITS;
bit:=fd_mask(1) shl (fd mod NFDBITS);
ev:=fo_poll(fp, selflags(ibits, idx, bit));
@@ -1032,16 +1127,22 @@ var
ni:QWORD;
begin
if (nfds > maxfilesperproc) and (nfds > FD_SETSIZE) then
+ begin
Exit(EINVAL);
+ end;
td:=curkthread;
ni:=nfds * sizeof(t_pollfd);
+
if (ni > sizeof(smallbits)) then
bits:=AllocMem(ni)
else
bits:=@smallbits;
+
error:=copyin(fds, bits, ni);
if (error<>0) then
+ begin
goto done;
+ end;
if (timeout<>INFTIM) then
begin
atv:=USEC_TO_UNIT(_msec2usec(timeout));
@@ -1072,28 +1173,40 @@ begin
end;
error:=seltdwait(td, timo);
if (error<>0) then
+ begin
break;
+ end;
error:=pollrescan(td);
if (error<>0) or (td^.td_retval[0]<>0) then
+ begin
break;
+ end;
until false;
seltdclear(td);
done:
{ poll is not restarted after signals... }
if (error=ERESTART) then
+ begin
error:=EINTR;
+ end;
if (error=EWOULDBLOCK) then
+ begin
error:=0;
+ end;
if (error=0) then
begin
error:=_pollout(td, bits, fds, nfds);
if (error<>0) then
+ begin
goto _out;
+ end;
end;
_out:
if (ni > sizeof(smallbits)) then
+ begin
FreeMem(bits);
+ end;
Exit(error);
end;
@@ -1129,7 +1242,9 @@ begin
if (cap_funwrap(fp, CAP_POLL_EVENT, @fp)<>0) then
begin
if (fp<>nil) then
+ begin
fdrop(fp);
+ end;
//
fd^.revents:=POLLNVAL;
Inc(n);
@@ -1144,7 +1259,9 @@ begin
}
fd^.revents:=fo_poll(fp, fd^.events);
if (fd^.revents<>0) then
+ begin
Inc(n);
+ end;
//
fdrop(fp);
//
@@ -1168,9 +1285,13 @@ begin
begin
error:=copyout(@fds^.revents, @ufds^.revents, sizeof(ufds^.revents));
if (error<>0) then
+ begin
Exit(error);
+ end;
if (fds^.revents<>0) then
+ begin
Inc(n);
+ end;
Inc(fds);
Inc(ufds);
end;
@@ -1217,14 +1338,20 @@ begin
* set simultaneously with POLLHUP.
}
if ((fds^.revents and POLLHUP)<>0) then
+ begin
fds^.revents:=fds^.revents and (not POLLOUT);
+ end;
if (fds^.revents<>0) then
+ begin
Inc(n);
+ end;
end;
//
if (fp<>nil) then
+ begin
fdrop(fp);
+ end;
end;
//
Inc(i);
@@ -1245,11 +1372,15 @@ var
begin
stp:=td^.td_sel;
if (stp^.st_free1=nil) then
+ begin
stp^.st_free1:=AllocMem(SizeOf(t_selfd));
+ end;
stp^.st_free1^.sf_td:=stp;
stp^.st_free1^.sf_cookie:=cookie;
if (stp^.st_free2=nil) then
+ begin
stp^.st_free2:=AllocMem(SizeOf(t_selfd));
+ end;
stp^.st_free2^.sf_td:=stp;
stp^.st_free2^.sf_cookie:=cookie;
end;
@@ -1259,7 +1390,9 @@ begin
STAILQ_REMOVE(@stp^.st_selq,sfp,@sfp^.sf_link);
mtx_lock(sfp^.sf_mtx^);
if (sfp^.sf_si<>nil) then
+ begin
TAILQ_REMOVE(@sfp^.sf_si^.si_tdlist,sfp,@sfp^.sf_threads);
+ end;
mtx_unlock(sfp^.sf_mtx^);
FreeMem(sfp);
end;
@@ -1292,19 +1425,23 @@ begin
* Don't record when doing a rescan.
}
if ((stp^.st_flags and SELTD_RESCAN)<>0) then
+ begin
Exit;
+ end;
{
* Grab one of the preallocated descriptors.
}
sfp:=stp^.st_free1;
if (sfp<>nil) then
+ begin
stp^.st_free1:=nil
- else
+ end else
begin
sfp:=stp^.st_free2;
if (sfp<>nil) then
+ begin
stp^.st_free2:=nil
- else
+ end else
begin
Assert(false,'selrecord: No free selfd on selq');
Exit;
@@ -1312,7 +1449,9 @@ begin
end;
mtxp:=sip^.si_mtx;
if (mtxp=nil) then
+ begin
mtxp:=mtx_pool_find(mtxpool_select, sip);
+ end;
{
* Initialize the sfp and queue it in the thread.
}
@@ -1359,7 +1498,9 @@ var
begin
{ If it's not initialized there can't be any waiters. }
if (sip^.si_mtx=nil) then
+ begin
Exit;
+ end;
{
* Locking the selinfo locks all selfds associated with it.
}
@@ -1393,7 +1534,9 @@ var
begin
stp:=td^.td_sel;
if (stp<>nil) then
+ begin
goto _out;
+ end;
stp:=AllocMem(sizeof(t_seltd));
td^.td_sel:=stp;
mtx_init(stp^.st_mtx, 'sellck');
@@ -1423,10 +1566,12 @@ begin
mtx_unlock(stp^.st_mtx);
Exit(0);
end;
+
if (timo > 0) then
error:=_cv_timedwait_sig(@stp^.st_wait, @stp^.st_mtx, timo)
else
error:=_cv_wait_sig(@stp^.st_wait, @stp^.st_mtx);
+
mtx_unlock(stp^.st_mtx);
Exit(error);
@@ -1438,11 +1583,17 @@ var
begin
stp:=td^.td_sel;
if (stp=nil) then
+ begin
Exit;
+ end;
if (stp^.st_free1<>nil) then
+ begin
FreeMem(stp^.st_free1);
+ end;
if (stp^.st_free2<>nil) then
+ begin
FreeMem(stp^.st_free2);
+ end;
td^.td_sel:=nil;
FreeMem(stp);
end;