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