1249269Sed/* $NetBSD: only.c,v 1.2 2013/02/05 00:59:03 christos Exp $ */ 2249269Sed 3249269Sed/*- 4249269Sed * Copyright (c) 2013 The NetBSD Foundation, Inc. 5249269Sed * All rights reserved. 6249269Sed * 7249269Sed * This code is derived from software contributed to The NetBSD Foundation 8249269Sed * by Christos Zoulas. 9249269Sed * 10249269Sed * Redistribution and use in source and binary forms, with or without 11249269Sed * modification, are permitted provided that the following conditions 12249269Sed * are met: 13249269Sed * 1. Redistributions of source code must retain the above copyright 14249269Sed * notice, this list of conditions and the following disclaimer. 15249269Sed * 2. Redistributions in binary form must reproduce the above copyright 16249269Sed * notice, this list of conditions and the following disclaimer in the 17249269Sed * documentation and/or other materials provided with the distribution. 18249269Sed * 3. Neither the name of The NetBSD Foundation nor the names of its 19249269Sed * contributors may be used to endorse or promote products derived 20249269Sed * from this software without specific prior written permission. 21249269Sed * 22249269Sed * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23249269Sed * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24249269Sed * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25249269Sed * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26249269Sed * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27249269Sed * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28249269Sed * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29249269Sed * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30249269Sed * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31249269Sed * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32249269Sed * POSSIBILITY OF SUCH DAMAGE. 33249269Sed */ 34249269Sed#if HAVE_NBTOOL_CONFIG_H 35249269Sed#include "nbtool_config.h" 36249269Sed#endif 37249269Sed 38249269Sed#include <sys/cdefs.h> 39249269Sed 40249269Sed#if defined(__RCSID) && !defined(lint) 41249269Sed__RCSID("$NetBSD: only.c,v 1.2 2013/02/05 00:59:03 christos Exp $"); 42249269Sed#endif 43249269Sed 44249269Sed#include <sys/param.h> 45249269Sed 46249269Sed#include <stdio.h> 47249269Sed#include <stdlib.h> 48249269Sed#include <string.h> 49249269Sed#include <stdbool.h> 50249269Sed#include <time.h> 51249269Sed#include <err.h> 52249269Sed#include <util.h> 53249269Sed 54249269Sed#include "extern.h" 55249269Sed 56249269Sedstruct hentry { 57249269Sed char *str; 58249269Sed uint32_t hash; 59249269Sed struct hentry *next; 60249269Sed}; 61249269Sed 62249269Sedstatic struct hentry *table[1024]; 63249269Sedstatic bool loaded; 64249269Sed 65249269Sedstatic uint32_t 66249269Sedhash_str(const char *str) 67249269Sed{ 68249269Sed const uint8_t *s = (const uint8_t *)str; 69249269Sed uint8_t c; 70249269Sed uint32_t hash = 0; 71249269Sed while ((c = *s++) != '\0') 72249269Sed hash = hash * 33 + c; /* "perl": k=33, r=r+r/32 */ 73249269Sed return hash + (hash >> 5); 74249269Sed} 75249269Sed 76249269Sedstatic bool 77249269Sedhash_find(const char *str, uint32_t *h) 78249269Sed{ 79249269Sed struct hentry *e; 80249269Sed *h = hash_str(str) % __arraycount(table); 81249269Sed 82249269Sed for (e = table[*h]; e; e = e->next) 83249269Sed if (e->hash == *h && strcmp(e->str, str) == 0) 84249269Sed return true; 85249269Sed return false; 86249269Sed} 87249269Sed 88249269Sedstatic void 89249269Sedhash_insert(char *str, uint32_t h) 90249269Sed{ 91249269Sed struct hentry *e; 92249269Sed 93249269Sed if ((e = malloc(sizeof(*e))) == NULL) 94249269Sed mtree_err("memory allocation error"); 95249269Sed 96249269Sed e->str = str; 97249269Sed e->hash = h; 98249269Sed e->next = table[h]; 99249269Sed table[h] = e; 100249269Sed} 101249269Sed 102249269Sedstatic void 103249269Sedfill(char *str) 104249269Sed{ 105249269Sed uint32_t h; 106249269Sed char *ptr = strrchr(str, '/'); 107249269Sed 108249269Sed if (ptr == NULL) 109249269Sed return; 110249269Sed 111249269Sed *ptr = '\0'; 112249269Sed if (!hash_find(str, &h)) { 113249269Sed char *x = strdup(str); 114249269Sed if (x == NULL) 115249269Sed mtree_err("memory allocation error"); 116249269Sed hash_insert(x, h); 117249269Sed fill(str); 118249269Sed } 119249269Sed *ptr = '/'; 120249269Sed} 121249269Sed 122249269Sedvoid 123249269Sedload_only(const char *fname) 124249269Sed{ 125249269Sed FILE *fp; 126249269Sed char *line; 127249269Sed size_t len, lineno; 128249269Sed 129249269Sed if ((fp = fopen(fname, "r")) == NULL) 130249269Sed err(1, "Cannot open `%s'", fname); 131249269Sed 132249269Sed while ((line = fparseln(fp, &len, &lineno, NULL, FPARSELN_UNESCALL))) { 133249269Sed uint32_t h; 134249269Sed if (hash_find(line, &h)) 135249269Sed err(1, "Duplicate entry %s", line); 136249269Sed hash_insert(line, h); 137249269Sed fill(line); 138249269Sed } 139249269Sed 140249269Sed fclose(fp); 141249269Sed loaded = true; 142249269Sed} 143249269Sed 144249269Sedbool 145249269Sedfind_only(const char *path) 146249269Sed{ 147249269Sed uint32_t h; 148249269Sed 149249269Sed if (!loaded) 150249269Sed return true; 151249269Sed return hash_find(path, &h); 152249269Sed} 153