1171801Sdelphij/*	$NetBSD: h_tools.c,v 1.8 2007/07/23 15:05:43 jmmv Exp $	*/
2170809Sdelphij
3170809Sdelphij/*-
4170809Sdelphij * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
5170809Sdelphij * All rights reserved.
6170809Sdelphij *
7170809Sdelphij * This code is derived from software contributed to The NetBSD Foundation
8170809Sdelphij * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
9170809Sdelphij * 2005 program.
10170809Sdelphij *
11170809Sdelphij * Redistribution and use in source and binary forms, with or without
12170809Sdelphij * modification, are permitted provided that the following conditions
13170809Sdelphij * are met:
14170809Sdelphij * 1. Redistributions of source code must retain the above copyright
15170809Sdelphij *    notice, this list of conditions and the following disclaimer.
16170809Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
17170809Sdelphij *    notice, this list of conditions and the following disclaimer in the
18170809Sdelphij *    documentation and/or other materials provided with the distribution.
19170809Sdelphij *
20170809Sdelphij * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21170809Sdelphij * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22170809Sdelphij * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23170809Sdelphij * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24170809Sdelphij * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25170809Sdelphij * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26170809Sdelphij * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27170809Sdelphij * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28170809Sdelphij * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29170809Sdelphij * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30170809Sdelphij * POSSIBILITY OF SUCH DAMAGE.
31170809Sdelphij *
32170809Sdelphij * $FreeBSD$
33170809Sdelphij */
34170809Sdelphij
35170809Sdelphij/*
36170809Sdelphij * Helper tools for several tests.  These are kept in a single file due
37170809Sdelphij * to the limitations of bsd.prog.mk to build a single program in a
38170809Sdelphij * given directory.
39170809Sdelphij */
40170809Sdelphij
41170809Sdelphij#include <sys/param.h>
42170809Sdelphij#include <sys/types.h>
43170809Sdelphij#include <sys/event.h>
44170809Sdelphij#include <sys/mount.h>
45170809Sdelphij#include <sys/statvfs.h>
46197849Sdelphij#include <sys/stdint.h>
47170809Sdelphij#include <sys/socket.h>
48170809Sdelphij#include <sys/time.h>
49170809Sdelphij#include <sys/un.h>
50170809Sdelphij
51170809Sdelphij#include <assert.h>
52170809Sdelphij#include <err.h>
53170809Sdelphij#include <errno.h>
54170809Sdelphij#include <fcntl.h>
55170809Sdelphij#include <stdio.h>
56170809Sdelphij#include <stdlib.h>
57170809Sdelphij#include <string.h>
58170809Sdelphij#include <unistd.h>
59170809Sdelphij
60170809Sdelphij/* --------------------------------------------------------------------- */
61170809Sdelphij
62170809Sdelphijstatic int getfh_main(int, char **);
63170809Sdelphijstatic int kqueue_main(int, char **);
64170809Sdelphijstatic int rename_main(int, char **);
65170809Sdelphijstatic int sockets_main(int, char **);
66170809Sdelphijstatic int statvfs_main(int, char **);
67170809Sdelphij
68170809Sdelphij/* --------------------------------------------------------------------- */
69170809Sdelphij
70170809Sdelphijint
71170809Sdelphijgetfh_main(int argc, char **argv)
72170809Sdelphij{
73170809Sdelphij	int error;
74170809Sdelphij	fhandle_t fh;
75170809Sdelphij
76170809Sdelphij	if (argc < 2)
77170809Sdelphij		return EXIT_FAILURE;
78170809Sdelphij
79170809Sdelphij	error = getfh(argv[1], &fh);
80170809Sdelphij	if (error == 0)
81170809Sdelphij		err(EXIT_FAILURE, "can not getfh");
82170809Sdelphij
83170809Sdelphij	error = write(STDOUT_FILENO, &fh, sizeof(fh));
84170809Sdelphij	if (error == -1) {
85170809Sdelphij		perror("write");
86170809Sdelphij		return EXIT_FAILURE;
87170809Sdelphij	}
88170809Sdelphij
89170809Sdelphij	return 0;
90170809Sdelphij}
91170809Sdelphij
92170809Sdelphij/* --------------------------------------------------------------------- */
93170809Sdelphij
94170809Sdelphijint
95170809Sdelphijkqueue_main(int argc, char **argv)
96170809Sdelphij{
97170809Sdelphij	char *line;
98170809Sdelphij	int i, kq;
99170809Sdelphij	size_t len;
100170809Sdelphij	struct kevent *changes, event;
101170809Sdelphij
102170809Sdelphij	if (argc < 2)
103170809Sdelphij		return EXIT_FAILURE;
104170809Sdelphij
105170809Sdelphij	argc--;
106170809Sdelphij	argv++;
107170809Sdelphij
108170809Sdelphij	changes = malloc(sizeof(struct kevent) * (argc - 1));
109170809Sdelphij	if (changes == NULL)
110170809Sdelphij		errx(EXIT_FAILURE, "not enough memory");
111170809Sdelphij
112170809Sdelphij	for (i = 0; i < argc; i++) {
113170809Sdelphij		int fd;
114170809Sdelphij
115170809Sdelphij		fd = open(argv[i], O_RDONLY);
116170809Sdelphij		if (fd == -1)
117170809Sdelphij			err(EXIT_FAILURE, "cannot open %s", argv[i]);
118170809Sdelphij
119170809Sdelphij		EV_SET(&changes[i], fd, EVFILT_VNODE,
120170809Sdelphij		    EV_ADD | EV_ENABLE | EV_ONESHOT,
121170809Sdelphij		    NOTE_ATTRIB | NOTE_DELETE | NOTE_EXTEND | NOTE_LINK |
122170809Sdelphij		    NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE,
123170809Sdelphij		    0, 0);
124170809Sdelphij	}
125170809Sdelphij
126170809Sdelphij	kq = kqueue();
127170809Sdelphij	if (kq == -1)
128170809Sdelphij		err(EXIT_FAILURE, "kqueue");
129170809Sdelphij
130170809Sdelphij	while ((line = fgetln(stdin, &len)) != NULL) {
131170809Sdelphij		int ec, nev;
132170809Sdelphij		struct timespec to;
133170809Sdelphij
134170809Sdelphij		to.tv_sec = 0;
135170809Sdelphij		to.tv_nsec = 100000;
136170809Sdelphij
137170809Sdelphij		(void)kevent(kq, changes, argc, &event, 1, &to);
138170809Sdelphij
139170809Sdelphij		assert(len > 0);
140170809Sdelphij		assert(line[len - 1] == '\n');
141170809Sdelphij		line[len - 1] = '\0';
142170809Sdelphij		ec = system(line);
143170809Sdelphij		if (ec != EXIT_SUCCESS)
144170809Sdelphij			errx(ec, "%s returned %d", line, ec);
145170809Sdelphij
146170809Sdelphij		do {
147170809Sdelphij			nev = kevent(kq, changes, argc, &event, 1, &to);
148170809Sdelphij			if (nev == -1)
149170809Sdelphij				err(EXIT_FAILURE, "kevent");
150170809Sdelphij			else if (nev > 0) {
151170809Sdelphij				for (i = 0; i < argc; i++)
152170809Sdelphij					if (event.ident == changes[i].ident)
153170809Sdelphij						break;
154170809Sdelphij
155170809Sdelphij				if (event.fflags & NOTE_ATTRIB)
156170809Sdelphij					printf("%s - NOTE_ATTRIB\n", argv[i]);
157170809Sdelphij				if (event.fflags & NOTE_DELETE)
158170809Sdelphij					printf("%s - NOTE_DELETE\n", argv[i]);
159170809Sdelphij				if (event.fflags & NOTE_EXTEND)
160170809Sdelphij					printf("%s - NOTE_EXTEND\n", argv[i]);
161170809Sdelphij				if (event.fflags & NOTE_LINK)
162170809Sdelphij					printf("%s - NOTE_LINK\n", argv[i]);
163170809Sdelphij				if (event.fflags & NOTE_RENAME)
164170809Sdelphij					printf("%s - NOTE_RENAME\n", argv[i]);
165170809Sdelphij				if (event.fflags & NOTE_REVOKE)
166170809Sdelphij					printf("%s - NOTE_REVOKE\n", argv[i]);
167170809Sdelphij				if (event.fflags & NOTE_WRITE)
168170809Sdelphij					printf("%s - NOTE_WRITE\n", argv[i]);
169170809Sdelphij			}
170170809Sdelphij		} while (nev > 0);
171170809Sdelphij	}
172170809Sdelphij
173170809Sdelphij	for (i = 0; i < argc; i++)
174170809Sdelphij		close(changes[i].ident);
175170809Sdelphij	free(changes);
176170809Sdelphij
177170809Sdelphij	return EXIT_SUCCESS;
178170809Sdelphij}
179170809Sdelphij
180170809Sdelphij/* --------------------------------------------------------------------- */
181170809Sdelphij
182170809Sdelphijint
183170809Sdelphijrename_main(int argc, char **argv)
184170809Sdelphij{
185170809Sdelphij
186170809Sdelphij	if (argc < 3)
187170809Sdelphij		return EXIT_FAILURE;
188170809Sdelphij
189171801Sdelphij	if (rename(argv[1], argv[2]) == -1) {
190171801Sdelphij		perror("rename");
191171801Sdelphij		return EXIT_FAILURE;
192171801Sdelphij	}
193171801Sdelphij
194171801Sdelphij	return EXIT_SUCCESS;
195170809Sdelphij}
196170809Sdelphij
197170809Sdelphij/* --------------------------------------------------------------------- */
198170809Sdelphij
199170809Sdelphijint
200170809Sdelphijsockets_main(int argc, char **argv)
201170809Sdelphij{
202170809Sdelphij	int error, fd;
203170809Sdelphij	struct sockaddr_un addr;
204170809Sdelphij
205170809Sdelphij	if (argc < 2)
206170809Sdelphij		return EXIT_FAILURE;
207170809Sdelphij
208170809Sdelphij	fd = socket(PF_LOCAL, SOCK_STREAM, 0);
209170809Sdelphij	if (fd == -1) {
210170809Sdelphij		perror("socket");
211170809Sdelphij		return EXIT_FAILURE;
212170809Sdelphij	}
213170809Sdelphij
214170809Sdelphij	(void)strlcpy(addr.sun_path, argv[1], sizeof(addr.sun_path));
215170809Sdelphij	addr.sun_family = PF_UNIX;
216170809Sdelphij
217170809Sdelphij	error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
218170809Sdelphij	if (error == -1) {
219170809Sdelphij		perror("connect");
220170809Sdelphij		return EXIT_FAILURE;
221170809Sdelphij	}
222170809Sdelphij
223170809Sdelphij	close(fd);
224170809Sdelphij
225170809Sdelphij	return EXIT_SUCCESS;
226170809Sdelphij}
227170809Sdelphij
228170809Sdelphij/* --------------------------------------------------------------------- */
229170809Sdelphij
230170809Sdelphijint
231170809Sdelphijstatvfs_main(int argc, char **argv)
232170809Sdelphij{
233170809Sdelphij	int error;
234170809Sdelphij	struct statfs buf;
235170809Sdelphij
236170809Sdelphij	if (argc < 2)
237170809Sdelphij		return EXIT_FAILURE;
238170809Sdelphij
239170809Sdelphij	memset(&buf, 0, sizeof(buf));
240170809Sdelphij	buf.f_version = STATFS_VERSION;
241170809Sdelphij	error = statfs(argv[1], &buf);
242170809Sdelphij	if (error != 0) {
243170809Sdelphij		perror("statvfs");
244170809Sdelphij		return EXIT_FAILURE;
245170809Sdelphij	}
246170809Sdelphij
247197849Sdelphij	(void)printf("f_bsize=%ju\n", (uintmax_t)buf.f_bsize);
248197849Sdelphij	(void)printf("f_blocks=%ju\n", (uintmax_t)buf.f_blocks);
249197849Sdelphij	(void)printf("f_bfree=%ju\n", (uintmax_t)buf.f_bfree);
250197849Sdelphij	(void)printf("f_files=%ju\n", (uintmax_t)buf.f_files);
251170809Sdelphij
252170809Sdelphij	return EXIT_SUCCESS;
253170809Sdelphij}
254170809Sdelphij
255170809Sdelphij/* --------------------------------------------------------------------- */
256170809Sdelphij
257170809Sdelphijint
258170809Sdelphijmain(int argc, char **argv)
259170809Sdelphij{
260170809Sdelphij	int error;
261170809Sdelphij
262170809Sdelphij	if (argc < 2)
263170809Sdelphij		return EXIT_FAILURE;
264170809Sdelphij
265170809Sdelphij	argc -= 1;
266170809Sdelphij	argv += 1;
267170809Sdelphij
268170809Sdelphij	if (strcmp(argv[0], "getfh") == 0)
269170809Sdelphij		error = getfh_main(argc, argv);
270170809Sdelphij	else if (strcmp(argv[0], "kqueue") == 0)
271170809Sdelphij		error = kqueue_main(argc, argv);
272170809Sdelphij	else if (strcmp(argv[0], "rename") == 0)
273170809Sdelphij		error = rename_main(argc, argv);
274170809Sdelphij	else if (strcmp(argv[0], "sockets") == 0)
275170809Sdelphij		error = sockets_main(argc, argv);
276170809Sdelphij	else if (strcmp(argv[0], "statvfs") == 0)
277170809Sdelphij		error = statvfs_main(argc, argv);
278170809Sdelphij	else
279170809Sdelphij		error = EXIT_FAILURE;
280170809Sdelphij
281170809Sdelphij	return error;
282170809Sdelphij}
283