xref: /netbsd-src/tests/fs/tmpfs/h_tools.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: h_tools.c,v 1.1 2007/11/12 15:18:21 jmmv Exp $	*/
2 
3 /*
4  * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *        This product includes software developed by the NetBSD
18  *        Foundation, Inc. and its contributors.
19  * 4. Neither the name of The NetBSD Foundation nor the names of its
20  *    contributors may be used to endorse or promote products derived
21  *    from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /*
37  * Helper tools for several tests.  These are kept in a single file due
38  * to the limitations of bsd.prog.mk to build a single program in a
39  * given directory.
40  */
41 
42 #include <sys/param.h>
43 #include <sys/types.h>
44 #include <sys/event.h>
45 #include <sys/mount.h>
46 #include <sys/statvfs.h>
47 #include <sys/socket.h>
48 #include <sys/time.h>
49 #include <sys/un.h>
50 
51 #include <assert.h>
52 #include <err.h>
53 #include <errno.h>
54 #include <fcntl.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <unistd.h>
59 
60 /* --------------------------------------------------------------------- */
61 
62 static int getfh_main(int, char **);
63 static int kqueue_main(int, char **);
64 static int rename_main(int, char **);
65 static int sockets_main(int, char **);
66 static int statvfs_main(int, char **);
67 
68 /* --------------------------------------------------------------------- */
69 
70 int
71 getfh_main(int argc, char **argv)
72 {
73 	int error;
74 	void *fh;
75 	size_t fh_size;
76 
77 	if (argc < 2)
78 		return EXIT_FAILURE;
79 
80 	fh_size = 0;
81 	fh = NULL;
82 	for (;;) {
83 		if (fh_size) {
84 			fh = malloc(fh_size);
85 			if (fh == NULL) {
86 				fprintf(stderr, "out of memory");
87 				return EXIT_FAILURE;
88 			}
89 		}
90 		/*
91 		 * The kernel provides the necessary size in fh_size -
92 		 * but it may change if someone moves things around,
93 		 * so retry untill we have enough memory.
94 		 */
95 		error = getfh(argv[1], fh, &fh_size);
96 		if (error == 0) {
97 			break;
98 		} else {
99 			if (fh != NULL)
100 				free(fh);
101 			if (errno != E2BIG) {
102 				perror("getfh");
103 				return EXIT_FAILURE;
104 			}
105 		}
106 	}
107 
108 	error = write(STDOUT_FILENO, fh, fh_size);
109 	if (error == -1) {
110 		perror("write");
111 		return EXIT_FAILURE;
112 	}
113 	free(fh);
114 
115 	return 0;
116 }
117 
118 /* --------------------------------------------------------------------- */
119 
120 int
121 kqueue_main(int argc, char **argv)
122 {
123 	char *line;
124 	int i, kq;
125 	size_t len;
126 	struct kevent *changes, event;
127 
128 	if (argc < 2)
129 		return EXIT_FAILURE;
130 
131 	argc--;
132 	argv++;
133 
134 	changes = malloc(sizeof(struct kevent) * (argc - 1));
135 	if (changes == NULL)
136 		errx(EXIT_FAILURE, "not enough memory");
137 
138 	for (i = 0; i < argc; i++) {
139 		int fd;
140 
141 		fd = open(argv[i], O_RDONLY);
142 		if (fd == -1)
143 			err(EXIT_FAILURE, "cannot open %s", argv[i]);
144 
145 		EV_SET(&changes[i], fd, EVFILT_VNODE,
146 		    EV_ADD | EV_ENABLE | EV_ONESHOT,
147 		    NOTE_ATTRIB | NOTE_DELETE | NOTE_EXTEND | NOTE_LINK |
148 		    NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE,
149 		    0, 0);
150 	}
151 
152 	kq = kqueue();
153 	if (kq == -1)
154 		err(EXIT_FAILURE, "kqueue");
155 
156 	while ((line = fgetln(stdin, &len)) != NULL) {
157 		int ec, nev;
158 		struct timespec to;
159 
160 		to.tv_sec = 0;
161 		to.tv_nsec = 100000;
162 
163 		(void)kevent(kq, changes, argc, &event, 1, &to);
164 
165 		assert(len > 0);
166 		assert(line[len - 1] == '\n');
167 		line[len - 1] = '\0';
168 		ec = system(line);
169 		if (ec != EXIT_SUCCESS)
170 			errx(ec, "%s returned %d", line, ec);
171 
172 		do {
173 			nev = kevent(kq, changes, argc, &event, 1, &to);
174 			if (nev == -1)
175 				err(EXIT_FAILURE, "kevent");
176 			else if (nev > 0) {
177 				for (i = 0; i < argc; i++)
178 					if (event.ident == changes[i].ident)
179 						break;
180 
181 				if (event.fflags & NOTE_ATTRIB)
182 					printf("%s - NOTE_ATTRIB\n", argv[i]);
183 				if (event.fflags & NOTE_DELETE)
184 					printf("%s - NOTE_DELETE\n", argv[i]);
185 				if (event.fflags & NOTE_EXTEND)
186 					printf("%s - NOTE_EXTEND\n", argv[i]);
187 				if (event.fflags & NOTE_LINK)
188 					printf("%s - NOTE_LINK\n", argv[i]);
189 				if (event.fflags & NOTE_RENAME)
190 					printf("%s - NOTE_RENAME\n", argv[i]);
191 				if (event.fflags & NOTE_REVOKE)
192 					printf("%s - NOTE_REVOKE\n", argv[i]);
193 				if (event.fflags & NOTE_WRITE)
194 					printf("%s - NOTE_WRITE\n", argv[i]);
195 			}
196 		} while (nev > 0);
197 	}
198 
199 	for (i = 0; i < argc; i++)
200 		close(changes[i].ident);
201 	free(changes);
202 
203 	return EXIT_SUCCESS;
204 }
205 
206 /* --------------------------------------------------------------------- */
207 
208 int
209 rename_main(int argc, char **argv)
210 {
211 
212 	if (argc < 3)
213 		return EXIT_FAILURE;
214 
215 	if (rename(argv[1], argv[2]) == -1) {
216 		perror("rename");
217 		return EXIT_FAILURE;
218 	}
219 
220 	return EXIT_SUCCESS;
221 }
222 
223 /* --------------------------------------------------------------------- */
224 
225 int
226 sockets_main(int argc, char **argv)
227 {
228 	int error, fd;
229 	struct sockaddr_un addr;
230 
231 	if (argc < 2)
232 		return EXIT_FAILURE;
233 
234 	fd = socket(PF_LOCAL, SOCK_STREAM, 0);
235 	if (fd == -1) {
236 		perror("socket");
237 		return EXIT_FAILURE;
238 	}
239 
240 	(void)strlcpy(addr.sun_path, argv[1], sizeof(addr.sun_path));
241 	addr.sun_family = PF_UNIX;
242 
243 	error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
244 	if (error == -1) {
245 		perror("connect");
246 		return EXIT_FAILURE;
247 	}
248 
249 	close(fd);
250 
251 	return EXIT_SUCCESS;
252 }
253 
254 /* --------------------------------------------------------------------- */
255 
256 int
257 statvfs_main(int argc, char **argv)
258 {
259 	int error;
260 	struct statvfs buf;
261 
262 	if (argc < 2)
263 		return EXIT_FAILURE;
264 
265 	error = statvfs(argv[1], &buf);
266 	if (error != 0) {
267 		perror("statvfs");
268 		return EXIT_FAILURE;
269 	}
270 
271 	(void)printf("f_bsize=%lu\n", buf.f_bsize);
272 	(void)printf("f_blocks=%" PRId64 "\n", buf.f_blocks);
273 	(void)printf("f_bfree=%" PRId64 "\n", buf.f_bfree);
274 	(void)printf("f_files=%" PRId64 "\n", buf.f_files);
275 
276 	return EXIT_SUCCESS;
277 }
278 
279 /* --------------------------------------------------------------------- */
280 
281 int
282 main(int argc, char **argv)
283 {
284 	int error;
285 
286 	if (argc < 2)
287 		return EXIT_FAILURE;
288 
289 	argc -= 1;
290 	argv += 1;
291 
292 	if (strcmp(argv[0], "getfh") == 0)
293 		error = getfh_main(argc, argv);
294 	else if (strcmp(argv[0], "kqueue") == 0)
295 		error = kqueue_main(argc, argv);
296 	else if (strcmp(argv[0], "rename") == 0)
297 		error = rename_main(argc, argv);
298 	else if (strcmp(argv[0], "sockets") == 0)
299 		error = sockets_main(argc, argv);
300 	else if (strcmp(argv[0], "statvfs") == 0)
301 		error = statvfs_main(argc, argv);
302 	else
303 		error = EXIT_FAILURE;
304 
305 	return error;
306 }
307