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 33 /* 34 * Helper tools for several tests. These are kept in a single file due 35 * to the limitations of bsd.prog.mk to build a single program in a 36 * given directory. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/types.h> 41 #include <sys/event.h> 42 #include <sys/mount.h> 43 #include <sys/statvfs.h> 44 #include <sys/stdint.h> 45 #include <sys/socket.h> 46 #include <sys/time.h> 47 #include <sys/un.h> 48 49 #include <assert.h> 50 #include <err.h> 51 #include <errno.h> 52 #include <fcntl.h> 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #include <unistd.h> 57 58 /* --------------------------------------------------------------------- */ 59 60 static int getfh_main(int, char **); 61 static int kqueue_main(int, char **); 62 static int rename_main(int, char **); 63 static int sockets_main(int, char **); 64 static int statvfs_main(int, char **); 65 66 /* --------------------------------------------------------------------- */ 67 68 int 69 getfh_main(int argc, char **argv) 70 { 71 int error; 72 fhandle_t fh; 73 74 if (argc < 2) 75 return EXIT_FAILURE; 76 77 error = getfh(argv[1], &fh); 78 if (error == 0) 79 err(EXIT_FAILURE, "can not getfh"); 80 81 error = write(STDOUT_FILENO, &fh, sizeof(fh)); 82 if (error == -1) { 83 perror("write"); 84 return EXIT_FAILURE; 85 } 86 87 return 0; 88 } 89 90 /* --------------------------------------------------------------------- */ 91 92 int 93 kqueue_main(int argc, char **argv) 94 { 95 char *line; 96 int i, kq; 97 size_t len; 98 struct kevent *changes, event; 99 100 if (argc < 2) 101 return EXIT_FAILURE; 102 103 argc--; 104 argv++; 105 106 changes = malloc(sizeof(struct kevent) * (argc - 1)); 107 if (changes == NULL) 108 errx(EXIT_FAILURE, "not enough memory"); 109 110 for (i = 0; i < argc; i++) { 111 int fd; 112 113 fd = open(argv[i], O_RDONLY); 114 if (fd == -1) 115 err(EXIT_FAILURE, "cannot open %s", argv[i]); 116 117 EV_SET(&changes[i], fd, EVFILT_VNODE, 118 EV_ADD | EV_ENABLE | EV_ONESHOT, 119 NOTE_ATTRIB | NOTE_DELETE | NOTE_EXTEND | NOTE_LINK | 120 NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE, 121 0, 0); 122 } 123 124 kq = kqueue(); 125 if (kq == -1) 126 err(EXIT_FAILURE, "kqueue"); 127 128 while ((line = fgetln(stdin, &len)) != NULL) { 129 int ec, nev; 130 struct timespec to; 131 132 to.tv_sec = 0; 133 to.tv_nsec = 100000; 134 135 (void)kevent(kq, changes, argc, &event, 1, &to); 136 137 assert(len > 0); 138 assert(line[len - 1] == '\n'); 139 line[len - 1] = '\0'; 140 ec = system(line); 141 if (ec != EXIT_SUCCESS) 142 errx(ec, "%s returned %d", line, ec); 143 144 do { 145 nev = kevent(kq, changes, argc, &event, 1, &to); 146 if (nev == -1) 147 err(EXIT_FAILURE, "kevent"); 148 else if (nev > 0) { 149 for (i = 0; i < argc; i++) 150 if (event.ident == changes[i].ident) 151 break; 152 153 if (event.fflags & NOTE_ATTRIB) 154 printf("%s - NOTE_ATTRIB\n", argv[i]); 155 if (event.fflags & NOTE_DELETE) 156 printf("%s - NOTE_DELETE\n", argv[i]); 157 if (event.fflags & NOTE_EXTEND) 158 printf("%s - NOTE_EXTEND\n", argv[i]); 159 if (event.fflags & NOTE_LINK) 160 printf("%s - NOTE_LINK\n", argv[i]); 161 if (event.fflags & NOTE_RENAME) 162 printf("%s - NOTE_RENAME\n", argv[i]); 163 if (event.fflags & NOTE_REVOKE) 164 printf("%s - NOTE_REVOKE\n", argv[i]); 165 if (event.fflags & NOTE_WRITE) 166 printf("%s - NOTE_WRITE\n", argv[i]); 167 } 168 } while (nev > 0); 169 } 170 171 for (i = 0; i < argc; i++) 172 close(changes[i].ident); 173 free(changes); 174 175 return EXIT_SUCCESS; 176 } 177 178 /* --------------------------------------------------------------------- */ 179 180 int 181 rename_main(int argc, char **argv) 182 { 183 184 if (argc < 3) 185 return EXIT_FAILURE; 186 187 if (rename(argv[1], argv[2]) == -1) { 188 perror("rename"); 189 return EXIT_FAILURE; 190 } 191 192 return EXIT_SUCCESS; 193 } 194 195 /* --------------------------------------------------------------------- */ 196 197 int 198 sockets_main(int argc, char **argv) 199 { 200 int error, fd; 201 struct sockaddr_un addr; 202 203 if (argc < 2) 204 return EXIT_FAILURE; 205 206 fd = socket(PF_LOCAL, SOCK_STREAM, 0); 207 if (fd == -1) { 208 perror("socket"); 209 return EXIT_FAILURE; 210 } 211 212 (void)strlcpy(addr.sun_path, argv[1], sizeof(addr.sun_path)); 213 addr.sun_family = PF_UNIX; 214 215 error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); 216 if (error == -1) { 217 perror("connect"); 218 return EXIT_FAILURE; 219 } 220 221 close(fd); 222 223 return EXIT_SUCCESS; 224 } 225 226 /* --------------------------------------------------------------------- */ 227 228 int 229 statvfs_main(int argc, char **argv) 230 { 231 int error; 232 struct statfs buf; 233 234 if (argc < 2) 235 return EXIT_FAILURE; 236 237 memset(&buf, 0, sizeof(buf)); 238 buf.f_version = STATFS_VERSION; 239 error = statfs(argv[1], &buf); 240 if (error != 0) { 241 perror("statvfs"); 242 return EXIT_FAILURE; 243 } 244 245 (void)printf("f_bsize=%ju\n", (uintmax_t)buf.f_bsize); 246 (void)printf("f_blocks=%ju\n", (uintmax_t)buf.f_blocks); 247 (void)printf("f_bfree=%ju\n", (uintmax_t)buf.f_bfree); 248 (void)printf("f_files=%ju\n", (uintmax_t)buf.f_files); 249 250 return EXIT_SUCCESS; 251 } 252 253 /* --------------------------------------------------------------------- */ 254 255 int 256 main(int argc, char **argv) 257 { 258 int error; 259 260 if (argc < 2) 261 return EXIT_FAILURE; 262 263 argc -= 1; 264 argv += 1; 265 266 if (strcmp(argv[0], "getfh") == 0) 267 error = getfh_main(argc, argv); 268 else if (strcmp(argv[0], "kqueue") == 0) 269 error = kqueue_main(argc, argv); 270 else if (strcmp(argv[0], "rename") == 0) 271 error = rename_main(argc, argv); 272 else if (strcmp(argv[0], "sockets") == 0) 273 error = sockets_main(argc, argv); 274 else if (strcmp(argv[0], "statvfs") == 0) 275 error = statvfs_main(argc, argv); 276 else 277 error = EXIT_FAILURE; 278 279 return error; 280 } 281