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