blob: 3ccb657aad8f56722f2d9b32d16e1b698ea72fc2 [file] [log] [blame]
subrata_modak73e6ce72007-05-24 10:00:45 +00001/*
2 * Copyright (c) 2007 SWSoft. 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 * You should have received a copy of the GNU General Public License along
Wanlong Gaofed96412012-10-24 10:10:29 +080020 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
subrata_modak73e6ce72007-05-24 10:00:45 +000022 *
23 * Started by Andrew Vagin <avagin@sw.ru>
24 *
subrata_modak73e6ce72007-05-24 10:00:45 +000025 * DESCRIPTION
26 * Check that inotify work for a directory
27 *
28 * ALGORITHM
29 * Execute sequence file's operation and check return events
Cyril Hrubis26aa0a82013-08-08 14:58:42 +020030 */
subrata_modakc59422e2007-06-04 10:39:59 +000031
subrata_modak86faed42008-12-29 12:11:50 +000032#include "config.h"
33
subrata_modak73e6ce72007-05-24 10:00:45 +000034#include <stdio.h>
35#include <sys/stat.h>
36#include <sys/types.h>
37#include <sys/fcntl.h>
38#include <errno.h>
39#include <string.h>
subrata_modakc59422e2007-06-04 10:39:59 +000040#include <sys/syscall.h>
subrata_modak73e6ce72007-05-24 10:00:45 +000041#include "test.h"
Garrett Cooper53740502010-12-16 00:04:01 -080042#include "linux_syscall_numbers.h"
Garrett Cooper3bf3cb12012-05-20 10:51:55 -070043#include "inotify.h"
subrata_modak73e6ce72007-05-24 10:00:45 +000044
Garrett Cooper53740502010-12-16 00:04:01 -080045#if defined(HAVE_SYS_INOTIFY_H)
subrata_modak3e9f0942008-08-22 21:32:50 +000046#include <sys/inotify.h>
subrata_modakc59422e2007-06-04 10:39:59 +000047
subrata_modak3d726792007-10-25 14:09:01 +000048#ifndef IN_MOVE_SELF
49#define IN_MOVE_SELF 0x00000800
50#endif
51
subrata_modak73e6ce72007-05-24 10:00:45 +000052#define EVENT_MAX 1024
53/* size of the event structure, not counting name */
54#define EVENT_SIZE (sizeof (struct inotify_event))
55/* reasonable guess as to size of 1024 events */
56#define EVENT_BUF_LEN (EVENT_MAX * (EVENT_SIZE + 16))
57
Cyril Hrubis26aa0a82013-08-08 14:58:42 +020058static void setup(void);
59static void cleanup(void);
subrata_modak73e6ce72007-05-24 10:00:45 +000060
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020061char *TCID = "inotify02";
62int TST_TOTAL = 9;
subrata_modak73e6ce72007-05-24 10:00:45 +000063
64#define BUF_SIZE 256
Cyril Hrubis26aa0a82013-08-08 14:58:42 +020065static char fname1[BUF_SIZE], fname2[BUF_SIZE], fname3[BUF_SIZE];
Cyril Hrubis04f21772014-12-09 14:26:23 +010066static int fd, fd_notify, reap_wd;
Cyril Hrubis26aa0a82013-08-08 14:58:42 +020067static int wd;
subrata_modak73e6ce72007-05-24 10:00:45 +000068
69struct event_t {
subrata_modak56207ce2009-03-23 13:35:39 +000070 char name[BUF_SIZE];
Andrey Vagin6550b7a2014-09-10 14:00:53 +040071 unsigned int mask;
subrata_modak73e6ce72007-05-24 10:00:45 +000072};
73#define FILE_NAME1 "test_file1"
74#define FILE_NAME2 "test_file2"
75
Cyril Hrubis26aa0a82013-08-08 14:58:42 +020076static struct event_t event_set[EVENT_MAX];
subrata_modak73e6ce72007-05-24 10:00:45 +000077
Cyril Hrubis26aa0a82013-08-08 14:58:42 +020078static char event_buf[EVENT_BUF_LEN];
vapier03b05a02008-04-07 18:33:46 +000079
subrata_modak56207ce2009-03-23 13:35:39 +000080int main(int ac, char **av)
81{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020082 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020083 const char *msg;
Jan Kara1ea28212014-02-20 18:16:17 +010084 unsigned int stored_cookie = UINT_MAX;
subrata_modak73e6ce72007-05-24 10:00:45 +000085
Garrett Cooper45e285d2010-11-22 12:19:25 -080086 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -080087 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
subrata_modak73e6ce72007-05-24 10:00:45 +000088
subrata_modak56207ce2009-03-23 13:35:39 +000089 setup();
subrata_modak73e6ce72007-05-24 10:00:45 +000090
subrata_modak56207ce2009-03-23 13:35:39 +000091 for (lc = 0; TEST_LOOPING(lc); lc++) {
subrata_modak73e6ce72007-05-24 10:00:45 +000092
Caspar Zhangd59a6592013-03-07 14:59:12 +080093 tst_count = 0;
subrata_modak73e6ce72007-05-24 10:00:45 +000094
subrata_modak56207ce2009-03-23 13:35:39 +000095 /*
96 * generate sequence of events
97 */
98 if (chmod(".", 0755) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +080099 tst_brkm(TBROK | TERRNO, cleanup,
Garrett Cooper766f33c2010-11-22 14:53:00 -0800100 "chmod(\".\", 0755) failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000101 }
Caspar Zhangd59a6592013-03-07 14:59:12 +0800102 event_set[tst_count].mask = IN_ISDIR | IN_ATTRIB;
103 strcpy(event_set[tst_count].name, "");
104 tst_count++;
subrata_modak73e6ce72007-05-24 10:00:45 +0000105
subrata_modak56207ce2009-03-23 13:35:39 +0000106 if ((fd = creat(FILE_NAME1, 0755)) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800107 tst_brkm(TBROK | TERRNO, cleanup,
108 "creat(\"%s\", 755) failed", FILE_NAME1);
subrata_modak56207ce2009-03-23 13:35:39 +0000109 }
subrata_modak73e6ce72007-05-24 10:00:45 +0000110
Caspar Zhangd59a6592013-03-07 14:59:12 +0800111 event_set[tst_count].mask = IN_CREATE;
112 strcpy(event_set[tst_count].name, FILE_NAME1);
113 tst_count++;
114 event_set[tst_count].mask = IN_OPEN;
115 strcpy(event_set[tst_count].name, FILE_NAME1);
116 tst_count++;
subrata_modak73e6ce72007-05-24 10:00:45 +0000117
subrata_modak56207ce2009-03-23 13:35:39 +0000118 if (close(fd) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800119 tst_brkm(TBROK | TERRNO, cleanup,
Garrett Cooper766f33c2010-11-22 14:53:00 -0800120 "close(%s) failed", FILE_NAME1);
subrata_modak56207ce2009-03-23 13:35:39 +0000121 }
Caspar Zhangd59a6592013-03-07 14:59:12 +0800122 event_set[tst_count].mask = IN_CLOSE_WRITE;
123 strcpy(event_set[tst_count].name, FILE_NAME1);
124 tst_count++;
subrata_modak73e6ce72007-05-24 10:00:45 +0000125
subrata_modak56207ce2009-03-23 13:35:39 +0000126 if (rename(FILE_NAME1, FILE_NAME2) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800127 tst_brkm(TBROK | TERRNO, cleanup,
Garrett Cooper766f33c2010-11-22 14:53:00 -0800128 "rename(%s, %s) failed",
129 FILE_NAME1, FILE_NAME2);
subrata_modak56207ce2009-03-23 13:35:39 +0000130 }
Caspar Zhangd59a6592013-03-07 14:59:12 +0800131 event_set[tst_count].mask = IN_MOVED_FROM;
132 strcpy(event_set[tst_count].name, FILE_NAME1);
133 tst_count++;
134 event_set[tst_count].mask = IN_MOVED_TO;
135 strcpy(event_set[tst_count].name, FILE_NAME2);
136 tst_count++;
subrata_modak73e6ce72007-05-24 10:00:45 +0000137
subrata_modak56207ce2009-03-23 13:35:39 +0000138 if (getcwd(fname1, BUF_SIZE) == NULL) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800139 tst_brkm(TBROK | TERRNO, cleanup,
140 "getcwd(%p, %d) failed", fname1, BUF_SIZE);
subrata_modak56207ce2009-03-23 13:35:39 +0000141 }
subrata_modak73e6ce72007-05-24 10:00:45 +0000142
subrata_modak56207ce2009-03-23 13:35:39 +0000143 snprintf(fname2, BUF_SIZE, "%s.rename1", fname1);
144 if (rename(fname1, fname2) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800145 tst_brkm(TBROK | TERRNO, cleanup,
Garrett Cooper766f33c2010-11-22 14:53:00 -0800146 "rename(%s, %s) failed", fname1, fname2);
subrata_modak56207ce2009-03-23 13:35:39 +0000147 }
Caspar Zhangd59a6592013-03-07 14:59:12 +0800148 event_set[tst_count].mask = IN_MOVE_SELF;
149 strcpy(event_set[tst_count].name, "");
150 tst_count++;
subrata_modak73e6ce72007-05-24 10:00:45 +0000151
subrata_modak56207ce2009-03-23 13:35:39 +0000152 if (unlink(FILE_NAME2) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800153 tst_brkm(TBROK | TERRNO, cleanup,
Garrett Cooper766f33c2010-11-22 14:53:00 -0800154 "unlink(%s) failed", FILE_NAME2);
subrata_modak56207ce2009-03-23 13:35:39 +0000155 }
Caspar Zhangd59a6592013-03-07 14:59:12 +0800156 event_set[tst_count].mask = IN_DELETE;
157 strcpy(event_set[tst_count].name, FILE_NAME2);
158 tst_count++;
subrata_modak73e6ce72007-05-24 10:00:45 +0000159
subrata_modak56207ce2009-03-23 13:35:39 +0000160 /*
161 * test that duplicate events will be coalesced into
162 * a single event. This test case should be last, that
163 * we can correct determine kernel bug which exist before
164 * 2.6.25. See comment below.
165 */
166 snprintf(fname3, BUF_SIZE, "%s.rename2", fname1);
167 if (rename(fname2, fname3) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800168 tst_brkm(TBROK | TERRNO, cleanup,
Garrett Cooper766f33c2010-11-22 14:53:00 -0800169 "rename(%s, %s) failed", fname2, fname3);
subrata_modak56207ce2009-03-23 13:35:39 +0000170 }
subrata_modak73e6ce72007-05-24 10:00:45 +0000171
subrata_modak56207ce2009-03-23 13:35:39 +0000172 if (rename(fname3, fname1) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800173 tst_brkm(TBROK | TERRNO, cleanup,
Garrett Cooper766f33c2010-11-22 14:53:00 -0800174 "rename(%s, %s) failed", fname3, fname1);
subrata_modak56207ce2009-03-23 13:35:39 +0000175 }
Caspar Zhangd59a6592013-03-07 14:59:12 +0800176 event_set[tst_count].mask = IN_MOVE_SELF;
177 strcpy(event_set[tst_count].name, "");
178 tst_count++;
subrata_modak9a4c4092008-03-28 08:28:50 +0000179
Caspar Zhangd59a6592013-03-07 14:59:12 +0800180 if (tst_count != TST_TOTAL) {
subrata_modak56207ce2009-03-23 13:35:39 +0000181 tst_brkm(TBROK, cleanup,
Caspar Zhangd59a6592013-03-07 14:59:12 +0800182 "tst_count and TST_TOTAL are not equal");
subrata_modak56207ce2009-03-23 13:35:39 +0000183 }
subrata_modak73e6ce72007-05-24 10:00:45 +0000184
Caspar Zhangd59a6592013-03-07 14:59:12 +0800185 tst_count = 0;
subrata_modak73e6ce72007-05-24 10:00:45 +0000186
subrata_modak56207ce2009-03-23 13:35:39 +0000187 int len, i = 0, test_num = 0;
Garrett Cooper53740502010-12-16 00:04:01 -0800188 if ((len = read(fd_notify, event_buf, EVENT_BUF_LEN)) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800189 tst_brkm(TBROK | TERRNO, cleanup,
Markos Chandrasf4539c62012-01-03 09:41:10 +0000190 "read(%d, buf, %zu) failed",
Garrett Cooper766f33c2010-11-22 14:53:00 -0800191 fd_notify, EVENT_BUF_LEN);
subrata_modak73e6ce72007-05-24 10:00:45 +0000192
subrata_modak56207ce2009-03-23 13:35:39 +0000193 }
subrata_modak73e6ce72007-05-24 10:00:45 +0000194
subrata_modak56207ce2009-03-23 13:35:39 +0000195 while (i < len) {
196 struct inotify_event *event;
197 event = (struct inotify_event *)&event_buf[i];
198 if (test_num >= TST_TOTAL) {
199 if (tst_kvercmp(2, 6, 25) < 0
200 && event_set[TST_TOTAL - 1].mask ==
201 event->mask)
202 tst_resm(TWARN,
203 "This may be kernel bug. "
204 "Before kernel 2.6.25, a kernel bug "
205 "meant that the kernel code that was "
206 "intended to coalesce successive identical "
207 "events (i.e., the two most recent "
208 "events could potentially be coalesced "
209 "if the older had not yet been read) "
210 "instead checked if the most recent event "
211 "could be coalesced with the oldest "
212 "unread event. This has been fixed by commit"
213 "1c17d18e3775485bf1e0ce79575eb637a94494a2.");
214 tst_resm(TFAIL,
215 "get unnecessary event: "
216 "wd=%d mask=%x cookie=%u len=%u"
Andrey Vagind1e94ff2014-09-11 18:18:12 +0400217 "name=\"%.*s\"", event->wd, event->mask,
218 event->cookie, event->len, event->len,
subrata_modak56207ce2009-03-23 13:35:39 +0000219 event->name);
subrata_modak73e6ce72007-05-24 10:00:45 +0000220
subrata_modak56207ce2009-03-23 13:35:39 +0000221 } else if ((event_set[test_num].mask == event->mask)
222 &&
223 (!strncmp
224 (event_set[test_num].name, event->name,
225 event->len))) {
Jan Kara1ea28212014-02-20 18:16:17 +0100226 int fail = 0;
subrata_modak73e6ce72007-05-24 10:00:45 +0000227
Jan Kara1ea28212014-02-20 18:16:17 +0100228 if (event->mask == IN_MOVED_FROM) {
229 if (event->cookie == 0)
230 fail = 1;
231 else
232 stored_cookie = event->cookie;
233 } else if (event->mask == IN_MOVED_TO) {
234 if (event->cookie != stored_cookie)
235 fail = 1;
236 else
237 stored_cookie = UINT_MAX;
238 } else {
239 if (event->cookie != 0)
240 fail = 1;
241 }
242 if (!fail) {
243 tst_resm(TPASS,
244 "get event: wd=%d mask=%x "
Andrey Vagind1e94ff2014-09-11 18:18:12 +0400245 "cookie=%u len=%u name=\"%.*s\"",
Jan Kara1ea28212014-02-20 18:16:17 +0100246 event->wd, event->mask,
247 event->cookie, event->len,
Andrey Vagind1e94ff2014-09-11 18:18:12 +0400248 event->len, event->name);
Jan Kara1ea28212014-02-20 18:16:17 +0100249 } else {
250 tst_resm(TFAIL,
251 "get event: wd=%d mask=%x "
252 "cookie=%u (wrong) len=%u "
253 "name=\"%s\"",
254 event->wd, event->mask,
255 event->cookie, event->len,
256 event->name);
257 }
subrata_modak56207ce2009-03-23 13:35:39 +0000258 } else {
259 tst_resm(TFAIL, "get event: wd=%d mask=%x "
260 "(expected %x) cookie=%u len=%u "
261 "name=\"%s\" (expected \"%s\") %d",
262 event->wd, event->mask,
263 event_set[test_num].mask,
264 event->cookie, event->len, event->name,
265 event_set[test_num].name,
266 strcmp(event_set[test_num].name,
267 event->name));
268 }
269 test_num++;
270 i += EVENT_SIZE + event->len;
271 }
subrata_modak73e6ce72007-05-24 10:00:45 +0000272
subrata_modak56207ce2009-03-23 13:35:39 +0000273 for (; test_num < TST_TOTAL; test_num++) {
Garrett Cooper766f33c2010-11-22 14:53:00 -0800274 tst_resm(TFAIL, "didn't get event: mask=%x ",
275 event_set[test_num].mask);
subrata_modak56207ce2009-03-23 13:35:39 +0000276 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800277 }
subrata_modak73e6ce72007-05-24 10:00:45 +0000278
subrata_modak56207ce2009-03-23 13:35:39 +0000279 cleanup();
Garrett Cooper766f33c2010-11-22 14:53:00 -0800280 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800281}
subrata_modak73e6ce72007-05-24 10:00:45 +0000282
Cyril Hrubis26aa0a82013-08-08 14:58:42 +0200283static void setup(void)
subrata_modak56207ce2009-03-23 13:35:39 +0000284{
Garrett Cooper2c282152010-12-16 00:55:50 -0800285
subrata_modak56207ce2009-03-23 13:35:39 +0000286 tst_sig(NOFORK, DEF_HANDLER, cleanup);
subrata_modak73e6ce72007-05-24 10:00:45 +0000287
subrata_modak56207ce2009-03-23 13:35:39 +0000288 TEST_PAUSE;
subrata_modak73e6ce72007-05-24 10:00:45 +0000289
subrata_modak56207ce2009-03-23 13:35:39 +0000290 tst_tmpdir();
subrata_modak73e6ce72007-05-24 10:00:45 +0000291
subrata_modak56207ce2009-03-23 13:35:39 +0000292 if ((fd_notify = myinotify_init()) < 0) {
293 if (errno == ENOSYS) {
Garrett Cooper766f33c2010-11-22 14:53:00 -0800294 tst_brkm(TCONF, cleanup,
subrata_modak56207ce2009-03-23 13:35:39 +0000295 "inotify is not configured in this kernel.");
subrata_modak56207ce2009-03-23 13:35:39 +0000296 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800297 tst_brkm(TBROK | TERRNO, cleanup,
Garrett Cooper766f33c2010-11-22 14:53:00 -0800298 "inotify_init () failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000299 }
300 }
subrata_modak73e6ce72007-05-24 10:00:45 +0000301
subrata_modak56207ce2009-03-23 13:35:39 +0000302 if ((wd = myinotify_add_watch(fd_notify, ".", IN_ALL_EVENTS)) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800303 tst_brkm(TBROK | TERRNO, cleanup,
Garrett Cooper766f33c2010-11-22 14:53:00 -0800304 "inotify_add_watch (%d, \".\", IN_ALL_EVENTS) failed",
305 fd_notify);
Cyril Hrubis04f21772014-12-09 14:26:23 +0100306 reap_wd = 1;
subrata_modak56207ce2009-03-23 13:35:39 +0000307 };
subrata_modak73e6ce72007-05-24 10:00:45 +0000308
Garrett Cooper2c282152010-12-16 00:55:50 -0800309}
subrata_modak73e6ce72007-05-24 10:00:45 +0000310
Cyril Hrubis26aa0a82013-08-08 14:58:42 +0200311static void cleanup(void)
subrata_modak56207ce2009-03-23 13:35:39 +0000312{
Cyril Hrubis04f21772014-12-09 14:26:23 +0100313 if (reap_wd && myinotify_rm_watch(fd_notify, wd) < 0) {
subrata_modak56207ce2009-03-23 13:35:39 +0000314 tst_resm(TWARN,
Garrett Cooper766f33c2010-11-22 14:53:00 -0800315 "inotify_rm_watch (%d, %d) failed,", fd_notify, wd);
subrata_modak73e6ce72007-05-24 10:00:45 +0000316
subrata_modak56207ce2009-03-23 13:35:39 +0000317 }
subrata_modak73e6ce72007-05-24 10:00:45 +0000318
Cyril Hrubis04f21772014-12-09 14:26:23 +0100319 if (fd_notify > 0 && close(fd_notify))
Garrett Cooper766f33c2010-11-22 14:53:00 -0800320 tst_resm(TWARN, "close(%d) failed", fd_notify);
subrata_modak73e6ce72007-05-24 10:00:45 +0000321
subrata_modak56207ce2009-03-23 13:35:39 +0000322 tst_rmdir();
Garrett Cooper2c282152010-12-16 00:55:50 -0800323}
subrata_modakc59422e2007-06-04 10:39:59 +0000324
325#else
326
Cyril Hrubisfdce7d52013-04-04 18:35:48 +0200327char *TCID = "inotify02";
328int TST_TOTAL = 0;
subrata_modakc59422e2007-06-04 10:39:59 +0000329
Garrett Cooperddc4c0d2010-11-22 15:05:35 -0800330int main(void)
subrata_modakc59422e2007-06-04 10:39:59 +0000331{
Garrett Cooper53740502010-12-16 00:04:01 -0800332 tst_brkm(TCONF, NULL, "system doesn't have required inotify support");
subrata_modakc59422e2007-06-04 10:39:59 +0000333}
334
Markos Chandrasf4539c62012-01-03 09:41:10 +0000335#endif