mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	dll: fuseintf: Create implementation
This commit is contained in:
		| @@ -298,7 +298,145 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem, | ||||
|     UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize, | ||||
|     PVOID *PFileNode, FSP_FSCTL_FILE_INFO *FileInfo) | ||||
| { | ||||
|     return STATUS_INVALID_DEVICE_REQUEST; | ||||
|     struct fuse *f = FileSystem->UserContext; | ||||
|     struct fuse_context *context = fsp_fuse_get_context(0); | ||||
|     struct fsp_fuse_context_header *contexthdr = | ||||
|         (PVOID)((PUINT8)context - sizeof *contexthdr); | ||||
|     UINT32 Uid, Gid, Mode; | ||||
|     FSP_FSCTL_FILE_INFO FileInfoBuf; | ||||
|     struct fsp_fuse_file_desc *filedesc = 0; | ||||
|     struct fuse_file_info fi; | ||||
|     BOOLEAN Opened = FALSE; | ||||
|     int err; | ||||
|     NTSTATUS Result; | ||||
|  | ||||
|     filedesc = MemAlloc(sizeof *filedesc); | ||||
|     if (0 == filedesc) | ||||
|     { | ||||
|         Result = STATUS_INSUFFICIENT_RESOURCES; | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     Uid = context->uid; | ||||
|     Gid = context->gid; | ||||
|     Mode = 0777; | ||||
|     if (0 != SecurityDescriptor) | ||||
|     { | ||||
|         Result = FspPosixMapSecurityDescriptorToPermissions(SecurityDescriptor, | ||||
|             &Uid, &Gid, &Mode); | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|             goto exit; | ||||
|     } | ||||
|     Mode &= ~context->umask; | ||||
|  | ||||
|     memset(&fi, 0, sizeof fi); | ||||
|  | ||||
|     if (CreateOptions & FILE_DIRECTORY_FILE) | ||||
|     { | ||||
|         if (0 != f->ops.mkdir) | ||||
|         { | ||||
|             err = f->ops.mkdir(contexthdr->PosixPath, Mode); | ||||
|             if (0 != err) | ||||
|             { | ||||
|                 Result = fsp_fuse_ntstatus_from_errno(f->env, err); | ||||
|                 goto exit; | ||||
|             } | ||||
|  | ||||
|             if (0 != f->ops.opendir) | ||||
|             { | ||||
|                 err = f->ops.opendir(contexthdr->PosixPath, &fi); | ||||
|                 Result = fsp_fuse_ntstatus_from_errno(f->env, err); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|             Result = STATUS_SUCCESS; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if (0 != f->ops.create) | ||||
|         { | ||||
|             err = f->ops.create(contexthdr->PosixPath, Mode, &fi); | ||||
|             Result = fsp_fuse_ntstatus_from_errno(f->env, err); | ||||
|         } | ||||
|         else if (0 != f->ops.mknod && 0 != f->ops.open) | ||||
|         { | ||||
|             err = f->ops.mknod(contexthdr->PosixPath, Mode, 0); | ||||
|             if (0 != err) | ||||
|             { | ||||
|                 Result = fsp_fuse_ntstatus_from_errno(f->env, err); | ||||
|                 goto exit; | ||||
|             } | ||||
|  | ||||
|             fi.flags = O_RDWR; | ||||
|             err = f->ops.open(contexthdr->PosixPath, &fi); | ||||
|             Result = fsp_fuse_ntstatus_from_errno(f->env, err); | ||||
|         } | ||||
|         else | ||||
|             Result = STATUS_INVALID_DEVICE_REQUEST; | ||||
|     } | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         goto exit; | ||||
|  | ||||
|     Opened = TRUE; | ||||
|  | ||||
|     if (Uid != context->uid || Gid != context->gid) | ||||
|         if (0 != f->ops.chown) | ||||
|         { | ||||
|             err = f->ops.chown(contexthdr->PosixPath, Uid, Gid); | ||||
|             if (0 != err) | ||||
|             { | ||||
|                 Result = fsp_fuse_ntstatus_from_errno(f->env, err); | ||||
|                 goto exit; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     /* | ||||
|      * Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache | ||||
|      * WinFsp does not currently support disabling the cache manager | ||||
|      * for an individual file although it should not be hard to add | ||||
|      * if required. | ||||
|      * | ||||
|      * Ignore fuse_file_info::nonseekable. | ||||
|      */ | ||||
|  | ||||
|     Result = fsp_fuse_intf_GetFileInfoByPath(FileSystem, contexthdr->PosixPath, | ||||
|         &Uid, &Gid, &Mode, &FileInfoBuf); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         goto exit; | ||||
|  | ||||
|     *PFileNode = 0; | ||||
|     memcpy(FileInfo, &FileInfoBuf, sizeof FileInfoBuf); | ||||
|  | ||||
|     filedesc->PosixPath = contexthdr->PosixPath; | ||||
|     filedesc->IsDirectory = !!(FileInfoBuf.FileAttributes & FILE_ATTRIBUTE_DIRECTORY); | ||||
|     filedesc->OpenFlags = fi.flags; | ||||
|     filedesc->FileHandle = fi.fh; | ||||
|     contexthdr->PosixPath = 0; | ||||
|     contexthdr->Response->Rsp.Create.Opened.UserContext2 = (UINT64)(UINT_PTR)filedesc; | ||||
|  | ||||
|     Result = STATUS_SUCCESS; | ||||
|  | ||||
| exit: | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
|         if (Opened) | ||||
|         { | ||||
|             if (CreateOptions & FILE_DIRECTORY_FILE) | ||||
|             { | ||||
|                 if (0 != f->ops.releasedir) | ||||
|                     f->ops.releasedir(filedesc->PosixPath, &fi); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (0 != f->ops.release) | ||||
|                     f->ops.release(filedesc->PosixPath, &fi); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         MemFree(filedesc); | ||||
|     } | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| static NTSTATUS fsp_fuse_intf_Open(FSP_FILE_SYSTEM *FileSystem, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user