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