1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2020 CTERA Networks. All Rights Reserved. 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * Started by Amir Goldstein <amir73il@gmail.com> 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/*\ 9f08c3bdfSopenharmony_ci * [Description] 10f08c3bdfSopenharmony_ci * Check fanotify directory entry modification events, events on child and 11f08c3bdfSopenharmony_ci * on self with group init flags: 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * - FAN_REPORT_DFID_NAME (dir fid + name) 14f08c3bdfSopenharmony_ci * - FAN_REPORT_DIR_FID (dir fid) 15f08c3bdfSopenharmony_ci * - FAN_REPORT_DIR_FID | FAN_REPORT_FID (dir fid + child fid) 16f08c3bdfSopenharmony_ci * - FAN_REPORT_DFID_NAME | FAN_REPORT_FID (dir fid + name + child fid) 17f08c3bdfSopenharmony_ci * - FAN_REPORT_DFID_NAME_TARGET (dir fid + name + created/deleted file fid) 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci#define _GNU_SOURCE 21f08c3bdfSopenharmony_ci#include "config.h" 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_ci#include <stdio.h> 24f08c3bdfSopenharmony_ci#include <sys/stat.h> 25f08c3bdfSopenharmony_ci#include <sys/types.h> 26f08c3bdfSopenharmony_ci#include <errno.h> 27f08c3bdfSopenharmony_ci#include <string.h> 28f08c3bdfSopenharmony_ci#include <sys/mount.h> 29f08c3bdfSopenharmony_ci#include <sys/syscall.h> 30f08c3bdfSopenharmony_ci#include "tst_test.h" 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#ifdef HAVE_SYS_FANOTIFY_H 33f08c3bdfSopenharmony_ci#include "fanotify.h" 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci#define EVENT_MAX 20 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_ci/* Size of the event structure, not including file handle */ 38f08c3bdfSopenharmony_ci#define EVENT_SIZE (sizeof(struct fanotify_event_metadata) + \ 39f08c3bdfSopenharmony_ci sizeof(struct fanotify_event_info_fid)) 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci/* Tripple events buffer size to account for file handles and names */ 42f08c3bdfSopenharmony_ci#define EVENT_BUF_LEN (EVENT_MAX * EVENT_SIZE * 3) 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci#define BUF_SIZE 256 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_ci#ifdef HAVE_NAME_TO_HANDLE_AT 47f08c3bdfSopenharmony_cistruct event_t { 48f08c3bdfSopenharmony_ci unsigned long long mask; 49f08c3bdfSopenharmony_ci struct fanotify_fid_t *fid; 50f08c3bdfSopenharmony_ci struct fanotify_fid_t *child_fid; 51f08c3bdfSopenharmony_ci char name[BUF_SIZE]; 52f08c3bdfSopenharmony_ci char name2[BUF_SIZE]; 53f08c3bdfSopenharmony_ci char *old_name; 54f08c3bdfSopenharmony_ci char *new_name; 55f08c3bdfSopenharmony_ci}; 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cistatic char fname1[BUF_SIZE + 11], fname2[BUF_SIZE + 11]; 58f08c3bdfSopenharmony_cistatic char dname1[BUF_SIZE], dname2[BUF_SIZE], tmpdir[BUF_SIZE]; 59f08c3bdfSopenharmony_cistatic int fd_notify; 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_cistatic struct event_t event_set[EVENT_MAX]; 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_cistatic char event_buf[EVENT_BUF_LEN]; 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci#define DIR_NAME1 "test_dir1" 66f08c3bdfSopenharmony_ci#define DIR_NAME2 "test_dir2" 67f08c3bdfSopenharmony_ci#define FILE_NAME1 "test_file1" 68f08c3bdfSopenharmony_ci#define FILE_NAME2 "test_file2" 69f08c3bdfSopenharmony_ci#define MOUNT_PATH "fs_mnt" 70f08c3bdfSopenharmony_ci#define TEMP_DIR MOUNT_PATH "/temp_dir" 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_cistatic int fan_report_target_fid_unsupported; 73f08c3bdfSopenharmony_cistatic int rename_events_unsupported; 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_cistatic struct test_case_t { 76f08c3bdfSopenharmony_ci const char *tname; 77f08c3bdfSopenharmony_ci struct fanotify_group_type group; 78f08c3bdfSopenharmony_ci struct fanotify_mark_type mark; 79f08c3bdfSopenharmony_ci unsigned long mask; 80f08c3bdfSopenharmony_ci struct fanotify_mark_type sub_mark; 81f08c3bdfSopenharmony_ci unsigned long sub_mask; 82f08c3bdfSopenharmony_ci unsigned long tmpdir_ignored_mask; 83f08c3bdfSopenharmony_ci} test_cases[] = { 84f08c3bdfSopenharmony_ci { 85f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME monitor filesystem for create/delete/move/open/close", 86f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME), 87f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), 88f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR, 89f08c3bdfSopenharmony_ci /* Mount watch for events possible on children */ 90f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(MOUNT), 91f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_ONDIR, 92f08c3bdfSopenharmony_ci 0, 93f08c3bdfSopenharmony_ci }, 94f08c3bdfSopenharmony_ci { 95f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME monitor directories for create/delete/move/open/close", 96f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME), 97f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 98f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_ONDIR, 99f08c3bdfSopenharmony_ci /* Watches for self events on subdir and events on subdir's children */ 100f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 101f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR | 102f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_EVENT_ON_CHILD, 103f08c3bdfSopenharmony_ci 0, 104f08c3bdfSopenharmony_ci }, 105f08c3bdfSopenharmony_ci { 106f08c3bdfSopenharmony_ci "FAN_REPORT_DIR_FID monitor filesystem for create/delete/move/open/close", 107f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DIR_FID), 108f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), 109f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR, 110f08c3bdfSopenharmony_ci /* Mount watch for events possible on children */ 111f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(MOUNT), 112f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_ONDIR, 113f08c3bdfSopenharmony_ci 0, 114f08c3bdfSopenharmony_ci }, 115f08c3bdfSopenharmony_ci { 116f08c3bdfSopenharmony_ci "FAN_REPORT_DIR_FID monitor directories for create/delete/move/open/close", 117f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DIR_FID), 118f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 119f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_ONDIR, 120f08c3bdfSopenharmony_ci /* Watches for self events on subdir and events on subdir's children */ 121f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 122f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR | 123f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_EVENT_ON_CHILD, 124f08c3bdfSopenharmony_ci 0, 125f08c3bdfSopenharmony_ci }, 126f08c3bdfSopenharmony_ci { 127f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_FID monitor filesystem for create/delete/move/open/close", 128f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_FID), 129f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), 130f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR, 131f08c3bdfSopenharmony_ci /* Mount watch for events possible on children */ 132f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(MOUNT), 133f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_ONDIR, 134f08c3bdfSopenharmony_ci 0, 135f08c3bdfSopenharmony_ci }, 136f08c3bdfSopenharmony_ci { 137f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_FID monitor directories for create/delete/move/open/close", 138f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_FID), 139f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 140f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_ONDIR, 141f08c3bdfSopenharmony_ci /* Watches for self events on subdir and events on subdir's children */ 142f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 143f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR | 144f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_EVENT_ON_CHILD, 145f08c3bdfSopenharmony_ci 0, 146f08c3bdfSopenharmony_ci }, 147f08c3bdfSopenharmony_ci { 148f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME_FID monitor filesystem for create/delete/move/open/close", 149f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME_FID), 150f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), 151f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR, 152f08c3bdfSopenharmony_ci /* Mount watch for events possible on children */ 153f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(MOUNT), 154f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_ONDIR, 155f08c3bdfSopenharmony_ci 0, 156f08c3bdfSopenharmony_ci }, 157f08c3bdfSopenharmony_ci { 158f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME_FID monitor directories for create/delete/move/open/close", 159f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME_FID), 160f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 161f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_ONDIR, 162f08c3bdfSopenharmony_ci /* Watches for self events on subdir and events on subdir's children */ 163f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 164f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR | 165f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_EVENT_ON_CHILD, 166f08c3bdfSopenharmony_ci 0, 167f08c3bdfSopenharmony_ci }, 168f08c3bdfSopenharmony_ci { 169f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME_TARGET monitor filesystem for create/delete/move/open/close", 170f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME_TARGET), 171f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), 172f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR, 173f08c3bdfSopenharmony_ci /* Mount watch for events possible on children */ 174f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(MOUNT), 175f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_ONDIR, 176f08c3bdfSopenharmony_ci 0, 177f08c3bdfSopenharmony_ci }, 178f08c3bdfSopenharmony_ci { 179f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME_TARGET monitor directories for create/delete/move/open/close", 180f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME_TARGET), 181f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 182f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_ONDIR, 183f08c3bdfSopenharmony_ci /* Watches for self events on subdir and events on subdir's children */ 184f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 185f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR | 186f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_EVENT_ON_CHILD, 187f08c3bdfSopenharmony_ci 0, 188f08c3bdfSopenharmony_ci }, 189f08c3bdfSopenharmony_ci { 190f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME_FID monitor filesystem for create/delete/move/rename/open/close", 191f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME_FID), 192f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), 193f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_RENAME | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR, 194f08c3bdfSopenharmony_ci /* Mount watch for events possible on children */ 195f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(MOUNT), 196f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_ONDIR, 197f08c3bdfSopenharmony_ci 0, 198f08c3bdfSopenharmony_ci }, 199f08c3bdfSopenharmony_ci { 200f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME_FID monitor directories for create/delete/move/rename/open/close", 201f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME_FID), 202f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 203f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_RENAME | FAN_ONDIR, 204f08c3bdfSopenharmony_ci /* Watches for self events on subdir and events on subdir's children */ 205f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 206f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_RENAME | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR | 207f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_EVENT_ON_CHILD, 208f08c3bdfSopenharmony_ci 0, 209f08c3bdfSopenharmony_ci }, 210f08c3bdfSopenharmony_ci { 211f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME_TARGET monitor filesystem for create/delete/move/rename/open/close", 212f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME_TARGET), 213f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), 214f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_RENAME | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR, 215f08c3bdfSopenharmony_ci /* Mount watch for events possible on children */ 216f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(MOUNT), 217f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_ONDIR, 218f08c3bdfSopenharmony_ci 0, 219f08c3bdfSopenharmony_ci }, 220f08c3bdfSopenharmony_ci { 221f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME_TARGET monitor directories for create/delete/move/rename/open/close", 222f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME_TARGET), 223f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 224f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_RENAME | FAN_ONDIR, 225f08c3bdfSopenharmony_ci /* Watches for self events on subdir and events on subdir's children */ 226f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 227f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_RENAME | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR | 228f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_EVENT_ON_CHILD, 229f08c3bdfSopenharmony_ci 0, 230f08c3bdfSopenharmony_ci }, 231f08c3bdfSopenharmony_ci { 232f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME_FID monitor directories and ignore FAN_RENAME events to/from temp directory", 233f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME_FID), 234f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 235f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_RENAME | FAN_ONDIR, 236f08c3bdfSopenharmony_ci /* Watches for self events on subdir and events on subdir's children */ 237f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(INODE), 238f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_RENAME | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR | 239f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_EVENT_ON_CHILD, 240f08c3bdfSopenharmony_ci /* Ignore FAN_RENAME to/from tmpdir */ 241f08c3bdfSopenharmony_ci FAN_MOVE | FAN_RENAME, 242f08c3bdfSopenharmony_ci }, 243f08c3bdfSopenharmony_ci { 244f08c3bdfSopenharmony_ci "FAN_REPORT_DFID_NAME_FID monitor filesystem and ignore FAN_RENAME events to/from temp directory", 245f08c3bdfSopenharmony_ci INIT_FANOTIFY_GROUP_TYPE(REPORT_DFID_NAME_FID), 246f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(FILESYSTEM), 247f08c3bdfSopenharmony_ci FAN_CREATE | FAN_DELETE | FAN_MOVE | FAN_RENAME | FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR, 248f08c3bdfSopenharmony_ci /* Mount watch for events possible on children */ 249f08c3bdfSopenharmony_ci INIT_FANOTIFY_MARK_TYPE(MOUNT), 250f08c3bdfSopenharmony_ci FAN_OPEN | FAN_CLOSE | FAN_ONDIR, 251f08c3bdfSopenharmony_ci /* Ignore FAN_RENAME to/from tmpdir */ 252f08c3bdfSopenharmony_ci FAN_MOVE | FAN_RENAME, 253f08c3bdfSopenharmony_ci }, 254f08c3bdfSopenharmony_ci}; 255f08c3bdfSopenharmony_ci 256f08c3bdfSopenharmony_cistatic void do_test(unsigned int number) 257f08c3bdfSopenharmony_ci{ 258f08c3bdfSopenharmony_ci int fd, dirfd, len = 0, i = 0, test_num = 0, tst_count = 0; 259f08c3bdfSopenharmony_ci struct test_case_t *tc = &test_cases[number]; 260f08c3bdfSopenharmony_ci struct fanotify_group_type *group = &tc->group; 261f08c3bdfSopenharmony_ci struct fanotify_mark_type *mark = &tc->mark; 262f08c3bdfSopenharmony_ci struct fanotify_mark_type *sub_mark = &tc->sub_mark; 263f08c3bdfSopenharmony_ci struct fanotify_fid_t root_fid, dir_fid, file_fid; 264f08c3bdfSopenharmony_ci struct fanotify_fid_t *child_fid = NULL, *subdir_fid = NULL; 265f08c3bdfSopenharmony_ci int report_name = (group->flag & FAN_REPORT_NAME); 266f08c3bdfSopenharmony_ci int report_target_fid = (group->flag & FAN_REPORT_TARGET_FID); 267f08c3bdfSopenharmony_ci int report_rename = (tc->mask & FAN_RENAME); 268f08c3bdfSopenharmony_ci int fs_mark = (mark->flag == FAN_MARK_FILESYSTEM); 269f08c3bdfSopenharmony_ci int rename_ignored = (tc->tmpdir_ignored_mask & FAN_RENAME); 270f08c3bdfSopenharmony_ci 271f08c3bdfSopenharmony_ci tst_res(TINFO, "Test #%d: %s", number, tc->tname); 272f08c3bdfSopenharmony_ci 273f08c3bdfSopenharmony_ci if (report_rename && rename_events_unsupported) { 274f08c3bdfSopenharmony_ci tst_res(TCONF, "FAN_RENAME not supported in kernel?"); 275f08c3bdfSopenharmony_ci return; 276f08c3bdfSopenharmony_ci } 277f08c3bdfSopenharmony_ci 278f08c3bdfSopenharmony_ci if (fan_report_target_fid_unsupported && report_target_fid) { 279f08c3bdfSopenharmony_ci FANOTIFY_INIT_FLAGS_ERR_MSG(FAN_REPORT_TARGET_FID, 280f08c3bdfSopenharmony_ci fan_report_target_fid_unsupported); 281f08c3bdfSopenharmony_ci return; 282f08c3bdfSopenharmony_ci } 283f08c3bdfSopenharmony_ci 284f08c3bdfSopenharmony_ci fd_notify = SAFE_FANOTIFY_INIT(group->flag, 0); 285f08c3bdfSopenharmony_ci 286f08c3bdfSopenharmony_ci /* 287f08c3bdfSopenharmony_ci * Watch dir modify events with name in filesystem/dir 288f08c3bdfSopenharmony_ci */ 289f08c3bdfSopenharmony_ci SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_ADD | mark->flag, tc->mask, 290f08c3bdfSopenharmony_ci AT_FDCWD, MOUNT_PATH); 291f08c3bdfSopenharmony_ci 292f08c3bdfSopenharmony_ci /* Save the mount root fid */ 293f08c3bdfSopenharmony_ci fanotify_save_fid(MOUNT_PATH, &root_fid); 294f08c3bdfSopenharmony_ci 295f08c3bdfSopenharmony_ci /* 296f08c3bdfSopenharmony_ci * Create subdir and watch open events "on children" with name. 297f08c3bdfSopenharmony_ci * Make it a mount root. 298f08c3bdfSopenharmony_ci */ 299f08c3bdfSopenharmony_ci SAFE_MKDIR(dname1, 0755); 300f08c3bdfSopenharmony_ci SAFE_MOUNT(dname1, dname1, "none", MS_BIND, NULL); 301f08c3bdfSopenharmony_ci 302f08c3bdfSopenharmony_ci /* Save the subdir fid */ 303f08c3bdfSopenharmony_ci fanotify_save_fid(dname1, &dir_fid); 304f08c3bdfSopenharmony_ci /* With FAN_REPORT_TARGET_FID, report subdir fid also for dirent events */ 305f08c3bdfSopenharmony_ci if (report_target_fid) 306f08c3bdfSopenharmony_ci subdir_fid = &dir_fid; 307f08c3bdfSopenharmony_ci 308f08c3bdfSopenharmony_ci if (tc->sub_mask) 309f08c3bdfSopenharmony_ci SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_ADD | sub_mark->flag, 310f08c3bdfSopenharmony_ci tc->sub_mask, AT_FDCWD, dname1); 311f08c3bdfSopenharmony_ci /* 312f08c3bdfSopenharmony_ci * ignore FAN_RENAME to/from tmpdir, so we won't get the FAN_RENAME events 313f08c3bdfSopenharmony_ci * when subdir is moved via tmpdir. 314f08c3bdfSopenharmony_ci * FAN_MOVE is also set in ignored mark of tmpdir, but it will have no effect 315f08c3bdfSopenharmony_ci * and the MOVED_FROM/TO events will still be reported. 316f08c3bdfSopenharmony_ci */ 317f08c3bdfSopenharmony_ci if (tc->tmpdir_ignored_mask) 318f08c3bdfSopenharmony_ci SAFE_FANOTIFY_MARK(fd_notify, FAN_MARK_ADD | 319f08c3bdfSopenharmony_ci FAN_MARK_IGNORED_MASK | 320f08c3bdfSopenharmony_ci FAN_MARK_IGNORED_SURV_MODIFY, 321f08c3bdfSopenharmony_ci tc->tmpdir_ignored_mask, AT_FDCWD, TEMP_DIR); 322f08c3bdfSopenharmony_ci 323f08c3bdfSopenharmony_ci memset(event_set, 0, sizeof(event_set)); 324f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_CREATE | FAN_ONDIR; 325f08c3bdfSopenharmony_ci event_set[tst_count].fid = &root_fid; 326f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = subdir_fid; 327f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, DIR_NAME1); 328f08c3bdfSopenharmony_ci tst_count++; 329f08c3bdfSopenharmony_ci 330f08c3bdfSopenharmony_ci /* Generate modify events "on child" */ 331f08c3bdfSopenharmony_ci fd = SAFE_CREAT(fname1, 0755); 332f08c3bdfSopenharmony_ci 333f08c3bdfSopenharmony_ci /* Save the file fid */ 334f08c3bdfSopenharmony_ci fanotify_save_fid(fname1, &file_fid); 335f08c3bdfSopenharmony_ci /* With FAN_REPORT_TARGET_FID, report child fid also for dirent events */ 336f08c3bdfSopenharmony_ci if (report_target_fid) 337f08c3bdfSopenharmony_ci child_fid = &file_fid; 338f08c3bdfSopenharmony_ci 339f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd, "1", 1); 340f08c3bdfSopenharmony_ci SAFE_RENAME(fname1, fname2); 341f08c3bdfSopenharmony_ci 342f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 343f08c3bdfSopenharmony_ci 344f08c3bdfSopenharmony_ci /* Generate delete events with fname2 */ 345f08c3bdfSopenharmony_ci SAFE_UNLINK(fname2); 346f08c3bdfSopenharmony_ci 347f08c3bdfSopenharmony_ci /* Read events on files in subdir */ 348f08c3bdfSopenharmony_ci len += SAFE_READ(0, fd_notify, event_buf + len, EVENT_BUF_LEN - len); 349f08c3bdfSopenharmony_ci 350f08c3bdfSopenharmony_ci /* 351f08c3bdfSopenharmony_ci * FAN_CREATE|FAN_DELETE|FAN_MOVE events with the same name are merged. 352f08c3bdfSopenharmony_ci */ 353f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_CREATE | FAN_MOVED_FROM; 354f08c3bdfSopenharmony_ci event_set[tst_count].fid = &dir_fid; 355f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = child_fid; 356f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, FILE_NAME1); 357f08c3bdfSopenharmony_ci tst_count++; 358f08c3bdfSopenharmony_ci /* 359f08c3bdfSopenharmony_ci * Event on non-dir child with the same name may be merged with the 360f08c3bdfSopenharmony_ci * directory entry modification events above, unless FAN_REPORT_FID is 361f08c3bdfSopenharmony_ci * set and child fid is reported. If FAN_REPORT_FID is set but 362f08c3bdfSopenharmony_ci * FAN_REPORT_NAME is not set, then FAN_CREATE above is merged with 363f08c3bdfSopenharmony_ci * FAN_DELETE below and FAN_OPEN will be merged with FAN_CLOSE. 364f08c3bdfSopenharmony_ci */ 365f08c3bdfSopenharmony_ci if (report_name) { 366f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_OPEN; 367f08c3bdfSopenharmony_ci event_set[tst_count].fid = &dir_fid; 368f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = &file_fid; 369f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, FILE_NAME1); 370f08c3bdfSopenharmony_ci tst_count++; 371f08c3bdfSopenharmony_ci } 372f08c3bdfSopenharmony_ci /* 373f08c3bdfSopenharmony_ci * FAN_RENAME event is independent of MOVED_FROM/MOVED_TO and not merged 374f08c3bdfSopenharmony_ci * with any other event because it has different info records. 375f08c3bdfSopenharmony_ci */ 376f08c3bdfSopenharmony_ci if (report_rename) { 377f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_RENAME; 378f08c3bdfSopenharmony_ci event_set[tst_count].fid = &dir_fid; 379f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = child_fid; 380f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, FILE_NAME1); 381f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name2, FILE_NAME2); 382f08c3bdfSopenharmony_ci event_set[tst_count].old_name = event_set[tst_count].name; 383f08c3bdfSopenharmony_ci event_set[tst_count].new_name = event_set[tst_count].name2; 384f08c3bdfSopenharmony_ci tst_count++; 385f08c3bdfSopenharmony_ci } 386f08c3bdfSopenharmony_ci 387f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_DELETE | FAN_MOVED_TO; 388f08c3bdfSopenharmony_ci /* 389f08c3bdfSopenharmony_ci * With FAN_REPORT_TARGET_FID, close of FILE_NAME2 is merged with 390f08c3bdfSopenharmony_ci * moved_to and delete events, because they all have parent and 391f08c3bdfSopenharmony_ci * child fid records. 392f08c3bdfSopenharmony_ci */ 393f08c3bdfSopenharmony_ci if (report_target_fid) 394f08c3bdfSopenharmony_ci event_set[tst_count].mask |= FAN_CLOSE_WRITE; 395f08c3bdfSopenharmony_ci event_set[tst_count].fid = &dir_fid; 396f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = child_fid; 397f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, FILE_NAME2); 398f08c3bdfSopenharmony_ci tst_count++; 399f08c3bdfSopenharmony_ci /* 400f08c3bdfSopenharmony_ci * When not reporting name, open of FILE_NAME1 is merged 401f08c3bdfSopenharmony_ci * with close of FILE_NAME2. 402f08c3bdfSopenharmony_ci */ 403f08c3bdfSopenharmony_ci if (!report_name) { 404f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_OPEN | FAN_CLOSE_WRITE; 405f08c3bdfSopenharmony_ci event_set[tst_count].fid = &dir_fid; 406f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = &file_fid; 407f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, ""); 408f08c3bdfSopenharmony_ci tst_count++; 409f08c3bdfSopenharmony_ci } 410f08c3bdfSopenharmony_ci /* 411f08c3bdfSopenharmony_ci * Directory watch does not get self events on children. 412f08c3bdfSopenharmony_ci * Filesystem watch gets self event w/o name info if FAN_REPORT_FID 413f08c3bdfSopenharmony_ci * is set. 414f08c3bdfSopenharmony_ci */ 415f08c3bdfSopenharmony_ci if (fs_mark && (group->flag & FAN_REPORT_FID)) { 416f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_DELETE_SELF | FAN_MOVE_SELF; 417f08c3bdfSopenharmony_ci event_set[tst_count].fid = &file_fid; 418f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = NULL; 419f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, ""); 420f08c3bdfSopenharmony_ci tst_count++; 421f08c3bdfSopenharmony_ci } 422f08c3bdfSopenharmony_ci /* 423f08c3bdfSopenharmony_ci * Without FAN_REPORT_TARGET_FID, close of FILE_NAME2 is not merged with 424f08c3bdfSopenharmony_ci * open of FILE_NAME1 and it is received after the merged self events. 425f08c3bdfSopenharmony_ci */ 426f08c3bdfSopenharmony_ci if (report_name && !report_target_fid) { 427f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_CLOSE_WRITE; 428f08c3bdfSopenharmony_ci event_set[tst_count].fid = &dir_fid; 429f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = &file_fid; 430f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, FILE_NAME2); 431f08c3bdfSopenharmony_ci tst_count++; 432f08c3bdfSopenharmony_ci } 433f08c3bdfSopenharmony_ci 434f08c3bdfSopenharmony_ci dirfd = SAFE_OPEN(dname1, O_RDONLY | O_DIRECTORY); 435f08c3bdfSopenharmony_ci SAFE_CLOSE(dirfd); 436f08c3bdfSopenharmony_ci 437f08c3bdfSopenharmony_ci SAFE_UMOUNT(dname1); 438f08c3bdfSopenharmony_ci 439f08c3bdfSopenharmony_ci /* 440f08c3bdfSopenharmony_ci * Directory watch gets open/close events on itself and on its subdirs. 441f08c3bdfSopenharmony_ci * Filesystem watch gets open/close event on all directories with name ".". 442f08c3bdfSopenharmony_ci */ 443f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_OPEN | FAN_CLOSE_NOWRITE | FAN_ONDIR; 444f08c3bdfSopenharmony_ci event_set[tst_count].fid = &dir_fid; 445f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = NULL; 446f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, "."); 447f08c3bdfSopenharmony_ci tst_count++; 448f08c3bdfSopenharmony_ci /* 449f08c3bdfSopenharmony_ci * Directory watch gets self event on itself and filesystem watch gets 450f08c3bdfSopenharmony_ci * self event on all directories with name ".". 451f08c3bdfSopenharmony_ci */ 452f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_DELETE_SELF | FAN_MOVE_SELF | FAN_ONDIR; 453f08c3bdfSopenharmony_ci event_set[tst_count].fid = &dir_fid; 454f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = NULL; 455f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, "."); 456f08c3bdfSopenharmony_ci tst_count++; 457f08c3bdfSopenharmony_ci 458f08c3bdfSopenharmony_ci /* 459f08c3bdfSopenharmony_ci * If only root dir and subdir are watched, a rename via an unwatched tmpdir 460f08c3bdfSopenharmony_ci * will observe the same MOVED_FROM/MOVED_TO events as a direct rename, 461f08c3bdfSopenharmony_ci * but will observe 2 FAN_RENAME events with 1 info dir+name record each 462f08c3bdfSopenharmony_ci * instead of 1 FAN_RENAME event with 2 dir+name info records. 463f08c3bdfSopenharmony_ci * 464f08c3bdfSopenharmony_ci * If tmpdir is ignoring FAN_RENAME, we will get the MOVED_FROM/MOVED_TO 465f08c3bdfSopenharmony_ci * events and will not get the FAN_RENAME event for rename via tmpdir. 466f08c3bdfSopenharmony_ci */ 467f08c3bdfSopenharmony_ci if (!fs_mark || rename_ignored) { 468f08c3bdfSopenharmony_ci SAFE_RENAME(dname1, tmpdir); 469f08c3bdfSopenharmony_ci SAFE_RENAME(tmpdir, dname2); 470f08c3bdfSopenharmony_ci } else { 471f08c3bdfSopenharmony_ci SAFE_RENAME(dname1, dname2); 472f08c3bdfSopenharmony_ci } 473f08c3bdfSopenharmony_ci SAFE_RMDIR(dname2); 474f08c3bdfSopenharmony_ci 475f08c3bdfSopenharmony_ci /* Read more events on dirs */ 476f08c3bdfSopenharmony_ci len += SAFE_READ(0, fd_notify, event_buf + len, EVENT_BUF_LEN - len); 477f08c3bdfSopenharmony_ci 478f08c3bdfSopenharmony_ci /* 479f08c3bdfSopenharmony_ci * FAN_RENAME event is independent of MOVED_FROM/MOVED_TO and not merged 480f08c3bdfSopenharmony_ci * with any other event because it has different info records. 481f08c3bdfSopenharmony_ci * When renamed via an unwatched tmpdir, the 1st FAN_RENAME event has the 482f08c3bdfSopenharmony_ci * info record of root_fid+DIR_NAME1 and the 2nd FAN_RENAME event has the 483f08c3bdfSopenharmony_ci * info record of root_fid+DIR_NAME2. 484f08c3bdfSopenharmony_ci * If tmpdir is ignoring FAN_RENAME, we get no FAN_RENAME events at all. 485f08c3bdfSopenharmony_ci */ 486f08c3bdfSopenharmony_ci if (report_rename && !rename_ignored) { 487f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_RENAME | FAN_ONDIR; 488f08c3bdfSopenharmony_ci event_set[tst_count].fid = &root_fid; 489f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = subdir_fid; 490f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, DIR_NAME1); 491f08c3bdfSopenharmony_ci event_set[tst_count].old_name = event_set[tst_count].name; 492f08c3bdfSopenharmony_ci if (fs_mark) { 493f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name2, DIR_NAME2); 494f08c3bdfSopenharmony_ci event_set[tst_count].new_name = event_set[tst_count].name2; 495f08c3bdfSopenharmony_ci } 496f08c3bdfSopenharmony_ci tst_count++; 497f08c3bdfSopenharmony_ci } 498f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_MOVED_FROM | FAN_ONDIR; 499f08c3bdfSopenharmony_ci event_set[tst_count].fid = &root_fid; 500f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = subdir_fid; 501f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, DIR_NAME1); 502f08c3bdfSopenharmony_ci tst_count++; 503f08c3bdfSopenharmony_ci if (report_rename && !fs_mark && !rename_ignored) { 504f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_RENAME | FAN_ONDIR; 505f08c3bdfSopenharmony_ci event_set[tst_count].fid = &root_fid; 506f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = subdir_fid; 507f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, DIR_NAME2); 508f08c3bdfSopenharmony_ci event_set[tst_count].new_name = event_set[tst_count].name; 509f08c3bdfSopenharmony_ci tst_count++; 510f08c3bdfSopenharmony_ci } 511f08c3bdfSopenharmony_ci event_set[tst_count].mask = FAN_DELETE | FAN_MOVED_TO | FAN_ONDIR; 512f08c3bdfSopenharmony_ci event_set[tst_count].fid = &root_fid; 513f08c3bdfSopenharmony_ci event_set[tst_count].child_fid = subdir_fid; 514f08c3bdfSopenharmony_ci strcpy(event_set[tst_count].name, DIR_NAME2); 515f08c3bdfSopenharmony_ci tst_count++; 516f08c3bdfSopenharmony_ci /* Expect no more events */ 517f08c3bdfSopenharmony_ci event_set[tst_count].mask = 0; 518f08c3bdfSopenharmony_ci 519f08c3bdfSopenharmony_ci /* 520f08c3bdfSopenharmony_ci * Cleanup the marks 521f08c3bdfSopenharmony_ci */ 522f08c3bdfSopenharmony_ci SAFE_CLOSE(fd_notify); 523f08c3bdfSopenharmony_ci fd_notify = -1; 524f08c3bdfSopenharmony_ci 525f08c3bdfSopenharmony_ci while (i < len) { 526f08c3bdfSopenharmony_ci struct event_t *expected = &event_set[test_num]; 527f08c3bdfSopenharmony_ci struct fanotify_event_metadata *event; 528f08c3bdfSopenharmony_ci struct fanotify_event_info_fid *event_fid; 529f08c3bdfSopenharmony_ci struct fanotify_event_info_fid *child_fid; 530f08c3bdfSopenharmony_ci struct fanotify_fid_t *expected_fid = expected->fid; 531f08c3bdfSopenharmony_ci struct fanotify_fid_t *expected_child_fid = expected->child_fid; 532f08c3bdfSopenharmony_ci struct file_handle *file_handle; 533f08c3bdfSopenharmony_ci unsigned int fhlen; 534f08c3bdfSopenharmony_ci const char *filename; 535f08c3bdfSopenharmony_ci int namelen, info_type, mask_match, info_id = 0; 536f08c3bdfSopenharmony_ci 537f08c3bdfSopenharmony_ci event = (struct fanotify_event_metadata *)&event_buf[i]; 538f08c3bdfSopenharmony_ci event_fid = (struct fanotify_event_info_fid *)(event + 1); 539f08c3bdfSopenharmony_ci file_handle = (struct file_handle *)event_fid->handle; 540f08c3bdfSopenharmony_ci fhlen = file_handle->handle_bytes; 541f08c3bdfSopenharmony_ci filename = (char *)file_handle->f_handle + fhlen; 542f08c3bdfSopenharmony_ci child_fid = (void *)((char *)event_fid + event_fid->hdr.len); 543f08c3bdfSopenharmony_ci namelen = (char *)child_fid - (char *)filename; 544f08c3bdfSopenharmony_ci /* End of event_fid could have name, zero padding, both or none */ 545f08c3bdfSopenharmony_ci if (namelen > 0) { 546f08c3bdfSopenharmony_ci namelen = strlen(filename); 547f08c3bdfSopenharmony_ci } else { 548f08c3bdfSopenharmony_ci filename = ""; 549f08c3bdfSopenharmony_ci namelen = 0; 550f08c3bdfSopenharmony_ci } 551f08c3bdfSopenharmony_ci /* Is there a child fid after first fid record? */ 552f08c3bdfSopenharmony_ci if (((char *)child_fid - (char *)event) >= event->event_len) 553f08c3bdfSopenharmony_ci child_fid = NULL; 554f08c3bdfSopenharmony_ci 555f08c3bdfSopenharmony_ci if (!(group->flag & FAN_REPORT_FID)) 556f08c3bdfSopenharmony_ci expected_child_fid = NULL; 557f08c3bdfSopenharmony_ci 558f08c3bdfSopenharmony_ci if (!report_name) 559f08c3bdfSopenharmony_ci expected->name[0] = 0; 560f08c3bdfSopenharmony_ci 561f08c3bdfSopenharmony_ci if (expected->mask & FAN_RENAME) { 562f08c3bdfSopenharmony_ci /* If old name is not reported, first record is new name */ 563f08c3bdfSopenharmony_ci info_type = expected->old_name ? 564f08c3bdfSopenharmony_ci FAN_EVENT_INFO_TYPE_OLD_DFID_NAME : 565f08c3bdfSopenharmony_ci FAN_EVENT_INFO_TYPE_NEW_DFID_NAME; 566f08c3bdfSopenharmony_ci /* The 2nd fid is same as 1st becaue we rename in same parent */ 567f08c3bdfSopenharmony_ci if (expected->name2[0]) 568f08c3bdfSopenharmony_ci expected_child_fid = expected_fid; 569f08c3bdfSopenharmony_ci } else if (expected->name[0]) { 570f08c3bdfSopenharmony_ci info_type = FAN_EVENT_INFO_TYPE_DFID_NAME; 571f08c3bdfSopenharmony_ci } else if (expected->mask & FAN_ONDIR) { 572f08c3bdfSopenharmony_ci info_type = FAN_EVENT_INFO_TYPE_DFID; 573f08c3bdfSopenharmony_ci } else if (expected->mask & (FAN_DELETE_SELF | FAN_MOVE_SELF)) { 574f08c3bdfSopenharmony_ci /* Self event on non-dir has only child fid */ 575f08c3bdfSopenharmony_ci info_type = FAN_EVENT_INFO_TYPE_FID; 576f08c3bdfSopenharmony_ci } else { 577f08c3bdfSopenharmony_ci info_type = FAN_EVENT_INFO_TYPE_DFID; 578f08c3bdfSopenharmony_ci } 579f08c3bdfSopenharmony_ci 580f08c3bdfSopenharmony_ci /* 581f08c3bdfSopenharmony_ci * Event may contain more than the expected mask, but it must 582f08c3bdfSopenharmony_ci * have all the bits in expected mask. 583f08c3bdfSopenharmony_ci * Expected event on dir must not get event on non dir and the 584f08c3bdfSopenharmony_ci * other way around. 585f08c3bdfSopenharmony_ci */ 586f08c3bdfSopenharmony_ci mask_match = ((event->mask & expected->mask) && 587f08c3bdfSopenharmony_ci !(expected->mask & ~event->mask) && 588f08c3bdfSopenharmony_ci !((event->mask ^ expected->mask) & FAN_ONDIR)); 589f08c3bdfSopenharmony_ci 590f08c3bdfSopenharmony_cicheck_match: 591f08c3bdfSopenharmony_ci if (test_num >= tst_count) { 592f08c3bdfSopenharmony_ci tst_res(TFAIL, 593f08c3bdfSopenharmony_ci "got unnecessary event: mask=%llx " 594f08c3bdfSopenharmony_ci "pid=%u fd=%d name='%s' " 595f08c3bdfSopenharmony_ci "len=%d info_type=%d info_len=%d fh_len=%d", 596f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 597f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, filename, 598f08c3bdfSopenharmony_ci event->event_len, event_fid->hdr.info_type, 599f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen); 600f08c3bdfSopenharmony_ci } else if (!fhlen || namelen < 0) { 601f08c3bdfSopenharmony_ci tst_res(TFAIL, 602f08c3bdfSopenharmony_ci "got event without fid: mask=%llx pid=%u fd=%d, " 603f08c3bdfSopenharmony_ci "len=%d info_type=%d info_len=%d fh_len=%d", 604f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 605f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, 606f08c3bdfSopenharmony_ci event->event_len, event_fid->hdr.info_type, 607f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen); 608f08c3bdfSopenharmony_ci } else if (!mask_match) { 609f08c3bdfSopenharmony_ci tst_res(TFAIL, 610f08c3bdfSopenharmony_ci "got event: mask=%llx (expected %llx) " 611f08c3bdfSopenharmony_ci "pid=%u fd=%d name='%s' " 612f08c3bdfSopenharmony_ci "len=%d info_type=%d info_len=%d fh_len=%d", 613f08c3bdfSopenharmony_ci (unsigned long long)event->mask, expected->mask, 614f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, filename, 615f08c3bdfSopenharmony_ci event->event_len, event_fid->hdr.info_type, 616f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen); 617f08c3bdfSopenharmony_ci } else if (info_type != event_fid->hdr.info_type) { 618f08c3bdfSopenharmony_ci tst_res(TFAIL, 619f08c3bdfSopenharmony_ci "got event: mask=%llx pid=%u fd=%d, " 620f08c3bdfSopenharmony_ci "len=%d info_type=%d expected(%d) info_len=%d fh_len=%d", 621f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 622f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, 623f08c3bdfSopenharmony_ci event->event_len, event_fid->hdr.info_type, 624f08c3bdfSopenharmony_ci info_type, event_fid->hdr.len, fhlen); 625f08c3bdfSopenharmony_ci } else if (fhlen != expected_fid->handle.handle_bytes) { 626f08c3bdfSopenharmony_ci tst_res(TFAIL, 627f08c3bdfSopenharmony_ci "got event: mask=%llx pid=%u fd=%d name='%s' " 628f08c3bdfSopenharmony_ci "len=%d info_type=%d info_len=%d fh_len=%d expected(%d) " 629f08c3bdfSopenharmony_ci "fh_type=%d", 630f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 631f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, filename, 632f08c3bdfSopenharmony_ci event->event_len, info_type, 633f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen, 634f08c3bdfSopenharmony_ci expected_fid->handle.handle_bytes, 635f08c3bdfSopenharmony_ci file_handle->handle_type); 636f08c3bdfSopenharmony_ci } else if (file_handle->handle_type != 637f08c3bdfSopenharmony_ci expected_fid->handle.handle_type) { 638f08c3bdfSopenharmony_ci tst_res(TFAIL, 639f08c3bdfSopenharmony_ci "got event: mask=%llx pid=%u fd=%d name='%s' " 640f08c3bdfSopenharmony_ci "len=%d info_type=%d info_len=%d fh_len=%d " 641f08c3bdfSopenharmony_ci "fh_type=%d expected(%x)", 642f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 643f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, filename, 644f08c3bdfSopenharmony_ci event->event_len, info_type, 645f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen, 646f08c3bdfSopenharmony_ci file_handle->handle_type, 647f08c3bdfSopenharmony_ci expected_fid->handle.handle_type); 648f08c3bdfSopenharmony_ci } else if (memcmp(file_handle->f_handle, 649f08c3bdfSopenharmony_ci expected_fid->handle.f_handle, fhlen)) { 650f08c3bdfSopenharmony_ci tst_res(TFAIL, 651f08c3bdfSopenharmony_ci "got event: mask=%llx pid=%u fd=%d name='%s' " 652f08c3bdfSopenharmony_ci "len=%d info_type=%d info_len=%d fh_len=%d " 653f08c3bdfSopenharmony_ci "fh_type=%d unexpected file handle (%x...)", 654f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 655f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, filename, 656f08c3bdfSopenharmony_ci event->event_len, info_type, 657f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen, 658f08c3bdfSopenharmony_ci file_handle->handle_type, 659f08c3bdfSopenharmony_ci *(int *)(file_handle->f_handle)); 660f08c3bdfSopenharmony_ci } else if (memcmp(&event_fid->fsid, &expected_fid->fsid, 661f08c3bdfSopenharmony_ci sizeof(event_fid->fsid)) != 0) { 662f08c3bdfSopenharmony_ci tst_res(TFAIL, 663f08c3bdfSopenharmony_ci "got event: mask=%llx pid=%u fd=%d name='%s' " 664f08c3bdfSopenharmony_ci "len=%d info_type=%d info_len=%d fh_len=%d " 665f08c3bdfSopenharmony_ci "fsid=%x.%x (expected %x.%x)", 666f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 667f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, filename, 668f08c3bdfSopenharmony_ci event->event_len, info_type, 669f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen, 670f08c3bdfSopenharmony_ci FSID_VAL_MEMBER(event_fid->fsid, 0), 671f08c3bdfSopenharmony_ci FSID_VAL_MEMBER(event_fid->fsid, 1), 672f08c3bdfSopenharmony_ci expected_fid->fsid.val[0], 673f08c3bdfSopenharmony_ci expected_fid->fsid.val[1]); 674f08c3bdfSopenharmony_ci } else if (strcmp(expected->name, filename)) { 675f08c3bdfSopenharmony_ci tst_res(TFAIL, 676f08c3bdfSopenharmony_ci "got event: mask=%llx " 677f08c3bdfSopenharmony_ci "pid=%u fd=%d name='%s' expected('%s') " 678f08c3bdfSopenharmony_ci "len=%d info_type=%d info_len=%d fh_len=%d", 679f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 680f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, 681f08c3bdfSopenharmony_ci filename, expected->name, 682f08c3bdfSopenharmony_ci event->event_len, event_fid->hdr.info_type, 683f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen); 684f08c3bdfSopenharmony_ci } else if (event->pid != getpid()) { 685f08c3bdfSopenharmony_ci tst_res(TFAIL, 686f08c3bdfSopenharmony_ci "got event: mask=%llx pid=%u " 687f08c3bdfSopenharmony_ci "(expected %u) fd=%d name='%s' " 688f08c3bdfSopenharmony_ci "len=%d info_type=%d info_len=%d fh_len=%d", 689f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 690f08c3bdfSopenharmony_ci (unsigned int)event->pid, 691f08c3bdfSopenharmony_ci (unsigned int)getpid(), 692f08c3bdfSopenharmony_ci event->fd, filename, 693f08c3bdfSopenharmony_ci event->event_len, event_fid->hdr.info_type, 694f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen); 695f08c3bdfSopenharmony_ci } else if (!!child_fid != !!expected_child_fid) { 696f08c3bdfSopenharmony_ci tst_res(TFAIL, 697f08c3bdfSopenharmony_ci "got event: mask=%llx " 698f08c3bdfSopenharmony_ci "pid=%u fd=%d name='%s' num_info=%d (expected %d) " 699f08c3bdfSopenharmony_ci "len=%d info_type=%d info_len=%d fh_len=%d", 700f08c3bdfSopenharmony_ci (unsigned long long)event->mask, 701f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, 702f08c3bdfSopenharmony_ci filename, 1 + !!child_fid, 1 + !!expected_child_fid, 703f08c3bdfSopenharmony_ci event->event_len, event_fid->hdr.info_type, 704f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen); 705f08c3bdfSopenharmony_ci } else if (child_fid) { 706f08c3bdfSopenharmony_ci tst_res(TINFO, 707f08c3bdfSopenharmony_ci "got event #%d: info #%d: info_type=%d info_len=%d fh_len=%d", 708f08c3bdfSopenharmony_ci test_num, info_id, event_fid->hdr.info_type, 709f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen); 710f08c3bdfSopenharmony_ci 711f08c3bdfSopenharmony_ci /* Recheck event_fid match with child_fid */ 712f08c3bdfSopenharmony_ci event_fid = child_fid; 713f08c3bdfSopenharmony_ci expected_fid = expected->child_fid; 714f08c3bdfSopenharmony_ci info_id = 1; 715f08c3bdfSopenharmony_ci info_type = FAN_EVENT_INFO_TYPE_FID; 716f08c3bdfSopenharmony_ci /* 717f08c3bdfSopenharmony_ci * With FAN_RENAME event, expect a second record of 718f08c3bdfSopenharmony_ci * type NEW_DFID_NAME, which in our case 719f08c3bdfSopenharmony_ci * has the same fid as the source dir in 1st record. 720f08c3bdfSopenharmony_ci * TODO: check the 2nd name and the 3rd child fid record. 721f08c3bdfSopenharmony_ci */ 722f08c3bdfSopenharmony_ci if (event->mask & FAN_RENAME && expected->name2[0]) { 723f08c3bdfSopenharmony_ci info_type = FAN_EVENT_INFO_TYPE_NEW_DFID_NAME; 724f08c3bdfSopenharmony_ci expected_fid = expected->fid; 725f08c3bdfSopenharmony_ci } 726f08c3bdfSopenharmony_ci file_handle = (struct file_handle *)event_fid->handle; 727f08c3bdfSopenharmony_ci fhlen = file_handle->handle_bytes; 728f08c3bdfSopenharmony_ci child_fid = NULL; 729f08c3bdfSopenharmony_ci expected_child_fid = NULL; 730f08c3bdfSopenharmony_ci goto check_match; 731f08c3bdfSopenharmony_ci } else { 732f08c3bdfSopenharmony_ci tst_res(TPASS, 733f08c3bdfSopenharmony_ci "got event #%d: mask=%llx pid=%u fd=%d name='%s' " 734f08c3bdfSopenharmony_ci "len=%d; info #%d: info_type=%d info_len=%d fh_len=%d", 735f08c3bdfSopenharmony_ci test_num, (unsigned long long)event->mask, 736f08c3bdfSopenharmony_ci (unsigned int)event->pid, event->fd, filename, 737f08c3bdfSopenharmony_ci event->event_len, info_id, event_fid->hdr.info_type, 738f08c3bdfSopenharmony_ci event_fid->hdr.len, fhlen); 739f08c3bdfSopenharmony_ci } 740f08c3bdfSopenharmony_ci 741f08c3bdfSopenharmony_ci if (test_num < tst_count) 742f08c3bdfSopenharmony_ci test_num++; 743f08c3bdfSopenharmony_ci 744f08c3bdfSopenharmony_ci if (mask_match) { 745f08c3bdfSopenharmony_ci /* In case of merged event match next expected mask */ 746f08c3bdfSopenharmony_ci event->mask &= ~expected->mask | FAN_ONDIR; 747f08c3bdfSopenharmony_ci if (event->mask & ~FAN_ONDIR) 748f08c3bdfSopenharmony_ci continue; 749f08c3bdfSopenharmony_ci } 750f08c3bdfSopenharmony_ci 751f08c3bdfSopenharmony_ci i += event->event_len; 752f08c3bdfSopenharmony_ci if (event->fd > 0) 753f08c3bdfSopenharmony_ci SAFE_CLOSE(event->fd); 754f08c3bdfSopenharmony_ci } 755f08c3bdfSopenharmony_ci 756f08c3bdfSopenharmony_ci for (; test_num < tst_count; test_num++) { 757f08c3bdfSopenharmony_ci tst_res(TFAIL, "didn't get event: mask=%llx, name='%s'", 758f08c3bdfSopenharmony_ci event_set[test_num].mask, event_set[test_num].name); 759f08c3bdfSopenharmony_ci 760f08c3bdfSopenharmony_ci } 761f08c3bdfSopenharmony_ci} 762f08c3bdfSopenharmony_ci 763f08c3bdfSopenharmony_cistatic void setup(void) 764f08c3bdfSopenharmony_ci{ 765f08c3bdfSopenharmony_ci REQUIRE_FANOTIFY_INIT_FLAGS_SUPPORTED_ON_FS(FAN_REPORT_DIR_FID, MOUNT_PATH); 766f08c3bdfSopenharmony_ci fan_report_target_fid_unsupported = 767f08c3bdfSopenharmony_ci fanotify_init_flags_supported_on_fs(FAN_REPORT_DFID_NAME_TARGET, MOUNT_PATH); 768f08c3bdfSopenharmony_ci rename_events_unsupported = 769f08c3bdfSopenharmony_ci fanotify_events_supported_by_kernel(FAN_RENAME, FAN_REPORT_DFID_NAME, 0); 770f08c3bdfSopenharmony_ci 771f08c3bdfSopenharmony_ci SAFE_MKDIR(TEMP_DIR, 0755); 772f08c3bdfSopenharmony_ci sprintf(dname1, "%s/%s", MOUNT_PATH, DIR_NAME1); 773f08c3bdfSopenharmony_ci sprintf(dname2, "%s/%s", MOUNT_PATH, DIR_NAME2); 774f08c3bdfSopenharmony_ci sprintf(tmpdir, "%s/%s", TEMP_DIR, DIR_NAME2); 775f08c3bdfSopenharmony_ci sprintf(fname1, "%s/%s", dname1, FILE_NAME1); 776f08c3bdfSopenharmony_ci sprintf(fname2, "%s/%s", dname1, FILE_NAME2); 777f08c3bdfSopenharmony_ci} 778f08c3bdfSopenharmony_ci 779f08c3bdfSopenharmony_cistatic void cleanup(void) 780f08c3bdfSopenharmony_ci{ 781f08c3bdfSopenharmony_ci if (fd_notify > 0) 782f08c3bdfSopenharmony_ci SAFE_CLOSE(fd_notify); 783f08c3bdfSopenharmony_ci} 784f08c3bdfSopenharmony_ci 785f08c3bdfSopenharmony_cistatic struct tst_test test = { 786f08c3bdfSopenharmony_ci .test = do_test, 787f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(test_cases), 788f08c3bdfSopenharmony_ci .setup = setup, 789f08c3bdfSopenharmony_ci .cleanup = cleanup, 790f08c3bdfSopenharmony_ci .mount_device = 1, 791f08c3bdfSopenharmony_ci .mntpoint = MOUNT_PATH, 792f08c3bdfSopenharmony_ci .all_filesystems = 1, 793f08c3bdfSopenharmony_ci .needs_root = 1 794f08c3bdfSopenharmony_ci}; 795f08c3bdfSopenharmony_ci 796f08c3bdfSopenharmony_ci#else 797f08c3bdfSopenharmony_ci TST_TEST_TCONF("system does not have required name_to_handle_at() support"); 798f08c3bdfSopenharmony_ci#endif 799f08c3bdfSopenharmony_ci#else 800f08c3bdfSopenharmony_ci TST_TEST_TCONF("system doesn't have required fanotify support"); 801f08c3bdfSopenharmony_ci#endif 802