From 10635db99bbca1073a0a5aefcc9a23fef8aba03b Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 13 Sep 2016 22:17:31 -0700 Subject: [PATCH] dll: fuse: reparse point fixes - symlinks to directories have the FILE_ATTRIBUTE_DIRECTORY added - new symlinks/special files are now created with correct uid/gid in fuse_context --- src/dll/fuse/fuse_intf.c | 58 +++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/src/dll/fuse/fuse_intf.c b/src/dll/fuse/fuse_intf.c index 32a87537..6d6cc7b4 100644 --- a/src/dll/fuse/fuse_intf.c +++ b/src/dll/fuse/fuse_intf.c @@ -345,6 +345,38 @@ exit: return Result; } +static BOOLEAN fsp_fuse_intf_CheckSymlinkDirectory(FSP_FILE_SYSTEM *FileSystem, + const char *PosixPath) +{ + struct fuse *f = FileSystem->UserContext; + char *PosixDotPath = 0; + size_t Length; + struct fuse_stat stbuf; + int err; + BOOLEAN Result = FALSE; + + Length = lstrlenA(PosixPath); + PosixDotPath = MemAlloc(Length + 3); + if (0 != PosixDotPath) + { + memcpy(PosixDotPath, PosixPath, Length); + PosixDotPath[Length + 0] = '/'; + PosixDotPath[Length + 1] = '.'; + PosixDotPath[Length + 2] = '\0'; + + if (0 != f->ops.getattr) + err = f->ops.getattr(PosixDotPath, (void *)&stbuf); + else + err = -ENOSYS; + + MemFree(PosixDotPath); + + Result = 0 == err && 0040000 == (stbuf.st_mode & 0170000); + } + + return Result; +} + #define fsp_fuse_intf_GetFileInfoEx(FileSystem, PosixPath, fi, PUid, PGid, PMode, FileInfo)\ fsp_fuse_intf_GetFileInfoFunnel(FileSystem, PosixPath, fi, PUid, PGid, PMode, 0, FileInfo) static NTSTATUS fsp_fuse_intf_GetFileInfoFunnel(FSP_FILE_SYSTEM *FileSystem, @@ -402,6 +434,8 @@ static NTSTATUS fsp_fuse_intf_GetFileInfoFunnel(FSP_FILE_SYSTEM *FileSystem, { FileInfo->FileAttributes = FILE_ATTRIBUTE_REPARSE_POINT; FileInfo->ReparseTag = IO_REPARSE_TAG_SYMLINK; + if (fsp_fuse_intf_CheckSymlinkDirectory(FileSystem, PosixPath)) + FileInfo->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; break; } /* fall through */ @@ -1874,6 +1908,7 @@ static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem, PWSTR FileName, PVOID Buffer, SIZE_T Size) { struct fuse *f = FileSystem->UserContext; + struct fuse_context *context = fsp_fuse_get_context(f->env); struct fsp_fuse_file_desc *filedesc = (PVOID)(UINT_PTR)Request->Req.FileSystemControl.UserContext2; struct fuse_file_info fi; @@ -1983,7 +2018,9 @@ static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(Result)) goto exit; + context->uid = Uid, context->gid = Gid; err = f->ops.symlink(PosixTargetPath, PosixHiddenPath); + context->uid = -1, context->gid = -1; if (0 != err) { Result = fsp_fuse_ntstatus_from_errno(f->env, err); @@ -2026,7 +2063,9 @@ static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem, if (!NT_SUCCESS(Result)) goto exit; + context->uid = Uid, context->gid = Gid; err = f->ops.mknod(PosixHiddenPath, Mode, Dev); + context->uid = -1, context->gid = -1; if (0 != err) { Result = fsp_fuse_ntstatus_from_errno(f->env, err); @@ -2034,25 +2073,6 @@ static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem, } } - /* - * At least SSHFS has problems with chown as it attempts to chown the target file - * rather than lchown the symlink. So comment out for now! - */ -#if 0 - if (0 != f->ops.chown) - { - err = f->ops.chown(PosixHiddenPath, Uid, Gid); - if (0 != err) - { - /* on failure unlink "hidden" symlink */ - f->ops.unlink(PosixHiddenPath); - - Result = fsp_fuse_ntstatus_from_errno(f->env, err); - goto exit; - } - } -#endif - err = f->ops.rename(PosixHiddenPath, filedesc->PosixPath); if (0 != err) {