mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
dll: fuseintf: ReadDirectory implementation
This commit is contained in:
parent
ea8ed690f6
commit
240bdfeb39
@ -415,6 +415,8 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||
filedesc->IsDirectory = !!(FileInfoBuf.FileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
filedesc->OpenFlags = fi.flags;
|
||||
filedesc->FileHandle = fi.fh;
|
||||
filedesc->DirBuffer = 0;
|
||||
filedesc->DirBufferSize = 0;
|
||||
contexthdr->PosixPath = 0;
|
||||
contexthdr->Response->Rsp.Create.Opened.UserContext2 = (UINT64)(UINT_PTR)filedesc;
|
||||
|
||||
@ -522,6 +524,8 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
||||
filedesc->IsDirectory = !!(FileInfoBuf.FileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
filedesc->OpenFlags = fi.flags;
|
||||
filedesc->FileHandle = fi.fh;
|
||||
filedesc->DirBuffer = 0;
|
||||
filedesc->DirBufferSize = 0;
|
||||
contexthdr->PosixPath = 0;
|
||||
contexthdr->Response->Rsp.Create.Opened.UserContext2 = (UINT64)(UINT_PTR)filedesc;
|
||||
|
||||
@ -547,7 +551,8 @@ static VOID fsp_fuse_intf_Cleanup(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode, PWSTR FileName, BOOLEAN Delete)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = (PVOID)(UINT_PTR)Request->Req.Close.UserContext2;
|
||||
struct fsp_fuse_file_desc *filedesc =
|
||||
(PVOID)(UINT_PTR)Request->Req.Cleanup.UserContext2;
|
||||
|
||||
/*
|
||||
* In Windows a DeleteFile/RemoveDirectory is the sequence of the following:
|
||||
@ -584,7 +589,8 @@ static VOID fsp_fuse_intf_Close(FSP_FILE_SYSTEM *FileSystem,
|
||||
PVOID FileNode)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = (PVOID)(UINT_PTR)Request->Req.Close.UserContext2;
|
||||
struct fsp_fuse_file_desc *filedesc =
|
||||
(PVOID)(UINT_PTR)Request->Req.Close.UserContext2;
|
||||
struct fuse_file_info fi;
|
||||
|
||||
memset(&fi, 0, sizeof fi);
|
||||
@ -604,6 +610,7 @@ static VOID fsp_fuse_intf_Close(FSP_FILE_SYSTEM *FileSystem,
|
||||
f->ops.release(filedesc->PosixPath, &fi);
|
||||
}
|
||||
|
||||
MemFree(filedesc->DirBuffer);
|
||||
MemFree(filedesc->PosixPath);
|
||||
MemFree(filedesc);
|
||||
}
|
||||
@ -638,7 +645,8 @@ static NTSTATUS fsp_fuse_intf_GetFileInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = (PVOID)(UINT_PTR)Request->Req.Close.UserContext2;
|
||||
struct fsp_fuse_file_desc *filedesc =
|
||||
(PVOID)(UINT_PTR)Request->Req.QueryInformation.UserContext2;
|
||||
UINT32 Uid, Gid, Mode;
|
||||
struct fuse_file_info fi;
|
||||
|
||||
@ -712,11 +720,11 @@ struct fuse_dirhandle
|
||||
char *PosixPath, *PosixName;
|
||||
PVOID Buffer;
|
||||
ULONG Length;
|
||||
PULONG PBytesTransferred;
|
||||
ULONG BytesTransferred;
|
||||
};
|
||||
|
||||
int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off)
|
||||
int fsp_fuse_intf_AddDirInfoCommon(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off, BOOLEAN GrowBuffer)
|
||||
{
|
||||
struct fuse_dirhandle *dh = buf;
|
||||
UINT32 Uid, Gid, Mode;
|
||||
@ -781,13 +789,43 @@ int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + Size);
|
||||
DirInfo->NextOffset = off;
|
||||
|
||||
return ! FspFileSystemAddDirInfo(DirInfo, dh->Buffer, dh->Length, dh->PBytesTransferred);
|
||||
if (GrowBuffer)
|
||||
{
|
||||
DirInfo->NextOffset = dh->BytesTransferred + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size);
|
||||
|
||||
if (0 != dh->Buffer &&
|
||||
FspFileSystemAddDirInfo(DirInfo, dh->Buffer, dh->Length, &dh->BytesTransferred))
|
||||
return 0;
|
||||
|
||||
if (0 == dh->Length)
|
||||
dh->Length = 8 * 1024; /* initial alloc: 16 == 8 * 2; see below */
|
||||
else if (dh->Length >= 2 * 1024 * 1024)
|
||||
return 1;
|
||||
|
||||
PVOID Buffer = MemAlloc(dh->Length * 2);
|
||||
if (0 == Buffer)
|
||||
return 1;
|
||||
|
||||
memcpy(Buffer, dh->Buffer, dh->BytesTransferred);
|
||||
MemFree(dh->Buffer);
|
||||
|
||||
dh->Buffer = Buffer;
|
||||
dh->Length *= 2;
|
||||
}
|
||||
|
||||
return ! FspFileSystemAddDirInfo(DirInfo, dh->Buffer, dh->Length, &dh->BytesTransferred);
|
||||
}
|
||||
|
||||
int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
||||
const struct fuse_stat *stbuf, fuse_off_t off)
|
||||
{
|
||||
return fsp_fuse_intf_AddDirInfoCommon(buf, name, stbuf, off, TRUE);
|
||||
}
|
||||
|
||||
int fsp_fuse_intf_AddDirInfoOld(fuse_dirh_t dh, const char *name,
|
||||
int type, fuse_ino_t ino)
|
||||
{
|
||||
return fsp_fuse_intf_AddDirInfo(dh, name, 0, 0) ? -ENOMEM : 0;
|
||||
return fsp_fuse_intf_AddDirInfoCommon(dh, name, 0, 0, TRUE) ? -ENOMEM : 0;
|
||||
}
|
||||
|
||||
static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
@ -797,12 +835,18 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
PULONG PBytesTransferred)
|
||||
{
|
||||
struct fuse *f = FileSystem->UserContext;
|
||||
struct fsp_fuse_file_desc *filedesc = (PVOID)(UINT_PTR)Request->Req.Close.UserContext2;
|
||||
struct fsp_fuse_file_desc *filedesc =
|
||||
(PVOID)(UINT_PTR)Request->Req.QueryDirectory.UserContext2;
|
||||
struct fuse_file_info fi;
|
||||
struct fuse_dirhandle dh;
|
||||
FSP_FSCTL_DIR_INFO *DirInfo;
|
||||
PUINT8 DirInfoEnd;
|
||||
ULONG Size;
|
||||
int err;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == filedesc->DirBuffer)
|
||||
{
|
||||
memset(&dh, 0, sizeof dh);
|
||||
|
||||
Size = lstrlenA(filedesc->PosixPath);
|
||||
@ -819,19 +863,13 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
dh.PosixPath[Size++] = '/';
|
||||
dh.PosixName = dh.PosixPath + Size;
|
||||
|
||||
dh.Buffer = Buffer;
|
||||
dh.Length = Length;
|
||||
dh.PBytesTransferred = PBytesTransferred;
|
||||
|
||||
if (0 != f->ops.readdir)
|
||||
{
|
||||
struct fuse_file_info fi;
|
||||
|
||||
memset(&fi, 0, sizeof fi);
|
||||
fi.flags = filedesc->OpenFlags;
|
||||
fi.fh = filedesc->FileHandle;
|
||||
|
||||
err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfo, Offset, &fi);
|
||||
err = f->ops.readdir(filedesc->PosixPath, &dh, fsp_fuse_intf_AddDirInfo, 0, &fi);
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
}
|
||||
else if (0 != f->ops.getdir)
|
||||
@ -845,8 +883,36 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||
exit:
|
||||
MemFree(dh.PosixPath);
|
||||
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
filedesc->DirBuffer = dh.Buffer;
|
||||
filedesc->DirBufferSize = dh.BytesTransferred;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemFree(dh.Buffer);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
DirInfo = (PVOID)((PUINT8)filedesc->DirBuffer + Offset);
|
||||
DirInfoEnd = (PUINT8)filedesc->DirBuffer + filedesc->DirBufferSize;
|
||||
for (;
|
||||
(PUINT8)DirInfo + sizeof(DirInfo->Size) <= DirInfoEnd;
|
||||
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)))
|
||||
{
|
||||
if (sizeof(FSP_FSCTL_DIR_INFO) > DirInfo->Size)
|
||||
break;
|
||||
|
||||
if (!FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred))
|
||||
break;
|
||||
}
|
||||
|
||||
if ((PUINT8)DirInfo + sizeof(DirInfo->Size) > DirInfoEnd)
|
||||
FspFileSystemAddDirInfo(0, Buffer, Length, PBytesTransferred);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
||||
{
|
||||
|
@ -51,6 +51,8 @@ struct fsp_fuse_file_desc
|
||||
BOOLEAN IsDirectory;
|
||||
int OpenFlags;
|
||||
UINT64 FileHandle;
|
||||
PVOID DirBuffer;
|
||||
ULONG DirBufferSize;
|
||||
};
|
||||
|
||||
static inline
|
||||
|
Loading…
x
Reference in New Issue
Block a user