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