1 /* 2 * Copyright (c) 2014 SUSE Linux. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * Started by Jan Kara <jack (at) suse.cz> 20 * 21 * DESCRIPTION 22 * Check that inotify overflow event is properly generated 23 * 24 * ALGORITHM 25 * Generate enough events without reading them and check that overflow 26 * event is generated. 27 */ 28 #include "config.h" 29 30 #include <stdio.h> 31 #include <sys/stat.h> 32 #include <sys/types.h> 33 #include <sys/fcntl.h> 34 #include <errno.h> 35 #include <string.h> 36 #include <sys/syscall.h> 37 #include "test.h" 38 #include "linux_syscall_numbers.h" 39 #include "inotify.h" 40 #include "safe_macros.h" 41 42 char *TCID = "inotify05"; 43 int TST_TOTAL = 1; 44 45 #if defined(HAVE_SYS_INOTIFY_H) 46 #include <sys/inotify.h> 47 48 /* size of the event structure, not counting name */ 49 #define EVENT_SIZE (sizeof(struct inotify_event)) 50 #define EVENT_BUF_LEN (EVENT_SIZE * 16) 51 52 static void setup(void); 53 static void cleanup(void); 54 55 #define BUF_SIZE 256 56 static char fname[BUF_SIZE]; 57 static char buf[BUF_SIZE]; 58 static int fd, fd_notify; 59 static int wd; 60 static int max_events; 61 62 static char event_buf[EVENT_BUF_LEN]; 63 64 int main(int ac, char **av) 65 { 66 int lc, i; 67 int len, stop; 68 69 tst_parse_opts(ac, av, NULL, NULL); 70 71 setup(); 72 73 for (lc = 0; TEST_LOOPING(lc); lc++) { 74 /* 75 * generate events 76 */ 77 fd = SAFE_OPEN(cleanup, fname, O_RDWR); 78 79 for (i = 0; i < max_events; i++) { 80 SAFE_LSEEK(cleanup, fd, 0, SEEK_SET); 81 SAFE_READ(cleanup, 1, fd, buf, BUF_SIZE); 82 SAFE_LSEEK(cleanup, fd, 0, SEEK_SET); 83 SAFE_WRITE(cleanup, 1, fd, buf, BUF_SIZE); 84 } 85 86 SAFE_CLOSE(cleanup, fd); 87 88 stop = 0; 89 while (!stop) { 90 /* 91 * get list on events 92 */ 93 len = read(fd_notify, event_buf, EVENT_BUF_LEN); 94 if (len < 0) { 95 tst_brkm(TBROK | TERRNO, cleanup, 96 "read(%d, buf, %zu) failed", 97 fd_notify, EVENT_BUF_LEN); 98 } 99 100 /* 101 * check events 102 */ 103 i = 0; 104 while (i < len) { 105 struct inotify_event *event; 106 107 event = (struct inotify_event *)&event_buf[i]; 108 if (event->mask != IN_ACCESS && 109 event->mask != IN_MODIFY && 110 event->mask != IN_OPEN && 111 event->mask != IN_Q_OVERFLOW) { 112 tst_resm(TFAIL, 113 "get event: wd=%d mask=%x " 114 "cookie=%u (expected 0) len=%u", 115 event->wd, event->mask, 116 event->cookie, event->len); 117 stop = 1; 118 break; 119 } 120 if (event->mask == IN_Q_OVERFLOW) { 121 if (event->len != 0 || 122 event->cookie != 0 || 123 event->wd != -1) { 124 tst_resm(TFAIL, 125 "invalid overflow event: " 126 "wd=%d mask=%x " 127 "cookie=%u len=%u", 128 event->wd, event->mask, 129 event->cookie, 130 event->len); 131 stop = 1; 132 break; 133 } 134 if ((int)(i + EVENT_SIZE) != len) { 135 tst_resm(TFAIL, 136 "overflow event is not last"); 137 stop = 1; 138 break; 139 } 140 tst_resm(TPASS, "get event: wd=%d " 141 "mask=%x cookie=%u len=%u", 142 event->wd, event->mask, 143 event->cookie, event->len); 144 stop = 1; 145 break; 146 } 147 i += EVENT_SIZE + event->len; 148 } 149 } 150 } 151 152 cleanup(); 153 tst_exit(); 154 } 155 156 static void setup(void) 157 { 158 tst_sig(NOFORK, DEF_HANDLER, cleanup); 159 160 TEST_PAUSE; 161 162 tst_tmpdir(); 163 164 sprintf(fname, "tfile_%d", getpid()); 165 fd = SAFE_OPEN(cleanup, fname, O_RDWR | O_CREAT, 0700); 166 SAFE_WRITE(cleanup, 1, fd, buf, BUF_SIZE); 167 SAFE_CLOSE(cleanup, fd); 168 169 fd_notify = syscall(__NR_inotify_init1, O_NONBLOCK); 170 if (fd_notify < 0) { 171 if (errno == ENOSYS) { 172 tst_brkm(TCONF, cleanup, 173 "inotify is not configured in this kernel."); 174 } else { 175 tst_brkm(TBROK | TERRNO, cleanup, 176 "inotify_init failed"); 177 } 178 } 179 180 wd = myinotify_add_watch(fd_notify, fname, IN_ALL_EVENTS); 181 if (wd < 0) { 182 tst_brkm(TBROK | TERRNO, cleanup, 183 "inotify_add_watch (%d, %s, IN_ALL_EVENTS) failed", 184 fd_notify, fname); 185 }; 186 187 SAFE_FILE_SCANF(cleanup, "/proc/sys/fs/inotify/max_queued_events", 188 "%d", &max_events); 189 } 190 191 static void cleanup(void) 192 { 193 if (fd_notify > 0 && myinotify_rm_watch(fd_notify, wd) == -1) { 194 tst_resm(TWARN | TERRNO, "inotify_rm_watch (%d, %d) failed", 195 fd_notify, wd); 196 197 } 198 199 if (fd_notify > 0 && close(fd_notify) == -1) 200 tst_resm(TWARN, "close(%d) failed", fd_notify); 201 202 tst_rmdir(); 203 } 204 205 #else 206 207 int main(void) 208 { 209 tst_brkm(TCONF, NULL, "system doesn't have required inotify support"); 210 } 211 212 #endif 213