1 /*
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
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * Started by Andrew Vagin <avagin@sw.ru>
24 *
25 * DESCRIPTION
26 * Check that inotify work for a file
27 *
28 * ALGORITHM
29 * Execute sequence file's operation and check return events
30 */
31 #include "config.h"
32
33 #include <stdio.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <sys/fcntl.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <sys/syscall.h>
40 #include "test.h"
41 #include "linux_syscall_numbers.h"
42 #include "inotify.h"
43
44 #if defined(HAVE_SYS_INOTIFY_H)
45 #include <sys/inotify.h>
46
47 #define EVENT_MAX 1024
48 /* size of the event structure, not counting name */
49 #define EVENT_SIZE (sizeof (struct inotify_event))
50 /* reasonable guess as to size of 1024 events */
51 #define EVENT_BUF_LEN (EVENT_MAX * (EVENT_SIZE + 16))
52
53 char *TCID = "inotify01";
54 int TST_TOTAL = 7;
55
56 static void setup(void);
57 static void cleanup(void);
58
59 #define BUF_SIZE 256
60 static char fname[BUF_SIZE];
61 static char buf[BUF_SIZE];
62 static int fd, fd_notify;
63 static int wd, reap_wd;
64
65 static int event_set[EVENT_MAX];
66
67 static char event_buf[EVENT_BUF_LEN];
68
main(int ac,char ** av)69 int main(int ac, char **av)
70 {
71 int lc;
72
73 tst_parse_opts(ac, av, NULL, NULL);
74
75 setup();
76
77 for (lc = 0; TEST_LOOPING(lc); lc++) {
78 tst_count = 0;
79
80 /*
81 * generate sequence of events
82 */
83 if (chmod(fname, 0755) < 0) {
84 tst_brkm(TBROK | TERRNO, cleanup,
85 "chmod(%s, 0755) failed", fname);
86 }
87 event_set[tst_count] = IN_ATTRIB;
88 tst_count++;
89
90 if ((fd = open(fname, O_RDONLY)) == -1) {
91 tst_brkm(TBROK | TERRNO, cleanup,
92 "open(%s, O_RDWR|O_CREAT,0700) failed", fname);
93 }
94 event_set[tst_count] = IN_OPEN;
95 tst_count++;
96
97 if (read(fd, buf, BUF_SIZE) == -1) {
98 tst_brkm(TBROK | TERRNO, cleanup,
99 "read(%d, buf, %d) failed", fd, BUF_SIZE);
100 }
101 event_set[tst_count] = IN_ACCESS;
102 tst_count++;
103
104 if (close(fd) == -1) {
105 tst_brkm(TBROK, cleanup, "close(%s) failed", fname);
106 }
107 event_set[tst_count] = IN_CLOSE_NOWRITE;
108 tst_count++;
109
110 if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1) {
111 tst_brkm(TBROK, cleanup,
112 "open(%s, O_RDWR|O_CREAT,0700) failed", fname);
113 }
114 event_set[tst_count] = IN_OPEN;
115 tst_count++;
116
117 if (write(fd, buf, BUF_SIZE) == -1) {
118 tst_brkm(TBROK, cleanup,
119 "write(%d, %s, 1) failed", fd, fname);
120 }
121 event_set[tst_count] = IN_MODIFY;
122 tst_count++;
123
124 if (close(fd) == -1) {
125 tst_brkm(TBROK, cleanup, "close(%s) failed", fname);
126 }
127 event_set[tst_count] = IN_CLOSE_WRITE;
128 tst_count++;
129
130 if (TST_TOTAL != tst_count) {
131 tst_brkm(TBROK, cleanup,
132 "TST_TOTAL and tst_count are not equal");
133 }
134 tst_count = 0;
135
136 /*
137 * get list on events
138 */
139 int len, i = 0, test_num = 0;
140 if ((len = read(fd_notify, event_buf, EVENT_BUF_LEN)) < 0) {
141 tst_brkm(TBROK, cleanup,
142 "read(%d, buf, %zu) failed",
143 fd_notify, EVENT_BUF_LEN);
144
145 }
146
147 /*
148 * check events
149 */
150 while (i < len) {
151 struct inotify_event *event;
152 event = (struct inotify_event *)&event_buf[i];
153 if (test_num >= TST_TOTAL) {
154 tst_resm(TFAIL,
155 "get unnecessary event: wd=%d mask=%x "
156 "cookie=%u len=%u",
157 event->wd, event->mask,
158 event->cookie, event->len);
159 } else if (event_set[test_num] == event->mask) {
160 if (event->cookie != 0) {
161 tst_resm(TFAIL,
162 "get event: wd=%d mask=%x "
163 "cookie=%u (expected 0) len=%u",
164 event->wd, event->mask,
165 event->cookie, event->len);
166 } else {
167 tst_resm(TPASS, "get event: wd=%d "
168 "mask=%x cookie=%u len=%u",
169 event->wd, event->mask,
170 event->cookie, event->len);
171 }
172
173 } else {
174 tst_resm(TFAIL, "get event: wd=%d mask=%x "
175 "(expected %x) cookie=%u len=%u",
176 event->wd, event->mask,
177 event_set[test_num],
178 event->cookie, event->len);
179 }
180 test_num++;
181 i += EVENT_SIZE + event->len;
182 }
183 for (; test_num < TST_TOTAL; test_num++) {
184 tst_resm(TFAIL, "didn't get event: mask=%x",
185 event_set[test_num]);
186
187 }
188
189 }
190
191 cleanup();
192 tst_exit();
193 }
194
setup(void)195 static void setup(void)
196 {
197
198 tst_sig(NOFORK, DEF_HANDLER, cleanup);
199
200 TEST_PAUSE;
201
202 tst_tmpdir();
203
204 sprintf(fname, "tfile_%d", getpid());
205 if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1) {
206 tst_brkm(TBROK | TERRNO, cleanup,
207 "open(%s, O_RDWR|O_CREAT,0700) failed", fname);
208 }
209 if ((write(fd, fname, 1)) == -1) {
210 tst_brkm(TBROK | TERRNO, cleanup, "write(%d, %s, 1) failed",
211 fd, fname);
212 }
213
214 /* close the file we have open */
215 if (close(fd) == -1) {
216 tst_brkm(TBROK, cleanup, "close(%s) failed", fname);
217 }
218 if ((fd_notify = myinotify_init()) < 0) {
219 if (errno == ENOSYS) {
220 tst_brkm(TCONF, cleanup,
221 "inotify is not configured in this kernel.");
222 } else {
223 tst_brkm(TBROK | TERRNO, cleanup,
224 "inotify_init failed");
225 }
226 }
227
228 if ((wd = myinotify_add_watch(fd_notify, fname, IN_ALL_EVENTS)) < 0) {
229 tst_brkm(TBROK | TERRNO, cleanup,
230 "inotify_add_watch (%d, %s, IN_ALL_EVENTS) failed",
231 fd_notify, fname);
232 reap_wd = 1;
233 };
234
235 }
236
cleanup(void)237 static void cleanup(void)
238 {
239 if (reap_wd && myinotify_rm_watch(fd_notify, wd) < 0) {
240 tst_resm(TWARN | TERRNO, "inotify_rm_watch (%d, %d) failed",
241 fd_notify, wd);
242
243 }
244
245 if (fd_notify > 0 && close(fd_notify))
246 tst_resm(TWARN, "close(%d) failed", fd_notify);
247
248 tst_rmdir();
249 }
250
251 #else
252
253 char *TCID = "inotify01";
254 int TST_TOTAL = 0;
255
main(void)256 int main(void)
257 {
258 tst_brkm(TCONF, NULL, "system doesn't have required inotify support");
259 }
260
261 #endif
262