h_tools.c revision 1.3
11.3Smartin/* $NetBSD: h_tools.c,v 1.3 2011/01/15 20:16:57 martin Exp $ */ 21.1Sjmmv 31.1Sjmmv/* 41.1Sjmmv * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. 51.1Sjmmv * All rights reserved. 61.1Sjmmv * 71.1Sjmmv * Redistribution and use in source and binary forms, with or without 81.1Sjmmv * modification, are permitted provided that the following conditions 91.1Sjmmv * are met: 101.1Sjmmv * 1. Redistributions of source code must retain the above copyright 111.1Sjmmv * notice, this list of conditions and the following disclaimer. 121.1Sjmmv * 2. Redistributions in binary form must reproduce the above copyright 131.1Sjmmv * notice, this list of conditions and the following disclaimer in the 141.1Sjmmv * documentation and/or other materials provided with the distribution. 151.1Sjmmv * 161.1Sjmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Sjmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Sjmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Sjmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Sjmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Sjmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Sjmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Sjmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Sjmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Sjmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Sjmmv * POSSIBILITY OF SUCH DAMAGE. 271.1Sjmmv */ 281.1Sjmmv 291.1Sjmmv/* 301.1Sjmmv * Helper tools for several tests. These are kept in a single file due 311.1Sjmmv * to the limitations of bsd.prog.mk to build a single program in a 321.1Sjmmv * given directory. 331.1Sjmmv */ 341.1Sjmmv 351.1Sjmmv#include <sys/param.h> 361.1Sjmmv#include <sys/types.h> 371.1Sjmmv#include <sys/event.h> 381.1Sjmmv#include <sys/mount.h> 391.1Sjmmv#include <sys/statvfs.h> 401.1Sjmmv#include <sys/socket.h> 411.1Sjmmv#include <sys/time.h> 421.1Sjmmv#include <sys/un.h> 431.1Sjmmv 441.1Sjmmv#include <assert.h> 451.1Sjmmv#include <err.h> 461.1Sjmmv#include <errno.h> 471.1Sjmmv#include <fcntl.h> 481.1Sjmmv#include <stdio.h> 491.1Sjmmv#include <stdlib.h> 501.1Sjmmv#include <string.h> 511.1Sjmmv#include <unistd.h> 521.1Sjmmv 531.1Sjmmv/* --------------------------------------------------------------------- */ 541.1Sjmmv 551.1Sjmmvstatic int getfh_main(int, char **); 561.1Sjmmvstatic int kqueue_main(int, char **); 571.1Sjmmvstatic int rename_main(int, char **); 581.1Sjmmvstatic int sockets_main(int, char **); 591.1Sjmmvstatic int statvfs_main(int, char **); 601.1Sjmmv 611.1Sjmmv/* --------------------------------------------------------------------- */ 621.1Sjmmv 631.1Sjmmvint 641.1Sjmmvgetfh_main(int argc, char **argv) 651.1Sjmmv{ 661.1Sjmmv int error; 671.1Sjmmv void *fh; 681.1Sjmmv size_t fh_size; 691.1Sjmmv 701.1Sjmmv if (argc < 2) 711.1Sjmmv return EXIT_FAILURE; 721.1Sjmmv 731.1Sjmmv fh_size = 0; 741.1Sjmmv fh = NULL; 751.1Sjmmv for (;;) { 761.1Sjmmv if (fh_size) { 771.1Sjmmv fh = malloc(fh_size); 781.1Sjmmv if (fh == NULL) { 791.1Sjmmv fprintf(stderr, "out of memory"); 801.1Sjmmv return EXIT_FAILURE; 811.1Sjmmv } 821.1Sjmmv } 831.1Sjmmv /* 841.1Sjmmv * The kernel provides the necessary size in fh_size - 851.1Sjmmv * but it may change if someone moves things around, 861.1Sjmmv * so retry untill we have enough memory. 871.1Sjmmv */ 881.1Sjmmv error = getfh(argv[1], fh, &fh_size); 891.1Sjmmv if (error == 0) { 901.1Sjmmv break; 911.1Sjmmv } else { 921.1Sjmmv if (fh != NULL) 931.1Sjmmv free(fh); 941.1Sjmmv if (errno != E2BIG) { 951.1Sjmmv perror("getfh"); 961.1Sjmmv return EXIT_FAILURE; 971.1Sjmmv } 981.1Sjmmv } 991.1Sjmmv } 1001.1Sjmmv 1011.1Sjmmv error = write(STDOUT_FILENO, fh, fh_size); 1021.1Sjmmv if (error == -1) { 1031.1Sjmmv perror("write"); 1041.1Sjmmv return EXIT_FAILURE; 1051.1Sjmmv } 1061.1Sjmmv free(fh); 1071.1Sjmmv 1081.1Sjmmv return 0; 1091.1Sjmmv} 1101.1Sjmmv 1111.1Sjmmv/* --------------------------------------------------------------------- */ 1121.1Sjmmv 1131.1Sjmmvint 1141.1Sjmmvkqueue_main(int argc, char **argv) 1151.1Sjmmv{ 1161.1Sjmmv char *line; 1171.1Sjmmv int i, kq; 1181.1Sjmmv size_t len; 1191.1Sjmmv struct kevent *changes, event; 1201.1Sjmmv 1211.1Sjmmv if (argc < 2) 1221.1Sjmmv return EXIT_FAILURE; 1231.1Sjmmv 1241.1Sjmmv argc--; 1251.1Sjmmv argv++; 1261.1Sjmmv 1271.3Smartin changes = malloc(sizeof(struct kevent) * argc); 1281.1Sjmmv if (changes == NULL) 1291.1Sjmmv errx(EXIT_FAILURE, "not enough memory"); 1301.1Sjmmv 1311.1Sjmmv for (i = 0; i < argc; i++) { 1321.1Sjmmv int fd; 1331.1Sjmmv 1341.1Sjmmv fd = open(argv[i], O_RDONLY); 1351.1Sjmmv if (fd == -1) 1361.1Sjmmv err(EXIT_FAILURE, "cannot open %s", argv[i]); 1371.1Sjmmv 1381.1Sjmmv EV_SET(&changes[i], fd, EVFILT_VNODE, 1391.1Sjmmv EV_ADD | EV_ENABLE | EV_ONESHOT, 1401.1Sjmmv NOTE_ATTRIB | NOTE_DELETE | NOTE_EXTEND | NOTE_LINK | 1411.1Sjmmv NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE, 1421.1Sjmmv 0, 0); 1431.1Sjmmv } 1441.1Sjmmv 1451.1Sjmmv kq = kqueue(); 1461.1Sjmmv if (kq == -1) 1471.1Sjmmv err(EXIT_FAILURE, "kqueue"); 1481.1Sjmmv 1491.1Sjmmv while ((line = fgetln(stdin, &len)) != NULL) { 1501.1Sjmmv int ec, nev; 1511.1Sjmmv struct timespec to; 1521.1Sjmmv 1531.1Sjmmv to.tv_sec = 0; 1541.1Sjmmv to.tv_nsec = 100000; 1551.1Sjmmv 1561.1Sjmmv (void)kevent(kq, changes, argc, &event, 1, &to); 1571.1Sjmmv 1581.1Sjmmv assert(len > 0); 1591.1Sjmmv assert(line[len - 1] == '\n'); 1601.1Sjmmv line[len - 1] = '\0'; 1611.1Sjmmv ec = system(line); 1621.1Sjmmv if (ec != EXIT_SUCCESS) 1631.1Sjmmv errx(ec, "%s returned %d", line, ec); 1641.1Sjmmv 1651.1Sjmmv do { 1661.1Sjmmv nev = kevent(kq, changes, argc, &event, 1, &to); 1671.1Sjmmv if (nev == -1) 1681.1Sjmmv err(EXIT_FAILURE, "kevent"); 1691.1Sjmmv else if (nev > 0) { 1701.1Sjmmv for (i = 0; i < argc; i++) 1711.1Sjmmv if (event.ident == changes[i].ident) 1721.1Sjmmv break; 1731.1Sjmmv 1741.1Sjmmv if (event.fflags & NOTE_ATTRIB) 1751.1Sjmmv printf("%s - NOTE_ATTRIB\n", argv[i]); 1761.1Sjmmv if (event.fflags & NOTE_DELETE) 1771.1Sjmmv printf("%s - NOTE_DELETE\n", argv[i]); 1781.1Sjmmv if (event.fflags & NOTE_EXTEND) 1791.1Sjmmv printf("%s - NOTE_EXTEND\n", argv[i]); 1801.1Sjmmv if (event.fflags & NOTE_LINK) 1811.1Sjmmv printf("%s - NOTE_LINK\n", argv[i]); 1821.1Sjmmv if (event.fflags & NOTE_RENAME) 1831.1Sjmmv printf("%s - NOTE_RENAME\n", argv[i]); 1841.1Sjmmv if (event.fflags & NOTE_REVOKE) 1851.1Sjmmv printf("%s - NOTE_REVOKE\n", argv[i]); 1861.1Sjmmv if (event.fflags & NOTE_WRITE) 1871.1Sjmmv printf("%s - NOTE_WRITE\n", argv[i]); 1881.1Sjmmv } 1891.1Sjmmv } while (nev > 0); 1901.1Sjmmv } 1911.1Sjmmv 1921.1Sjmmv for (i = 0; i < argc; i++) 1931.1Sjmmv close(changes[i].ident); 1941.1Sjmmv free(changes); 1951.1Sjmmv 1961.1Sjmmv return EXIT_SUCCESS; 1971.1Sjmmv} 1981.1Sjmmv 1991.1Sjmmv/* --------------------------------------------------------------------- */ 2001.1Sjmmv 2011.1Sjmmvint 2021.1Sjmmvrename_main(int argc, char **argv) 2031.1Sjmmv{ 2041.1Sjmmv 2051.1Sjmmv if (argc < 3) 2061.1Sjmmv return EXIT_FAILURE; 2071.1Sjmmv 2081.1Sjmmv if (rename(argv[1], argv[2]) == -1) { 2091.1Sjmmv perror("rename"); 2101.1Sjmmv return EXIT_FAILURE; 2111.1Sjmmv } 2121.1Sjmmv 2131.1Sjmmv return EXIT_SUCCESS; 2141.1Sjmmv} 2151.1Sjmmv 2161.1Sjmmv/* --------------------------------------------------------------------- */ 2171.1Sjmmv 2181.1Sjmmvint 2191.1Sjmmvsockets_main(int argc, char **argv) 2201.1Sjmmv{ 2211.1Sjmmv int error, fd; 2221.1Sjmmv struct sockaddr_un addr; 2231.1Sjmmv 2241.1Sjmmv if (argc < 2) 2251.1Sjmmv return EXIT_FAILURE; 2261.1Sjmmv 2271.1Sjmmv fd = socket(PF_LOCAL, SOCK_STREAM, 0); 2281.1Sjmmv if (fd == -1) { 2291.1Sjmmv perror("socket"); 2301.1Sjmmv return EXIT_FAILURE; 2311.1Sjmmv } 2321.1Sjmmv 2331.1Sjmmv (void)strlcpy(addr.sun_path, argv[1], sizeof(addr.sun_path)); 2341.1Sjmmv addr.sun_family = PF_UNIX; 2351.1Sjmmv 2361.1Sjmmv error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); 2371.1Sjmmv if (error == -1) { 2381.1Sjmmv perror("connect"); 2391.1Sjmmv return EXIT_FAILURE; 2401.1Sjmmv } 2411.1Sjmmv 2421.1Sjmmv close(fd); 2431.1Sjmmv 2441.1Sjmmv return EXIT_SUCCESS; 2451.1Sjmmv} 2461.1Sjmmv 2471.1Sjmmv/* --------------------------------------------------------------------- */ 2481.1Sjmmv 2491.1Sjmmvint 2501.1Sjmmvstatvfs_main(int argc, char **argv) 2511.1Sjmmv{ 2521.1Sjmmv int error; 2531.1Sjmmv struct statvfs buf; 2541.1Sjmmv 2551.1Sjmmv if (argc < 2) 2561.1Sjmmv return EXIT_FAILURE; 2571.1Sjmmv 2581.1Sjmmv error = statvfs(argv[1], &buf); 2591.1Sjmmv if (error != 0) { 2601.1Sjmmv perror("statvfs"); 2611.1Sjmmv return EXIT_FAILURE; 2621.1Sjmmv } 2631.1Sjmmv 2641.1Sjmmv (void)printf("f_bsize=%lu\n", buf.f_bsize); 2651.1Sjmmv (void)printf("f_blocks=%" PRId64 "\n", buf.f_blocks); 2661.1Sjmmv (void)printf("f_bfree=%" PRId64 "\n", buf.f_bfree); 2671.1Sjmmv (void)printf("f_files=%" PRId64 "\n", buf.f_files); 2681.1Sjmmv 2691.1Sjmmv return EXIT_SUCCESS; 2701.1Sjmmv} 2711.1Sjmmv 2721.1Sjmmv/* --------------------------------------------------------------------- */ 2731.1Sjmmv 2741.1Sjmmvint 2751.1Sjmmvmain(int argc, char **argv) 2761.1Sjmmv{ 2771.1Sjmmv int error; 2781.1Sjmmv 2791.1Sjmmv if (argc < 2) 2801.1Sjmmv return EXIT_FAILURE; 2811.1Sjmmv 2821.1Sjmmv argc -= 1; 2831.1Sjmmv argv += 1; 2841.1Sjmmv 2851.1Sjmmv if (strcmp(argv[0], "getfh") == 0) 2861.1Sjmmv error = getfh_main(argc, argv); 2871.1Sjmmv else if (strcmp(argv[0], "kqueue") == 0) 2881.1Sjmmv error = kqueue_main(argc, argv); 2891.1Sjmmv else if (strcmp(argv[0], "rename") == 0) 2901.1Sjmmv error = rename_main(argc, argv); 2911.1Sjmmv else if (strcmp(argv[0], "sockets") == 0) 2921.1Sjmmv error = sockets_main(argc, argv); 2931.1Sjmmv else if (strcmp(argv[0], "statvfs") == 0) 2941.1Sjmmv error = statvfs_main(argc, argv); 2951.1Sjmmv else 2961.1Sjmmv error = EXIT_FAILURE; 2971.1Sjmmv 2981.1Sjmmv return error; 2991.1Sjmmv} 300