1 1.3 nakayama /* $NetBSD: only.c,v 1.3 2017/09/07 04:04:13 nakayama Exp $ */ 2 1.1 christos 3 1.1 christos /*- 4 1.1 christos * Copyright (c) 2013 The NetBSD Foundation, Inc. 5 1.1 christos * All rights reserved. 6 1.1 christos * 7 1.1 christos * This code is derived from software contributed to The NetBSD Foundation 8 1.1 christos * by Christos Zoulas. 9 1.1 christos * 10 1.1 christos * Redistribution and use in source and binary forms, with or without 11 1.1 christos * modification, are permitted provided that the following conditions 12 1.1 christos * are met: 13 1.1 christos * 1. Redistributions of source code must retain the above copyright 14 1.1 christos * notice, this list of conditions and the following disclaimer. 15 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 christos * notice, this list of conditions and the following disclaimer in the 17 1.1 christos * documentation and/or other materials provided with the distribution. 18 1.1 christos * 3. Neither the name of The NetBSD Foundation nor the names of its 19 1.1 christos * contributors may be used to endorse or promote products derived 20 1.1 christos * from this software without specific prior written permission. 21 1.1 christos * 22 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 1.1 christos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 1.1 christos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 1.1 christos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 1.1 christos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 1.1 christos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 1.1 christos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 1.1 christos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 1.1 christos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 1.1 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 1.1 christos * POSSIBILITY OF SUCH DAMAGE. 33 1.1 christos */ 34 1.1 christos #if HAVE_NBTOOL_CONFIG_H 35 1.1 christos #include "nbtool_config.h" 36 1.1 christos #endif 37 1.1 christos 38 1.1 christos #include <sys/cdefs.h> 39 1.1 christos 40 1.1 christos #if defined(__RCSID) && !defined(lint) 41 1.3 nakayama __RCSID("$NetBSD: only.c,v 1.3 2017/09/07 04:04:13 nakayama Exp $"); 42 1.1 christos #endif 43 1.1 christos 44 1.1 christos #include <sys/param.h> 45 1.1 christos 46 1.1 christos #include <stdio.h> 47 1.1 christos #include <stdlib.h> 48 1.1 christos #include <string.h> 49 1.1 christos #include <stdbool.h> 50 1.1 christos #include <time.h> 51 1.1 christos #include <err.h> 52 1.1 christos #include <util.h> 53 1.1 christos 54 1.1 christos #include "extern.h" 55 1.1 christos 56 1.1 christos struct hentry { 57 1.1 christos char *str; 58 1.1 christos uint32_t hash; 59 1.1 christos struct hentry *next; 60 1.1 christos }; 61 1.1 christos 62 1.1 christos static struct hentry *table[1024]; 63 1.1 christos static bool loaded; 64 1.1 christos 65 1.1 christos static uint32_t 66 1.1 christos hash_str(const char *str) 67 1.1 christos { 68 1.1 christos const uint8_t *s = (const uint8_t *)str; 69 1.1 christos uint8_t c; 70 1.1 christos uint32_t hash = 0; 71 1.1 christos while ((c = *s++) != '\0') 72 1.1 christos hash = hash * 33 + c; /* "perl": k=33, r=r+r/32 */ 73 1.1 christos return hash + (hash >> 5); 74 1.1 christos } 75 1.1 christos 76 1.1 christos static bool 77 1.1 christos hash_find(const char *str, uint32_t *h) 78 1.1 christos { 79 1.1 christos struct hentry *e; 80 1.1 christos *h = hash_str(str) % __arraycount(table); 81 1.1 christos 82 1.1 christos for (e = table[*h]; e; e = e->next) 83 1.1 christos if (e->hash == *h && strcmp(e->str, str) == 0) 84 1.1 christos return true; 85 1.1 christos return false; 86 1.1 christos } 87 1.1 christos 88 1.1 christos static void 89 1.2 christos hash_insert(char *str, uint32_t h) 90 1.1 christos { 91 1.1 christos struct hentry *e; 92 1.3 nakayama char *x; 93 1.1 christos 94 1.1 christos if ((e = malloc(sizeof(*e))) == NULL) 95 1.1 christos mtree_err("memory allocation error"); 96 1.3 nakayama if ((x = strdup(str)) == NULL) 97 1.3 nakayama mtree_err("memory allocation error"); 98 1.1 christos 99 1.3 nakayama e->str = x; 100 1.1 christos e->hash = h; 101 1.1 christos e->next = table[h]; 102 1.1 christos table[h] = e; 103 1.1 christos } 104 1.1 christos 105 1.2 christos static void 106 1.2 christos fill(char *str) 107 1.2 christos { 108 1.2 christos uint32_t h; 109 1.2 christos char *ptr = strrchr(str, '/'); 110 1.2 christos 111 1.2 christos if (ptr == NULL) 112 1.2 christos return; 113 1.2 christos 114 1.2 christos *ptr = '\0'; 115 1.2 christos if (!hash_find(str, &h)) { 116 1.3 nakayama hash_insert(str, h); 117 1.2 christos fill(str); 118 1.2 christos } 119 1.2 christos *ptr = '/'; 120 1.2 christos } 121 1.2 christos 122 1.1 christos void 123 1.1 christos load_only(const char *fname) 124 1.1 christos { 125 1.1 christos FILE *fp; 126 1.1 christos char *line; 127 1.1 christos size_t len, lineno; 128 1.1 christos 129 1.1 christos if ((fp = fopen(fname, "r")) == NULL) 130 1.1 christos err(1, "Cannot open `%s'", fname); 131 1.1 christos 132 1.2 christos while ((line = fparseln(fp, &len, &lineno, NULL, FPARSELN_UNESCALL))) { 133 1.2 christos uint32_t h; 134 1.2 christos if (hash_find(line, &h)) 135 1.2 christos err(1, "Duplicate entry %s", line); 136 1.2 christos hash_insert(line, h); 137 1.2 christos fill(line); 138 1.3 nakayama free(line); 139 1.2 christos } 140 1.1 christos 141 1.1 christos fclose(fp); 142 1.1 christos loaded = true; 143 1.1 christos } 144 1.1 christos 145 1.1 christos bool 146 1.1 christos find_only(const char *path) 147 1.1 christos { 148 1.1 christos uint32_t h; 149 1.1 christos 150 1.1 christos if (!loaded) 151 1.1 christos return true; 152 1.1 christos return hash_find(path, &h); 153 1.1 christos } 154