Merge pull request #46 from github/rename-events

File/dir rename events
This commit is contained in:
Ashe Connor 2019-02-20 11:02:16 +11:00 коммит произвёл GitHub
Родитель 461833f3af ddcc1cf5f9
Коммит e3e37276f7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
16 изменённых файлов: 288 добавлений и 91 удалений

Просмотреть файл

@ -39,6 +39,7 @@ extern "C" {
#define PROJFS_CLOSE_WRITE 0x00000008 /* Writable file was closed */
#define PROJFS_OPEN 0x00000020 /* File was opened */
#define PROJFS_DELETE_SELF 0x00000400 /* Delete permission */
#define PROJFS_MOVE_SELF 0x00000800 /* File/dir was moved */
#define PROJFS_CREATE_SELF himask(0x0001) /* File was created */
/** Filesystem event flags */
@ -76,6 +77,7 @@ extern "C" {
#if (PROJFS_CLOSE_WRITE != IN_CLOSE_WRITE || \
PROJFS_OPEN != IN_OPEN || \
PROJFS_DELETE_SELF != IN_DELETE_SELF || \
PROJFS_MOVE_SELF != IN_MOVE_SELF || \
PROJFS_ONDIR != IN_ISDIR)
#error "Projfs notification API out of sync with sys/inotify.h API"
#endif

Просмотреть файл

@ -331,7 +331,6 @@ static int projfs_fuse_proj_file(const char *op, const char *path)
/* tried to project a directory as a file, ignore
* XXX should we just always project dirs as dirs and files as
* files? */
res = 0;
goto out;
} else if (res == ELOOP) {
/* tried to project a symlink. it already exists as a symlink
@ -531,9 +530,11 @@ static int projfs_op_open(char const *path, struct fuse_file_info *fi)
/* Per above, allow hydration to fail with ENOENT; if the file
* operation should fail for that reason (i.e. O_CREAT is not specified
* and the file doesn't exist), we'll return the failure from openat(2)
* below */
* below.
* We allow hydration to fail with EISDIR in case the user is doing an
* open(2) on a directory. */
res = projfs_fuse_proj_file("open", lowerpath(path));
if (res && res != ENOENT)
if (res && res != ENOENT && res != EISDIR)
return -res;
fd = openat(lowerdir_fd(), lowerpath(path), flags);
@ -649,16 +650,21 @@ static int projfs_op_rmdir(char const *path)
static int projfs_op_rename(char const *src, char const *dst,
unsigned int flags)
{
uint64_t mask = PROJFS_MOVE_SELF;
int res = projfs_fuse_proj_dir("rename", lowerpath(src), 1);
if (res)
return -res;
res = projfs_fuse_proj_file("rename", lowerpath(src));
if (res)
if (res == EISDIR)
mask |= PROJFS_ONDIR;
else if (res)
return -res;
res = projfs_fuse_proj_dir("rename2", lowerpath(dst), 1);
if (res)
return -res;
// TODO: may prevent us compiling on BSD; would renameat() suffice?
// TODO: for non Linux, use renameat(); fail if flags != 0
res = syscall(
SYS_renameat2,
lowerdir_fd(),
@ -666,7 +672,11 @@ static int projfs_op_rename(char const *src, char const *dst,
lowerdir_fd(),
lowerpath(dst),
flags);
return res == -1 ? -errno : 0;
if (res == -1)
return -errno;
res = projfs_fuse_notify_event(mask, src, dst);
return res;
}
static int projfs_op_opendir(char const *path, struct fuse_file_info *fi)

Просмотреть файл

@ -267,6 +267,8 @@ static int handle_nonproj_event(struct projfs_event *event, int perm)
if (mask & PROJFS_DELETE_SELF)
notificationType = PrjFS_NotificationType_PreDelete;
else if (mask & PROJFS_MOVE_SELF)
notificationType = PrjFS_NotificationType_FileRenamed;
else if (mask & PROJFS_CREATE_SELF)
notificationType = PrjFS_NotificationType_NewFileCreated;
// TODO: dispatch for additional event types

Просмотреть файл

@ -59,16 +59,30 @@ test_expect_success 'test permission granted on nested file deletion' '
test_path_is_missing target/d1/d2/f2.txt
'
projfs_event_printf perm delete_file f1.txt
test_expect_success 'test permission granted on top-level file deletion' '
projfs_event_exec rm target/f1.txt &&
test_path_is_missing target/f1.txt
projfs_event_printf notify rename_file f1.txt f1a.txt
test_expect_success 'test event handler on file rename' '
projfs_event_exec mv target/f1.txt target/f1a.txt &&
test_path_is_missing target/f1.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf perm delete_dir d1/d2
projfs_event_printf perm delete_file f1a.txt
test_expect_success 'test permission granted on top-level file deletion' '
projfs_event_exec rm target/f1a.txt &&
test_path_is_missing target/f1a.txt
'
projfs_event_printf notify rename_dir d1/d2 d1/d2a
test_expect_success 'test event handler on directory rename' '
projfs_event_exec mv target/d1/d2 target/d1/d2a &&
test_path_is_missing target/d1/d2 &&
test_path_is_dir target/d1/d2a
'
projfs_event_printf perm delete_dir d1/d2a
test_expect_success 'test permission granted on nested directory deletion' '
projfs_event_exec rmdir target/d1/d2 &&
test_path_is_missing target/d1/d2
projfs_event_exec rmdir target/d1/d2a &&
test_path_is_missing target/d1/d2a
'
projfs_event_printf perm delete_dir d1

Просмотреть файл

@ -43,16 +43,32 @@ test_expect_success 'test event handler error on file creation' '
test_path_is_file target/f1.txt
'
projfs_event_printf error ENOMEM perm delete_file f1.txt
test_expect_success 'test event handler error on file deletion' '
test_must_fail projfs_event_exec rm target/f1.txt &&
test_path_is_file target/f1.txt
# TODO: we expect mv to rename a dir despite the handler error and
# regardless of mv's failure exit code
projfs_event_printf error ENOMEM notify rename_dir d1 d1a
test_expect_success 'test event handler error on directory rename' '
test_must_fail projfs_event_exec mv target/d1 target/d1a &&
test_path_is_dir target/d1a
'
projfs_event_printf error ENOMEM perm delete_dir d1
# TODO: we expect mv to rename a file despite the handler error and
# regardless of mv's failure exit code
projfs_event_printf error ENOMEM notify rename_file f1.txt f1a.txt
test_expect_success 'test event handler error on file rename' '
test_must_fail projfs_event_exec mv target/f1.txt target/f1a.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf error ENOMEM perm delete_file f1a.txt
test_expect_success 'test event handler error on file deletion' '
test_must_fail projfs_event_exec rm target/f1a.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf error ENOMEM perm delete_dir d1a
test_expect_success 'test event handler error on directory deletion' '
test_must_fail projfs_event_exec rmdir target/d1 &&
test_path_is_dir target/d1
test_must_fail projfs_event_exec rmdir target/d1a &&
test_path_is_dir target/d1a
'
rm retval

Просмотреть файл

@ -39,16 +39,30 @@ test_expect_success 'test event handler on file creation' '
test_path_is_file target/f1.txt
'
projfs_event_printf perm delete_file f1.txt
test_expect_success 'test permission request denied on file deletion' '
test_must_fail projfs_event_exec rm target/f1.txt &&
test_path_is_file target/f1.txt
projfs_event_printf notify rename_dir d1 d1a
test_expect_success 'test event handler on directory rename' '
projfs_event_exec mv target/d1 target/d1a &&
test_path_is_missing target/d1 &&
test_path_is_dir target/d1a
'
projfs_event_printf perm delete_dir d1
projfs_event_printf notify rename_file f1.txt f1a.txt
test_expect_success 'test event handler on file rename' '
projfs_event_exec mv target/f1.txt target/f1a.txt &&
test_path_is_missing target/f1.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf perm delete_file f1a.txt
test_expect_success 'test permission request denied on file deletion' '
test_must_fail projfs_event_exec rm target/f1a.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf perm delete_dir d1a
test_expect_success 'test permission request denied on directory deletion' '
test_must_fail projfs_event_exec rmdir target/d1 &&
test_path_is_dir target/d1
test_must_fail projfs_event_exec rmdir target/d1a &&
test_path_is_dir target/d1a
'
rm retval

Просмотреть файл

@ -39,16 +39,30 @@ test_expect_success 'test event handler on file creation' '
test_path_is_file target/f1.txt
'
projfs_event_printf perm delete_file f1.txt
test_expect_success 'test permission request denied on file deletion' '
test_must_fail projfs_event_exec rm target/f1.txt &&
test_path_is_file target/f1.txt
projfs_event_printf notify rename_dir d1 d1a
test_expect_success 'test event handler on directory rename' '
projfs_event_exec mv target/d1 target/d1a &&
test_path_is_missing target/d1 &&
test_path_is_dir target/d1a
'
projfs_event_printf perm delete_dir d1
projfs_event_printf notify rename_file f1.txt f1a.txt
test_expect_success 'test event handler on file rename' '
projfs_event_exec mv target/f1.txt target/f1a.txt &&
test_path_is_missing target/f1.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf perm delete_file f1a.txt
test_expect_success 'test permission request denied on file deletion' '
test_must_fail projfs_event_exec rm target/f1a.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf perm delete_dir d1a
test_expect_success 'test permission request denied on directory deletion' '
test_must_fail projfs_event_exec rmdir target/d1 &&
test_path_is_dir target/d1
test_must_fail projfs_event_exec rmdir target/d1a &&
test_path_is_dir target/d1a
'
rm retval

Просмотреть файл

@ -39,16 +39,30 @@ test_expect_success 'test event handler on file creation' '
test_path_is_file target/f1.txt
'
projfs_event_printf perm delete_file f1.txt
test_expect_success 'test permission request allowed on file deletion' '
projfs_event_exec rm target/f1.txt &&
test_path_is_missing target/f1.txt
projfs_event_printf notify rename_dir d1 d1a
test_expect_success 'test event handler on directory rename' '
projfs_event_exec mv target/d1 target/d1a &&
test_path_is_missing target/d1 &&
test_path_is_dir target/d1a
'
projfs_event_printf perm delete_dir d1
projfs_event_printf notify rename_file f1.txt f1a.txt
test_expect_success 'test event handler on file rename' '
projfs_event_exec mv target/f1.txt target/f1a.txt &&
test_path_is_missing target/f1.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf perm delete_file f1a.txt
test_expect_success 'test permission request allowed on file deletion' '
projfs_event_exec rm target/f1a.txt &&
test_path_is_missing target/f1a.txt
'
projfs_event_printf perm delete_dir d1a
test_expect_success 'test permission request allowed on directory deletion' '
projfs_event_exec rmdir target/d1 &&
test_path_is_missing target/d1
projfs_event_exec rmdir target/d1a &&
test_path_is_missing target/d1a
'
rm retval

Просмотреть файл

@ -59,16 +59,30 @@ test_expect_success 'test permission granted on nested file deletion' '
test_path_is_missing target/d1/d2/f2.txt
'
projfs_event_printf vfs delete_file f1.txt
test_expect_success 'test permission granted on top-level file deletion' '
projfs_event_exec rm target/f1.txt &&
test_path_is_missing target/f1.txt
projfs_event_printf vfs rename_file f1.txt f1a.txt
test_expect_success 'test event handler on file rename' '
projfs_event_exec mv target/f1.txt target/f1a.txt &&
test_path_is_missing target/f1.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf vfs delete_dir d1/d2
projfs_event_printf vfs delete_file f1a.txt
test_expect_success 'test permission granted on top-level file deletion' '
projfs_event_exec rm target/f1a.txt &&
test_path_is_missing target/f1a.txt
'
projfs_event_printf vfs rename_dir d1/d2 d1/d2a
test_expect_success 'test event handler on directory rename' '
projfs_event_exec mv target/d1/d2 target/d1/d2a &&
test_path_is_missing target/d1/d2 &&
test_path_is_dir target/d1/d2a
'
projfs_event_printf vfs delete_dir d1/d2a
test_expect_success 'test permission granted on nested directory deletion' '
projfs_event_exec rmdir target/d1/d2 &&
test_path_is_missing target/d1/d2
projfs_event_exec rmdir target/d1/d2a &&
test_path_is_missing target/d1/d2a
'
projfs_event_printf vfs delete_dir d1

Просмотреть файл

@ -43,16 +43,32 @@ test_expect_success 'test event handler error on file creation' '
test_path_is_file target/f1.txt
'
projfs_event_printf error ENOMEM vfs delete_file f1.txt
test_expect_success 'test event handler error on file deletion' '
test_must_fail projfs_event_exec rm target/f1.txt &&
test_path_is_file target/f1.txt
# TODO: we expect mv to rename a dir despite the handler error and
# regardless of mv's failure exit code
projfs_event_printf error ENOMEM vfs rename_dir d1 d1a
test_expect_success 'test event handler error on directory rename' '
test_must_fail projfs_event_exec mv target/d1 target/d1a &&
test_path_is_dir target/d1a
'
projfs_event_printf error ENOMEM vfs delete_dir d1
# TODO: we expect mv to rename a file despite the handler error and
# regardless of mv's failure exit code
projfs_event_printf error ENOMEM vfs rename_file f1.txt f1a.txt
test_expect_success 'test event handler error on file rename' '
test_must_fail projfs_event_exec mv target/f1.txt target/f1a.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf error ENOMEM vfs delete_file f1a.txt
test_expect_success 'test event handler error on file deletion' '
test_must_fail projfs_event_exec rm target/f1a.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf error ENOMEM vfs delete_dir d1a
test_expect_success 'test event handler error on directory deletion' '
test_must_fail projfs_event_exec rmdir target/d1 &&
test_path_is_dir target/d1
test_must_fail projfs_event_exec rmdir target/d1a &&
test_path_is_dir target/d1a
'
rm retval

Просмотреть файл

@ -28,7 +28,7 @@ projfs_start test_vfsapi_handlers source target --retval-file retval || exit 1
echo deny > retval
# TODO: test_vfsapi_handlers always returns EPERM with --retval deny, unlike
# test_projfs_handlers, so mkdir gets a handler error; like t701.1,
# test_projfs_handlers, so mkdir sees a handler error; like t701.1,
# we expect mkdir to create a dir despite the handler error and
# regardless of mkdir's failure exit code
projfs_event_printf error EPERM vfs create_dir d1
@ -47,16 +47,38 @@ test_expect_success 'test event handler on file creation' '
test_path_is_file target/f1.txt
'
projfs_event_printf vfs delete_file f1.txt
test_expect_success 'test permission request denied on file deletion' '
test_must_fail projfs_event_exec rm target/f1.txt &&
test_path_is_file target/f1.txt
# TODO: test_vfsapi_handlers always returns EPERM with --retval deny, unlike
# test_projfs_handlers, so mv sees a handler error; like t701.3,
# we expect mv to rename a dir despite the handler error and
# regardless of mv's failure exit code
projfs_event_printf error EPERM vfs rename_dir d1 d1a
test_expect_success 'test event handler on directory rename' '
test_must_fail projfs_event_exec mv target/d1 target/d1a &&
test_path_is_missing target/d1 &&
test_path_is_dir target/d1a
'
projfs_event_printf vfs delete_dir d1
# TODO: test_vfsapi_handlers always returns EPERM with --retval deny, unlike
# test_projfs_handlers, so mv sees a handler error; like t701.4,
# we expect mv to rename a file despite the handler error and
# regardless of mv's failure exit code
projfs_event_printf error EPERM vfs rename_file f1.txt f1a.txt
test_expect_success 'test event handler on file rename' '
test_must_fail projfs_event_exec mv target/f1.txt target/f1a.txt &&
test_path_is_missing target/f1.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf vfs delete_file f1a.txt
test_expect_success 'test permission request denied on file deletion' '
test_must_fail projfs_event_exec rm target/f1a.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf vfs delete_dir d1a
test_expect_success 'test permission request denied on directory deletion' '
test_must_fail projfs_event_exec rmdir target/d1 &&
test_path_is_dir target/d1
test_must_fail projfs_event_exec rmdir target/d1a &&
test_path_is_dir target/d1a
'
rm retval

Просмотреть файл

@ -48,16 +48,38 @@ test_expect_success 'test event handler on file creation' '
test_path_is_file target/f1.txt
'
projfs_event_printf error EINVAL vfs delete_file f1.txt
test_expect_success 'test permission request denied on file deletion' '
test_must_fail projfs_event_exec rm target/f1.txt &&
test_path_is_file target/f1.txt
# TODO: test_vfsapi_handlers always returns EPERM with --retval deny, unlike
# test_projfs_handlers, so mv sees a handler error; like t701.3,
# we expect mv to rename a dir despite the handler error and
# regardless of mv's failure exit code
projfs_event_printf error EINVAL vfs rename_dir d1 d1a
test_expect_success 'test event handler on directory rename' '
test_must_fail projfs_event_exec mv target/d1 target/d1a &&
test_path_is_missing target/d1 &&
test_path_is_dir target/d1a
'
projfs_event_printf error EINVAL vfs delete_dir d1
# TODO: test_vfsapi_handlers always returns EPERM with --retval deny, unlike
# test_projfs_handlers, so mv sees a handler error; like t701.4,
# we expect mv to rename a file despite the handler error and
# regardless of mv's failure exit code
projfs_event_printf error EINVAL vfs rename_file f1.txt f1a.txt
test_expect_success 'test event handler on file rename' '
test_must_fail projfs_event_exec mv target/f1.txt target/f1a.txt &&
test_path_is_missing target/f1.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf error EINVAL vfs delete_file f1a.txt
test_expect_success 'test permission request denied on file deletion' '
test_must_fail projfs_event_exec rm target/f1a.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf error EINVAL vfs delete_dir d1a
test_expect_success 'test permission request denied on directory deletion' '
test_must_fail projfs_event_exec rmdir target/d1 &&
test_path_is_dir target/d1
test_must_fail projfs_event_exec rmdir target/d1a &&
test_path_is_dir target/d1a
'
rm retval

Просмотреть файл

@ -39,16 +39,30 @@ test_expect_success 'test event handler on file creation' '
test_path_is_file target/f1.txt
'
projfs_event_printf vfs delete_file f1.txt
test_expect_success 'test permission request allowed on file deletion' '
projfs_event_exec rm target/f1.txt &&
test_path_is_missing target/f1.txt
projfs_event_printf vfs rename_dir d1 d1a
test_expect_success 'test event handler on directory rename' '
projfs_event_exec mv target/d1 target/d1a &&
test_path_is_missing target/d1 &&
test_path_is_dir target/d1a
'
projfs_event_printf vfs delete_dir d1
projfs_event_printf vfs rename_file f1.txt f1a.txt
test_expect_success 'test event handler on file rename' '
projfs_event_exec mv target/f1.txt target/f1a.txt &&
test_path_is_missing target/f1.txt &&
test_path_is_file target/f1a.txt
'
projfs_event_printf vfs delete_file f1a.txt
test_expect_success 'test permission request allowed on file deletion' '
projfs_event_exec rm target/f1a.txt &&
test_path_is_missing target/f1a.txt
'
projfs_event_printf vfs delete_dir d1a
test_expect_success 'test permission request allowed on directory deletion' '
projfs_event_exec rmdir target/d1 &&
test_path_is_missing target/d1
projfs_event_exec rmdir target/d1a &&
test_path_is_missing target/d1a
'
rm retval

Просмотреть файл

@ -23,26 +23,32 @@ event_msg_perm="test permission request for"
event_msg_vfs="TestNotifyOperation for"
event_create_dir="0x0001-40000000"
event_delete_dir="0x0000-40000400"
event_rename_dir="0x0000-40000800"
event_create_dir="0x0001-40000000"
event_delete_file="0x0000-00000400"
event_rename_file="0x0000-00000800"
event_create_file="0x0001-00000000"
event_vfs_create_dir="1, 0x00000004"
event_vfs_delete_dir="1, 0x00000010"
event_vfs_rename_dir="1, 0x00000080"
event_vfs_create_file="0, 0x00000004"
event_vfs_delete_file="0, 0x00000010"
event_vfs_rename_file="0, 0x00000080"
# Format into "$event_msg" and "$event_err_msg" log and error messages
# matching those output by the test mount helper programs. If an error
# is expected, "$1" should be "error" and "$2" should contain the errno
# name, e.g., "ENOMEM". The next three arguments (starting at either
# Format into "$event_msg_head", "$event_msg_tail", and "$event_err_msg"
# log and error messages matching those output by the test mount helper
# programs.
# If an error is expected, "$1" should be "error" and "$2" should contain
# the errno name, e.g., "ENOMEM". The next arguments (starting at either
# "$3" or "$1", depending on whether an error is expected or not) should be
# the category of event (e.g., "notify" or "perm"), and the type of event
# (e.g., "create_dir" or "delete_file"), and the file path
# the category of event (e.g., "notify" or "perm"), the type of event
# (e.g., "create_dir" or "delete_file"), the file path
# (relative to the projfs mount point) on which the event is expected,
# and optionally the target file path of the event if one is expected.
projfs_event_printf () {
if test ":$1" = ":error"
then
@ -59,10 +65,20 @@ projfs_event_printf () {
if test ":$1" = ":vfs"
then
eval vfs_code=\$event_vfs_"$2"
event_msg_head=" $msg $3: "
event_msg_head=" $msg $3"
if test ":$4" != ":"
then
event_msg_head="$event_msg_head, $4"
fi
event_msg_head="$event_msg_head: "
event_msg_tail=", $vfs_code"
else
event_msg_head=" $msg $3: $code, "
event_msg_head=" $msg $3"
if test ":$4" != ":"
then
event_msg_head="$event_msg_head, $4"
fi
event_msg_head="$event_msg_head: $code, "
event_msg_tail=""
fi

Просмотреть файл

@ -38,9 +38,12 @@ static int test_handle_event(struct projfs_event *event, const char *desc,
if ((opt_flags & TEST_OPT_RETFILE) == TEST_OPT_NONE ||
(ret_flags & TEST_FILE_EXIST) != TEST_FILE_NONE) {
printf(" test %s for %s: "
printf(" test %s for %s%s%s: "
"0x%04" PRIx64 "-%08" PRIx64 ", %d\n",
desc, event->path,
((event->target_path == NULL) ? "" : ", "),
((event->target_path == NULL) ? ""
: event->target_path),
event->mask >> 32, event->mask & 0xFFFFFFFF,
event->pid);
}

Просмотреть файл

@ -28,6 +28,7 @@
#include "test_common.h"
static int test_handle_event(const char *desc, const char *path,
const char *target_path,
int pid, const char *procname,
int isdir, int type, int proj)
{
@ -41,8 +42,11 @@ static int test_handle_event(const char *desc, const char *path,
if ((opt_flags & TEST_OPT_RETFILE) == TEST_OPT_NONE ||
(ret_flags & TEST_FILE_EXIST) != TEST_FILE_NONE) {
printf(" Test%s for %s: %d, %s, %hhd, 0x%08X\n",
desc, path, pid, procname, isdir, type);
printf(" Test%s for %s%s%s: %d, %s, %hhd, 0x%08X\n",
desc, path,
((target_path == NULL) ? "" : ", "),
((target_path == NULL) ? "" : target_path),
pid, procname, isdir, type);
}
if (proj) {
@ -67,7 +71,7 @@ static PrjFS_Result TestEnumerateDirectory(
{
(void)commandId; // prevent compiler warnings
return test_handle_event("EnumerateDirectory", relativePath,
return test_handle_event("EnumerateDirectory", relativePath, NULL,
triggeringProcessId, triggeringProcessName,
1, 0, 1);
}
@ -87,9 +91,9 @@ static PrjFS_Result TestNotifyOperation(
(void)commandId; // prevent compiler warnings
(void)providerId;
(void)contentId;
(void)destinationRelativePath;
return test_handle_event("NotifyOperation", relativePath,
destinationRelativePath,
triggeringProcessId, triggeringProcessName,
isDirectory, notificationType, 0);
}