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