mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
26e2ae4e23
commit
917b19ce77
|
@ -388,13 +388,18 @@ var
|
|||
td:p_kthread;
|
||||
begin
|
||||
td:=curkthread;
|
||||
if (td=nil) then Exit;
|
||||
Result:=(not flags) or (td^.td_pflags and flags);
|
||||
td^.td_pflags:=td^.td_pflags or flags;
|
||||
end;
|
||||
|
||||
procedure curthread_pflags_restore(save:Integer);
|
||||
var
|
||||
td:p_kthread;
|
||||
begin
|
||||
curkthread^.td_pflags:=curkthread^.td_pflags and save;
|
||||
td:=curkthread;
|
||||
if (td=nil) then Exit;
|
||||
td^.td_pflags:=td^.td_pflags and save;
|
||||
end;
|
||||
|
||||
//
|
||||
|
|
|
@ -10,10 +10,6 @@ uses
|
|||
ntapi,
|
||||
time;
|
||||
|
||||
procedure timevalfix(t1:ptimeval);
|
||||
procedure timevaladd(t1,t2:ptimeval);
|
||||
procedure timevalsub(t1,t2:ptimeval);
|
||||
|
||||
function cputick2usec(time:QWORD):QWORD; inline;
|
||||
function get_unit_uptime:Int64;
|
||||
procedure getmicrouptime(tvp:ptimeval);
|
||||
|
@ -40,34 +36,6 @@ Const
|
|||
POW10_7 =10000000;
|
||||
POW10_9 =1000000000;
|
||||
|
||||
procedure timevalfix(t1:ptimeval);
|
||||
begin
|
||||
if (t1^.tv_usec < 0) then
|
||||
begin
|
||||
Dec(t1^.tv_sec);
|
||||
Inc(t1^.tv_usec,1000000);
|
||||
end;
|
||||
if (t1^.tv_usec >= 1000000) then
|
||||
begin
|
||||
Inc(t1^.tv_sec);
|
||||
Dec(t1^.tv_usec,1000000);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure timevaladd(t1,t2:ptimeval);
|
||||
begin
|
||||
Inc(t1^.tv_sec ,t2^.tv_sec);
|
||||
Inc(t1^.tv_usec,t2^.tv_usec);
|
||||
timevalfix(t1);
|
||||
end;
|
||||
|
||||
procedure timevalsub(t1,t2:ptimeval);
|
||||
begin
|
||||
Dec(t1^.tv_sec ,t2^.tv_sec);
|
||||
Dec(t1^.tv_usec,t2^.tv_usec);
|
||||
timevalfix(t1);
|
||||
end;
|
||||
|
||||
function cputick2usec(time:QWORD):QWORD; inline;
|
||||
begin
|
||||
Result:=time div 10;
|
||||
|
|
|
@ -12,6 +12,7 @@ const
|
|||
IOSIZE_MAX =High(Int64);
|
||||
DEVFS_IOSIZE_MAX=High(Int64);
|
||||
|
||||
function copystr(from,_to:Pointer;maxlen:ptruint;lencopied:pptruint):Integer;
|
||||
function copyin(udaddr,kaddr:Pointer;len:ptruint):Integer; inline;
|
||||
function copyinstr(udaddr,kaddr:Pointer;len:ptruint;lencopied:pptruint):Integer;
|
||||
function copyout(kaddr,udaddr:Pointer;len:ptruint):Integer; inline;
|
||||
|
@ -26,8 +27,19 @@ function suword64(var base:QWORD;word:QWORD):DWORD; inline;
|
|||
implementation
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
errno;
|
||||
|
||||
function copystr(from,_to:Pointer;maxlen:ptruint;lencopied:pptruint):Integer;
|
||||
begin
|
||||
strlcopy(_to,from,maxlen);
|
||||
if (lencopied<>nil) then
|
||||
begin
|
||||
lencopied^:=strlen(_to);
|
||||
end;
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
function copyin(udaddr,kaddr:Pointer;len:ptruint):Integer; inline;
|
||||
begin
|
||||
if (NtReadVirtualMemory(NtCurrentProcess,udaddr,kaddr,len,nil)=0) then
|
||||
|
|
|
@ -30,7 +30,8 @@ uses
|
|||
devfs,
|
||||
devfs_devs,
|
||||
devfs_vfsops,
|
||||
kern_descrip;
|
||||
kern_descrip,
|
||||
vfs_mountroot;
|
||||
|
||||
//Daemon for a separate thread
|
||||
procedure sys_update;
|
||||
|
@ -41,6 +42,7 @@ end;
|
|||
procedure module_init;
|
||||
begin
|
||||
vfs_register(@devfs_vfsconf);
|
||||
vfs_mountroot.vfs_mountroot();
|
||||
end;
|
||||
|
||||
//Manual order of lazy initialization
|
||||
|
|
|
@ -441,6 +441,10 @@
|
|||
<Filename Value="..\vfs\vttycom.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
<Unit>
|
||||
<Filename Value="..\vfs\vfs_mountroot.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
uses
|
||||
windows,
|
||||
dateutils,
|
||||
atomic,
|
||||
ntapi,
|
||||
mqueue,
|
||||
|
@ -53,7 +54,11 @@ uses
|
|||
sys_fnmatch,
|
||||
devfs,
|
||||
devfs_vfsops,
|
||||
devfs_vnops;
|
||||
devfs_vnops,
|
||||
vfs_mountroot,
|
||||
vstat,
|
||||
vfcntl,
|
||||
vdirent;
|
||||
|
||||
var
|
||||
mtx:umutex;
|
||||
|
@ -223,6 +228,96 @@ var
|
|||
ymm0:array[0..31] of Byte=(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
|
||||
ymm0_ptr:Pointer=@ymm0;
|
||||
|
||||
function ts_to_str(ts:timespec):RawByteString;
|
||||
var
|
||||
D:TDateTime;
|
||||
begin
|
||||
D:=UnixToDateTime(ts.tv_sec);
|
||||
D:=UniversalTimeToLocal(D);
|
||||
Result:=DateTimeToStr(D);
|
||||
end;
|
||||
|
||||
function IncludeUnixTrailing(Const Path:RawByteString):RawByteString;
|
||||
Var
|
||||
L:Integer;
|
||||
begin
|
||||
Result:=Path;
|
||||
L:=Length(Result);
|
||||
If (L=0) or (Path[L]<>'/') then
|
||||
begin
|
||||
SetLength(Result,L+1);
|
||||
Result[L+1]:='/';
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure test_dirs(const p:RawByteString;s:Byte);
|
||||
var
|
||||
td:p_kthread;
|
||||
sb:t_stat;
|
||||
buf:array[0..511] of Byte;
|
||||
dir:p_dirent;
|
||||
fd:Integer;
|
||||
err:Integer;
|
||||
c:Integer;
|
||||
begin
|
||||
td:=curkthread;
|
||||
err:=sys_stat(PChar(p),@sb);
|
||||
if (err<>0) then
|
||||
begin
|
||||
Writeln(Space(s),p,' | (',err,')');
|
||||
end else
|
||||
begin
|
||||
Write(Space(s),p,' | ',ts_to_str(sb.st_mtim),' |');
|
||||
|
||||
if ((sb.st_mode and S_IFDIR)<>0) then
|
||||
begin
|
||||
Write(' DIR');
|
||||
Assert(sb.st_size=512);
|
||||
|
||||
fd:=sys_open(PChar(p),O_RDONLY or O_DIRECTORY,0);
|
||||
|
||||
if (fd<0) then
|
||||
begin
|
||||
Write(' | (',fd,')');
|
||||
Exit;
|
||||
end else
|
||||
begin
|
||||
Writeln;
|
||||
end;
|
||||
Writeln(Space(s),'->');
|
||||
|
||||
repeat
|
||||
FillChar(buf,512,0);
|
||||
dir:=@buf;
|
||||
err:=sys_getdents(fd,dir,512);
|
||||
if (err<0) then Break;
|
||||
|
||||
c:=td^.td_retval[0];
|
||||
if (c=0) then Break;
|
||||
|
||||
while (dir<(@buf+c)) do
|
||||
begin
|
||||
case RawByteString(dir^.d_name) of
|
||||
'.':;
|
||||
'..':;
|
||||
else
|
||||
//Writeln(dir^.d_name);
|
||||
test_dirs(IncludeUnixTrailing(p)+RawByteString(dir^.d_name),s+1);
|
||||
end;
|
||||
|
||||
PByte(dir):=PByte(dir)+dir^.d_reclen;
|
||||
end;
|
||||
|
||||
until false;
|
||||
|
||||
Writeln(Space(s),'<-');
|
||||
end else
|
||||
begin
|
||||
Writeln(' ',sb.st_size);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure test_thread; sysv_abi_default;
|
||||
var
|
||||
rax:qword;
|
||||
|
@ -236,6 +331,10 @@ begin
|
|||
|
||||
if (tid<>curkthread^.td_tid) then
|
||||
begin
|
||||
Writeln('[--test_dirs--]');
|
||||
test_dirs('/',1);
|
||||
Writeln('[--test_dirs--]');
|
||||
|
||||
tid2:=curkthread^.td_tid;
|
||||
|
||||
evf:=evf_create('evf test',EVF_ATTR_TH_PRIO,0);
|
||||
|
|
32
sys/time.pas
32
sys/time.pas
|
@ -65,6 +65,10 @@ function _nsec2usec(nsec:QWORD):QWORD; //Nanosecond to Microsecond
|
|||
function _msec2nsec(msec:QWORD):QWORD; //Milisecond to Nanosecond
|
||||
function _nsec2msec(nsec:QWORD):QWORD; //Nanosecond to Milisecond
|
||||
|
||||
procedure timevalfix(t1:ptimeval);
|
||||
procedure timevaladd(t1,t2:ptimeval);
|
||||
procedure timevalsub(t1,t2:ptimeval);
|
||||
|
||||
function timespeccmp_lt(tvp,uvp:ptimespec):Integer; inline;
|
||||
|
||||
procedure TIMEVAL_TO_TIMESPEC(tv:ptimeval;ts:ptimespec); inline;
|
||||
|
@ -126,6 +130,34 @@ begin
|
|||
Result:=(nsec+999999) div 1000000;
|
||||
end;
|
||||
|
||||
procedure timevalfix(t1:ptimeval);
|
||||
begin
|
||||
if (t1^.tv_usec < 0) then
|
||||
begin
|
||||
Dec(t1^.tv_sec);
|
||||
Inc(t1^.tv_usec,1000000);
|
||||
end;
|
||||
if (t1^.tv_usec >= 1000000) then
|
||||
begin
|
||||
Inc(t1^.tv_sec);
|
||||
Dec(t1^.tv_usec,1000000);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure timevaladd(t1,t2:ptimeval);
|
||||
begin
|
||||
Inc(t1^.tv_sec ,t2^.tv_sec);
|
||||
Inc(t1^.tv_usec,t2^.tv_usec);
|
||||
timevalfix(t1);
|
||||
end;
|
||||
|
||||
procedure timevalsub(t1,t2:ptimeval);
|
||||
begin
|
||||
Dec(t1^.tv_sec ,t2^.tv_sec);
|
||||
Dec(t1^.tv_usec,t2^.tv_usec);
|
||||
timevalfix(t1);
|
||||
end;
|
||||
|
||||
function timespeccmp_lt(tvp,uvp:ptimespec):Integer; inline;
|
||||
begin
|
||||
if (tvp^.tv_sec=uvp^.tv_sec) then
|
||||
|
|
|
@ -58,7 +58,7 @@ begin
|
|||
end;
|
||||
save:=curthread_pflags_set(newflags);
|
||||
|
||||
while (n > 0 and uio^.uio_resid) do
|
||||
while (n > 0) and (uio^.uio_resid<>0) do
|
||||
begin
|
||||
iov:=uio^.uio_iov;
|
||||
cnt:=iov^.iov_len;
|
||||
|
@ -88,17 +88,16 @@ begin
|
|||
Move(cp^, iov^.iov_base^, cnt)
|
||||
else
|
||||
Move(iov^.iov_base^, cp^, cnt);
|
||||
break;
|
||||
end;
|
||||
UIO_NOCOPY:;
|
||||
else;
|
||||
end;
|
||||
|
||||
iov^.iov_base:=iov^.iov_base + cnt;
|
||||
Dec(iov^.iov_len,cnt);
|
||||
Dec(uio^.uio_resid,cnt);
|
||||
Inc(iov^.iov_base ,cnt);
|
||||
Dec(iov^.iov_len ,cnt);
|
||||
Dec(uio^.uio_resid ,cnt);
|
||||
Inc(uio^.uio_offset,cnt);
|
||||
cp:=cp + cnt;
|
||||
Inc(cp,cnt);
|
||||
Dec(n,cnt);
|
||||
end;
|
||||
|
||||
|
|
|
@ -528,6 +528,42 @@ begin
|
|||
{ NOTREACHED }
|
||||
end;
|
||||
|
||||
function lockmgr(lk:p_mtx;flags:Integer;ilk:p_mtx):Integer;
|
||||
var
|
||||
op:Integer;
|
||||
begin
|
||||
|
||||
op:=(flags and LK_TYPE_MASK);
|
||||
case op of
|
||||
LK_SHARED,
|
||||
LK_EXCLUSIVE:
|
||||
begin
|
||||
mtx_lock(lk^);
|
||||
end;
|
||||
LK_RELEASE:
|
||||
begin
|
||||
mtx_unlock(lk^);
|
||||
end;
|
||||
LK_UPGRADE:
|
||||
begin
|
||||
if not mtx_owned(lk^) then
|
||||
begin
|
||||
mtx_lock(lk^);
|
||||
end;
|
||||
end;
|
||||
LK_DOWNGRADE:;//
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
if ((flags and LK_INTERLOCK)<>0) then
|
||||
begin
|
||||
mtx_unlock(ilk^);
|
||||
end;
|
||||
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
{
|
||||
* Standard lock, unlock and islocked functions.
|
||||
}
|
||||
|
@ -537,14 +573,7 @@ var
|
|||
begin
|
||||
vp:=ap^.a_vp;
|
||||
|
||||
if (ap^.a_flags and LK_INTERLOCK)<>0 then
|
||||
begin
|
||||
mtx_unlock(VI_MTX(vp)^);
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
mtx_lock(vp^.v_vnlock^);
|
||||
Exit(0);
|
||||
Result:=lockmgr(vp^.v_vnlock,ap^.a_flags,VI_MTX(vp));
|
||||
|
||||
//Exit(_lockmgr_args(vp^.v_vnlock, ap^.a_flags, VI_MTX(vp),
|
||||
// LK_WMESG_DEFAULT, LK_PRIO_DEFAULT, LK_TIMO_DEFAULT, ap^.a_file,
|
||||
|
@ -558,14 +587,7 @@ var
|
|||
begin
|
||||
vp:=ap^.a_vp;
|
||||
|
||||
if (ap^.a_flags and LK_INTERLOCK)<>0 then
|
||||
begin
|
||||
mtx_unlock(VI_MTX(vp)^);
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
mtx_unlock(vp^.v_vnlock^);
|
||||
Exit(0);
|
||||
Result:=lockmgr(vp^.v_vnlock,ap^.a_flags or LK_RELEASE,VI_MTX(vp));
|
||||
|
||||
//Exit(lockmgr(vp^.v_vnlock, ap^.a_flags or LK_RELEASE, VI_MTX(vp)));
|
||||
end;
|
||||
|
@ -778,7 +800,7 @@ var
|
|||
off:QWORD;
|
||||
fileno:DWORD;
|
||||
va:t_vattr;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
td:p_kthread;
|
||||
dp:p_dirent;
|
||||
mvp:p_vnode;
|
||||
|
|
|
@ -67,7 +67,7 @@ end;
|
|||
* if symbolic link, massage name in buffer and continue
|
||||
* end;
|
||||
}
|
||||
procedure namei_cleanup_cnp(cnp:p_componentname);
|
||||
procedure namei_cleanup_cnp(cnp:p_componentname); inline;
|
||||
begin
|
||||
FreeMem(cnp^.cn_pnbuf);
|
||||
end;
|
||||
|
@ -92,10 +92,10 @@ begin
|
|||
cnp:=@ndp^.ni_cnd;
|
||||
td:=cnp^.cn_thread;
|
||||
|
||||
Assert(((cnp^.cn_flags and MPSAFE)<>0) or mtx_owned(VFS_Giant),('NOT MPSAFE and Giant not held'));
|
||||
Assert(((cnp^.cn_flags and MPSAFE)<>0) or mtx_owned(VFS_Giant),'NOT MPSAFE and Giant not held');
|
||||
|
||||
Assert((cnp^.cn_nameiop and (not OPMASK))=0,'namei: nameiop contaminated with flags');
|
||||
Assert((cnp^.cn_flags and OPMASK)=0,('namei: flags contaminated with nameiops'));
|
||||
Assert((cnp^.cn_flags and OPMASK)=0,'namei: flags contaminated with nameiops');
|
||||
if (lookup_shared=0) then
|
||||
cnp^.cn_flags:=cnp^.cn_flags and (not LOCKSHARED);
|
||||
|
||||
|
@ -113,8 +113,7 @@ begin
|
|||
|
||||
if (ndp^.ni_segflg=UIO_SYSSPACE) then
|
||||
begin
|
||||
ndp^.ni_pathlen:=strlcopy(ndp^.ni_dirp,cnp^.cn_pnbuf,MAXPATHLEN)-ndp^.ni_dirp;
|
||||
error:=0;
|
||||
error:=copystr(ndp^.ni_dirp, cnp^.cn_pnbuf, MAXPATHLEN, @ndp^.ni_pathlen);
|
||||
end else
|
||||
begin
|
||||
error:=copyinstr(ndp^.ni_dirp, cnp^.cn_pnbuf, MAXPATHLEN, @ndp^.ni_pathlen);
|
||||
|
@ -141,14 +140,6 @@ begin
|
|||
ndp^.ni_rootdir:=fdp^.fd_rdir;
|
||||
ndp^.ni_topdir:=fdp^.fd_jdir;
|
||||
|
||||
{
|
||||
* If we are auditing the kernel pathname, save the user pathname.
|
||||
}
|
||||
//if ((cnp^.cn_flags and AUDITVNODE1)<>0) then
|
||||
// AUDIT_ARG_UPATH1(td, ndp^.ni_dirfd, cnp^.cn_pnbuf);
|
||||
//if ((cnp^.cn_flags and AUDITVNODE2)<>0) then
|
||||
// AUDIT_ARG_UPATH2(td, ndp^.ni_dirfd, cnp^.cn_pnbuf);
|
||||
|
||||
dp:=nil;
|
||||
if (cnp^.cn_pnbuf[0]<>'/') then
|
||||
begin
|
||||
|
@ -159,13 +150,10 @@ begin
|
|||
end else
|
||||
if (ndp^.ni_dirfd<>AT_FDCWD) then
|
||||
begin
|
||||
//if (cnp^.cn_flags and AUDITVNODE1)
|
||||
// AUDIT_ARG_ATFD1(ndp^.ni_dirfd);
|
||||
//if (cnp^.cn_flags and AUDITVNODE2)
|
||||
// AUDIT_ARG_ATFD2(ndp^.ni_dirfd);
|
||||
error:=fgetvp_rights(ndp^.ni_dirfd,
|
||||
ndp^.ni_rightsneeded or CAP_LOOKUP,
|
||||
@ndp^.ni_baserights, @dp);
|
||||
ndp^.ni_rightsneeded or CAP_LOOKUP,
|
||||
@ndp^.ni_baserights,
|
||||
@dp);
|
||||
|
||||
end;
|
||||
if (error<>0) or (dp<>nil) then
|
||||
|
@ -276,15 +264,16 @@ begin
|
|||
else
|
||||
cp:=cnp^.cn_pnbuf;
|
||||
|
||||
aiov.iov_base:=cp;
|
||||
aiov.iov_len:=MAXPATHLEN;
|
||||
auio.uio_iov:=@aiov;
|
||||
aiov.iov_base :=cp;
|
||||
aiov.iov_len :=MAXPATHLEN;
|
||||
auio.uio_iov :=@aiov;
|
||||
auio.uio_iovcnt:=1;
|
||||
auio.uio_offset:=0;
|
||||
auio.uio_rw:=UIO_READ;
|
||||
auio.uio_rw :=UIO_READ;
|
||||
auio.uio_segflg:=UIO_SYSSPACE;
|
||||
auio.uio_td:=td;
|
||||
auio.uio_resid:=MAXPATHLEN;
|
||||
auio.uio_td :=td;
|
||||
auio.uio_resid :=MAXPATHLEN;
|
||||
|
||||
error:=VOP_READLINK(ndp^.ni_vp, @auio);
|
||||
if (error<>0) then
|
||||
begin
|
||||
|
@ -313,8 +302,8 @@ begin
|
|||
FreeMem(cnp^.cn_pnbuf);
|
||||
cnp^.cn_pnbuf:=cp;
|
||||
end else
|
||||
cnp^.cn_pnbuf[linklen]:='0';
|
||||
ndp^.ni_pathlen += linklen;
|
||||
cnp^.cn_pnbuf[linklen]:=#0;
|
||||
Inc(ndp^.ni_pathlen,linklen);
|
||||
vput(ndp^.ni_vp);
|
||||
dp:=ndp^.ni_dvp;
|
||||
end;
|
||||
|
@ -459,7 +448,7 @@ begin
|
|||
(cnp^.cn_nameiop<>LOOKUP)) then
|
||||
docache:=0;
|
||||
_rdonly:=cnp^.cn_flags and RDONLY;
|
||||
cnp^.cn_flags:= cnp^.cn_flags and (not ISSYMLINK);
|
||||
cnp^.cn_flags:=cnp^.cn_flags and (not ISSYMLINK);
|
||||
ndp^.ni_dvp:=nil;
|
||||
{
|
||||
* We use shared locks until we hit the parent of the last cn then
|
||||
|
@ -567,12 +556,6 @@ dirloop:
|
|||
end;
|
||||
ndp^.ni_vp:=dp;
|
||||
|
||||
//if (cnp^.cn_flags and AUDITVNODE1) then
|
||||
// AUDIT_ARG_VNODE1(dp);
|
||||
//else
|
||||
//if (cnp^.cn_flags and AUDITVNODE2) then
|
||||
// AUDIT_ARG_VNODE2(dp);
|
||||
|
||||
if ((cnp^.cn_flags and (LOCKPARENT or LOCKLEAF))=0) then
|
||||
VOP_UNLOCK(dp, 0);
|
||||
{ XXX This should probably move to the top of function. }
|
||||
|
@ -669,6 +652,7 @@ unionlookup:
|
|||
(VOP_ISLOCKED(dp)=LK_SHARED) and
|
||||
((cnp^.cn_flags and ISLASTCN)<>0) and ((cnp^.cn_flags and LOCKPARENT)<>0) then
|
||||
vn_lock(dp, LK_UPGRADE or LK_RETRY);
|
||||
|
||||
if ((dp^.v_iflag and VI_DOOMED)<>0) then
|
||||
begin
|
||||
error:=ENOENT;
|
||||
|
@ -893,13 +877,9 @@ nextname:
|
|||
ni_dvp_unlocked:=1;
|
||||
end;
|
||||
|
||||
//if (cnp^.cn_flags and AUDITVNODE1) then
|
||||
// AUDIT_ARG_VNODE1(dp);
|
||||
//else if (cnp^.cn_flags and AUDITVNODE2) then
|
||||
// AUDIT_ARG_VNODE2(dp);
|
||||
|
||||
if ((cnp^.cn_flags and LOCKLEAF)=0) then
|
||||
VOP_UNLOCK(dp, 0);
|
||||
|
||||
success:
|
||||
{
|
||||
* Because of lookup_shared we may have the vnode shared locked, but
|
||||
|
|
|
@ -33,6 +33,22 @@ const
|
|||
nil
|
||||
);
|
||||
|
||||
type
|
||||
{ A memory allocation which must be freed when we are done }
|
||||
p_mntaarg=^t_mntaarg;
|
||||
t_mntaarg=packed record
|
||||
next:SLIST_ENTRY; //mntaarg
|
||||
end;
|
||||
|
||||
{ The header for the mount arguments }
|
||||
p_mntarg=^t_mntarg;
|
||||
t_mntarg=packed record
|
||||
v:p_iovec;
|
||||
len:Integer;
|
||||
error:Integer;
|
||||
list:SLIST_HEAD; //mntaarg
|
||||
end;
|
||||
|
||||
procedure vfs_freeopt(opts:p_vfsoptlist;opt:p_vfsopt);
|
||||
procedure vfs_freeopts(opts:p_vfsoptlist);
|
||||
procedure vfs_deleteopt(opts:p_vfsoptlist;name:PChar);
|
||||
|
@ -77,6 +93,13 @@ function vfs_donmount(fsflags:QWORD;fsoptions:p_uio):Integer;
|
|||
|
||||
function dounmount(mp:p_mount;flags:Integer):Integer;
|
||||
|
||||
function mount_argb(ma:p_mntarg;flag:Integer;name:PChar):p_mntarg;
|
||||
function mount_argf(ma:p_mntarg;name,fmt:PChar;const Args:Array of const):p_mntarg; register;
|
||||
function mount_argsu(ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg;
|
||||
function mount_arg(ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg;
|
||||
procedure free_mntarg(ma:p_mntarg);
|
||||
function kernel_mount(ma:p_mntarg;flags:QWORD):Integer;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
|
@ -211,12 +234,12 @@ begin
|
|||
begin
|
||||
if (vfs_equalopts(opt^.name, opt2^.name)<>0) then
|
||||
begin
|
||||
tmp:=TAILQ_PREV(opt2,@opt^.link);
|
||||
tmp:=TAILQ_PREV(opt2,@opt2^.link);
|
||||
vfs_freeopt(opts, opt2);
|
||||
opt2:=tmp;
|
||||
end else
|
||||
begin
|
||||
opt2:=TAILQ_PREV(opt2,@opt^.link);
|
||||
opt2:=TAILQ_PREV(opt2,@opt2^.link);
|
||||
end;
|
||||
end;
|
||||
//
|
||||
|
@ -643,7 +666,8 @@ end;
|
|||
|
||||
function strlcpy(dst,src:PChar;size:ptrint):ptrint; inline;
|
||||
begin
|
||||
Result:=strlcopy(dst,src,size)-dst;
|
||||
strlcopy(dst,src,size);
|
||||
Result:=strlen(dst);
|
||||
end;
|
||||
|
||||
function vfs_setopts(opts:p_vfsoptlist;name,value:PChar):Integer;
|
||||
|
@ -720,11 +744,11 @@ begin
|
|||
mp^.mnt_stat.f_type:=vfsp^.vfc_typenum;
|
||||
Inc(mp^.mnt_gen);
|
||||
|
||||
strlcopy(mp^.mnt_stat.f_fstypename, vfsp^.vfc_name, MFSNAMELEN);
|
||||
strlcopy(@mp^.mnt_stat.f_fstypename, @vfsp^.vfc_name, MFSNAMELEN);
|
||||
|
||||
mp^.mnt_vnodecovered:=vp;
|
||||
|
||||
strlcopy(mp^.mnt_stat.f_mntonname, fspath, MNAMELEN);
|
||||
strlcopy(@mp^.mnt_stat.f_mntonname, fspath, MNAMELEN);
|
||||
|
||||
mp^.mnt_iosize_max:=DFLTPHYS;
|
||||
|
||||
|
@ -941,7 +965,7 @@ begin
|
|||
VI_UNLOCK(vp);
|
||||
vfs_unbusy(mp);
|
||||
vput(vp);
|
||||
Exit (EBUSY);
|
||||
Exit(EBUSY);
|
||||
end;
|
||||
vp^.v_iflag:=vp^.v_iflag or VI_MOUNT;
|
||||
VI_UNLOCK(vp);
|
||||
|
@ -951,6 +975,7 @@ begin
|
|||
mp^.mnt_flag:=mp^.mnt_flag and (not MNT_UPDATEMASK);
|
||||
mp^.mnt_flag:=(mp^.mnt_flag or fsflags) and (MNT_RELOAD or MNT_FORCE or MNT_UPDATE or
|
||||
MNT_SNAPSHOT or MNT_ROOTFS or MNT_UPDATEMASK or MNT_RDONLY);
|
||||
|
||||
if ((mp^.mnt_flag and MNT_ASYNC)=0) then
|
||||
mp^.mnt_kern_flag:=mp^.mnt_kern_flag and (not MNTK_ASYNC);
|
||||
MNT_IUNLOCK(mp);
|
||||
|
@ -1050,7 +1075,7 @@ function vfs_domount(fstype:PChar; { Filesystem type. }
|
|||
):Integer;
|
||||
var
|
||||
vfsp:p_vfsconf;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vp:p_vnode;
|
||||
pathbuf:PChar;
|
||||
error:Integer;
|
||||
|
@ -1462,6 +1487,153 @@ begin
|
|||
Exit(0);
|
||||
end;
|
||||
|
||||
{
|
||||
* Add a boolean argument.
|
||||
*
|
||||
* flag is the boolean value.
|
||||
* name must start with 'no'.
|
||||
}
|
||||
function mount_argb(ma:p_mntarg;flag:Integer;name:PChar):p_mntarg;
|
||||
begin
|
||||
Assert((name[0]='n') and (name[1]='o'),'mount_argb(...,%s): name must start with no');
|
||||
|
||||
Exit(mount_arg(ma, name + (ord(flag<>0)*2), nil, 0));
|
||||
end;
|
||||
|
||||
{
|
||||
* Add an argument printf style
|
||||
}
|
||||
function mount_argf(ma:p_mntarg;name,fmt:PChar;const Args:Array of const):p_mntarg; register;
|
||||
var
|
||||
maa:p_mntaarg;
|
||||
len:Integer;
|
||||
sb:RawByteString;
|
||||
begin
|
||||
if (ma=nil) then
|
||||
begin
|
||||
ma:=AllocMem(sizeof(t_mntarg));
|
||||
SLIST_INIT(@ma^.list);
|
||||
end;
|
||||
if (ma^.error<>0) then
|
||||
Exit(ma);
|
||||
|
||||
ma^.v:=ReAllocMem(ma^.v, sizeof(iovec) * (ma^.len + 2));
|
||||
ma^.v[ma^.len].iov_base:=name;
|
||||
ma^.v[ma^.len].iov_len :=strlen(name) + 1;
|
||||
Inc(ma^.len);
|
||||
|
||||
sb:=Format(fmt,Args);
|
||||
len:=Length(sb) + 1;
|
||||
maa:=AllocMem(sizeof(t_mntaarg) + len);
|
||||
SLIST_INSERT_HEAD(@ma^.list,maa,@maa^.next);
|
||||
Move(PChar(sb)^, (maa + 1)^, len);
|
||||
|
||||
ma^.v[ma^.len].iov_base:=maa + 1;
|
||||
ma^.v[ma^.len].iov_len :=len;
|
||||
Inc(ma^.len);
|
||||
|
||||
Exit(ma);
|
||||
end;
|
||||
|
||||
{
|
||||
* Add an argument which is a userland string.
|
||||
}
|
||||
function mount_argsu(ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg;
|
||||
var
|
||||
maa:p_mntaarg;
|
||||
tbuf:Pointer;
|
||||
begin
|
||||
if (val=nil) then
|
||||
Exit(ma);
|
||||
if (ma=nil) then
|
||||
begin
|
||||
ma:=AllocMem(sizeof(t_mntarg));
|
||||
SLIST_INIT(@ma^.list);
|
||||
end;
|
||||
if (ma^.error<>0) then
|
||||
Exit(ma);
|
||||
maa:=AllocMem(sizeof(t_mntaarg) + len);
|
||||
SLIST_INSERT_HEAD(@ma^.list,maa,@maa^.next);
|
||||
tbuf:=Pointer(maa + 1);
|
||||
ma^.error:=copyinstr(val, tbuf, len, nil);
|
||||
Exit(mount_arg(ma, name, tbuf, -1));
|
||||
end;
|
||||
|
||||
{
|
||||
* Plain argument.
|
||||
*
|
||||
* If length is -1, treat value as a C string.
|
||||
}
|
||||
function mount_arg(ma:p_mntarg;name:PChar;val:Pointer;len:Integer):p_mntarg;
|
||||
begin
|
||||
if (ma=nil) then
|
||||
begin
|
||||
ma:=AllocMem(sizeof(t_mntarg));
|
||||
SLIST_INIT(@ma^.list);
|
||||
end;
|
||||
if (ma^.error<>0) then
|
||||
Exit(ma);
|
||||
|
||||
ma^.v:=ReAllocMem(ma^.v, sizeof(iovec) * (ma^.len + 2));
|
||||
ma^.v[ma^.len].iov_base:=name;
|
||||
ma^.v[ma^.len].iov_len :=strlen(name) + 1;
|
||||
Inc(ma^.len);
|
||||
|
||||
ma^.v[ma^.len].iov_base:=val;
|
||||
if (len < 0) then
|
||||
ma^.v[ma^.len].iov_len:=strlen(val) + 1
|
||||
else
|
||||
ma^.v[ma^.len].iov_len:=len;
|
||||
Inc(ma^.len);
|
||||
|
||||
Exit(ma);
|
||||
end;
|
||||
|
||||
{
|
||||
* Free a mntarg structure
|
||||
}
|
||||
procedure free_mntarg(ma:p_mntarg);
|
||||
var
|
||||
maa:p_mntaarg;
|
||||
begin
|
||||
while (not SLIST_EMPTY(@ma^.list)) do
|
||||
begin
|
||||
maa:=SLIST_FIRST(@ma^.list);
|
||||
SLIST_REMOVE_HEAD(@ma^.list,@p_mntaarg(nil)^.next);
|
||||
FreeMem(maa);
|
||||
end;
|
||||
FreeMem(ma^.v);
|
||||
FreeMem(ma);
|
||||
end;
|
||||
|
||||
{
|
||||
* Mount a filesystem
|
||||
}
|
||||
function kernel_mount(ma:p_mntarg;flags:QWORD):Integer;
|
||||
var
|
||||
auio:t_uio;
|
||||
error:Integer;
|
||||
begin
|
||||
Assert(ma<>nil, 'kernel_mount nil ma');
|
||||
Assert(ma^.v<>nil, 'kernel_mount nil ma^.v');
|
||||
Assert((ma^.len and 1)=0, 'kernel_mount odd ma^.len (%d)');
|
||||
|
||||
auio.uio_iov:=ma^.v;
|
||||
auio.uio_iovcnt:=ma^.len;
|
||||
auio.uio_segflg:=UIO_SYSSPACE;
|
||||
|
||||
error:=ma^.error;
|
||||
if (error=0) then
|
||||
error:=vfs_donmount(flags, @auio);
|
||||
free_mntarg(ma);
|
||||
Exit(error);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end.
|
||||
|
||||
|
|
|
@ -0,0 +1,349 @@
|
|||
unit vfs_mountroot;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
{$CALLING SysV_ABI_CDecl}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
mqueue,
|
||||
vmount;
|
||||
|
||||
procedure vfs_mountroot();
|
||||
function vfs_mountroot_simple(fstype,fspath,from,opts:PChar):Integer;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
errno,
|
||||
vuio,
|
||||
vnamei,
|
||||
vfs_vnode,
|
||||
vnode_if,
|
||||
vfiledesc,
|
||||
vfs_subr,
|
||||
vfs_init,
|
||||
vfs_mount,
|
||||
vfs_syscalls,
|
||||
vfs_lookup,
|
||||
kern_thr,
|
||||
kern_mtx;
|
||||
|
||||
function strdup(src:PChar):PChar; inline;
|
||||
var
|
||||
i:ptrint;
|
||||
begin
|
||||
i:=strlen(src);
|
||||
Result:=AllocMem(i+1);
|
||||
Move(src^,Result^,i);
|
||||
end;
|
||||
|
||||
function strsep(stringp:PPChar;delim:PChar):PChar;
|
||||
var
|
||||
b,e:PChar;
|
||||
begin
|
||||
b:=stringp^;
|
||||
if (b=nil) then Exit(nil);
|
||||
|
||||
e:=strpos(b,delim)+strlen(delim);
|
||||
|
||||
if (e^<>#0) then
|
||||
begin
|
||||
e^:=#0;
|
||||
Inc(e);
|
||||
stringp^:=e;
|
||||
end else
|
||||
begin
|
||||
stringp^:=nil;
|
||||
end;
|
||||
|
||||
Result:=b;
|
||||
end;
|
||||
|
||||
function parse_mountroot_options(ma:p_mntarg;options:PChar):p_mntarg;
|
||||
var
|
||||
p:PChar;
|
||||
name,name_arg:PChar;
|
||||
val,val_arg:PChar;
|
||||
opts:PChar;
|
||||
begin
|
||||
if (options=nil) or (options[0]=#0) then
|
||||
Exit(ma);
|
||||
|
||||
p:=strdup(options);
|
||||
opts:=p;
|
||||
|
||||
if (opts=nil) then
|
||||
begin
|
||||
Exit(ma);
|
||||
end;
|
||||
|
||||
name:=strsep(@p, ',');
|
||||
while (name<>nil) do
|
||||
begin
|
||||
if (name[0]=#0) then
|
||||
break;
|
||||
|
||||
val:=strscan(name, '=');
|
||||
if (val<>nil) then
|
||||
begin
|
||||
val^:=#0;
|
||||
Inc(val);
|
||||
end;
|
||||
|
||||
name_arg:=strdup(name);
|
||||
val_arg:=nil;
|
||||
|
||||
if (val<>nil) then
|
||||
val_arg:=strdup(val);
|
||||
|
||||
ma:=mount_arg(ma, name_arg, val_arg, (ord(val_arg<>nil)*(-1)));
|
||||
|
||||
name:=strsep(@p, ',');
|
||||
end;
|
||||
|
||||
FreeMem(opts);
|
||||
Exit(ma);
|
||||
end;
|
||||
|
||||
procedure set_rootvnode();
|
||||
begin
|
||||
if (VFS_ROOT(TAILQ_FIRST(@mountlist), LK_EXCLUSIVE, @rootvnode)<>0) then
|
||||
Assert(False,'Cannot find root vnode');
|
||||
|
||||
VOP_UNLOCK(rootvnode, 0);
|
||||
|
||||
FILEDESC_XLOCK(@fd_table);
|
||||
|
||||
if (fd_table.fd_cdir<>nil) then
|
||||
vrele(fd_table.fd_cdir);
|
||||
|
||||
fd_table.fd_cdir:=rootvnode;
|
||||
VREF(rootvnode);
|
||||
|
||||
if (fd_table.fd_rdir<>nil) then
|
||||
vrele(fd_table.fd_rdir);
|
||||
|
||||
fd_table.fd_rdir:=rootvnode;
|
||||
VREF(rootvnode);
|
||||
|
||||
FILEDESC_XUNLOCK(@fd_table);
|
||||
end;
|
||||
|
||||
function vfs_mountroot_devfs(mpp:pp_mount):Integer;
|
||||
var
|
||||
opts:p_vfsoptlist;
|
||||
vfsp:p_vfsconf;
|
||||
mp:p_mount;
|
||||
error:Integer;
|
||||
begin
|
||||
mpp^:=nil;
|
||||
|
||||
vfsp:=vfs_byname('devfs');
|
||||
Assert(vfsp<>nil,'Could not find devfs by name');
|
||||
|
||||
if (vfsp=nil) then
|
||||
Exit(ENOENT);
|
||||
|
||||
mp:=vfs_mount_alloc(nil, vfsp, '/dev');
|
||||
|
||||
error:=vmount.VFS_MOUNT(mp);
|
||||
Assert(error=0,'VFS_MOUNT(devfs) failed');
|
||||
|
||||
if (error<>0) then
|
||||
Exit(error);
|
||||
|
||||
opts:=AllocMem(sizeof(vfsoptlist));
|
||||
TAILQ_INIT(opts);
|
||||
mp^.mnt_opt:=opts;
|
||||
|
||||
mtx_lock(mountlist_mtx);
|
||||
TAILQ_INSERT_HEAD(@mountlist,mp,@mp^.mnt_list);
|
||||
mtx_unlock(mountlist_mtx);
|
||||
|
||||
mpp^:=mp;
|
||||
set_rootvnode();
|
||||
|
||||
error:=kern_symlink('/', 'dev', UIO_SYSSPACE);
|
||||
if (error<>0) then
|
||||
begin
|
||||
Writeln('kern_symlink /dev / returns ',error);
|
||||
end;
|
||||
|
||||
Exit(error);
|
||||
end;
|
||||
|
||||
|
||||
function vfs_mountroot_shuffle(mpdevfs:p_mount):Integer;
|
||||
var
|
||||
nd:t_nameidata;
|
||||
mporoot,mpnroot:p_mount;
|
||||
vp,vporoot,vpdevfs:p_vnode;
|
||||
fspath:PChar;
|
||||
error:Integer;
|
||||
begin
|
||||
mpnroot:=TAILQ_NEXT(mpdevfs,@mpdevfs^.mnt_list);
|
||||
|
||||
{ Shuffle the mountlist. }
|
||||
mtx_lock(mountlist_mtx);
|
||||
mporoot:=TAILQ_FIRST(@mountlist);
|
||||
TAILQ_REMOVE(@mountlist,mpdevfs,@mpdevfs^.mnt_list);
|
||||
if (mporoot<>mpdevfs) then
|
||||
begin
|
||||
TAILQ_REMOVE(@mountlist,mpnroot,@mpnroot^.mnt_list);
|
||||
TAILQ_INSERT_HEAD(@mountlist,mpnroot,@mpnroot^.mnt_list);
|
||||
end;
|
||||
TAILQ_INSERT_TAIL(@mountlist,mpdevfs,@mpdevfs^.mnt_list);
|
||||
mtx_unlock(mountlist_mtx);
|
||||
|
||||
//cache_purgevfs(mporoot);
|
||||
//if (mporoot<>mpdevfs) then
|
||||
// cache_purgevfs(mpdevfs);
|
||||
|
||||
VFS_ROOT(mporoot, LK_EXCLUSIVE, @vporoot);
|
||||
|
||||
VI_LOCK(vporoot);
|
||||
vporoot^.v_iflag:=vporoot^.v_iflag and (not VI_MOUNT);
|
||||
VI_UNLOCK(vporoot);
|
||||
vporoot^.v_mountedhere:=nil;
|
||||
mporoot^.mnt_flag:=mporoot^.mnt_flag and (not MNT_ROOTFS);
|
||||
mporoot^.mnt_vnodecovered:=nil;
|
||||
vput(vporoot);
|
||||
|
||||
{ Set up the new rootvnode, and purge the cache }
|
||||
mpnroot^.mnt_vnodecovered:=nil;
|
||||
set_rootvnode();
|
||||
//cache_purgevfs(rootvnode^.v_mount);
|
||||
|
||||
if (mporoot<>mpdevfs) then
|
||||
begin
|
||||
{ Remount old root under /.mount or /mnt }
|
||||
fspath:='/.mount';
|
||||
NDINIT(@nd, LOOKUP, FOLLOW or LOCKLEAF, UIO_SYSSPACE, fspath, curkthread);
|
||||
error:=_namei(@nd);
|
||||
if (error<>0) then
|
||||
begin
|
||||
NDFREE(@nd, NDF_ONLY_PNBUF);
|
||||
fspath:='/mnt';
|
||||
NDINIT(@nd, LOOKUP, FOLLOW or LOCKLEAF, UIO_SYSSPACE, fspath, curkthread);
|
||||
error:=_namei(@nd);
|
||||
end;
|
||||
if (error=0) then
|
||||
begin
|
||||
vp:=nd.ni_vp;
|
||||
|
||||
if (vp^.v_type=VDIR) then
|
||||
error:=0
|
||||
else
|
||||
error:=ENOTDIR;
|
||||
|
||||
//if (error=0) then
|
||||
// error:=vinvalbuf(vp, V_SAVE, 0, 0);
|
||||
|
||||
if (error=0) then
|
||||
begin
|
||||
//cache_purge(vp);
|
||||
mporoot^.mnt_vnodecovered:=vp;
|
||||
vp^.v_mountedhere:=mporoot;
|
||||
strlcopy(@mporoot^.mnt_stat.f_mntonname, fspath, MNAMELEN);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
end else
|
||||
vput(vp);
|
||||
end;
|
||||
NDFREE(@nd, NDF_ONLY_PNBUF);
|
||||
|
||||
if (error<>0) then
|
||||
Writeln('mountroot: unable to remount previous root under /.mount or /mnt ', error);
|
||||
end;
|
||||
|
||||
{ Remount devfs under /dev }
|
||||
NDINIT(@nd, LOOKUP, FOLLOW or LOCKLEAF, UIO_SYSSPACE, '/dev', curkthread);
|
||||
error:=_namei(@nd);
|
||||
if (error=0) then
|
||||
begin
|
||||
vp:=nd.ni_vp;
|
||||
|
||||
if (vp^.v_type=VDIR) then
|
||||
error:=0
|
||||
else
|
||||
error:=ENOTDIR;
|
||||
|
||||
//if (error=0) then
|
||||
// error:=vinvalbuf(vp, V_SAVE, 0, 0);
|
||||
|
||||
if (error=0) then
|
||||
begin
|
||||
vpdevfs:=mpdevfs^.mnt_vnodecovered;
|
||||
if (vpdevfs<>nil) then
|
||||
begin
|
||||
//cache_purge(vpdevfs);
|
||||
vpdevfs^.v_mountedhere:=nil;
|
||||
vrele(vpdevfs);
|
||||
end;
|
||||
mpdevfs^.mnt_vnodecovered:=vp;
|
||||
vp^.v_mountedhere:=mpdevfs;
|
||||
VOP_UNLOCK(vp, 0);
|
||||
end else
|
||||
vput(vp);
|
||||
end;
|
||||
if (error<>0) then
|
||||
Writeln('mountroot: unable to remount devfs under /dev ', error);
|
||||
|
||||
NDFREE(@nd, NDF_ONLY_PNBUF);
|
||||
|
||||
if (mporoot=mpdevfs) then
|
||||
begin
|
||||
vfs_unbusy(mpdevfs);
|
||||
{ Unlink the no longer needed /dev/dev ^. / symlink }
|
||||
error:=kern_unlink('/dev/dev', UIO_SYSSPACE);
|
||||
if (error<>0) then
|
||||
Writeln('mountroot: unable to unlink /dev/dev ', error);
|
||||
end;
|
||||
|
||||
Exit(0);
|
||||
end;
|
||||
|
||||
function vfs_mountroot_simple(fstype,fspath,from,opts:PChar):Integer;
|
||||
const
|
||||
ERRMSGL=255;
|
||||
var
|
||||
ma:p_mntarg;
|
||||
errmsg:RawByteString;
|
||||
begin
|
||||
errmsg:='';
|
||||
SetLength(errmsg,ERRMSGL);
|
||||
FillChar(PChar(errmsg)^,ERRMSGL,0);
|
||||
|
||||
if (vfs_byname(fstype)=nil) then
|
||||
begin
|
||||
strlcopy(PChar(errmsg),'unknown file system',ERRMSGL);
|
||||
Exit(ENOENT);
|
||||
end;
|
||||
|
||||
ma:=nil;
|
||||
ma:=mount_arg(ma, 'fstype', fstype, -1);
|
||||
ma:=mount_arg(ma, 'fspath', fspath, -1);
|
||||
ma:=mount_arg(ma, 'from' , from , -1);
|
||||
ma:=mount_arg(ma, 'errmsg', PChar(errmsg), ERRMSGL);
|
||||
|
||||
ma:=parse_mountroot_options(ma, opts);
|
||||
Result:=kernel_mount(ma, MNT_ROOTFS);
|
||||
end;
|
||||
|
||||
procedure vfs_mountroot();
|
||||
var
|
||||
mp:p_mount;
|
||||
error:Integer;
|
||||
begin
|
||||
error:=vfs_mountroot_devfs(@mp);
|
||||
|
||||
if (error<>0) then
|
||||
begin
|
||||
error:=vfs_mountroot_shuffle(mp);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -79,11 +79,14 @@ function sys_renameat(oldfd:Integer;old:PChar;newfd:Integer;new:PChar):Integer;
|
|||
function sys_mkdir(path:PChar;mode:Integer):Integer;
|
||||
function sys_mkdirat(fd:Integer;path:PChar;mode:Integer):Integer;
|
||||
function sys_rmdir(path:PChar):Integer;
|
||||
function sys_getdirentries(fd:Integer;buf:PChar;count:DWORD;basep:PInt64):Integer;
|
||||
function sys_getdents(fd:Integer;buf:PChar;count:DWORD):Integer;
|
||||
function sys_getdirentries(fd:Integer;buf:Pointer;count:DWORD;basep:PInt64):Integer;
|
||||
function sys_getdents(fd:Integer;buf:Pointer;count:DWORD):Integer;
|
||||
function sys_umask(newmask:Integer):Integer;
|
||||
function sys_revoke(path:PChar):Integer;
|
||||
|
||||
function kern_symlink(path,link:PChar;segflg:uio_seg):Integer;
|
||||
function kern_unlink(path:PChar;pathseg:uio_seg):Integer;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
|
@ -146,7 +149,7 @@ var
|
|||
sb:t_statfs;
|
||||
vfslocked:Integer;
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
begin
|
||||
NDINIT(@nd, LOOKUP, FOLLOW or LOCKSHARED or LOCKLEAF or MPSAFE or AUDITVNODE1, pathseg, path, curkthread);
|
||||
error:=_namei(@nd);
|
||||
|
@ -496,7 +499,7 @@ end;
|
|||
function kern_chdir(path:PChar;pathseg:uio_seg):Integer;
|
||||
var
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vp:p_vnode;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
|
@ -582,7 +585,7 @@ label
|
|||
e_vunlock;
|
||||
var
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
error:=EPERM;
|
||||
|
@ -728,7 +731,7 @@ var
|
|||
nfp:p_file;
|
||||
_type,indx,error,error_open:Integer;
|
||||
lf:t_flock;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
rights_needed:cap_rights_t;
|
||||
begin
|
||||
|
@ -925,7 +928,7 @@ var
|
|||
mp:p_mount;
|
||||
vattr:t_vattr;
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
restart:
|
||||
|
@ -985,7 +988,7 @@ var
|
|||
vattr:t_vattr;
|
||||
error:Integer;
|
||||
whiteout:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
whiteout:=0;
|
||||
|
@ -1134,7 +1137,7 @@ function kern_linkat(fd1,fd2:Integer;path1,path2:PChar;segflg:uio_seg;follow:Int
|
|||
var
|
||||
vp:p_vnode;
|
||||
mp:p_mount;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
lvfslocked:Integer;
|
||||
error:Integer;
|
||||
|
@ -1236,7 +1239,7 @@ var
|
|||
vattr:t_vattr;
|
||||
syspath:PChar;
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
if (segflg=UIO_SYSSPACE) then
|
||||
|
@ -1326,7 +1329,7 @@ var
|
|||
mp:p_mount;
|
||||
vp:p_vnode;
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
sb:t_stat;
|
||||
vfslocked:Integer;
|
||||
|
||||
|
@ -1575,7 +1578,7 @@ label
|
|||
out1;
|
||||
var
|
||||
vp:p_vnode;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
error:Integer;
|
||||
begin
|
||||
|
@ -1616,7 +1619,7 @@ function kern_statat_vnhook(flag,fd:Integer;
|
|||
sbp:p_stat;
|
||||
hook:t_statat_hook_cb):Integer;
|
||||
var
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
sb:t_stat;
|
||||
error, vfslocked:Integer;
|
||||
begin
|
||||
|
@ -1656,7 +1659,6 @@ end;
|
|||
function kern_statat(flag,fd:Integer;path:PChar;
|
||||
pathseg:uio_seg;sbp:p_stat):Integer;
|
||||
begin
|
||||
|
||||
Exit(kern_statat_vnhook(flag, fd, path, pathseg, sbp, nil));
|
||||
end;
|
||||
|
||||
|
@ -1712,7 +1714,7 @@ end;
|
|||
function kern_pathconf(path:PChar;pathseg:uio_seg;name:Integer;flags:QWORD):Integer;
|
||||
var
|
||||
td:p_kthread;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
error,vfslocked:Integer;
|
||||
begin
|
||||
td:=curkthread;
|
||||
|
@ -1750,7 +1752,7 @@ var
|
|||
aiov:iovec;
|
||||
auio:t_uio;
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
if (count > IOSIZE_MAX) then
|
||||
|
@ -1859,7 +1861,7 @@ end;
|
|||
function sys_chflags(path:PChar;flags:Integer):Integer;
|
||||
var
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
NDINIT(@nd, LOOKUP, FOLLOW or MPSAFE or AUDITVNODE1, UIO_USERSPACE, path, curkthread);
|
||||
|
@ -1880,7 +1882,7 @@ end;
|
|||
function sys_lchflags(path:PChar;flags:Integer):Integer;
|
||||
var
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
NDINIT(@nd, LOOKUP, NOFOLLOW or MPSAFE or AUDITVNODE1, UIO_USERSPACE, path, curkthread);
|
||||
|
@ -1944,7 +1946,7 @@ end;
|
|||
function kern_fchmodat(fd:Integer;path:PChar;pathseg:uio_seg;mode,flag:Integer):Integer;
|
||||
var
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
follow:Integer;
|
||||
begin
|
||||
|
@ -2043,7 +2045,7 @@ end;
|
|||
|
||||
function kern_fchownat(fd:Integer;path:PChar;pathseg:uio_seg;uid,gid,flag:Integer):Integer;
|
||||
var
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
error,vfslocked,follow:Integer;
|
||||
begin
|
||||
if (flag and AT_SYMLINK_NOFOLLOW)<>0 then
|
||||
|
@ -2194,7 +2196,7 @@ end;
|
|||
function kern_utimesat(fd:Integer;path:PChar;pathseg:uio_seg;
|
||||
tptr:ptimeval;tptrseg:uio_seg):Integer;
|
||||
var
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
ts:array[0..1] of timespec;
|
||||
error,vfslocked:Integer;
|
||||
begin
|
||||
|
@ -2238,7 +2240,7 @@ function kern_lutimes(path:PChar;pathseg:uio_seg;
|
|||
var
|
||||
ts:array[0..1] of timespec;
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
error:=getutimes(tptr, tptrseg, ts);
|
||||
|
@ -2300,7 +2302,7 @@ var
|
|||
vp:p_vnode;
|
||||
rl_cookie:Pointer;
|
||||
vattr:t_vattr;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
error,vfslocked:Integer;
|
||||
begin
|
||||
if (length < 0) then
|
||||
|
@ -2413,7 +2415,7 @@ label
|
|||
var
|
||||
mp:p_mount;
|
||||
tvp,fvp,tdvp:p_vnode;
|
||||
fromnd,tond:nameidata;
|
||||
fromnd,tond:t_nameidata;
|
||||
tvfslocked:Integer;
|
||||
fvfslocked:Integer;
|
||||
error:Integer;
|
||||
|
@ -2556,7 +2558,7 @@ var
|
|||
vp:p_vnode;
|
||||
vattr:t_vattr;
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
restart:
|
||||
|
@ -2641,7 +2643,7 @@ var
|
|||
mp:p_mount;
|
||||
vp:p_vnode;
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
restart:
|
||||
|
@ -2720,7 +2722,7 @@ begin
|
|||
Exit(kern_rmdir(path, UIO_USERSPACE));
|
||||
end;
|
||||
|
||||
function kern_getdirentries(fd:Integer;buf:PChar;count:DWORD;basep:PInt64):Integer;
|
||||
function kern_getdirentries(fd:Integer;buf:Pointer;count:DWORD;basep:PInt64):Integer;
|
||||
label
|
||||
unionread,
|
||||
fail;
|
||||
|
@ -2781,9 +2783,9 @@ unionread:
|
|||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
goto fail;
|
||||
end;
|
||||
if (count=auio.uio_resid and
|
||||
(vp^.v_vflag and VV_ROOT) and
|
||||
(p_mount(vp^.v_mount)^.mnt_flag and MNT_UNION)) then
|
||||
if (count=auio.uio_resid) and
|
||||
((vp^.v_vflag and VV_ROOT)<>0) and
|
||||
((p_mount(vp^.v_mount)^.mnt_flag and MNT_UNION)<>0) then
|
||||
begin
|
||||
tvp:=vp;
|
||||
vp:=p_mount(vp^.v_mount)^.mnt_vnodecovered;
|
||||
|
@ -2808,7 +2810,7 @@ end;
|
|||
{
|
||||
* Read a block of directory entries in a filesystem independent format.
|
||||
}
|
||||
function sys_getdirentries(fd:Integer;buf:PChar;count:DWORD;basep:PInt64):Integer;
|
||||
function sys_getdirentries(fd:Integer;buf:Pointer;count:DWORD;basep:PInt64):Integer;
|
||||
var
|
||||
base:Int64;
|
||||
error:Integer;
|
||||
|
@ -2821,7 +2823,7 @@ begin
|
|||
Exit(error);
|
||||
end;
|
||||
|
||||
function sys_getdents(fd:Integer;buf:PChar;count:DWORD):Integer;
|
||||
function sys_getdents(fd:Integer;buf:Pointer;count:DWORD):Integer;
|
||||
begin
|
||||
Exit(sys_getdirentries(fd,buf,count,nil));
|
||||
end;
|
||||
|
@ -2849,7 +2851,7 @@ var
|
|||
vp:p_vnode;
|
||||
vattr:t_vattr;
|
||||
error:Integer;
|
||||
nd:nameidata;
|
||||
nd:t_nameidata;
|
||||
vfslocked:Integer;
|
||||
begin
|
||||
NDINIT(@nd, LOOKUP, FOLLOW or LOCKLEAF or MPSAFE or AUDITVNODE1,
|
||||
|
|
|
@ -275,7 +275,7 @@ function vn_rangelock_rlock(vp:p_vnode;start,__end:Int64):Pointer;
|
|||
function vn_rangelock_wlock(vp:p_vnode;start,__end:Int64):Pointer;
|
||||
|
||||
var
|
||||
rootvnode:p_vnode;
|
||||
rootvnode:p_vnode=nil;
|
||||
|
||||
implementation
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ const
|
|||
|
||||
function foffset_get(fp:p_file):Int64; inline;
|
||||
function foffset_lock(fp:p_file;flags:Integer):Int64;
|
||||
procedure foffset_lock(fp:p_file;val:Int64;flags:Integer);
|
||||
procedure foffset_unlock(fp:p_file;val:Int64;flags:Integer);
|
||||
procedure foffset_lock_uio(fp:p_file;uio:p_uio;flags:Integer);
|
||||
procedure foffset_unlock_uio(fp:p_file;uio:p_uio;flags:Integer);
|
||||
|
@ -319,16 +318,19 @@ function vn_start_write_locked(mp:p_mount;flags:Integer):Integer;
|
|||
label
|
||||
unlock;
|
||||
var
|
||||
td:p_kthread;
|
||||
error:Integer;
|
||||
begin
|
||||
mtx_assert(MNT_MTX(mp)^);
|
||||
error:=0;
|
||||
|
||||
td:=curkthread;
|
||||
{
|
||||
* Check on status of suspension.
|
||||
}
|
||||
if ((curkthread^.td_pflags and TDP_IGNSUSP)=0) or
|
||||
(mp^.mnt_susp_owner<>curkthread) then
|
||||
if (td<>nil) then
|
||||
if ((td^.td_pflags and TDP_IGNSUSP)=0) or
|
||||
(mp^.mnt_susp_owner<>td) then
|
||||
begin
|
||||
while ((mp^.mnt_kern_flag and MNTK_SUSPEND)<>0) do
|
||||
begin
|
||||
|
@ -342,6 +344,7 @@ begin
|
|||
goto unlock;
|
||||
end;
|
||||
end;
|
||||
|
||||
if ((flags and V_XSLEEP)<>0) then
|
||||
goto unlock;
|
||||
Inc(mp^.mnt_writeopcount);
|
||||
|
@ -495,9 +498,9 @@ begin
|
|||
end;
|
||||
sb^.st_mode:=mode;
|
||||
sb^.st_nlink:=vap^.va_nlink;
|
||||
sb^.st_uid:=vap^.va_uid;
|
||||
sb^.st_gid:=vap^.va_gid;
|
||||
sb^.st_rdev:=vap^.va_rdev;
|
||||
sb^.st_uid :=vap^.va_uid;
|
||||
sb^.st_gid :=vap^.va_gid;
|
||||
sb^.st_rdev :=vap^.va_rdev;
|
||||
if (vap^.va_size > High(Int64)) then
|
||||
Exit(EOVERFLOW);
|
||||
sb^.st_size:=vap^.va_size;
|
||||
|
@ -539,37 +542,55 @@ begin
|
|||
end;
|
||||
|
||||
function foffset_lock(fp:p_file;flags:Integer):Int64;
|
||||
var
|
||||
mtxp:p_mtx;
|
||||
begin
|
||||
Result:=0;
|
||||
Assert((flags and FOF_OFFSET)=0, 'FOF_OFFSET passed');
|
||||
|
||||
if ((flags and FOF_NOLOCK)<>0) then
|
||||
Exit(fp^.f_offset);
|
||||
end;
|
||||
mtxp:=mtx_pool_find(mtxpool_sleep, fp);
|
||||
mtx_lock(mtxp^);
|
||||
|
||||
procedure foffset_lock(fp:p_file;val:Int64;flags:Integer);
|
||||
begin
|
||||
Assert((flags and FOF_OFFSET)=0, ('FOF_OFFSET passed'));
|
||||
|
||||
if ((flags and FOF_NOLOCK)<>0) then
|
||||
if ((flags and FOF_NOLOCK)=0) then
|
||||
begin
|
||||
if ((flags and FOF_NOUPDATE)=0) then
|
||||
fp^.f_offset:=val;
|
||||
if ((flags and FOF_NEXTOFF)<>0) then
|
||||
fp^.f_nextoff:=val;
|
||||
while ((fp^.f_vnread_flags and FOFFSET_LOCKED)<>0) do
|
||||
begin
|
||||
fp^.f_vnread_flags:=fp^.f_vnread_flags or FOFFSET_LOCK_WAITING;
|
||||
msleep(@fp^.f_vnread_flags, mtxp, PUSER, 'vofflock', 0);
|
||||
end;
|
||||
fp^.f_vnread_flags:=fp^.f_vnread_flags or FOFFSET_LOCKED;
|
||||
end;
|
||||
Result:=fp^.f_offset;
|
||||
|
||||
mtx_unlock(mtxp^);
|
||||
end;
|
||||
|
||||
procedure foffset_unlock(fp:p_file;val:Int64;flags:Integer);
|
||||
var
|
||||
mtxp:p_mtx;
|
||||
begin
|
||||
Assert((flags and FOF_OFFSET)=0, ('FOF_OFFSET passed'));
|
||||
Assert((flags and FOF_OFFSET)=0,'FOF_OFFSET passed');
|
||||
|
||||
if ((flags and FOF_NOLOCK)<>0) then
|
||||
mtxp:=mtx_pool_find(mtxpool_sleep, fp);
|
||||
mtx_lock(mtxp^);
|
||||
|
||||
if ((flags and FOF_NOUPDATE)=0) then
|
||||
fp^.f_offset:=val;
|
||||
|
||||
if ((flags and FOF_NEXTOFF)<>0) then
|
||||
fp^.f_nextoff:=val;
|
||||
|
||||
if ((flags and FOF_NOLOCK)=0) then
|
||||
begin
|
||||
if ((flags and FOF_NOUPDATE)=0) then
|
||||
fp^.f_offset:=val;
|
||||
if ((flags and FOF_NEXTOFF)<>0) then
|
||||
fp^.f_nextoff:=val;
|
||||
Assert((fp^.f_vnread_flags and FOFFSET_LOCKED)<>0,'Lost FOFFSET_LOCKED');
|
||||
|
||||
if ((fp^.f_vnread_flags and FOFFSET_LOCK_WAITING)<>0) then
|
||||
wakeup(@fp^.f_vnread_flags);
|
||||
|
||||
fp^.f_vnread_flags:=0;
|
||||
end;
|
||||
|
||||
mtx_unlock(mtxp^);
|
||||
end;
|
||||
|
||||
procedure foffset_lock_uio(fp:p_file;uio:p_uio;flags:Integer);
|
||||
|
|
|
@ -100,45 +100,45 @@ type
|
|||
{
|
||||
* Encapsulation of namei parameters.
|
||||
}
|
||||
p_nameidata=^nameidata;
|
||||
nameidata=packed record
|
||||
{
|
||||
* Arguments to namei/lookup.
|
||||
}
|
||||
ni_dirp:PChar; { pathname pointer }
|
||||
ni_segflg:uio_seg; { location of pathname }
|
||||
_align1 :Integer;
|
||||
ni_rightsneeded:cap_rights_t; { rights required to look up vnode }
|
||||
{
|
||||
* Arguments to lookup.
|
||||
}
|
||||
ni_startdir:p_vnode; { starting directory }
|
||||
ni_rootdir :p_vnode; { logical root directory }
|
||||
ni_topdir :p_vnode; { logical top directory }
|
||||
ni_dirfd :Integer; { starting directory for *at functions }
|
||||
ni_strictrelative:Integer; { relative lookup only; no '..' }
|
||||
{
|
||||
* Results: returned from namei
|
||||
}
|
||||
ni_baserights:cap_rights_t; { rights the *at base has (or -1) }
|
||||
{
|
||||
* Results: returned from/manipulated by lookup
|
||||
}
|
||||
ni_vp :p_vnode; { vnode of result }
|
||||
ni_dvp:p_vnode; { vnode of intermediate directory }
|
||||
{
|
||||
* Shared between namei and lookup/commit routines.
|
||||
}
|
||||
ni_pathlen:QWORD; { remaining chars in path }
|
||||
ni_next :PChar; { next location in pathname }
|
||||
ni_loopcnt:QWORD; { count of symlinks encountered }
|
||||
{
|
||||
* Lookup parameters: this structure describes the subset of
|
||||
* information from the nameidata structure that is passed
|
||||
* through the VOP interface.
|
||||
}
|
||||
ni_cnd:componentname;
|
||||
end;
|
||||
p_nameidata=^t_nameidata;
|
||||
t_nameidata=packed record
|
||||
{
|
||||
* Arguments to namei/lookup.
|
||||
}
|
||||
ni_dirp:PChar; { pathname pointer }
|
||||
ni_segflg:uio_seg; { location of pathname }
|
||||
_align1 :Integer;
|
||||
ni_rightsneeded:cap_rights_t; { rights required to look up vnode }
|
||||
{
|
||||
* Arguments to lookup.
|
||||
}
|
||||
ni_startdir:p_vnode; { starting directory }
|
||||
ni_rootdir :p_vnode; { logical root directory }
|
||||
ni_topdir :p_vnode; { logical top directory }
|
||||
ni_dirfd :Integer; { starting directory for *at functions }
|
||||
ni_strictrelative:Integer; { relative lookup only; no '..' }
|
||||
{
|
||||
* Results: returned from namei
|
||||
}
|
||||
ni_baserights:cap_rights_t; { rights the *at base has (or -1) }
|
||||
{
|
||||
* Results: returned from/manipulated by lookup
|
||||
}
|
||||
ni_vp :p_vnode; { vnode of result }
|
||||
ni_dvp:p_vnode; { vnode of intermediate directory }
|
||||
{
|
||||
* Shared between namei and lookup/commit routines.
|
||||
}
|
||||
ni_pathlen:QWORD; { remaining chars in path }
|
||||
ni_next :PChar; { next location in pathname }
|
||||
ni_loopcnt:QWORD; { count of symlinks encountered }
|
||||
{
|
||||
* Lookup parameters: this structure describes the subset of
|
||||
* information from the nameidata structure that is passed
|
||||
* through the VOP interface.
|
||||
}
|
||||
ni_cnd:componentname;
|
||||
end;
|
||||
|
||||
function NDHASGIANT(ndp:p_nameidata):Integer; inline;
|
||||
|
||||
|
|
Loading…
Reference in New Issue