mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
tst: passthrough-fuse: FSP_FUSE_CAP_*
This commit is contained in:
parent
35d1adb360
commit
712870ddd9
@ -41,6 +41,15 @@ extern "C" {
|
|||||||
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
|
#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
|
||||||
#define FUSE_CAP_BIG_WRITES (1 << 5)
|
#define FUSE_CAP_BIG_WRITES (1 << 5)
|
||||||
#define FUSE_CAP_DONT_MASK (1 << 6)
|
#define FUSE_CAP_DONT_MASK (1 << 6)
|
||||||
|
#define FUSE_CAP_ALLOCATE (1 << 27) /* reserved (OSXFUSE) */
|
||||||
|
#define FUSE_CAP_EXCHANGE_DATA (1 << 28) /* reserved (OSXFUSE) */
|
||||||
|
#define FUSE_CAP_CASE_INSENSITIVE (1 << 29) /* file system is case insensitive */
|
||||||
|
#define FUSE_CAP_VOL_RENAME (1 << 30) /* reserved (OSXFUSE) */
|
||||||
|
#define FUSE_CAP_XTIMES (1 << 31) /* reserved (OSXFUSE) */
|
||||||
|
|
||||||
|
#define FSP_FUSE_CAP_READDIR_PLUS (1 << 21) /* file system supports enhanced readdir */
|
||||||
|
#define FSP_FUSE_CAP_READ_ONLY (1 << 22) /* file system is marked read-only */
|
||||||
|
#define FSP_FUSE_CAP_CASE_INSENSITIVE FUSE_CAP_CASE_INSENSITIVE
|
||||||
|
|
||||||
#define FUSE_IOCTL_COMPAT (1 << 0)
|
#define FUSE_IOCTL_COMPAT (1 << 0)
|
||||||
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
|
||||||
|
@ -38,8 +38,6 @@ struct fsp_fuse_core_opt_data
|
|||||||
set_attr_timeout, attr_timeout,
|
set_attr_timeout, attr_timeout,
|
||||||
rellinks;
|
rellinks;
|
||||||
int set_FileInfoTimeout;
|
int set_FileInfoTimeout;
|
||||||
int CaseInsensitiveSearch,
|
|
||||||
ReadOnlyVolume;
|
|
||||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -89,8 +87,6 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
|||||||
FSP_FUSE_CORE_OPT("VolumeSerialNumber=%lx", VolumeParams.VolumeSerialNumber, 0),
|
FSP_FUSE_CORE_OPT("VolumeSerialNumber=%lx", VolumeParams.VolumeSerialNumber, 0),
|
||||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=", set_FileInfoTimeout, 1),
|
FSP_FUSE_CORE_OPT("FileInfoTimeout=", set_FileInfoTimeout, 1),
|
||||||
FSP_FUSE_CORE_OPT("FileInfoTimeout=%d", VolumeParams.FileInfoTimeout, 0),
|
FSP_FUSE_CORE_OPT("FileInfoTimeout=%d", VolumeParams.FileInfoTimeout, 0),
|
||||||
FSP_FUSE_CORE_OPT("CaseInsensitiveSearch", CaseInsensitiveSearch, 1),
|
|
||||||
FSP_FUSE_CORE_OPT("ReadOnlyVolume", ReadOnlyVolume, 1),
|
|
||||||
FUSE_OPT_KEY("--UNC=", 'U'),
|
FUSE_OPT_KEY("--UNC=", 'U'),
|
||||||
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
|
FUSE_OPT_KEY("--VolumePrefix=", 'U'),
|
||||||
FUSE_OPT_KEY("--FileSystemName=", 'F'),
|
FUSE_OPT_KEY("--FileSystemName=", 'F'),
|
||||||
@ -252,9 +248,17 @@ static NTSTATUS fsp_fuse_svcstart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
//FUSE_CAP_ATOMIC_O_TRUNC | /* due to Windows/WinFsp design, no support */
|
//FUSE_CAP_ATOMIC_O_TRUNC | /* due to Windows/WinFsp design, no support */
|
||||||
//FUSE_CAP_EXPORT_SUPPORT | /* not needed in Windows/WinFsp */
|
//FUSE_CAP_EXPORT_SUPPORT | /* not needed in Windows/WinFsp */
|
||||||
FUSE_CAP_BIG_WRITES |
|
FUSE_CAP_BIG_WRITES |
|
||||||
FUSE_CAP_DONT_MASK;
|
FUSE_CAP_DONT_MASK |
|
||||||
|
FSP_FUSE_CAP_READDIR_PLUS |
|
||||||
|
FSP_FUSE_CAP_READ_ONLY |
|
||||||
|
FSP_FUSE_CAP_CASE_INSENSITIVE;
|
||||||
if (0 != f->ops.init)
|
if (0 != f->ops.init)
|
||||||
|
{
|
||||||
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.CaseSensitiveSearch = 0 == (conn.want & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
||||||
|
f->conn_want = conn.want;
|
||||||
|
}
|
||||||
f->fsinit = TRUE;
|
f->fsinit = TRUE;
|
||||||
if (0 != f->ops.statfs)
|
if (0 != f->ops.statfs)
|
||||||
{
|
{
|
||||||
@ -417,7 +421,6 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
" -o VolumeCreationTime=T volume creation time (FILETIME hex format)\n"
|
" -o VolumeCreationTime=T volume creation time (FILETIME hex format)\n"
|
||||||
" -o VolumeSerialNumber=N 32-bit wide\n"
|
" -o VolumeSerialNumber=N 32-bit wide\n"
|
||||||
" -o FileInfoTimeout=N FileInfo/Security/VolumeInfo timeout (millisec)\n"
|
" -o FileInfoTimeout=N FileInfo/Security/VolumeInfo timeout (millisec)\n"
|
||||||
" -o CaseInsensitiveSearch file system supports case-insensitive file names\n"
|
|
||||||
" --UNC=U --VolumePrefix=U UNC prefix (\\Server\\Share)\n"
|
" --UNC=U --VolumePrefix=U UNC prefix (\\Server\\Share)\n"
|
||||||
" --FileSystemName=FSN Name of user mode file system\n");
|
" --FileSystemName=FSN Name of user mode file system\n");
|
||||||
opt_data->help = 1;
|
opt_data->help = 1;
|
||||||
@ -501,12 +504,12 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
|
|
||||||
if (!opt_data.set_FileInfoTimeout && opt_data.set_attr_timeout)
|
if (!opt_data.set_FileInfoTimeout && opt_data.set_attr_timeout)
|
||||||
opt_data.VolumeParams.FileInfoTimeout = opt_data.set_attr_timeout * 1000;
|
opt_data.VolumeParams.FileInfoTimeout = opt_data.set_attr_timeout * 1000;
|
||||||
opt_data.VolumeParams.CaseSensitiveSearch = !opt_data.CaseInsensitiveSearch;
|
opt_data.VolumeParams.CaseSensitiveSearch = TRUE;
|
||||||
opt_data.VolumeParams.PersistentAcls = TRUE;
|
opt_data.VolumeParams.PersistentAcls = TRUE;
|
||||||
opt_data.VolumeParams.ReparsePoints = TRUE;
|
opt_data.VolumeParams.ReparsePoints = TRUE;
|
||||||
opt_data.VolumeParams.ReparsePointsAccessCheck = FALSE;
|
opt_data.VolumeParams.ReparsePointsAccessCheck = FALSE;
|
||||||
opt_data.VolumeParams.NamedStreams = FALSE;
|
opt_data.VolumeParams.NamedStreams = FALSE;
|
||||||
opt_data.VolumeParams.ReadOnlyVolume = !!opt_data.ReadOnlyVolume;
|
opt_data.VolumeParams.ReadOnlyVolume = FALSE;
|
||||||
opt_data.VolumeParams.PostCleanupWhenModifiedOnly = TRUE;
|
opt_data.VolumeParams.PostCleanupWhenModifiedOnly = TRUE;
|
||||||
opt_data.VolumeParams.UmFileContextIsUserContext2 = TRUE;
|
opt_data.VolumeParams.UmFileContextIsUserContext2 = TRUE;
|
||||||
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
|
if (L'\0' == opt_data.VolumeParams.FileSystemName[0])
|
||||||
|
@ -311,28 +311,34 @@ static BOOLEAN fsp_fuse_intf_CheckSymlinkDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, fi, PUid, PGid, PMode, FileInfo)\
|
#define fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, fi, PUid, PGid, PMode, FileInfo)\
|
||||||
fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, PUid, PGid, PMode, 0, FileInfo)
|
fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, 0, PUid, PGid, PMode, 0, FileInfo)
|
||||||
static NTSTATUS fsp_fuse_intf_GetFileInfoFunnel(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_GetFileInfoFunnel(FSP_FILE_SYSTEM *FileSystem,
|
||||||
const char *PosixPath, struct fuse_file_info *fi,
|
const char *PosixPath, struct fuse_file_info *fi, const struct fuse_stat *stbufp,
|
||||||
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode, PUINT32 PDev,
|
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode, PUINT32 PDev,
|
||||||
FSP_FSCTL_FILE_INFO *FileInfo)
|
FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
UINT64 AllocationUnit;
|
UINT64 AllocationUnit;
|
||||||
struct fuse_stat stbuf;
|
struct fuse_stat stbuf;
|
||||||
int err;
|
|
||||||
|
|
||||||
memset(&stbuf, 0, sizeof stbuf);
|
if (0 != stbufp)
|
||||||
|
memcpy(&stbuf, stbufp, sizeof stbuf);
|
||||||
if (0 != f->ops.fgetattr && 0 != fi && -1 != fi->fh)
|
|
||||||
err = f->ops.fgetattr(PosixPath, (void *)&stbuf, fi);
|
|
||||||
else if (0 != f->ops.getattr)
|
|
||||||
err = f->ops.getattr(PosixPath, (void *)&stbuf);
|
|
||||||
else
|
else
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
if (0 != err)
|
memset(&stbuf, 0, sizeof stbuf);
|
||||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
|
||||||
|
if (0 != f->ops.fgetattr && 0 != fi && -1 != fi->fh)
|
||||||
|
err = f->ops.fgetattr(PosixPath, (void *)&stbuf, fi);
|
||||||
|
else if (0 != f->ops.getattr)
|
||||||
|
err = f->ops.getattr(PosixPath, (void *)&stbuf);
|
||||||
|
else
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
|
||||||
|
if (0 != err)
|
||||||
|
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||||
|
}
|
||||||
|
|
||||||
if (f->set_umask)
|
if (f->set_umask)
|
||||||
stbuf.st_mode = (stbuf.st_mode & 0170000) | (0777 & ~f->umask);
|
stbuf.st_mode = (stbuf.st_mode & 0170000) | (0777 & ~f->umask);
|
||||||
@ -513,7 +519,7 @@ static NTSTATUS fsp_fuse_intf_GetReparsePointEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
SIZE_T Size;
|
SIZE_T Size;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi,
|
Result = fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, 0,
|
||||||
&Uid, &Gid, &Mode, &Dev, &FileInfo);
|
&Uid, &Gid, &Mode, &Dev, &FileInfo);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
return Result;
|
return Result;
|
||||||
@ -1576,6 +1582,17 @@ static int fsp_fuse_intf_AddDirInfo(void *buf, const char *name,
|
|||||||
memset(DirInfo, 0, sizeof *DirInfo);
|
memset(DirInfo, 0, sizeof *DirInfo);
|
||||||
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + SizeW * sizeof(WCHAR));
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + SizeW * sizeof(WCHAR));
|
||||||
|
|
||||||
|
if (dh->ReaddirPlus && 0 != stbuf)
|
||||||
|
{
|
||||||
|
UINT32 Uid, Gid, Mode;
|
||||||
|
NTSTATUS Result0;
|
||||||
|
|
||||||
|
Result0 = fsp_fuse_intf_GetFileInfoFunnel(dh->FileSystem, 0, 0, stbuf,
|
||||||
|
&Uid, &Gid, &Mode, 0, &DirInfo->FileInfo);
|
||||||
|
if (NT_SUCCESS(Result0))
|
||||||
|
DirInfo->Padding[0] = 1; /* HACK: remember that the FileInfo is valid */
|
||||||
|
}
|
||||||
|
|
||||||
return !FspFileSystemFillDirectoryBuffer(&filedesc->DirBuffer, DirInfo, &dh->Result);
|
return !FspFileSystemFillDirectoryBuffer(&filedesc->DirBuffer, DirInfo, &dh->Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1619,44 +1636,53 @@ static NTSTATUS fsp_fuse_intf_FixDirInfo(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
DirInfo = (FSP_FSCTL_DIR_INFO *)(Buffer + *Index);
|
DirInfo = (FSP_FSCTL_DIR_INFO *)(Buffer + *Index);
|
||||||
SizeW = (DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR);
|
SizeW = (DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR);
|
||||||
|
|
||||||
if (1 == SizeW && L'.' == DirInfo->FileNameBuf[0])
|
if (DirInfo->Padding[0])
|
||||||
{
|
{
|
||||||
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 1 : PosixName;
|
/* DirInfo has been filled already! */
|
||||||
SavedPathChar = *PosixPathEnd;
|
|
||||||
*PosixPathEnd = '\0';
|
DirInfo->Padding[0] = 0;
|
||||||
}
|
|
||||||
else
|
|
||||||
if (2 == SizeW && L'.' == DirInfo->FileNameBuf[0] && L'.' == DirInfo->FileNameBuf[1])
|
|
||||||
{
|
|
||||||
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 2 : PosixName;
|
|
||||||
while (PosixPath < PosixPathEnd && '/' != *PosixPathEnd)
|
|
||||||
PosixPathEnd--;
|
|
||||||
if (PosixPath == PosixPathEnd)
|
|
||||||
PosixPathEnd++;
|
|
||||||
SavedPathChar = *PosixPathEnd;
|
|
||||||
*PosixPathEnd = '\0';
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PosixPathEnd = 0;
|
if (1 == SizeW && L'.' == DirInfo->FileNameBuf[0])
|
||||||
SizeA = WideCharToMultiByte(CP_UTF8, 0, DirInfo->FileNameBuf, SizeW, PosixName, 255, 0, 0);
|
|
||||||
if (0 == SizeA)
|
|
||||||
{
|
{
|
||||||
/* this should never happen because we just converted using MultiByteToWideChar */
|
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 1 : PosixName;
|
||||||
Result = STATUS_OBJECT_NAME_INVALID;
|
SavedPathChar = *PosixPathEnd;
|
||||||
goto exit;
|
*PosixPathEnd = '\0';
|
||||||
}
|
}
|
||||||
PosixName[SizeA] = '\0';
|
else
|
||||||
|
if (2 == SizeW && L'.' == DirInfo->FileNameBuf[0] && L'.' == DirInfo->FileNameBuf[1])
|
||||||
|
{
|
||||||
|
PosixPathEnd = 1 < PosixName - PosixPath ? PosixName - 2 : PosixName;
|
||||||
|
while (PosixPath < PosixPathEnd && '/' != *PosixPathEnd)
|
||||||
|
PosixPathEnd--;
|
||||||
|
if (PosixPath == PosixPathEnd)
|
||||||
|
PosixPathEnd++;
|
||||||
|
SavedPathChar = *PosixPathEnd;
|
||||||
|
*PosixPathEnd = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PosixPathEnd = 0;
|
||||||
|
SizeA = WideCharToMultiByte(CP_UTF8, 0, DirInfo->FileNameBuf, SizeW, PosixName, 255, 0, 0);
|
||||||
|
if (0 == SizeA)
|
||||||
|
{
|
||||||
|
/* this should never happen because we just converted using MultiByteToWideChar */
|
||||||
|
Result = STATUS_OBJECT_NAME_INVALID;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
PosixName[SizeA] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, 0,
|
||||||
|
&Uid, &Gid, &Mode, &DirInfo->FileInfo);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (0 != PosixPathEnd)
|
||||||
|
*PosixPathEnd = SavedPathChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, 0,
|
|
||||||
&Uid, &Gid, &Mode, &DirInfo->FileInfo);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
if (0 != PosixPathEnd)
|
|
||||||
*PosixPathEnd = SavedPathChar;
|
|
||||||
|
|
||||||
FspPosixDecodeWindowsPath(DirInfo->FileNameBuf, SizeW);
|
FspPosixDecodeWindowsPath(DirInfo->FileNameBuf, SizeW);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1683,6 +1709,8 @@ static NTSTATUS fsp_fuse_intf_ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
memset(&dh, 0, sizeof dh);
|
memset(&dh, 0, sizeof dh);
|
||||||
dh.filedesc = filedesc;
|
dh.filedesc = filedesc;
|
||||||
|
dh.FileSystem = FileSystem;
|
||||||
|
dh.ReaddirPlus = 0 != (f->conn_want & FSP_FUSE_CAP_READDIR_PLUS);
|
||||||
dh.Result = STATUS_SUCCESS;
|
dh.Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
if (0 != f->ops.readdir)
|
if (0 != f->ops.readdir)
|
||||||
|
@ -40,12 +40,13 @@ struct fuse
|
|||||||
int rellinks;
|
int rellinks;
|
||||||
struct fuse_operations ops;
|
struct fuse_operations ops;
|
||||||
void *data;
|
void *data;
|
||||||
|
unsigned conn_want;
|
||||||
|
BOOLEAN fsinit;
|
||||||
UINT32 DebugLog;
|
UINT32 DebugLog;
|
||||||
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy;
|
FSP_FILE_SYSTEM_OPERATION_GUARD_STRATEGY OpGuardStrategy;
|
||||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||||
PWSTR MountPoint;
|
PWSTR MountPoint;
|
||||||
FSP_FILE_SYSTEM *FileSystem;
|
FSP_FILE_SYSTEM *FileSystem;
|
||||||
BOOLEAN fsinit;
|
|
||||||
FSP_SERVICE *Service; /* weak */
|
FSP_SERVICE *Service; /* weak */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,8 +67,12 @@ struct fsp_fuse_file_desc
|
|||||||
|
|
||||||
struct fuse_dirhandle
|
struct fuse_dirhandle
|
||||||
{
|
{
|
||||||
|
/* ReadDirectory */
|
||||||
struct fsp_fuse_file_desc *filedesc;
|
struct fsp_fuse_file_desc *filedesc;
|
||||||
|
FSP_FILE_SYSTEM *FileSystem;
|
||||||
|
BOOLEAN ReaddirPlus;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
/* CanDelete */
|
||||||
BOOLEAN DotFiles, HasChild;
|
BOOLEAN DotFiles, HasChild;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -187,7 +187,11 @@ static int ptfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, fus
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
if (0 == (de = readdir(dirp)))
|
if (0 == (de = readdir(dirp)))
|
||||||
break;
|
break;
|
||||||
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
if (0 != filler(buf, de->d_name, &de->d_stat, 0))
|
||||||
|
#else
|
||||||
if (0 != filler(buf, de->d_name, 0, 0))
|
if (0 != filler(buf, de->d_name, 0, 0))
|
||||||
|
#endif
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,6 +205,19 @@ static int ptfs_releasedir(const char *path, struct fuse_file_info *fi)
|
|||||||
return -1 != closedir(dirp) ? 0 : -errno;
|
return -1 != closedir(dirp) ? 0 : -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *ptfs_init(struct fuse_conn_info *conn)
|
||||||
|
{
|
||||||
|
#if 0 && defined(FSP_FUSE_CAP_READDIR_PLUS)
|
||||||
|
conn->want |= (conn->capable & FSP_FUSE_CAP_READDIR_PLUS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 && defined(FSP_FUSE_CAP_CASE_INSENSITIVE)
|
||||||
|
conn->want |= (conn->capable & FSP_FUSE_CAP_CASE_INSENSITIVE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return fuse_get_context()->private_data;
|
||||||
|
}
|
||||||
|
|
||||||
static int ptfs_create(const char *path, fuse_mode_t mode, struct fuse_file_info *fi)
|
static int ptfs_create(const char *path, fuse_mode_t mode, struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
ptfs_impl_fullpath(path);
|
ptfs_impl_fullpath(path);
|
||||||
@ -254,7 +271,7 @@ static struct fuse_operations ptfs_ops =
|
|||||||
ptfs_readdir,
|
ptfs_readdir,
|
||||||
ptfs_releasedir,
|
ptfs_releasedir,
|
||||||
0, //fsyncdir
|
0, //fsyncdir
|
||||||
0, //init
|
ptfs_init,
|
||||||
0, //destroy
|
0, //destroy
|
||||||
0, //access
|
0, //access
|
||||||
ptfs_create,
|
ptfs_create,
|
||||||
|
@ -115,7 +115,7 @@ int statvfs(const char *path, struct fuse_statvfs *stbuf)
|
|||||||
|
|
||||||
memset(stbuf, 0, sizeof *stbuf);
|
memset(stbuf, 0, sizeof *stbuf);
|
||||||
stbuf->f_bsize = SectorsPerCluster * BytesPerSector;
|
stbuf->f_bsize = SectorsPerCluster * BytesPerSector;
|
||||||
stbuf->f_frsize = BytesPerSector;
|
stbuf->f_frsize = SectorsPerCluster * BytesPerSector;
|
||||||
stbuf->f_blocks = TotalNumberOfClusters;
|
stbuf->f_blocks = TotalNumberOfClusters;
|
||||||
stbuf->f_bfree = NumberOfFreeClusters;
|
stbuf->f_bfree = NumberOfFreeClusters;
|
||||||
stbuf->f_bavail = TotalNumberOfClusters;
|
stbuf->f_bavail = TotalNumberOfClusters;
|
||||||
@ -388,6 +388,8 @@ void rewinddir(DIR *dirp)
|
|||||||
struct dirent *readdir(DIR *dirp)
|
struct dirent *readdir(DIR *dirp)
|
||||||
{
|
{
|
||||||
WIN32_FIND_DATAA FindData;
|
WIN32_FIND_DATAA FindData;
|
||||||
|
UINT64 CreationTime, LastAccessTime, LastWriteTime;
|
||||||
|
struct fuse_stat *stbuf = &dirp->de.d_stat;
|
||||||
|
|
||||||
if (INVALID_HANDLE_VALUE == dirp->fh)
|
if (INVALID_HANDLE_VALUE == dirp->fh)
|
||||||
{
|
{
|
||||||
@ -405,6 +407,24 @@ struct dirent *readdir(DIR *dirp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CreationTime = ((PLARGE_INTEGER)(&FindData.ftCreationTime))->QuadPart - 116444736000000000;
|
||||||
|
LastAccessTime = ((PLARGE_INTEGER)(&FindData.ftLastAccessTime))->QuadPart - 116444736000000000;
|
||||||
|
LastWriteTime = ((PLARGE_INTEGER)(&FindData.ftLastWriteTime))->QuadPart - 116444736000000000;
|
||||||
|
|
||||||
|
memset(stbuf, 0, sizeof *stbuf);
|
||||||
|
stbuf->st_mode = 0777 |
|
||||||
|
((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0040000/* S_IFDIR */ : 0);
|
||||||
|
stbuf->st_nlink = 1;
|
||||||
|
stbuf->st_size = ((UINT64)FindData.nFileSizeHigh << 32) | ((UINT64)FindData.nFileSizeLow);
|
||||||
|
stbuf->st_atim.tv_sec = LastAccessTime / 10000000;
|
||||||
|
stbuf->st_atim.tv_nsec = LastAccessTime % 10000000 * 100;
|
||||||
|
stbuf->st_mtim.tv_sec = LastWriteTime / 10000000;
|
||||||
|
stbuf->st_mtim.tv_nsec = LastWriteTime % 10000000 * 100;
|
||||||
|
stbuf->st_ctim.tv_sec = LastWriteTime / 10000000;
|
||||||
|
stbuf->st_ctim.tv_nsec = LastWriteTime % 10000000 * 100;
|
||||||
|
stbuf->st_birthtim.tv_sec = CreationTime / 10000000;
|
||||||
|
stbuf->st_birthtim.tv_nsec = CreationTime % 10000000 * 100;
|
||||||
|
|
||||||
strcpy(dirp->de.d_name, FindData.cFileName);
|
strcpy(dirp->de.d_name, FindData.cFileName);
|
||||||
|
|
||||||
return &dirp->de;
|
return &dirp->de;
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
typedef struct _DIR DIR;
|
typedef struct _DIR DIR;
|
||||||
struct dirent
|
struct dirent
|
||||||
{
|
{
|
||||||
|
struct fuse_stat d_stat;
|
||||||
char d_name[255];
|
char d_name[255];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user