1356533Sbdrewery/*	$NetBSD: only.c,v 1.3 2017/09/07 04:04:13 nakayama 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)
41356533Sbdrewery__RCSID("$NetBSD: only.c,v 1.3 2017/09/07 04:04:13 nakayama 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;
92356533Sbdrewery	char *x;
93249269Sed
94249269Sed	if ((e = malloc(sizeof(*e))) == NULL)
95249269Sed		mtree_err("memory allocation error");
96356533Sbdrewery	if ((x = strdup(str)) == NULL)
97356533Sbdrewery		mtree_err("memory allocation error");
98249269Sed
99356533Sbdrewery	e->str = x;
100249269Sed	e->hash = h;
101249269Sed	e->next = table[h];
102249269Sed	table[h] = e;
103249269Sed}
104249269Sed
105249269Sedstatic void
106249269Sedfill(char *str)
107249269Sed{
108249269Sed	uint32_t h;
109249269Sed	char *ptr = strrchr(str, '/');
110249269Sed
111249269Sed	if (ptr == NULL)
112249269Sed		return;
113249269Sed
114249269Sed	*ptr = '\0';
115249269Sed	if (!hash_find(str, &h)) {
116356533Sbdrewery		hash_insert(str, 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);
138356533Sbdrewery		free(line);
139249269Sed	}
140249269Sed
141249269Sed	fclose(fp);
142249269Sed	loaded = true;
143249269Sed}
144249269Sed
145249269Sedbool
146249269Sedfind_only(const char *path)
147249269Sed{
148249269Sed	uint32_t h;
149249269Sed
150249269Sed	if (!loaded)
151249269Sed		return true;
152249269Sed	return hash_find(path, &h);
153249269Sed}
154