mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 08:53:01 -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->IsDirectory = !!(FileInfoBuf.FileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
filedesc->OpenFlags = fi.flags;
|
filedesc->OpenFlags = fi.flags;
|
||||||
filedesc->FileHandle = fi.fh;
|
filedesc->FileHandle = fi.fh;
|
||||||
|
filedesc->DirBuffer = 0;
|
||||||
|
filedesc->DirBufferSize = 0;
|
||||||
contexthdr->PosixPath = 0;
|
contexthdr->PosixPath = 0;
|
||||||
contexthdr->Response->Rsp.Create.Opened.UserContext2 = (UINT64)(UINT_PTR)filedesc;
|
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->IsDirectory = !!(FileInfoBuf.FileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
filedesc->OpenFlags = fi.flags;
|
filedesc->OpenFlags = fi.flags;
|
||||||
filedesc->FileHandle = fi.fh;
|
filedesc->FileHandle = fi.fh;
|
||||||
|
filedesc->DirBuffer = 0;
|
||||||
|
filedesc->DirBufferSize = 0;
|
||||||
contexthdr->PosixPath = 0;
|
contexthdr->PosixPath = 0;
|
||||||
contexthdr->Response->Rsp.Create.Opened.UserContext2 = (UINT64)(UINT_PTR)filedesc;
|
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)
|
PVOID FileNode, PWSTR FileName, BOOLEAN Delete)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
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:
|
* 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)
|
PVOID FileNode)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
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;
|
struct fuse_file_info fi;
|
||||||
|
|
||||||
memset(&fi, 0, sizeof 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);
|
f->ops.release(filedesc->PosixPath, &fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemFree(filedesc->DirBuffer);
|
||||||
MemFree(filedesc->PosixPath);
|
MemFree(filedesc->PosixPath);
|
||||||
MemFree(filedesc);
|
MemFree(filedesc);
|
||||||
}
|
}
|
||||||
@ -638,7 +645,8 @@ static NTSTATUS fsp_fuse_intf_GetFileInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
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;
|
UINT32 Uid, Gid, Mode;
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
|
|
||||||
@ -712,11 +720,11 @@ struct fuse_dirhandle
|
|||||||
char *PosixPath, *PosixName;
|
char *PosixPath, *PosixName;
|
||||||
PVOID Buffer;
|
PVOID Buffer;
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
PULONG PBytesTransferred;
|
ULONG BytesTransferred;
|
||||||
};
|
};
|
||||||
|
|
||||||
int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
int fsp_fuse_intf_AddDirInfoCommon(void *buf, const char *name,
|
||||||
const struct fuse_stat *stbuf, fuse_off_t off)
|
const struct fuse_stat *stbuf, fuse_off_t off, BOOLEAN GrowBuffer)
|
||||||
{
|
{
|
||||||
struct fuse_dirhandle *dh = buf;
|
struct fuse_dirhandle *dh = buf;
|
||||||
UINT32 Uid, Gid, Mode;
|
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->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + Size);
|
||||||
DirInfo->NextOffset = off;
|
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 fsp_fuse_intf_AddDirInfoOld(fuse_dirh_t dh, const char *name,
|
||||||
int type, fuse_ino_t ino)
|
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,
|
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)
|
PULONG PBytesTransferred)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
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;
|
struct fuse_dirhandle dh;
|
||||||
|
FSP_FSCTL_DIR_INFO *DirInfo;
|
||||||
|
PUINT8 DirInfoEnd;
|
||||||
ULONG Size;
|
ULONG Size;
|
||||||
int err;
|
int err;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (0 == filedesc->DirBuffer)
|
||||||
|
{
|
||||||
memset(&dh, 0, sizeof dh);
|
memset(&dh, 0, sizeof dh);
|
||||||
|
|
||||||
Size = lstrlenA(filedesc->PosixPath);
|
Size = lstrlenA(filedesc->PosixPath);
|
||||||
@ -819,19 +863,13 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
dh.PosixPath[Size++] = '/';
|
dh.PosixPath[Size++] = '/';
|
||||||
dh.PosixName = dh.PosixPath + Size;
|
dh.PosixName = dh.PosixPath + Size;
|
||||||
|
|
||||||
dh.Buffer = Buffer;
|
|
||||||
dh.Length = Length;
|
|
||||||
dh.PBytesTransferred = PBytesTransferred;
|
|
||||||
|
|
||||||
if (0 != f->ops.readdir)
|
if (0 != f->ops.readdir)
|
||||||
{
|
{
|
||||||
struct fuse_file_info fi;
|
|
||||||
|
|
||||||
memset(&fi, 0, sizeof fi);
|
memset(&fi, 0, sizeof fi);
|
||||||
fi.flags = filedesc->OpenFlags;
|
fi.flags = filedesc->OpenFlags;
|
||||||
fi.fh = filedesc->FileHandle;
|
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);
|
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||||
}
|
}
|
||||||
else if (0 != f->ops.getdir)
|
else if (0 != f->ops.getdir)
|
||||||
@ -845,8 +883,36 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
exit:
|
exit:
|
||||||
MemFree(dh.PosixPath);
|
MemFree(dh.PosixPath);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
filedesc->DirBuffer = dh.Buffer;
|
||||||
|
filedesc->DirBufferSize = dh.BytesTransferred;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MemFree(dh.Buffer);
|
||||||
return Result;
|
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 =
|
FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
|
||||||
{
|
{
|
||||||
|
@ -51,6 +51,8 @@ struct fsp_fuse_file_desc
|
|||||||
BOOLEAN IsDirectory;
|
BOOLEAN IsDirectory;
|
||||||
int OpenFlags;
|
int OpenFlags;
|
||||||
UINT64 FileHandle;
|
UINT64 FileHandle;
|
||||||
|
PVOID DirBuffer;
|
||||||
|
ULONG DirBufferSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
|
Loading…
x
Reference in New Issue
Block a user