util.c revision 275034
1/*
2 * Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
3 * Copyright (c) 1989, 1993
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * James A. Woods.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by the University of
20 *	California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * $FreeBSD: stable/10/usr.bin/locate/locate/util.c 275034 2014-11-25 12:45:31Z dim $
38 */
39
40
41#include <stdlib.h>
42#include <string.h>
43#include <err.h>
44#include <sys/param.h>
45#include <arpa/inet.h>
46#include <stdio.h>
47
48#include "locate.h"
49
50char 	**colon(char **, char*, char*);
51char 	*patprep(char *);
52void print_matches(u_int);
53u_char 	*tolower_word(u_char *);
54int 	getwm(caddr_t);
55int 	getwf(FILE *);
56int	check_bigram_char(int);
57
58/*
59 * Validate bigram chars. If the test failed the database is corrupt
60 * or the database is obviously not a locate database.
61 */
62int
63check_bigram_char(ch)
64	int ch;
65{
66	/* legal bigram: 0, ASCII_MIN ... ASCII_MAX */
67	if (ch == 0 ||
68	    (ch >= ASCII_MIN && ch <= ASCII_MAX))
69		return(ch);
70
71	errx(1,
72		"locate database header corrupt, bigram char outside 0, %d-%d: %d",
73		ASCII_MIN, ASCII_MAX, ch);
74	exit(1);
75}
76
77/* split a colon separated string into a char vector
78 *
79 * "bla:foo" -> {"foo", "bla"}
80 * "bla:"    -> {"foo", dot}
81 * "bla"     -> {"bla"}
82 * ""	     -> do nothing
83 *
84 */
85char **
86colon(dbv, path, dot)
87	char **dbv;
88	char *path;
89	char *dot; /* default for single ':' */
90{
91	int vlen, slen;
92	char *c, *ch, *p;
93	char **pv;
94
95	if (dbv == NULL) {
96		if ((dbv = malloc(sizeof(char **))) == NULL)
97			err(1, "malloc");
98		*dbv = NULL;
99	}
100
101	/* empty string */
102	if (*path == '\0') {
103		warnx("empty database name, ignored");
104		return(dbv);
105	}
106
107	/* length of string vector */
108	for(vlen = 0, pv = dbv; *pv != NULL; pv++, vlen++);
109
110	for (ch = c = path; ; ch++) {
111		if (*ch == ':' ||
112		    (!*ch && !(*(ch - 1) == ':' && ch == 1+ path))) {
113			/* single colon -> dot */
114			if (ch == c)
115				p = dot;
116			else {
117				/* a string */
118				slen = ch - c;
119				if ((p = malloc(sizeof(char) * (slen + 1)))
120				    == NULL)
121					err(1, "malloc");
122				bcopy(c, p, slen);
123				*(p + slen) = '\0';
124			}
125			/* increase dbv with element p */
126			if ((dbv = realloc(dbv, sizeof(char **) * (vlen + 2)))
127			    == NULL)
128				err(1, "realloc");
129			*(dbv + vlen) = p;
130			*(dbv + ++vlen) = NULL;
131			c = ch + 1;
132		}
133		if (*ch == '\0')
134			break;
135	}
136	return (dbv);
137}
138
139void
140print_matches(counter)
141	u_int counter;
142{
143	(void)printf("%d\n", counter);
144}
145
146
147/*
148 * extract last glob-free subpattern in name for fast pre-match; prepend
149 * '\0' for backwards match; return end of new pattern
150 */
151static char globfree[100];
152
153char *
154patprep(name)
155	char *name;
156{
157	register char *endmark, *p, *subp;
158
159	subp = globfree;
160	*subp++ = '\0';   /* set first element to '\0' */
161	p = name + strlen(name) - 1;
162
163	/* skip trailing metacharacters */
164	for (; p >= name; p--)
165		if (strchr(LOCATE_REG, *p) == NULL)
166			break;
167
168	/*
169	 * check if maybe we are in a character class
170	 *
171	 * 'foo.[ch]'
172	 *        |----< p
173	 */
174	if (p >= name &&
175	    (strchr(p, '[') != NULL || strchr(p, ']') != NULL)) {
176		for (p = name; *p != '\0'; p++)
177			if (*p == ']' || *p == '[')
178				break;
179		p--;
180
181		/*
182		 * cannot find a non-meta character, give up
183		 * '*\*[a-z]'
184		 *    |-------< p
185		 */
186		if (p >= name && strchr(LOCATE_REG, *p) != NULL)
187			p = name - 1;
188	}
189
190	if (p < name)
191		/* only meta chars: "???", force '/' search */
192		*subp++ = '/';
193
194	else {
195		for (endmark = p; p >= name; p--)
196			if (strchr(LOCATE_REG, *p) != NULL)
197				break;
198		for (++p;
199		    (p <= endmark) && subp < (globfree + sizeof(globfree));)
200			*subp++ = *p++;
201	}
202	*subp = '\0';
203	return(--subp);
204}
205
206/* tolower word */
207u_char *
208tolower_word(word)
209	u_char *word;
210{
211	register u_char *p;
212
213	for(p = word; *p != '\0'; p++)
214		*p = TOLOWER(*p);
215
216	return(word);
217}
218
219
220/*
221 * Read integer from mmap pointer.
222 * Essentially a simple ``return *(int *)p'' but avoids sigbus
223 * for integer alignment (SunOS 4.x, 5.x).
224 *
225 * Convert network byte order to host byte order if necessary.
226 * So we can read a locate database on FreeBSD/i386 (little endian)
227 * which was built on SunOS/sparc (big endian).
228 */
229
230int
231getwm(p)
232	caddr_t p;
233{
234	union {
235		char buf[INTSIZE];
236		int i;
237	} u;
238	register int i, hi;
239
240	for (i = 0; i < (int)INTSIZE; i++)
241		u.buf[i] = *p++;
242
243	i = u.i;
244
245	if (i > MAXPATHLEN || i < -(MAXPATHLEN)) {
246		hi = ntohl(i);
247		if (hi > MAXPATHLEN || hi < -(MAXPATHLEN))
248			errx(1, "integer out of +-MAXPATHLEN (%d): %u",
249			    MAXPATHLEN, abs(i) < abs(hi) ? i : hi);
250		return(hi);
251	}
252	return(i);
253}
254
255/*
256 * Read integer from stream.
257 *
258 * Convert network byte order to host byte order if necessary.
259 * So we can read on FreeBSD/i386 (little endian) a locate database
260 * which was built on SunOS/sparc (big endian).
261 */
262
263int
264getwf(fp)
265	FILE *fp;
266{
267	register int word, hword;
268
269	word = getw(fp);
270
271	if (word > MAXPATHLEN || word < -(MAXPATHLEN)) {
272		hword = ntohl(word);
273		if (hword > MAXPATHLEN || hword < -(MAXPATHLEN))
274			errx(1, "integer out of +-MAXPATHLEN (%d): %u",
275			    MAXPATHLEN, abs(word) < abs(hword) ? word : hword);
276		return(hword);
277	}
278	return(word);
279}
280