1272343Sngie/* $NetBSD: h_tools.c,v 1.4 2011/06/11 18:03:17 christos Exp $ */ 2272343Sngie 3272343Sngie/* 4272343Sngie * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26272343Sngie * POSSIBILITY OF SUCH DAMAGE. 27272343Sngie */ 28272343Sngie 29272343Sngie/* 30272343Sngie * Helper tools for several tests. These are kept in a single file due 31272343Sngie * to the limitations of bsd.prog.mk to build a single program in a 32272343Sngie * given directory. 33272343Sngie */ 34272343Sngie 35272343Sngie#include <sys/param.h> 36272343Sngie#include <sys/types.h> 37272343Sngie#include <sys/event.h> 38272343Sngie#include <sys/mount.h> 39272343Sngie#include <sys/statvfs.h> 40272343Sngie#include <sys/socket.h> 41272343Sngie#include <sys/time.h> 42272343Sngie#include <sys/un.h> 43272343Sngie 44272343Sngie#include <assert.h> 45272343Sngie#include <err.h> 46272343Sngie#include <errno.h> 47272343Sngie#include <fcntl.h> 48272343Sngie#include <stdio.h> 49272343Sngie#include <stdlib.h> 50272343Sngie#include <string.h> 51272343Sngie#include <unistd.h> 52272343Sngie 53309668Sngie#ifdef __FreeBSD__ 54309668Sngie#include <inttypes.h> 55309668Sngie#endif 56309668Sngie 57272343Sngie/* --------------------------------------------------------------------- */ 58272343Sngie 59272343Sngiestatic int getfh_main(int, char **); 60272343Sngiestatic int kqueue_main(int, char **); 61272343Sngiestatic int rename_main(int, char **); 62272343Sngiestatic int sockets_main(int, char **); 63272343Sngiestatic int statvfs_main(int, char **); 64272343Sngie 65272343Sngie/* --------------------------------------------------------------------- */ 66272343Sngie 67272343Sngieint 68272343Sngiegetfh_main(int argc, char **argv) 69272343Sngie{ 70272343Sngie int error; 71272343Sngie void *fh; 72272343Sngie size_t fh_size; 73272343Sngie 74272343Sngie if (argc < 2) 75272343Sngie return EXIT_FAILURE; 76272343Sngie 77309668Sngie#ifdef __FreeBSD__ 78309668Sngie fh_size = sizeof(fhandle_t); 79309668Sngie#else 80272343Sngie fh_size = 0; 81309668Sngie#endif 82309668Sngie 83272343Sngie fh = NULL; 84272343Sngie for (;;) { 85272343Sngie if (fh_size) { 86272343Sngie fh = malloc(fh_size); 87272343Sngie if (fh == NULL) { 88272343Sngie fprintf(stderr, "out of memory"); 89272343Sngie return EXIT_FAILURE; 90272343Sngie } 91272343Sngie } 92272343Sngie /* 93272343Sngie * The kernel provides the necessary size in fh_size - 94272343Sngie * but it may change if someone moves things around, 95272343Sngie * so retry untill we have enough memory. 96272343Sngie */ 97309668Sngie#ifdef __FreeBSD__ 98309668Sngie error = getfh(argv[1], fh); 99309668Sngie#else 100272343Sngie error = getfh(argv[1], fh, &fh_size); 101309668Sngie#endif 102272343Sngie if (error == 0) { 103272343Sngie break; 104272343Sngie } else { 105272343Sngie if (fh != NULL) 106272343Sngie free(fh); 107272343Sngie if (errno != E2BIG) { 108272343Sngie warn("getfh"); 109272343Sngie return EXIT_FAILURE; 110272343Sngie } 111272343Sngie } 112272343Sngie } 113272343Sngie 114272343Sngie error = write(STDOUT_FILENO, fh, fh_size); 115272343Sngie if (error == -1) { 116272343Sngie warn("write"); 117272343Sngie return EXIT_FAILURE; 118272343Sngie } 119272343Sngie free(fh); 120272343Sngie 121272343Sngie return 0; 122272343Sngie} 123272343Sngie 124272343Sngie/* --------------------------------------------------------------------- */ 125272343Sngie 126272343Sngieint 127272343Sngiekqueue_main(int argc, char **argv) 128272343Sngie{ 129272343Sngie char *line; 130272343Sngie int i, kq; 131272343Sngie size_t len; 132272343Sngie struct kevent *changes, event; 133272343Sngie 134272343Sngie if (argc < 2) 135272343Sngie return EXIT_FAILURE; 136272343Sngie 137272343Sngie argc--; 138272343Sngie argv++; 139272343Sngie 140272343Sngie changes = malloc(sizeof(struct kevent) * argc); 141272343Sngie if (changes == NULL) 142272343Sngie errx(EXIT_FAILURE, "not enough memory"); 143272343Sngie 144272343Sngie for (i = 0; i < argc; i++) { 145272343Sngie int fd; 146272343Sngie 147272343Sngie fd = open(argv[i], O_RDONLY); 148272343Sngie if (fd == -1) 149272343Sngie err(EXIT_FAILURE, "cannot open %s", argv[i]); 150272343Sngie 151272343Sngie EV_SET(&changes[i], fd, EVFILT_VNODE, 152272343Sngie EV_ADD | EV_ENABLE | EV_ONESHOT, 153272343Sngie NOTE_ATTRIB | NOTE_DELETE | NOTE_EXTEND | NOTE_LINK | 154272343Sngie NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE, 155272343Sngie 0, 0); 156272343Sngie } 157272343Sngie 158272343Sngie kq = kqueue(); 159272343Sngie if (kq == -1) 160272343Sngie err(EXIT_FAILURE, "kqueue"); 161272343Sngie 162272343Sngie while ((line = fgetln(stdin, &len)) != NULL) { 163272343Sngie int ec, nev; 164272343Sngie struct timespec to; 165272343Sngie 166272343Sngie to.tv_sec = 0; 167272343Sngie to.tv_nsec = 100000; 168272343Sngie 169272343Sngie (void)kevent(kq, changes, argc, &event, 1, &to); 170272343Sngie 171272343Sngie assert(len > 0); 172272343Sngie assert(line[len - 1] == '\n'); 173272343Sngie line[len - 1] = '\0'; 174272343Sngie ec = system(line); 175272343Sngie if (ec != EXIT_SUCCESS) 176272343Sngie errx(ec, "%s returned %d", line, ec); 177272343Sngie 178272343Sngie do { 179272343Sngie nev = kevent(kq, changes, argc, &event, 1, &to); 180272343Sngie if (nev == -1) 181272343Sngie err(EXIT_FAILURE, "kevent"); 182272343Sngie else if (nev > 0) { 183272343Sngie for (i = 0; i < argc; i++) 184272343Sngie if (event.ident == changes[i].ident) 185272343Sngie break; 186272343Sngie 187272343Sngie if (event.fflags & NOTE_ATTRIB) 188272343Sngie printf("%s - NOTE_ATTRIB\n", argv[i]); 189272343Sngie if (event.fflags & NOTE_DELETE) 190272343Sngie printf("%s - NOTE_DELETE\n", argv[i]); 191272343Sngie if (event.fflags & NOTE_EXTEND) 192272343Sngie printf("%s - NOTE_EXTEND\n", argv[i]); 193272343Sngie if (event.fflags & NOTE_LINK) 194272343Sngie printf("%s - NOTE_LINK\n", argv[i]); 195272343Sngie if (event.fflags & NOTE_RENAME) 196272343Sngie printf("%s - NOTE_RENAME\n", argv[i]); 197272343Sngie if (event.fflags & NOTE_REVOKE) 198272343Sngie printf("%s - NOTE_REVOKE\n", argv[i]); 199272343Sngie if (event.fflags & NOTE_WRITE) 200272343Sngie printf("%s - NOTE_WRITE\n", argv[i]); 201272343Sngie } 202272343Sngie } while (nev > 0); 203272343Sngie } 204272343Sngie 205272343Sngie for (i = 0; i < argc; i++) 206272343Sngie close(changes[i].ident); 207272343Sngie free(changes); 208272343Sngie 209272343Sngie return EXIT_SUCCESS; 210272343Sngie} 211272343Sngie 212272343Sngie/* --------------------------------------------------------------------- */ 213272343Sngie 214272343Sngieint 215272343Sngierename_main(int argc, char **argv) 216272343Sngie{ 217272343Sngie 218272343Sngie if (argc < 3) 219272343Sngie return EXIT_FAILURE; 220272343Sngie 221272343Sngie if (rename(argv[1], argv[2]) == -1) { 222272343Sngie warn("rename"); 223272343Sngie return EXIT_FAILURE; 224272343Sngie } 225272343Sngie 226272343Sngie return EXIT_SUCCESS; 227272343Sngie} 228272343Sngie 229272343Sngie/* --------------------------------------------------------------------- */ 230272343Sngie 231272343Sngieint 232272343Sngiesockets_main(int argc, char **argv) 233272343Sngie{ 234272343Sngie int error, fd; 235272343Sngie struct sockaddr_un addr; 236272343Sngie 237272343Sngie if (argc < 2) 238272343Sngie return EXIT_FAILURE; 239272343Sngie 240272343Sngie fd = socket(PF_LOCAL, SOCK_STREAM, 0); 241272343Sngie if (fd == -1) { 242272343Sngie warn("socket"); 243272343Sngie return EXIT_FAILURE; 244272343Sngie } 245272343Sngie 246311622Sngie#ifdef __FreeBSD__ 247311622Sngie memset(&addr, 0, sizeof(addr)); 248311622Sngie#endif 249272343Sngie (void)strlcpy(addr.sun_path, argv[1], sizeof(addr.sun_path)); 250272343Sngie addr.sun_family = PF_UNIX; 251311622Sngie#ifdef __FreeBSD__ 252311622Sngie error = bind(fd, (struct sockaddr *)&addr, SUN_LEN(&addr)); 253311622Sngie#else 254272343Sngie error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); 255311622Sngie#endif 256272343Sngie if (error == -1) { 257272343Sngie warn("connect"); 258311622Sngie#ifdef __FreeBSD__ 259311622Sngie (void)close(fd); 260311622Sngie#endif 261272343Sngie return EXIT_FAILURE; 262272343Sngie } 263272343Sngie 264272343Sngie close(fd); 265272343Sngie 266272343Sngie return EXIT_SUCCESS; 267272343Sngie} 268272343Sngie 269272343Sngie/* --------------------------------------------------------------------- */ 270272343Sngie 271272343Sngieint 272272343Sngiestatvfs_main(int argc, char **argv) 273272343Sngie{ 274272343Sngie int error; 275272343Sngie struct statvfs buf; 276272343Sngie 277272343Sngie if (argc < 2) 278272343Sngie return EXIT_FAILURE; 279272343Sngie 280272343Sngie error = statvfs(argv[1], &buf); 281272343Sngie if (error != 0) { 282272343Sngie warn("statvfs"); 283272343Sngie return EXIT_FAILURE; 284272343Sngie } 285272343Sngie 286272343Sngie (void)printf("f_bsize=%lu\n", buf.f_bsize); 287272343Sngie (void)printf("f_blocks=%" PRId64 "\n", buf.f_blocks); 288272343Sngie (void)printf("f_bfree=%" PRId64 "\n", buf.f_bfree); 289272343Sngie (void)printf("f_files=%" PRId64 "\n", buf.f_files); 290272343Sngie 291272343Sngie return EXIT_SUCCESS; 292272343Sngie} 293272343Sngie 294272343Sngie/* --------------------------------------------------------------------- */ 295272343Sngie 296272343Sngieint 297272343Sngiemain(int argc, char **argv) 298272343Sngie{ 299272343Sngie int error; 300272343Sngie 301272343Sngie if (argc < 2) 302272343Sngie return EXIT_FAILURE; 303272343Sngie 304272343Sngie argc -= 1; 305272343Sngie argv += 1; 306272343Sngie 307272343Sngie if (strcmp(argv[0], "getfh") == 0) 308272343Sngie error = getfh_main(argc, argv); 309272343Sngie else if (strcmp(argv[0], "kqueue") == 0) 310272343Sngie error = kqueue_main(argc, argv); 311272343Sngie else if (strcmp(argv[0], "rename") == 0) 312272343Sngie error = rename_main(argc, argv); 313272343Sngie else if (strcmp(argv[0], "sockets") == 0) 314272343Sngie error = sockets_main(argc, argv); 315272343Sngie else if (strcmp(argv[0], "statvfs") == 0) 316272343Sngie error = statvfs_main(argc, argv); 317272343Sngie else 318272343Sngie error = EXIT_FAILURE; 319272343Sngie 320272343Sngie return error; 321272343Sngie} 322