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 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 * 32 * $FreeBSD$ 33 */ 34 35 /* 36 * Helper tools for several tests. These are kept in a single file due 37 * to the limitations of bsd.prog.mk to build a single program in a 38 * given directory. 39 */ 40 41 #include <sys/param.h> 42 #include <sys/types.h> 43 #include <sys/event.h> 44 #include <sys/mount.h> 45 #include <sys/statvfs.h> 46 #include <sys/stdint.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 fhandle_t fh; 75 76 if (argc < 2) 77 return EXIT_FAILURE; 78 79 error = getfh(argv[1], &fh); 80 if (error == 0) 81 err(EXIT_FAILURE, "can not getfh"); 82 83 error = write(STDOUT_FILENO, &fh, sizeof(fh)); 84 if (error == -1) { 85 perror("write"); 86 return EXIT_FAILURE; 87 } 88 89 return 0; 90 } 91 92 /* --------------------------------------------------------------------- */ 93 94 int 95 kqueue_main(int argc, char **argv) 96 { 97 char *line; 98 int i, kq; 99 size_t len; 100 struct kevent *changes, event; 101 102 if (argc < 2) 103 return EXIT_FAILURE; 104 105 argc--; 106 argv++; 107 108 changes = malloc(sizeof(struct kevent) * (argc - 1)); 109 if (changes == NULL) 110 errx(EXIT_FAILURE, "not enough memory"); 111 112 for (i = 0; i < argc; i++) { 113 int fd; 114 115 fd = open(argv[i], O_RDONLY); 116 if (fd == -1) 117 err(EXIT_FAILURE, "cannot open %s", argv[i]); 118 119 EV_SET(&changes[i], fd, EVFILT_VNODE, 120 EV_ADD | EV_ENABLE | EV_ONESHOT, 121 NOTE_ATTRIB | NOTE_DELETE | NOTE_EXTEND | NOTE_LINK | 122 NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE, 123 0, 0); 124 } 125 126 kq = kqueue(); 127 if (kq == -1) 128 err(EXIT_FAILURE, "kqueue"); 129 130 while ((line = fgetln(stdin, &len)) != NULL) { 131 int ec, nev; 132 struct timespec to; 133 134 to.tv_sec = 0; 135 to.tv_nsec = 100000; 136 137 (void)kevent(kq, changes, argc, &event, 1, &to); 138 139 assert(len > 0); 140 assert(line[len - 1] == '\n'); 141 line[len - 1] = '\0'; 142 ec = system(line); 143 if (ec != EXIT_SUCCESS) 144 errx(ec, "%s returned %d", line, ec); 145 146 do { 147 nev = kevent(kq, changes, argc, &event, 1, &to); 148 if (nev == -1) 149 err(EXIT_FAILURE, "kevent"); 150 else if (nev > 0) { 151 for (i = 0; i < argc; i++) 152 if (event.ident == changes[i].ident) 153 break; 154 155 if (event.fflags & NOTE_ATTRIB) 156 printf("%s - NOTE_ATTRIB\n", argv[i]); 157 if (event.fflags & NOTE_DELETE) 158 printf("%s - NOTE_DELETE\n", argv[i]); 159 if (event.fflags & NOTE_EXTEND) 160 printf("%s - NOTE_EXTEND\n", argv[i]); 161 if (event.fflags & NOTE_LINK) 162 printf("%s - NOTE_LINK\n", argv[i]); 163 if (event.fflags & NOTE_RENAME) 164 printf("%s - NOTE_RENAME\n", argv[i]); 165 if (event.fflags & NOTE_REVOKE) 166 printf("%s - NOTE_REVOKE\n", argv[i]); 167 if (event.fflags & NOTE_WRITE) 168 printf("%s - NOTE_WRITE\n", argv[i]); 169 } 170 } while (nev > 0); 171 } 172 173 for (i = 0; i < argc; i++) 174 close(changes[i].ident); 175 free(changes); 176 177 return EXIT_SUCCESS; 178 } 179 180 /* --------------------------------------------------------------------- */ 181 182 int 183 rename_main(int argc, char **argv) 184 { 185 186 if (argc < 3) 187 return EXIT_FAILURE; 188 189 if (rename(argv[1], argv[2]) == -1) { 190 perror("rename"); 191 return EXIT_FAILURE; 192 } 193 194 return EXIT_SUCCESS; 195 } 196 197 /* --------------------------------------------------------------------- */ 198 199 int 200 sockets_main(int argc, char **argv) 201 { 202 int error, fd; 203 struct sockaddr_un addr; 204 205 if (argc < 2) 206 return EXIT_FAILURE; 207 208 fd = socket(PF_LOCAL, SOCK_STREAM, 0); 209 if (fd == -1) { 210 perror("socket"); 211 return EXIT_FAILURE; 212 } 213 214 (void)strlcpy(addr.sun_path, argv[1], sizeof(addr.sun_path)); 215 addr.sun_family = PF_UNIX; 216 217 error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); 218 if (error == -1) { 219 perror("connect"); 220 return EXIT_FAILURE; 221 } 222 223 close(fd); 224 225 return EXIT_SUCCESS; 226 } 227 228 /* --------------------------------------------------------------------- */ 229 230 int 231 statvfs_main(int argc, char **argv) 232 { 233 int error; 234 struct statfs buf; 235 236 if (argc < 2) 237 return EXIT_FAILURE; 238 239 memset(&buf, 0, sizeof(buf)); 240 buf.f_version = STATFS_VERSION; 241 error = statfs(argv[1], &buf); 242 if (error != 0) { 243 perror("statvfs"); 244 return EXIT_FAILURE; 245 } 246 247 (void)printf("f_bsize=%ju\n", (uintmax_t)buf.f_bsize); 248 (void)printf("f_blocks=%ju\n", (uintmax_t)buf.f_blocks); 249 (void)printf("f_bfree=%ju\n", (uintmax_t)buf.f_bfree); 250 (void)printf("f_files=%ju\n", (uintmax_t)buf.f_files); 251 252 return EXIT_SUCCESS; 253 } 254 255 /* --------------------------------------------------------------------- */ 256 257 int 258 main(int argc, char **argv) 259 { 260 int error; 261 262 if (argc < 2) 263 return EXIT_FAILURE; 264 265 argc -= 1; 266 argv += 1; 267 268 if (strcmp(argv[0], "getfh") == 0) 269 error = getfh_main(argc, argv); 270 else if (strcmp(argv[0], "kqueue") == 0) 271 error = kqueue_main(argc, argv); 272 else if (strcmp(argv[0], "rename") == 0) 273 error = rename_main(argc, argv); 274 else if (strcmp(argv[0], "sockets") == 0) 275 error = sockets_main(argc, argv); 276 else if (strcmp(argv[0], "statvfs") == 0) 277 error = statvfs_main(argc, argv); 278 else 279 error = EXIT_FAILURE; 280 281 return error; 282 } 283