mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
dll: fuse: getpath
This commit is contained in:
parent
0a91292e05
commit
e5879a9cb0
@ -103,8 +103,10 @@ struct fuse_operations
|
|||||||
/* _ */ int (*flock)(const char *path, struct fuse_file_info *, int op);
|
/* _ */ int (*flock)(const char *path, struct fuse_file_info *, int op);
|
||||||
/* _ */ int (*fallocate)(const char *path, int mode, fuse_off_t off, fuse_off_t len,
|
/* _ */ int (*fallocate)(const char *path, int mode, fuse_off_t off, fuse_off_t len,
|
||||||
struct fuse_file_info *fi);
|
struct fuse_file_info *fi);
|
||||||
|
/* WinFsp */
|
||||||
|
/* S */ int (*getpath)(const char *path, char *buf, size_t size,
|
||||||
|
struct fuse_file_info *fi);
|
||||||
/* OSXFUSE */
|
/* OSXFUSE */
|
||||||
/* _ */ int (*reserved00)();
|
|
||||||
/* _ */ int (*reserved01)();
|
/* _ */ int (*reserved01)();
|
||||||
/* _ */ int (*reserved02)();
|
/* _ */ int (*reserved02)();
|
||||||
/* _ */ int (*statfs_x)(const char *path, struct fuse_statfs *stbuf);
|
/* _ */ int (*statfs_x)(const char *path, struct fuse_statfs *stbuf);
|
||||||
|
@ -850,6 +850,29 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID fsp_fuse_intf_GetOpenFileInfoPath(
|
||||||
|
struct fuse *f,
|
||||||
|
const char *PosixPath,
|
||||||
|
struct fuse_file_info *fi,
|
||||||
|
FSP_FSCTL_OPEN_FILE_INFO *OpenFileInfo)
|
||||||
|
{
|
||||||
|
char PosixNormalizedName[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
||||||
|
PWSTR NormalizedName;
|
||||||
|
ULONG NormalizedNameSize;
|
||||||
|
|
||||||
|
if (0 == f->ops.getpath(PosixPath, PosixNormalizedName, sizeof PosixNormalizedName, fi) &&
|
||||||
|
NT_SUCCESS(FspPosixMapPosixToWindowsPath(PosixNormalizedName, &NormalizedName)))
|
||||||
|
{
|
||||||
|
NormalizedNameSize = lstrlenW(NormalizedName) * sizeof(WCHAR);
|
||||||
|
if (OpenFileInfo->NormalizedNameSize >= NormalizedNameSize)
|
||||||
|
{
|
||||||
|
OpenFileInfo->NormalizedNameSize = (UINT16)NormalizedNameSize;
|
||||||
|
memcpy(OpenFileInfo->NormalizedName, NormalizedName, NormalizedNameSize);
|
||||||
|
}
|
||||||
|
FspPosixDeletePath(NormalizedName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess,
|
||||||
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize,
|
||||||
@ -1015,13 +1038,6 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache.
|
|
||||||
* NOTE: Originally WinFsp dit not support disabling the cache manager
|
|
||||||
* for an individual file. This is now possible and we should revisit.
|
|
||||||
*
|
|
||||||
* Ignore fuse_file_info::nonseekable.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, contexthdr->PosixPath,
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, contexthdr->PosixPath,
|
||||||
FUSE_FILE_INFO(CreateOptions & FILE_DIRECTORY_FILE, &fi),
|
FUSE_FILE_INFO(CreateOptions & FILE_DIRECTORY_FILE, &fi),
|
||||||
@ -1029,6 +1045,14 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache.
|
||||||
|
* NOTE: Originally WinFsp did not support disabling the cache manager
|
||||||
|
* for an individual file. This is now possible and we should revisit.
|
||||||
|
*
|
||||||
|
* Ignore fuse_file_info::nonseekable.
|
||||||
|
*/
|
||||||
|
|
||||||
*PFileDesc = filedesc;
|
*PFileDesc = filedesc;
|
||||||
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
|
memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf);
|
||||||
|
|
||||||
@ -1040,6 +1064,10 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
filedesc->DirBuffer = 0;
|
filedesc->DirBuffer = 0;
|
||||||
contexthdr->PosixPath = 0;
|
contexthdr->PosixPath = 0;
|
||||||
|
|
||||||
|
if (!f->VolumeParams.CaseSensitiveSearch && 0 != f->ops.getpath)
|
||||||
|
fsp_fuse_intf_GetOpenFileInfoPath(f, filedesc->PosixPath, -1 != fi.fh ? &fi : 0,
|
||||||
|
FspFileSystemGetOpenFileInfo(FileInfo));
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -1163,10 +1191,9 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache
|
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache.
|
||||||
* WinFsp does not currently support disabling the cache manager
|
* NOTE: Originally WinFsp did not support disabling the cache manager
|
||||||
* for an individual file although it should not be hard to add
|
* for an individual file. This is now possible and we should revisit.
|
||||||
* if required.
|
|
||||||
*
|
*
|
||||||
* Ignore fuse_file_info::nonseekable.
|
* Ignore fuse_file_info::nonseekable.
|
||||||
*/
|
*/
|
||||||
@ -1182,6 +1209,10 @@ static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
filedesc->DirBuffer = 0;
|
filedesc->DirBuffer = 0;
|
||||||
contexthdr->PosixPath = 0;
|
contexthdr->PosixPath = 0;
|
||||||
|
|
||||||
|
if (!f->VolumeParams.CaseSensitiveSearch && 0 != f->ops.getpath)
|
||||||
|
fsp_fuse_intf_GetOpenFileInfoPath(f, filedesc->PosixPath, -1 != fi.fh ? &fi : 0,
|
||||||
|
FspFileSystemGetOpenFileInfo(FileInfo));
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -2112,6 +2143,10 @@ static NTSTATUS fsp_fuse_intf_GetDirInfoByName(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
char PosixPath[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
char PosixPath[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
||||||
int ParentLength, FSlashLength, PosixNameLength;
|
int ParentLength, FSlashLength, PosixNameLength;
|
||||||
UINT32 Uid, Gid, Mode;
|
UINT32 Uid, Gid, Mode;
|
||||||
|
char PosixNormalizedName[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
|
||||||
|
PWSTR NormalizedName, NormalizedNameSuffix;
|
||||||
|
ULONG NormalizedNameSize;
|
||||||
|
BOOLEAN Normalized = FALSE;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
if (!filedesc->IsDirectory || filedesc->IsReparsePoint)
|
if (!filedesc->IsDirectory || filedesc->IsReparsePoint)
|
||||||
@ -2145,13 +2180,33 @@ static NTSTATUS fsp_fuse_intf_GetDirInfoByName(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* FUSE does not do FileName normalization; so just return the FileName as given to us!
|
|
||||||
*/
|
|
||||||
|
|
||||||
//memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
|
//memset(DirInfo->Padding, 0, sizeof DirInfo->Padding);
|
||||||
|
|
||||||
|
if (!f->VolumeParams.CaseSensitiveSearch && 0 != f->ops.getpath)
|
||||||
|
{
|
||||||
|
if (0 == f->ops.getpath(PosixPath, PosixNormalizedName, sizeof PosixNormalizedName, 0) &&
|
||||||
|
NT_SUCCESS(FspPosixMapPosixToWindowsPath(PosixNormalizedName, &NormalizedName)))
|
||||||
|
{
|
||||||
|
NormalizedNameSuffix = NormalizedName;
|
||||||
|
for (PWSTR P = NormalizedNameSuffix; *P; P++)
|
||||||
|
if (L'\\' == *P)
|
||||||
|
NormalizedNameSuffix = P + 1;
|
||||||
|
NormalizedNameSize = lstrlenW(NormalizedNameSuffix) * sizeof(WCHAR);
|
||||||
|
if (f->VolumeParams.MaxComponentLength * sizeof(WCHAR) >= NormalizedNameSize)
|
||||||
|
{
|
||||||
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + NormalizedNameSize);
|
||||||
|
memcpy(DirInfo->FileNameBuf, NormalizedNameSuffix, NormalizedNameSize);
|
||||||
|
Normalized = TRUE;
|
||||||
|
}
|
||||||
|
FspPosixDeletePath(NormalizedName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Normalized)
|
||||||
|
{
|
||||||
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + lstrlenW(FileName) * sizeof(WCHAR));
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + lstrlenW(FileName) * sizeof(WCHAR));
|
||||||
memcpy(DirInfo->FileNameBuf, FileName, DirInfo->Size - sizeof(FSP_FSCTL_DIR_INFO));
|
memcpy(DirInfo->FileNameBuf, FileName, DirInfo->Size - sizeof(FSP_FSCTL_DIR_INFO));
|
||||||
|
}
|
||||||
|
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
@ -95,9 +95,9 @@ static NTSTATUS fsp_fuse_loop_start(struct fuse *f)
|
|||||||
context->private_data = f->data = f->ops.init(&conn);
|
context->private_data = f->data = f->ops.init(&conn);
|
||||||
f->VolumeParams.ReadOnlyVolume = 0 != (conn.want & FSP_FUSE_CAP_READ_ONLY);
|
f->VolumeParams.ReadOnlyVolume = 0 != (conn.want & FSP_FUSE_CAP_READ_ONLY);
|
||||||
f->VolumeParams.CaseSensitiveSearch = 0 == (conn.want & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
f->VolumeParams.CaseSensitiveSearch = 0 == (conn.want & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
||||||
if (!f->VolumeParams.CaseSensitiveSearch)
|
if (!f->VolumeParams.CaseSensitiveSearch && 0 == f->ops.getpath)
|
||||||
/*
|
/*
|
||||||
* Disable GetDirInfoByName when file system is case-insensitive.
|
* Disable GetDirInfoByName when file system is case-insensitive and getpath == 0.
|
||||||
* The reason is that Windows always sends us queries with uppercase
|
* The reason is that Windows always sends us queries with uppercase
|
||||||
* file names in GetDirInfoByName and we have no way in FUSE to normalize
|
* file names in GetDirInfoByName and we have no way in FUSE to normalize
|
||||||
* those file names when embedding them in FSP_FSCTL_DIR_INFO.
|
* those file names when embedding them in FSP_FSCTL_DIR_INFO.
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <fuse.h>
|
#include <fuse.h>
|
||||||
|
|
||||||
@ -59,6 +60,7 @@
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char *rootdir;
|
const char *rootdir;
|
||||||
|
size_t rootlen;
|
||||||
} PTFS;
|
} PTFS;
|
||||||
|
|
||||||
static int ptfs_getattr(const char *path, struct fuse_stat *stbuf)
|
static int ptfs_getattr(const char *path, struct fuse_stat *stbuf)
|
||||||
@ -293,6 +295,43 @@ static int ptfs_utimens(const char *path, const struct fuse_timespec tv[2])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
static int ptfs_getpath(const char *path, char *buf, size_t size,
|
||||||
|
struct fuse_file_info *fi)
|
||||||
|
{
|
||||||
|
if (0 == fi)
|
||||||
|
{
|
||||||
|
ptfs_impl_fullpath(path);
|
||||||
|
|
||||||
|
if (-1 == getpath(path, buf, size))
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int fd = fi_fd(fi);
|
||||||
|
|
||||||
|
if (-1 == fgetpath(fd, buf, size))
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
PTFS *ptfs = fuse_get_context()->private_data;
|
||||||
|
size = strlen(buf);
|
||||||
|
if (size > ptfs->rootlen)
|
||||||
|
{
|
||||||
|
size -= ptfs->rootlen;
|
||||||
|
memmove(buf, buf + ptfs->rootlen, size);
|
||||||
|
buf[size] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buf[0] = '/';
|
||||||
|
buf[1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN64) || defined(_WIN32)
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
static int ptfs_setcrtime(const char *path, const struct fuse_timespec *tv)
|
static int ptfs_setcrtime(const char *path, const struct fuse_timespec *tv)
|
||||||
{
|
{
|
||||||
@ -344,6 +383,9 @@ static struct fuse_operations ptfs_ops =
|
|||||||
#if defined(PTFS_UTIMENS)
|
#if defined(PTFS_UTIMENS)
|
||||||
.utimens = ptfs_utimens,
|
.utimens = ptfs_utimens,
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
.getpath = ptfs_getpath,
|
||||||
|
#endif
|
||||||
#if defined(_WIN64) || defined(_WIN32)
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
.setcrtime = ptfs_setcrtime,
|
.setcrtime = ptfs_setcrtime,
|
||||||
#endif
|
#endif
|
||||||
@ -413,5 +455,17 @@ int main(int argc, char *argv[])
|
|||||||
if (0 == ptfs.rootdir)
|
if (0 == ptfs.rootdir)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
{
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
if (-1 != getpath(ptfs.rootdir, buf, sizeof buf))
|
||||||
|
{
|
||||||
|
ptfs.rootlen = strlen(buf);
|
||||||
|
if (1 == ptfs.rootlen)
|
||||||
|
ptfs.rootlen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return fuse_main(argc, argv, &ptfs_ops, &ptfs);
|
return fuse_main(argc, argv, &ptfs_ops, &ptfs);
|
||||||
}
|
}
|
||||||
|
@ -212,6 +212,28 @@ int open(const char *path, int oflag, ...)
|
|||||||
return (int)(intptr_t)h;
|
return (int)(intptr_t)h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fgetpath(int fd, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
HANDLE h = (HANDLE)(intptr_t)fd;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
FILE_NAME_INFO V;
|
||||||
|
UINT8 B[FIELD_OFFSET(FILE_NAME_INFO, FileName) + FSP_FSCTL_TRANSACT_PATH_SIZEMAX];
|
||||||
|
} NameInfo;
|
||||||
|
|
||||||
|
if (!GetFileInformationByHandleEx(h, FileNormalizedNameInfo, &NameInfo, sizeof NameInfo))
|
||||||
|
return error();
|
||||||
|
|
||||||
|
FspPosixEncodeWindowsPath(NameInfo.V.FileName, NameInfo.V.FileNameLength / sizeof(WCHAR));
|
||||||
|
size = WideCharToMultiByte(CP_UTF8, 0,
|
||||||
|
NameInfo.V.FileName, NameInfo.V.FileNameLength / sizeof(WCHAR), buf, (int)(size - 1), 0, 0);
|
||||||
|
if (0 == size)
|
||||||
|
return error();
|
||||||
|
buf[size] = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int fstat(int fd, struct fuse_stat *stbuf)
|
int fstat(int fd, struct fuse_stat *stbuf)
|
||||||
{
|
{
|
||||||
HANDLE h = (HANDLE)(intptr_t)fd;
|
HANDLE h = (HANDLE)(intptr_t)fd;
|
||||||
@ -303,6 +325,22 @@ int close(int fd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getpath(const char *path, char *buf, size_t size)
|
||||||
|
{
|
||||||
|
HANDLE h = CreateFileA(path,
|
||||||
|
FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE == h)
|
||||||
|
return error();
|
||||||
|
|
||||||
|
int res = fgetpath((int)(intptr_t)h, buf, size);
|
||||||
|
|
||||||
|
CloseHandle(h);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
int lstat(const char *path, struct fuse_stat *stbuf)
|
int lstat(const char *path, struct fuse_stat *stbuf)
|
||||||
{
|
{
|
||||||
HANDLE h = CreateFileA(path,
|
HANDLE h = CreateFileA(path,
|
||||||
|
@ -46,6 +46,7 @@ char *realpath(const char *path, char *resolved);
|
|||||||
int statvfs(const char *path, struct fuse_statvfs *stbuf);
|
int statvfs(const char *path, struct fuse_statvfs *stbuf);
|
||||||
|
|
||||||
int open(const char *path, int oflag, ...);
|
int open(const char *path, int oflag, ...);
|
||||||
|
int fgetpath(int fd, char *buf, size_t size);
|
||||||
int fstat(int fd, struct fuse_stat *stbuf);
|
int fstat(int fd, struct fuse_stat *stbuf);
|
||||||
int ftruncate(int fd, fuse_off_t size);
|
int ftruncate(int fd, fuse_off_t size);
|
||||||
int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset);
|
int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset);
|
||||||
@ -53,6 +54,7 @@ int pwrite(int fd, const void *buf, size_t nbyte, fuse_off_t offset);
|
|||||||
int fsync(int fd);
|
int fsync(int fd);
|
||||||
int close(int fd);
|
int close(int fd);
|
||||||
|
|
||||||
|
int getpath(const char *path, char *buf, size_t size);
|
||||||
int lstat(const char *path, struct fuse_stat *stbuf);
|
int lstat(const char *path, struct fuse_stat *stbuf);
|
||||||
int chmod(const char *path, fuse_mode_t mode);
|
int chmod(const char *path, fuse_mode_t mode);
|
||||||
int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid);
|
int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user