diff --git a/inc/fuse/fuse.h b/inc/fuse/fuse.h index e140b117..793234ec 100644 --- a/inc/fuse/fuse.h +++ b/inc/fuse/fuse.h @@ -152,6 +152,8 @@ FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_exit)(struct fsp_fuse_env *env, struct fuse *f); FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_exited)(struct fsp_fuse_env *env, struct fuse *f); +FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_notify)(struct fsp_fuse_env *env, + struct fuse *f, const char *path, uint32_t action); FSP_FUSE_API struct fuse_context *FSP_FUSE_API_NAME(fsp_fuse_get_context)(struct fsp_fuse_env *env); FSP_FUSE_SYM( @@ -212,6 +214,13 @@ int fuse_exited(struct fuse *f), (fsp_fuse_env(), f); }) +FSP_FUSE_SYM( +int fuse_notify(struct fuse *f, const char *path, uint32_t action), +{ + return FSP_FUSE_API_CALL(fsp_fuse_notify) + (fsp_fuse_env(), f, path, action); +}) + FSP_FUSE_SYM( struct fuse_context *fuse_get_context(void), { diff --git a/inc/fuse/fuse_common.h b/inc/fuse/fuse_common.h index 0562eacb..936ca215 100644 --- a/inc/fuse/fuse_common.h +++ b/inc/fuse/fuse_common.h @@ -79,6 +79,17 @@ extern "C" { #define UF_ARCHIVE FSP_FUSE_UF_ARCHIVE #endif +/* notify extension */ +#define FSP_FUSE_NOTIFY_MKDIR 0x0001 +#define FSP_FUSE_NOTIFY_RMDIR 0x0002 +#define FSP_FUSE_NOTIFY_CREATE 0x0004 +#define FSP_FUSE_NOTIFY_UNLINK 0x0008 +#define FSP_FUSE_NOTIFY_CHMOD 0x0010 +#define FSP_FUSE_NOTIFY_CHOWN 0x0020 +#define FSP_FUSE_NOTIFY_UTIME 0x0040 +#define FSP_FUSE_NOTIFY_CHFLAGS 0x0080 +#define FSP_FUSE_NOTIFY_TRUNCATE 0x0100 + struct fuse_file_info { int flags; diff --git a/src/dll/fuse/fuse.c b/src/dll/fuse/fuse.c index d18eaef0..83f7c468 100644 --- a/src/dll/fuse/fuse.c +++ b/src/dll/fuse/fuse.c @@ -610,6 +610,99 @@ FSP_FUSE_API int FSP_FUSE_API_NAME(fsp_fuse_exited)(struct fsp_fuse_env *env, return f->exited; } +FSP_FUSE_API int fsp_fuse_notify(struct fsp_fuse_env *env, + struct fuse *f, const char *path, uint32_t action) +{ + PWSTR Path = 0; + int PathLength; + union + { + FSP_FSCTL_NOTIFY_INFO V; + UINT8 B[sizeof(FSP_FSCTL_NOTIFY_INFO) + FSP_FSCTL_TRANSACT_PATH_SIZEMAX]; + } NotifyInfo; + NTSTATUS Result; + int result; + + Result = FspPosixMapPosixToWindowsPath(path, &Path); + if (!NT_SUCCESS(Result)) + { + result = -ENOMEM; + goto exit; + } + + PathLength = lstrlenW(Path); + if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR) <= PathLength) + { + result = -ENAMETOOLONG; + goto exit; + } + + NotifyInfo.V.Size = (UINT16)(sizeof(FSP_FSCTL_NOTIFY_INFO) + PathLength * sizeof(WCHAR)); + NotifyInfo.V.Filter = 0; + NotifyInfo.V.Action = 0; + memcpy(NotifyInfo.V.FileNameBuf, Path, NotifyInfo.V.Size - sizeof(FSP_FSCTL_NOTIFY_INFO)); + + if (action & FSP_FUSE_NOTIFY_MKDIR) + { + NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_DIR_NAME; + NotifyInfo.V.Action = FILE_ACTION_ADDED; + } + else if (action & FSP_FUSE_NOTIFY_RMDIR) + { + NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_DIR_NAME; + NotifyInfo.V.Action = FILE_ACTION_REMOVED; + } + else if (action & FSP_FUSE_NOTIFY_CREATE) + { + NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_FILE_NAME; + NotifyInfo.V.Action = FILE_ACTION_REMOVED; + } + else if (action & FSP_FUSE_NOTIFY_UNLINK) + { + NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_FILE_NAME; + NotifyInfo.V.Action = FILE_ACTION_REMOVED; + } + + if (action & (FSP_FUSE_NOTIFY_CHMOD | FSP_FUSE_NOTIFY_CHOWN)) + { + NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_SECURITY; + NotifyInfo.V.Action = FILE_ACTION_MODIFIED; + } + + if (action & FSP_FUSE_NOTIFY_UTIME) + { + NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_LAST_WRITE; + NotifyInfo.V.Action = FILE_ACTION_MODIFIED; + } + + if (action & FSP_FUSE_NOTIFY_CHFLAGS) + { + NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_ATTRIBUTES; + NotifyInfo.V.Action = FILE_ACTION_MODIFIED; + } + + if (action & FSP_FUSE_NOTIFY_TRUNCATE) + { + NotifyInfo.V.Filter = FILE_NOTIFY_CHANGE_SIZE; + NotifyInfo.V.Action = FILE_ACTION_MODIFIED; + } + + Result = FspFileSystemNotify(f->FileSystem, &NotifyInfo.V, NotifyInfo.V.Size); + if (!NT_SUCCESS(Result)) + { + result = -ENOMEM; + goto exit; + } + + result = 0; + +exit: + if (0 != Path) + FspPosixDeletePath(Path); + + return result; +} + FSP_FUSE_API struct fuse_context *fsp_fuse_get_context(struct fsp_fuse_env *env) { struct fuse_context *context;