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