This commit is contained in:
Pavel 2023-05-24 16:58:08 +03:00
parent 0b73576b10
commit d1c2fb94be
4 changed files with 259 additions and 15 deletions

View File

@ -50,6 +50,8 @@ function md_rename(ap:p_vop_rename_args):Integer;
function md_create(ap:p_vop_create_args):Integer;
function md_open(ap:p_vop_open_args):Integer;
function md_close(ap:p_vop_close_args):Integer;
function md_fsync(ap:p_vop_fsync_args):Integer;
function md_setattr(ap:p_vop_setattr_args):Integer;
const
md_vnodeops_host:vop_vector=(
@ -66,7 +68,7 @@ const
vop_access :nil; //parent
vop_accessx :nil;
vop_getattr :@md_getattr;
vop_setattr :@ufs_setattr;
vop_setattr :@md_setattr;
vop_markatime :nil;
vop_read :nil; //parent
vop_write :nil;
@ -74,7 +76,7 @@ const
vop_poll :nil;
vop_kqfilter :nil;
vop_revoke :nil;
vop_fsync :nil; //TODO
vop_fsync :@md_fsync;
vop_remove :@md_remove;
vop_link :@md_link;
vop_rename :@md_rename;
@ -210,13 +212,19 @@ begin
end;
end;
function get_unix_file_time(time:LARGE_INTEGER):timespec;
function get_unix_file_time(time:LARGE_INTEGER):timespec; inline;
begin
Int64(time):=Int64(time)-DELTA_EPOCH_IN_UNIT;
Result.tv_sec :=(Int64(time) div UNIT_PER_SEC);
Result.tv_nsec:=(Int64(time) mod UNIT_PER_SEC)*100;
end;
function get_win_file_time(time:timespec):LARGE_INTEGER; inline;
begin
Int64(Result):=(time.tv_sec*UNIT_PER_SEC)+(time.tv_nsec div 100);
Int64(Result):=Int64(Result)+DELTA_EPOCH_IN_UNIT;
end;
function NT_FA_TO_DT(a,e:ULONG):Byte;
begin
if ((a and FILE_ATTRIBUTE_REPARSE_POINT)<>0) and
@ -1767,7 +1775,7 @@ begin
end else
if ((flags and O_TRUNC)<>0) then
begin
Result:=FILE_OVERWRITE;
Result:=FILE_OVERWRITE_IF;
end else
begin
Result:=FILE_OPEN_IF;
@ -1775,7 +1783,7 @@ begin
end else
if ((flags and O_TRUNC)<>0) then
begin
Result:=FILE_OVERWRITE_IF;
Result:=FILE_OVERWRITE;
end else
begin
Result:=FILE_OPEN;
@ -1886,7 +1894,6 @@ begin
begin
md_unlink_cache(de);
sx_xunlock(@dd^.ufs_md_lock);
NtClose(FD);
Exit;
end;
@ -1935,6 +1942,245 @@ begin
Result:=0;
end;
function md_fsync(ap:p_vop_fsync_args):Integer;
var
vp:p_vnode;
FD:THandle;
fullsync:Boolean;
BLK:IO_STATUS_BLOCK;
begin
vp:=ap^.a_vp;
FD:=THandle(vp^.v_un);
fullsync:=((ap^.a_waitfor and 2)<>0);
if (FD=0) then Exit(EINVAL);
BLK:=Default(IO_STATUS_BLOCK);
//result doesn't matter
NtFlushBuffersFile(FD,@BLK);
if fullsync then
begin
//atime
//mtime
end;
Result:=0;
end;
function md_setattr(ap:p_vop_setattr_args):Integer;
label
_err;
var
de:p_ufs_dirent;
vap:p_vattr;
vp:p_vnode;
error:Integer;
uid:uid_t;
gid:gid_t;
change_time,change_size:Boolean;
FD,RL:THandle;
FBI:FILE_BASIC_INFORMATION;
BLK:IO_STATUS_BLOCK;
SIZE:Int64;
R:DWORD;
procedure _settime(var dst:LARGE_INTEGER;var src:timespec); inline;
begin
if (src.tv_sec<>-1) and (src.tv_nsec<>-1) then
begin
dst:=get_win_file_time(src);
end;
end;
begin
Result:=0;
vap:=ap^.a_vap;
vp:=ap^.a_vp;
if (vap^.va_type <>VNON) or
(vap^.va_nlink <>VNOVAL) or
(vap^.va_fsid <>VNOVAL) or
(vap^.va_fileid <>VNOVAL) or
(vap^.va_blocksize<>VNOVAL) or
((vap^.va_flags <>VNOVAL) and (vap^.va_flags<>0)) or
(vap^.va_rdev <>VNOVAL) or
(vap^.va_bytes <>VNOVAL) or
(vap^.va_gen <>VNOVAL) then
begin
Exit(EINVAL);
end;
de:=vp^.v_data;
error:=0;
change_time:=False;
change_size:=False;
if (vap^.va_uid=VNOVAL) then
uid:=de^.ufs_uid
else
uid:=vap^.va_uid;
if (vap^.va_gid=VNOVAL) then
gid:=de^.ufs_gid
else
gid:=vap^.va_gid;
if (uid<>de^.ufs_uid) or (gid<>de^.ufs_gid) then
begin
//if ((ap^.a_cred^.cr_uid<>de^.de_uid) or uid<>de^.de_uid or
// (gid<>de^.de_gid and !groupmember(gid, ap^.a_cred))) then
//begin
// error:=priv_check(td, PRIV_VFS_CHOWN);
// if (error<>) then
// Exit(error);
//end;
de^.ufs_uid:=uid;
de^.ufs_gid:=gid;
end;
if (vap^.va_mode<>VNOVAL) then
begin
//if (ap^.a_cred^.cr_uid<>de^.de_uid) then
//begin
// error:=priv_check(td, PRIV_VFS_ADMIN);
// if (error<>0) then
// Exit(error);
//end;
de^.ufs_mode:=vap^.va_mode;
end;
if (vap^.va_atime.tv_sec<>VNOVAL) or
(vap^.va_mtime.tv_sec<>VNOVAL) or
(vap^.va_birthtime.tv_sec<>VNOVAL) then
begin
{ See the comment in ufs_vnops::ufs_setattr(). }
error:=VOP_ACCESS(vp, VADMIN);
if (error<>0) then
begin
if ((vap^.va_vaflags and VA_UTIMES_NULL)=0) then Exit(error);
error:=VOP_ACCESS(vp, VWRITE);
if (error<>0) then Exit(error);
end;
if (vap^.va_atime.tv_sec<>VNOVAL) then
begin
de^.ufs_atime:=vap^.va_atime;
end;
if (vap^.va_mtime.tv_sec<>VNOVAL) then
begin
de^.ufs_mtime:=vap^.va_mtime;
end;
if (vap^.va_birthtime.tv_sec<>VNOVAL) then
begin
de^.ufs_btime:=vap^.va_birthtime;
end;
change_time:=True;
end;
if (vap^.va_size<>VNOVAL) then
begin
change_size:=True;
end;
if change_time or change_size then
begin
if (vp^.v_un<>nil) then
begin
FD:=THandle(vp^.v_un);
RL:=0;
end else
if (de^.ufs_md_fp<>nil) then
begin
FD:=THandle(de^.ufs_md_fp);
RL:=0;
end else
begin
Result:=md_open_dirent_file(de,True,@FD);
if (Result<>0) then Exit;
RL:=FD;
end;
if change_time then
begin
BLK:=Default(IO_STATUS_BLOCK);
R:=NtQueryInformationFile(
FD,
@BLK,
@FBI,
SizeOf(FBI),
FileBasicInformation);
Result:=ntf2px(R);
if (Result<>0) then goto _err;
//update
de^.ufs_ctime:=get_unix_file_time(FBI.ChangeTime);
_settime(FBI.LastAccessTime,de^.ufs_atime);
_settime(FBI.LastWriteTime ,de^.ufs_mtime);
_settime(FBI.CreationTime ,de^.ufs_btime);
BLK:=Default(IO_STATUS_BLOCK);
R:=NtSetInformationFile(
FD,
@BLK,
@FBI,
SizeOf(FBI),
FileBasicInformation);
Result:=ntf2px(R);
if (Result<>0) then goto _err;
end;
if change_size then
begin
SIZE:=vap^.va_size;
R:=NtSetInformationFile(
FD,
@BLK,
@SIZE,
SizeOf(Int64),
FileEndOfFileInformation);
if (R<>0) then
begin
R:=NtSetInformationFile(
FD,
@BLK,
@SIZE,
SizeOf(Int64),
FileAllocationInformation);
end;
Result:=ntf2px(R);
if (Result<>0) then goto _err;
de^.ufs_size:=SIZE;
end;
_err:
if (RL<>0) then
begin
NtClose(RL);
end;
end;
end;
end.

View File

@ -682,6 +682,7 @@ begin
(vap^.va_birthtime.tv_sec<>VNOVAL) then
begin
{ See the comment in ufs_vnops::ufs_setattr(). }
error:=VOP_ACCESS(vp, VADMIN);
if (error<>0) then
begin
@ -689,6 +690,7 @@ begin
error:=VOP_ACCESS(vp, VWRITE);
if (error<>0) then Exit(error);
end;
if (vap^.va_atime.tv_sec<>VNOVAL) then
begin
de^.ufs_atime:=vap^.va_atime;

View File

@ -273,11 +273,14 @@ var
begin
td:=curkthread;
Writeln('sys_open=',sys_open('/app0/test.txt',O_RDWR or O_CREAT,&777));
Writeln('sys_open=',sys_open('/app0/test.txt',O_RDWR or O_CREAT or O_TRUNC,&777));
fd_1:=td^.td_retval[0];
Writeln('sys_fstatfs=',sys_fstatfs(fd_1,@fs));
Writeln('sys_fsync=',sys_fsync(fd_1));
Writeln('sys_fdatasync=',sys_fdatasync(fd_1));
Writeln('sys_open=',sys_open('/app0/test.txt',O_RDWR or O_CREAT,&777));
fd_2:=td^.td_retval[0];

View File

@ -2422,15 +2422,12 @@ function kern_fsync(fd:Integer;fullsync:Boolean):Integer;
label
drop;
var
td:p_kthread;
vp:p_vnode;
mp:p_mount;
fp:p_file;
vfslocked:Integer;
error,lock_flags:Integer;
begin
td:=curkthread;
error:=getvnode(fd, CAP_FSYNC, @fp);
if (error<>0) then Exit(error);
@ -2449,17 +2446,13 @@ begin
end;
vn_lock(vp, lock_flags or LK_RETRY);
td^.td_fpop:=fp;
//if (vp^.v_object<>nil) then
//begin
// VM_OBJECT_LOCK(vp^.v_object);
// vm_object_page_clean(vp^.v_object, 0, 0, 0);
// VM_OBJECT_UNLOCK(vp^.v_object);
//end;
error:=VOP_FSYNC(vp, MNT_WAIT);
td^.td_fpop:=nil;
error:=VOP_FSYNC(vp, MNT_WAIT or ((ord(fullsync) and 1) shl 1));
VOP_UNLOCK(vp, 0);
vn_finished_write(mp);