1 /* pathsearch.c: look up a filename in a path.
3 Copyright 1993, 1994, 1995, 1997, 2007 Karl Berry.
4 Copyright 1997-2005 Olaf Weber.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with this library; if not, see <http://www.gnu.org/licenses/>. */
19 #include <kpathsea/config.h>
20 #include <kpathsea/c-pathch.h>
21 #include <kpathsea/c-fopen.h>
22 #include <kpathsea/absolute.h>
23 #include <kpathsea/expand.h>
24 #include <kpathsea/db.h>
25 #include <kpathsea/pathsearch.h>
26 #include <kpathsea/readable.h>
27 #include <kpathsea/str-list.h>
28 #include <kpathsea/str-llist.h>
29 #include <kpathsea/variable.h>
31 #include <time.h> /* for `time' */
34 #include <sys/stat.h> /* for stat bits */
37 /* The very first search is for texmf.cnf, called when someone tries to
38 initialize the TFM path or whatever. init_path calls kpse_cnf_get
39 which calls kpse_all_path_search to find all the texmf.cnf's. We
40 need to do various special things in this case, since we obviously
41 don't yet have the configuration files when we're searching for the
42 configuration files. */
43 static boolean first_search = true;
47 /* This function is called after every search (except the first, since
48 we definitely want to allow enabling the logging in texmf.cnf) to
49 record the filename(s) found in $TEXMFLOG. */
52 log_search P1C(str_list_type, filenames)
54 static FILE *log_file = NULL;
55 static boolean first_time = true; /* Need to open the log file? */
58 /* Get name from either envvar or config file. */
59 string log_name = kpse_var_value ("TEXMFLOG");
62 log_file = fopen (log_name, FOPEN_A_MODE);
69 if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH) || log_file) {
72 /* FILENAMES should never be null, but safety doesn't hurt. */
73 for (e = 0; e < STR_LIST_LENGTH (filenames) && STR_LIST_ELT (filenames, e);
75 string filename = STR_LIST_ELT (filenames, e);
77 /* Only record absolute filenames, for privacy. */
78 if (log_file && kpse_absolute_p (filename, false))
79 fprintf (log_file, "%lu %s\n", (long unsigned) time (NULL),
82 /* And show them online, if debugging. We've already started
83 the debugging line in `search', where this is called, so
84 just print the filename here, don't use DEBUGF. */
85 if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
87 fputs (filename, stderr);
93 /* Concatenate each element in DIRS with NAME (assume each ends with a
94 /, to save time). If SEARCH_ALL is false, return the first readable
95 regular file. Else continue to search for more. In any case, if
96 none, return a list containing just NULL.
98 We keep a single buffer for the potential filenames and reallocate
99 only when necessary. I'm not sure it's noticeably faster, but it
100 does seem cleaner. (We do waste a bit of space in the return
101 value, though, since we don't shrink it to the final size returned.) */
103 #define INIT_ALLOC 75 /* Doesn't much matter what this number is. */
106 dir_list_search P3C(str_llist_type *, dirs, const_string, name,
109 str_llist_elt_type *elt;
111 unsigned name_len = strlen (name);
112 unsigned allocated = INIT_ALLOC;
113 string potential = (string)xmalloc (allocated);
115 ret = str_list_init ();
117 for (elt = *dirs; elt; elt = STR_LLIST_NEXT (*elt))
119 const_string dir = STR_LLIST (*elt);
120 unsigned dir_len = strlen (dir);
122 while (dir_len + name_len + 1 > allocated)
124 allocated += allocated;
125 XRETALLOC (potential, allocated, char);
128 strcpy (potential, dir);
129 strcat (potential, name);
131 if (kpse_readable_file (potential))
133 str_list_add (&ret, potential);
135 /* Move this element towards the top of the list. */
136 str_llist_float (dirs, elt);
138 /* If caller only wanted one file returned, no need to
139 terminate the list with NULL; the caller knows to only look
140 at the first element. */
144 /* Start new filename. */
145 allocated = INIT_ALLOC;
146 potential = (string)xmalloc (allocated);
150 /* If we get here, either we didn't find any files, or we were finding
151 all the files. But we're done with the last filename, anyway. */
158 dir_list_search_list P3C(str_llist_type *, dirs, const_string*, names,
161 str_llist_elt_type *elt;
163 unsigned allocated = INIT_ALLOC;
164 string potential = XTALLOC(allocated, char);
166 ret = str_list_init ();
168 for (elt = *dirs; elt; elt = STR_LLIST_NEXT(*elt)) {
169 const_string dir = STR_LLIST (*elt);
170 unsigned dir_len = strlen (dir);
173 for (i = 0; names[i]; i++) {
174 const_string name = names[i];
177 /* Don't bother with absolute & explicit relative. */
178 if (kpse_absolute_p(name, true))
181 name_len = strlen(name);
183 while (dir_len + name_len + 1 > allocated) {
184 allocated += allocated;
185 XRETALLOC (potential, allocated, char);
188 strcpy (potential, dir);
189 strcat (potential+dir_len, name);
191 if (kpse_readable_file (potential)) {
192 str_list_add (&ret, potential);
194 /* Move this element towards the top of the list. */
195 str_llist_float (dirs, elt);
197 /* If caller only wanted one file returned, no need to
198 terminate the list with NULL; the caller knows to only look
199 at the first element. */
203 /* Start new filename. */
204 allocated = INIT_ALLOC;
205 potential = XTALLOC(allocated, char);
210 /* If we get here, either we didn't find any files, or we were finding
211 all the files. But we're done with the last filename, anyway. */
217 /* This is called when NAME is absolute or explicitly relative; if it's
218 readable, return (a list containing) it; otherwise, return NULL. */
221 absolute_search P1C(string, name)
223 str_list_type ret_list;
224 string found = kpse_readable_file (name);
226 /* Some old compilers can't initialize structs. */
227 ret_list = str_list_init ();
229 /* If NAME wasn't found, free the expansion. */
233 /* Add `found' to the return list even if it's null; that tells
234 the caller we didn't find anything. */
235 str_list_add (&ret_list, found);
240 /* This is the hard case -- look for NAME in PATH. If ALL is false,
241 return the first file found. Otherwise, search all elements of PATH. */
244 path_search P4C(const_string, path, string, name,
245 boolean, must_exist, boolean, all)
248 str_list_type ret_list;
249 boolean done = false;
250 ret_list = str_list_init (); /* some compilers lack struct initialization */
252 for (elt = kpse_path_element (path); !done && elt;
253 elt = kpse_path_element (NULL)) {
254 str_list_type *found;
255 boolean allow_disk_search = true;
257 if (*elt == '!' && *(elt + 1) == '!') {
258 /* Those magic leading chars in a path element means don't search the
259 disk for this elt. And move past the magic to get to the name. */
260 allow_disk_search = false;
264 /* See elt-dirs.c for side effects of this function */
265 kpse_normalize_path(elt);
267 /* Try ls-R, unless we're searching for texmf.cnf. Our caller
268 (search), also tests first_search, and does the resetting. */
269 found = first_search ? NULL : kpse_db_search (name, elt, all);
271 /* Search the filesystem if (1) the path spec allows it, and either
272 (2a) we are searching for texmf.cnf ; or
273 (2b) no db exists; or
274 (2c) no db's are relevant to this elt; or
275 (3) MUST_EXIST && NAME was not in the db.
276 In (2*), `found' will be NULL.
277 In (3), `found' will be an empty list. */
278 if (allow_disk_search && (!found || (must_exist && !STR_LIST (*found)))) {
279 str_llist_type *dirs = kpse_element_dirs (elt);
282 found = XTALLOC1 (str_list_type);
283 *found = dir_list_search (dirs, name, all);
287 /* Did we find anything anywhere? */
288 if (found && STR_LIST (*found)) {
290 str_list_concat (&ret_list, *found);
292 str_list_add (&ret_list, STR_LIST_ELT (*found, 0));
297 /* Free the list space, if any (but not the elements). */
299 str_list_free (found);
304 /* Free the expanded name we were passed. It can't be in the return
305 list, since the path directories got unconditionally prepended. */
311 /* Search PATH for ORIGINAL_NAME. If ALL is false, or ORIGINAL_NAME is
312 absolute_p, check ORIGINAL_NAME itself. Otherwise, look at each
313 element of PATH for the first readable ORIGINAL_NAME.
315 Always return a list; if no files are found, the list will
316 contain just NULL. If ALL is true, the list will be
317 terminated with NULL. */
320 search P4C(const_string, path, const_string, original_name,
321 boolean, must_exist, boolean, all)
323 str_list_type ret_list;
328 /* We will use `stat' heavily, so let's request for
329 the fastest possible version of `stat', by telling
330 it what members of struct stat do we really need.
332 We need to set this on each call because this is a
333 library function; the caller might need other options
334 from `stat'. Thus save the flags and restore them
337 This call tells `stat' that we do NOT need to recognize
338 executable files (neither by an extension nor by a magic
339 signature); that we do NOT need time stamp of root directories;
340 and that we do NOT need the write access bit in st_mode.
342 Note that `kpse_set_progname' needs the EXEC bits,
343 but it was already called by the time we get here. */
344 unsigned short save_djgpp_flags = _djstat_flags;
346 _djstat_flags = _STAT_EXEC_MAGIC | _STAT_EXEC_EXT
347 | _STAT_ROOT_TIME | _STAT_WRITEBIT;
350 /* Make a leading ~ count as an absolute filename, and expand $FOO's. */
351 name = kpse_expand (original_name);
353 /* If the first name is absolute or explicitly relative, no need to
354 consider PATH at all. */
355 absolute_p = kpse_absolute_p (name, true);
357 if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
358 DEBUGF4 ("start search(file=%s, must_exist=%d, find_all=%d, path=%s).\n",
359 name, must_exist, all, path);
361 /* Find the file(s). */
362 ret_list = absolute_p ? absolute_search (name)
363 : path_search (path, name, must_exist, all);
365 /* Append NULL terminator if we didn't find anything at all, or we're
366 supposed to find ALL and the list doesn't end in NULL now. */
367 if (STR_LIST_LENGTH (ret_list) == 0
368 || (all && STR_LIST_LAST_ELT (ret_list) != NULL))
369 str_list_add (&ret_list, NULL);
371 /* The very first search is for texmf.cnf. We can't log that, since
372 we want to allow setting TEXMFLOG in texmf.cnf. */
374 first_search = false;
376 /* Record the filenames we found, if desired. And wrap them in a
377 debugging line if we're doing that. */
378 if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
379 DEBUGF1 ("search(%s) =>", original_name);
380 log_search (ret_list);
381 if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
386 /* Undo any side effects. */
387 _djstat_flags = save_djgpp_flags;
390 return STR_LIST (ret_list);
393 /* Search PATH for NAMES.
395 Always return a list; if no files are found, the list will
396 contain just NULL. If ALL is true, the list will be
397 terminated with NULL. */
399 search_list P4C(const_string, path, const_string*, names,
400 boolean, must_exist, boolean, all)
402 str_list_type ret_list;
405 boolean done = false;
406 boolean all_absolute = true;
409 /* We will use `stat' heavily, so let's request for
410 the fastest possible version of `stat', by telling
411 it what members of struct stat do we really need.
413 We need to set this on each call because this is a
414 library function; the caller might need other options
415 from `stat'. Thus save the flags and restore them
418 This call tells `stat' that we do NOT need to recognize
419 executable files (neither by an extension nor by a magic
420 signature); that we do NOT need time stamp of root directories;
421 and that we do NOT need the write access bit in st_mode.
423 Note that `kpse_set_progname' needs the EXEC bits,
424 but it was already called by the time we get here. */
425 unsigned short save_djgpp_flags = _djstat_flags;
427 _djstat_flags = _STAT_EXEC_MAGIC | _STAT_EXEC_EXT
428 | _STAT_ROOT_TIME | _STAT_WRITEBIT;
431 ret_list = str_list_init();
433 if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
434 DEBUGF1 ("start search(files=[%s", *names);
435 for (namep = names+1; *namep != NULL; namep++) {
437 fputs(*namep, stderr);
439 fprintf (stderr, "], must_exist=%d, find_all=%d, path=%s).\n",
440 must_exist, all, path);
443 /* FIXME: is this really true? No need to do any expansion on names. */
445 /* First catch any absolute or explicit relative names. */
446 for (namep = names; *namep; namep++) {
447 if (kpse_absolute_p(*namep, true)) {
448 if (kpse_readable_file(*namep)) {
449 str_list_add(&ret_list, xstrdup(*namep));
450 /* I know, I know... */
455 all_absolute = false;
458 /* Shortcut: if we were only given absolute/explicit relative names,
459 we can skip the rest. Typically, if one name is absolute, they
460 all are, because our caller derived them from each other. */
464 /* Look at each path element in turn. */
465 for (elt = kpse_path_element (path); !done && elt;
466 elt = kpse_path_element (NULL))
468 str_list_type *found;
469 boolean allow_disk_search = true;
470 if (elt[0] == '!' && elt[1] == '!') {
471 /* !! magic -> disallow disk searches. */
472 allow_disk_search = false;
476 /* See elt-dirs.c for side effects of this function. */
477 kpse_normalize_path(elt);
479 /* Try ls-R, unless we're searching for texmf.cnf. */
480 found = first_search ? NULL : kpse_db_search_list(names, elt, all);
482 /* Search the filesystem if (1) the path spec allows it, and either
483 (2a) we are searching for texmf.cnf ; or
484 (2b) no db exists; or
485 (2c) no db's are relevant to this elt; or
486 (3) MUST_EXIST && NAME was not in the db.
487 In (2*), `found' will be NULL.
488 In (3), `found' will be an empty list. */
489 if (allow_disk_search && (!found || (must_exist && !STR_LIST(*found)))) {
490 str_llist_type *dirs = kpse_element_dirs (elt);
493 found = XTALLOC1 (str_list_type);
494 *found = dir_list_search_list (dirs, names, all);
498 /* Did we find anything? */
499 if (found && STR_LIST (*found)) {
501 str_list_concat (&ret_list, *found);
503 str_list_add (&ret_list, STR_LIST_ELT (*found, 0));
510 /* Uniqify, since our paths can often end up finding the same file
512 str_list_uniqify (&ret_list);
514 /* Add NULL if we will be returning multiple elements. */
515 if (STR_LIST_LENGTH (ret_list) == 0
516 || (all && STR_LIST_LAST_ELT (ret_list) != NULL))
517 str_list_add (&ret_list, NULL);
520 first_search = false;
522 /* Record the filenames we found, if desired. And wrap them in a
523 debugging line if we're doing that. */
524 if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
525 DEBUGF1 ("search([%s", *names);
526 for (namep = names+1; *namep != NULL; namep++) {
528 fputs (*namep, stderr);
530 fputs ("]) =>", stderr);
532 log_search (ret_list);
533 if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
538 /* Undo any side effects. */
539 _djstat_flags = save_djgpp_flags;
542 return STR_LIST (ret_list);
545 /* Search PATH for the first NAME according to MUST_EXIST. */
548 kpse_path_search P3C(const_string, path, const_string, name,
551 string *ret_list = search (path, name, must_exist, false);
552 string ret = *ret_list;
557 /* Many inputs, return (more or less indeterminate) one matching string. */
560 kpse_path_search_list P3C(const_string, path, const_string*, names,
564 = kpse_path_search_list_generic (path, names, must_exist, false);
565 string ret = *ret_list;
570 /* Search PATH for all files named NAME. Might have been better not
571 to assert `must_exist' here, but it's too late to change. */
574 kpse_all_path_search P2C(const_string, path, const_string, name)
576 string *ret = search (path, name, true, true);
581 /* Many inputs, return list, allow specifying MUST_EXIST and ALL. */
584 kpse_path_search_list_generic P4C(const_string, path, const_string*, names,
585 boolean, must_exist, boolean, all)
587 string *ret = search_list (path, names, must_exist, all);
592 /* Many inputs, return list, MUST_EXIST and ALL always true. */
595 kpse_all_path_search_list P2C(const_string, path, const_string*, names)
597 return kpse_path_search_list_generic (path, names, true, true);
603 test_path_search (const_string path, const_string file)
608 printf ("\nSearch %s for %s:\t", path, file);
609 answer = kpse_path_search (path, file);
610 puts (answer ? answer : "(nil)");
612 printf ("Search %s for all %s:\t", path, file);
613 answer_list = kpse_all_path_search (path, file);
623 #define TEXFONTS "/usr/local/lib/tex/fonts"
628 /* All lists end with NULL. */
629 test_path_search (".", "nonexistent");
630 test_path_search (".", "/nonexistent");
631 test_path_search ("/k" ENV_SEP_STRING ".", "kpathsea.texi");
632 test_path_search ("/k" ENV_SEP_STRING ".", "/etc/fstab");
633 test_path_search ("." ENV_SEP_STRING TEXFONTS "//", "cmr10.tfm");
634 test_path_search ("." ENV_SEP_STRING TEXFONTS "//", "logo10.tfm");
635 test_path_search (TEXFONTS "//times" ENV_SEP_STRING "."
636 ENV_SEP_STRING ENV_SEP_STRING, "ptmr.vf");
637 test_path_search (TEXFONTS "/adobe//" ENV_SEP_STRING
638 "/usr/local/src/TeX+MF/typefaces//", "plcr.pfa");
640 test_path_search ("~karl", ".bashrc");
641 test_path_search ("/k", "~karl/.bashrc");
643 xputenv ("NONEXIST", "nonexistent");
644 test_path_search (".", "$NONEXISTENT");
645 xputenv ("KPATHSEA", "kpathsea");
646 test_path_search ("/k" ENV_SEP_STRING ".", "$KPATHSEA.texi");
647 test_path_search ("/k" ENV_SEP_STRING ".", "${KPATHSEA}.texi");
648 test_path_search ("$KPATHSEA" ENV_SEP_STRING ".", "README");
649 test_path_search ("." ENV_SEP_STRING "$KPATHSEA", "README");
659 test-compile-command: "gcc -posix -g -I. -I.. -DTEST pathsearch.c kpathsea.a"