move files op to ntapi

I hope I didn't break anything....
This commit is contained in:
Pavel 2023-01-12 20:30:56 +03:00
parent d91819f4ff
commit 5c144b1327
2 changed files with 178 additions and 117 deletions

View File

@ -6,6 +6,7 @@ interface
uses
Windows,
ntapi,
Classes,
SysUtils,
RWLock,
@ -187,50 +188,84 @@ begin
CloseHandle(Handle);
end;
function TFile.lseek (offset:Int64;whence:Integer):Int64;
function TFile.lseek(offset:Int64;whence:Integer):Int64;
label
_set_pos;
var
err:DWORD;
R:BOOL;
s:IO_STATUS_BLOCK;
i:FILE_STANDARD_INFORMATION;
e:Integer;
begin
Result:=0;
s:=Default(IO_STATUS_BLOCK);
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);
Case whence of
0:begin //beg
_set_pos:
e:=NtSetInformationFile(Handle,@s,@offset,SizeOf(Int64),FilePositionInformation);
end;
1:begin //cur
i.EndOfFile.QuadPart:=0;
e:=NtQueryInformationFile(Handle,@s,@i.EndOfFile,SizeOf(Int64),FilePositionInformation);
if (e>=0) then
begin
offset:=offset+i.EndOfFile.QuadPart;
goto _set_pos;
end;
end;
2:begin //end
i.EndOfFile.QuadPart:=0;
e:=NtQueryInformationFile(Handle,@s,@i,SizeOf(i),FileStandardInformation);
if (e>=0) then
begin
offset:=offset+i.EndOfFile.QuadPart;
goto _set_pos;
end;
end;
else
Exit(-EOVERFLOW);
e:=Integer(STATUS_INVALID_PARAMETER);
end;
end;
end;
function TFile.read (data:Pointer;size:Int64):Int64;
var
N:DWORD;
R:BOOL;
begin
Assert(size<High(DWORD));
N:=0;
rwlock_wrlock(lock);
R:=ReadFile(Handle,data^,size,N,nil);
rwlock_unlock(lock);
if R then
e:=-ntf2px(e);
if (e<>0) then
begin
Result:=N;
Result:=e;
end else
begin
Result:=-EIO;
Result:=offset;
end;
end;
function TFile.read(data:Pointer;size:Int64):Int64;
var
s:IO_STATUS_BLOCK;
e:Integer;
begin
s:=Default(IO_STATUS_BLOCK);
rwlock_wrlock(lock);
e:=NtReadFile(Handle,0,nil,nil,@s,data,size,nil,nil);
rwlock_unlock(lock);
e:=-ntf2px(e);
if (e<>0) then
begin
Result:=e;
end else
begin
Result:=Int64(s.Information);
end;
end;
{
function _get_pos(h:THandle):Int64;
const
zero:LARGE_INTEGER=(QuadPart:0);
@ -246,68 +281,77 @@ function _set_pos(h:THandle;p:Int64):Boolean;
begin
Result:=SetFilePointerEx(h,LARGE_INTEGER(p),nil,FILE_BEGIN);
end;
}
function TFile.pread (data:Pointer;size,offset:Int64):Int64;
function TFile.pread(data:Pointer;size,offset:Int64):Int64;
var
N:DWORD;
O:TOVERLAPPED;
p:Int64;
R:BOOL;
s:IO_STATUS_BLOCK;
e:Integer;
begin
Assert(size<High(DWORD));
s:=Default(IO_STATUS_BLOCK);
O:=Default(TOVERLAPPED);
PInt64(@O.Offset)^:=offset;
N:=0;
rwlock_wrlock(lock);
//NOTE: pread and pwrite don't change the file position, but ReadFile/WriteFile do, damn it.
p:=_get_pos(Handle);
R:=ReadFile(Handle,data^,size,N,@O);
if not _set_pos(Handle,p) then Assert(False);
//---------------------
///p:=_get_pos(Handle);
//---------------------
e:=NtReadFile(Handle,0,nil,nil,@s,data,size,@offset,nil);
//---------------------------------------------
//if not _set_pos(Handle,p) then Assert(False);
//---------------------------------------------
rwlock_unlock(lock);
if R then
e:=-ntf2px(e);
if (e<>0) then
begin
Result:=N;
Result:=e;
end else
begin
Result:=-EIO;
Result:=Int64(s.Information);
end;
end;
function TFile.readv (vector:p_iovec;count:Integer):Int64;
function TFile.readv(vector:p_iovec;count:Integer):Int64;
label
_exit;
var
N:DWORD;
R:BOOL;
s:IO_STATUS_BLOCK;
e:Integer;
i:Integer;
v:iovec;
begin
Result:=0;
rwlock_wrlock(lock);
For i:=0 to count-1 do
if (vector[i].iov_base<>nil) and (vector[i].iov_len<>0) then
begin
Assert(vector[i].iov_len<High(DWORD));
v:=vector[i];
N:=0;
R:=ReadFile(Handle,vector[i].iov_base^,vector[i].iov_len,N,nil);
if R then
if (v.iov_base<>nil) and (v.iov_len<>0) then
begin
Result:=Result+N;
if (N<vector[i].iov_len) then
s:=Default(IO_STATUS_BLOCK);
e:=NtReadFile(Handle,0,nil,nil,@s,v.iov_base,v.iov_len,nil,nil);
e:=-ntf2px(e);
if (e<>0) then
begin
Result:=e;
Goto _exit;
end else
begin
Result:=Result+Int64(s.Information);
if (Int64(s.Information)<v.iov_len) then
begin
Goto _exit;
end;
end;
end else
begin
Result:=-EIO;
Goto _exit;
end;
end;
end;
_exit:
@ -318,116 +362,131 @@ function TFile.preadv(vector:p_iovec;count:Integer;offset:Int64):Int64;
label
_exit;
var
N:DWORD;
R:BOOL;
p:Int64;
s:IO_STATUS_BLOCK;
e:Integer;
i:Integer;
v:iovec;
poffset:PLARGE_INTEGER;
begin
Result:=0;
poffset:=@offset; //first move to offset
rwlock_wrlock(lock);
p:=_get_pos(Handle);
if not _set_pos(Handle,offset) then Assert(False);
//--------------------------------------------------
//p:=_get_pos(Handle);
//if not _set_pos(Handle,offset) then Assert(False);
//--------------------------------------------------
For i:=0 to count-1 do
if (vector[i].iov_base<>nil) and (vector[i].iov_len<>0) then
begin
Assert(vector[i].iov_len<High(DWORD));
v:=vector[i];
N:=0;
R:=ReadFile(Handle,vector[i].iov_base^,vector[i].iov_len,N,nil);
if R then
if (v.iov_base<>nil) and (v.iov_len<>0) then
begin
Result:=Result+N;
if (N<vector[i].iov_len) then
s:=Default(IO_STATUS_BLOCK);
e:=NtReadFile(Handle,0,nil,nil,@s,v.iov_base,v.iov_len,poffset,nil);
poffset:=nil; //reset
e:=-ntf2px(e);
if (e<>0) then
begin
Result:=e;
Goto _exit;
end else
begin
Result:=Result+Int64(s.Information);
if (Int64(s.Information)<v.iov_len) then
begin
Goto _exit;
end;
end;
end else
begin
Result:=-EIO;
Goto _exit;
end;
end;
end;
_exit:
if not _set_pos(Handle,p) then Assert(False);
//--------------------------------------------------
//if not _set_pos(Handle,p) then Assert(False);
//--------------------------------------------------
rwlock_unlock(lock);
end;
function TFile.write (data:Pointer;size:Int64):Int64;
function TFile.write(data:Pointer;size:Int64):Int64;
var
N:DWORD;
R:BOOL;
s:IO_STATUS_BLOCK;
e:Integer;
begin
Assert(size<High(DWORD));
s:=Default(IO_STATUS_BLOCK);
N:=0;
rwlock_wrlock(lock);
R:=WriteFile(Handle,data^,size,N,nil);
e:=NtWriteFile(Handle,0,nil,nil,@s,data,size,nil,nil);
rwlock_unlock(lock);
if R then
e:=-ntf2px(e);
if (e<>0) then
begin
Result:=N;
Result:=e;
end else
begin
Result:=-EIO;
Result:=Int64(s.Information);
end;
end;
function TFile.pwrite(data:Pointer;size,offset:Int64):Int64;
var
N:DWORD;
O:TOVERLAPPED;
p:Int64;
R:BOOL;
s:IO_STATUS_BLOCK;
e:Integer;
begin
Assert(size<High(DWORD));
s:=Default(IO_STATUS_BLOCK);
O:=Default(TOVERLAPPED);
PInt64(@O.Offset)^:=offset;
N:=0;
rwlock_wrlock(lock);
//NOTE: pread and pwrite don't change the file position, but ReadFile/WriteFile do, damn it.
p:=_get_pos(Handle);
R:=WriteFile(Handle,data^,size,N,@O);
if not _set_pos(Handle,p) then Assert(False);
//---------------------
///p:=_get_pos(Handle);
//---------------------
e:=NtWriteFile(Handle,0,nil,nil,@s,data,size,@offset,nil);
//---------------------------------------------
//if not _set_pos(Handle,p) then Assert(False);
//---------------------------------------------
rwlock_unlock(lock);
if R then
e:=-ntf2px(e);
if (e<>0) then
begin
Result:=N;
Result:=e;
end else
begin
Result:=-EIO;
Result:=Int64(s.Information);
end;
end;
function TFile.ftruncate(size:Int64):Integer;
var
p:Int64;
s:IO_STATUS_BLOCK;
e:Integer;
begin
Result:=0;
rwlock_wrlock(lock);
p:=_get_pos(Handle);
s:=Default(IO_STATUS_BLOCK);
if _set_pos(Handle,size) then
rwlock_wrlock(lock);
e:=NtSetInformationFile(Handle,@s,@size,SizeOf(Int64),FileEndOfFileInformation);
if (e>=0) then
begin
if not SetEndOfFile(Handle) then
begin
Result:=EIO;
end;
end else
begin
Result:=EINVAL;
e:=NtSetInformationFile(Handle,@s,@size,SizeOf(Int64),FileAllocationInformation);
end;
if not _set_pos(Handle,p) then Assert(False);
rwlock_unlock(lock);
Result:=ntf2px(e);
end;
function file_attr_to_st_mode(attr:DWORD):Word;

View File

@ -33,6 +33,8 @@ function _set_errno(r:Integer):Integer;
function _set_sce_errno(r:Integer):Integer;
function _error:Pointer;
function ntf2px(n:Integer):Integer;
function SwFreeMem(p:pointer):ptruint;
function SwAllocMem(Size:ptruint):pointer;
@ -184,7 +186,7 @@ begin
if (t<>nil) then Result:=@t^.errno;
end;
function ntf2px(n:DWORD):Integer;
function ntf2px(n:Integer):Integer;
begin
case n of
STATUS_SUCCESS :Result:=0;