1 /* db.c: an external database to avoid filesystem lookups.
3 Copyright 1994, 1995, 1996, 1997, 2008, 2009, 2011, 2012, 2014 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/absolute.h>
21 #include <kpathsea/c-stat.h>
22 #include <kpathsea/c-fopen.h>
23 #include <kpathsea/c-pathch.h>
24 #include <kpathsea/db.h>
25 #include <kpathsea/hash.h>
26 #include <kpathsea/line.h>
27 #include <kpathsea/pathsearch.h>
28 #include <kpathsea/readable.h>
29 #include <kpathsea/str-list.h>
30 #include <kpathsea/tex-file.h>
31 #include <kpathsea/variable.h>
34 /* Based on the size of 2014 texmf-dist/ls-R, about 130,000 entries. */
35 #define DB_HASH_SIZE 64007
38 #define DB_NAME "ls-R"
41 #define DB_NAME_LC "ls-r"
44 /* In the loop in init() below where we check for DB_NAME_LC and DB_NAME
45 being the same file, it's convenient to ignore the first of a pair.
46 So put the canonical name second. Sure wish I hadn't used a capital
47 letter in the name in the first place. */
48 /* We use non-const strings initialized with string constants in order
49 to avoid some compiler warnings. */
50 static char db_name_lc
[] = DB_NAME_LC
;
51 static char db_name
[] = DB_NAME
;
52 static string db_names
[] = {
59 #define ALIAS_NAME "aliases"
61 #ifndef ALIAS_HASH_SIZE
62 #define ALIAS_HASH_SIZE 1009
66 /* If DIRNAME contains any element beginning with a `.' (that is more
67 than just `./'), return true. This is to allow ``hidden''
68 directories -- ones that don't get searched. */
71 ignore_dir_p (const_string dirname
)
73 const_string dot_pos
= dirname
;
75 while ((dot_pos
= strchr (dot_pos
+ 1, '.'))) {
76 /* If / before and no / after, skip it. */
77 if (IS_DIR_SEP_CH (dot_pos
[-1]) && dot_pos
[1] && !IS_DIR_SEP_CH (dot_pos
[1]))
84 /* If no DB_FILENAME, return false (maybe they aren't using this feature).
85 Otherwise, add entries from DB_FILENAME to TABLE, and return true. */
88 db_build (kpathsea kpse
, hash_table_type
*table
, const_string db_filename
)
91 unsigned dir_count
= 0, file_count
= 0, ignore_dir_count
= 0;
92 unsigned len
= strlen (db_filename
) - sizeof (DB_NAME
) + 1; /* Keep the /. */
93 string top_dir
= (string
)xmalloc (len
+ 1);
94 string cur_dir
= NULL
; /* First thing in ls-R might be a filename. */
95 FILE *db_file
= fopen (db_filename
, FOPEN_R_MODE
);
100 strncpy (top_dir
, db_filename
, len
);
104 while ((line
= read_line (db_file
)) != NULL
) {
108 for (pp
= line
; *pp
; pp
++) {
112 *pp
= TRANSFORM(*pp
);
116 /* A line like `/foo:' = new dir foo. Allow both absolute (/...)
117 and explicitly relative (./...) names here. It's a kludge to
118 pass in the directory name with the trailing : still attached,
119 but it doesn't actually hurt. */
120 if (len
> 0 && line
[len
- 1] == ':'
121 && kpathsea_absolute_p (kpse
, line
, true)) {
122 /* New directory line. */
123 if (!ignore_dir_p (line
)) {
124 /* If they gave a relative name, prepend full directory name now. */
125 line
[len
- 1] = DIR_SEP
;
126 /* Skip over leading `./', it confuses `match' and is just a
127 waste of space, anyway. This will lose on `../', but `match'
128 won't work there, either, so it doesn't matter. */
129 cur_dir
= *line
== '.' ? concat (top_dir
, line
+ 2) : xstrdup (line
);
136 /* Ignore blank, `.' and `..' lines. */
137 } else if (*line
!= 0 && cur_dir
/* a file line? */
139 && (line
[1] == 0 || (line
[1] == '.' && line
[2] == 0))))
141 /* Make a new hash table entry with a key of `line' and a data
142 of `cur_dir'. An already-existing identical key is ok, since
143 a file named `foo' can be in more than one directory. Share
144 `cur_dir' among all its files (and hence never free it).
146 Note that we assume that all names in the ls-R file have already
147 been case-smashed to lowercase where appropriate.
149 hash_insert_normalized (table
, xstrdup (line
), cur_dir
);
152 } /* else ignore blank lines or top-level files
153 or files in ignored directories*/
158 xfclose (db_file
, db_filename
);
160 if (file_count
== 0) {
161 WARNING1 ("kpathsea: %s: No usable entries in ls-R", db_filename
);
162 WARNING ("kpathsea: See the manual for how to generate ls-R");
165 str_list_add (&(kpse
->db_dir_list
), xstrdup (top_dir
));
169 if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH
)) {
170 /* Don't make this a debugging bit, since the output is so
171 voluminous, and being able to specify -1 is too useful.
172 Instead, let people who want it run the program under
173 a debugger and change the variable that way. */
174 boolean hash_summary_only
= true;
176 DEBUGF4 ("%s: %u entries in %d directories (%d hidden).\n",
177 db_filename
, file_count
, dir_count
, ignore_dir_count
);
178 DEBUGF ("ls-R hash table:");
179 hash_print (*table
, hash_summary_only
);
182 #endif /* KPSE_DEBUG */
187 return db_file
!= NULL
;
191 /* Insert FNAME into the hash table. This is for files that get built
192 during a run. We wouldn't want to reread all of ls-R, even if it got
196 kpathsea_db_insert (kpathsea kpse
, const_string passed_fname
)
198 /* We might not have found ls-R, or even had occasion to look for it
199 yet, so do nothing if we have no hash table. */
200 if (kpse
->db
.buckets
) {
201 const_string dir_part
;
202 string fname
= xstrdup (passed_fname
);
203 string baseptr
= fname
+ (xbasename (fname
) - fname
);
204 const_string file_part
= xstrdup (baseptr
);
206 *baseptr
= '\0'; /* Chop off the filename. */
207 dir_part
= fname
; /* That leaves the dir, with the trailing /. */
209 /* Note that we do not assuse that these names have been normalized. */
210 hash_insert (&(kpse
->db
), file_part
, dir_part
);
214 /* Return true if FILENAME could be in PATH_ELT, i.e., if the directory
215 part of FILENAME matches PATH_ELT. Have to consider // wildcards, but
216 $ and ~ expansion have already been done. */
219 match (const_string filename
, const_string path_elt
)
221 const_string original_filename
= filename
;
222 boolean matched
= false;
224 for (; *filename
&& *path_elt
; filename
++, path_elt
++) {
225 if (FILECHARCASEEQ (*filename
, *path_elt
)) /* normal character match */
228 else if (IS_DIR_SEP_CH (*path_elt
) /* at // */
229 && original_filename
< filename
&& IS_DIR_SEP_CH (path_elt
[-1])) {
230 while (IS_DIR_SEP_CH (*path_elt
))
231 path_elt
++; /* get past second and any subsequent /'s */
232 if (*path_elt
== 0) {
233 /* Trailing //, matches anything. We could make this part of the
234 other case, but it seems pointless to do the extra work. */
238 /* Intermediate //, have to match rest of PATH_ELT. */
239 for (; !matched
&& *filename
; filename
++) {
240 /* Try matching at each possible character. */
241 if (IS_DIR_SEP_CH (filename
[-1])
242 && FILECHARCASEEQ (*filename
, *path_elt
))
243 matched
= match (filename
, path_elt
);
245 /* Prevent filename++ when *filename='\0'. */
250 else /* normal character nonmatch, quit */
254 /* If we've reached the end of PATH_ELT, check that we're at the last
255 component of FILENAME (that is, no directory separators remaining);
256 only then have we matched. */
257 if (!matched
&& *path_elt
== 0) {
258 /* Typically PATH_ELT ends with, say, `vf', and FILENAME ends with
259 `vf/ptmr.vf'. In that case, we'll be at the /. On the other
260 hand, if PATH_ELT ended with a / (as in `vf/'), FILENAME being
261 the same `vf/ptmr.vf', we'll be at the `p'.
262 Upshot: if we're at a dir sep in FILENAME, skip it. */
263 if (IS_DIR_SEP_CH (*filename
))
266 /* Here are the basic possibilities for the check on being at the
268 1) PATH_ELT is empty and FILENAME is `ptmr.vf' => match.
269 (we now have original_filename == filename)
270 2) PATH_ELT is empty and FILENAME is `foo/ptmr.vf' => no match.
271 (we now have original_filename == filename)
272 3) PATH_ELT is `vf/' and FILENAME is `vf/ptmr.vf'
273 (we are now after the / in each) => match.
274 4) PATH_ELT is `vf' and FILENAME is `vfoo.ext'
275 (we are now after the f in each) => no match.
277 When (the original) PATH_ELT was the empty string, we want to match
278 a FILENAME without dir seps. (This could be argued, and may never
279 happen in practice, but is the historical behavior.) */
280 /* if original_filename != filename then original_filename < filename */
281 if (original_filename
== filename
|| IS_DIR_SEP_CH (filename
[-1])) {
282 while (*filename
&& !IS_DIR_SEP_CH (*filename
))
284 matched
= *filename
== 0;
292 /* If DB_DIR is a prefix of PATH_ELT, return true; otherwise false.
293 That is, the question is whether to try the db for a file looked up
294 in PATH_ELT. If PATH_ELT == ".", for example, the answer is no. If
295 PATH_ELT == "/usr/local/lib/texmf/fonts//tfm", the answer is yes.
297 In practice, ls-R is only needed for lengthy subdirectory
298 comparisons, but there's no gain to checking PATH_ELT to see if it is
299 a subdir match, since the only way to do that is to do a string
300 search in it, which is all we do anyway. */
303 elt_in_db (const_string db_dir
, const_string path_elt
)
305 boolean found
= false;
307 while (!found
&& FILECHARCASEEQ (*db_dir
++, *path_elt
++)) {
308 /* If we've matched the entire db directory, it's good. */
312 /* If we've reached the end of PATH_ELT, but not the end of the db
313 directory, it's no good. */
314 else if (*path_elt
== 0)
321 /* If ALIAS_FILENAME exists, read it into TABLE. */
324 alias_build (kpathsea kpse
, hash_table_type
*table
,
325 const_string alias_filename
)
327 string line
, real
, alias
;
329 FILE *alias_file
= fopen (alias_filename
, FOPEN_R_MODE
);
332 while ((line
= read_line (alias_file
)) != NULL
) {
333 /* comments or empty */
334 if (*line
== 0 || *line
== '%' || *line
== '#') {
337 /* Each line should have two fields: realname aliasname. */
339 while (*real
&& ISSPACE (*real
))
342 while (*alias
&& !ISSPACE (*alias
))
345 while (*alias
&& ISSPACE (*alias
))
347 /* Is the check for errors strong enough? Should we warn the user
348 for potential errors? */
349 if (strlen (real
) != 0 && strlen (alias
) != 0) {
350 /* Stuff in the alias file should be normalized. */
351 hash_insert_normalized (table
, xstrdup (alias
), xstrdup (real
));
359 if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH
)) {
360 /* As with ls-R above ... */
361 boolean hash_summary_only
= true;
362 DEBUGF2 ("%s: %u aliases.\n", alias_filename
, count
);
363 DEBUGF ("alias hash table:");
364 hash_print (*table
, hash_summary_only
);
367 #endif /* KPSE_DEBUG */
369 xfclose (alias_file
, alias_filename
);
372 return alias_file
!= NULL
;
375 /* Initialize the path for ls-R files, and read them all into the hash
376 table `db'. If no usable ls-R's found, set kpse->db.buckets to NULL. */
379 kpathsea_init_db (kpathsea kpse
)
381 const_string db_path
;
383 string
*orig_db_files
;
384 str_list_type unique_list
;
388 assert (sizeof(DB_NAME
) == sizeof(DB_NAME_LC
));
390 db_path
= kpathsea_init_format (kpse
, kpse_db_format
);
391 db_files
= kpathsea_path_search_list_generic (kpse
, db_path
, db_names
,
393 orig_db_files
= db_files
;
395 /* Mac OS X and others can use a case-insensitive, case-preserving
396 filesystem by default, in which case ls-R and ls-r point to the
397 same file. Also, Windows is case-insensitive. In these cases,
398 we want to avoid reading the same file multiple times. */
400 unique_list
= str_list_init ();
402 while (db_files
[dbi
] != NULL
) {
403 string path1
= db_files
[dbi
];
404 string path2
= db_files
[dbi
+ 1];
406 /* first-pass check in case path1/path2 aren't even
407 potentially equal; mainly in case the order from
408 kpathsea_path_search_list_generic changes. */
410 && strcasecmp (path1
, path2
) == 0
411 && same_file_p (path1
, path2
)) {
412 /* they are the same, skip over path1, we'll add path2
413 on the next iteration (when it's path1). */
415 if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH
)) {
416 DEBUGF2 ("db:init(): skipping db same_file_p %s, will add %s.\n",
423 /* they are not the same, add path1. */
425 if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH
)) {
426 DEBUGF1 ("db:init(): using db file %s.\n", path1
);
429 str_list_add (&unique_list
, path1
);
432 /* could be more clever and increment by two, but then would
433 have to avoid jumping off the end of db_files */
437 /* always add a NULL terminator. */
438 str_list_add (&unique_list
, NULL
);
440 free (orig_db_files
);
441 db_files
= STR_LIST (unique_list
);
442 orig_db_files
= db_files
;
444 /* Must do this after the path searching (which ends up calling
445 kpse_db_search recursively), so kpse->db.buckets stays NULL. */
446 kpse
->db
= hash_create (DB_HASH_SIZE
);
448 while (db_files
&& *db_files
) {
449 if (db_build (kpse
, &(kpse
->db
), *db_files
))
456 /* If db can't be built, leave `size' nonzero (so we don't
457 rebuild it), but clear `buckets' (so we don't look in it). */
458 free (kpse
->db
.buckets
);
459 kpse
->db
.buckets
= NULL
;
462 free (orig_db_files
);
464 /* Add the content of any alias databases. There may exist more than
465 one alias file along DB_NAME files. This duplicates the above code
466 -- should be a function. */
468 db_files
= kpathsea_all_path_search (kpse
, db_path
, ALIAS_NAME
);
469 orig_db_files
= db_files
;
471 kpse
->alias_db
= hash_create (ALIAS_HASH_SIZE
);
473 while (db_files
&& *db_files
) {
474 if (alias_build (kpse
, &(kpse
->alias_db
), *db_files
))
481 free (kpse
->alias_db
.buckets
);
482 kpse
->alias_db
.buckets
= NULL
;
485 free (orig_db_files
);
488 /* Avoid doing anything if this PATH_ELT is irrelevant to the databases. */
490 kpathsea_db_search (kpathsea kpse
, const_string name
,
491 const_string orig_path_elt
, boolean all
)
493 const_string
*db_dirs
, *orig_dirs
;
494 const_string last_slash
, path_elt
;
495 string temp_str
= NULL
;
498 str_list_type
*ret
= NULL
;
499 const_string
*aliases
, *r
;
500 boolean relevant
= false;
502 /* If we failed to build the database (or if this is the recursive
503 call to build the db path), quit. */
504 if (kpse
->db
.buckets
== NULL
)
507 /* When tex-glyph.c calls us looking for, e.g., dpi600/cmr10.pk, we
508 won't find it unless we change NAME to just `cmr10.pk' and append
509 `/dpi600' to PATH_ELT. We are justified in using a literal `/'
510 here, since that's what tex-glyph.c unconditionally uses in
511 DPI_BITMAP_SPEC. But don't do anything if the / begins NAME; that
512 should never happen. */
513 last_slash
= strrchr (name
, '/');
514 if (last_slash
&& last_slash
!= name
) {
515 unsigned len
= last_slash
- name
+ 1;
516 string dir_part
= (string
)xmalloc (len
);
517 strncpy (dir_part
, name
, len
- 1);
518 dir_part
[len
- 1] = 0;
519 path_elt
= temp_str
= concat3 (orig_path_elt
, "/", dir_part
);
520 name
= last_slash
+ 1;
523 path_elt
= orig_path_elt
;
525 /* Don't bother doing any lookups if this `path_elt' isn't covered by
526 any of database directories. We do this not so much because the
527 extra couple of hash lookups matter -- they don't -- but rather
528 because we want to return NULL in this case, so path_search can
529 know to do a disk search. */
530 for (e
= 0; !relevant
&& e
< STR_LIST_LENGTH (kpse
->db_dir_list
); e
++) {
531 relevant
= elt_in_db (STR_LIST_ELT (kpse
->db_dir_list
, e
), path_elt
);
536 /* If we have aliases for this name, use them. */
537 if (kpse
->alias_db
.buckets
)
538 aliases
= hash_lookup (kpse
->alias_db
, name
);
543 aliases
= XTALLOC1 (const_string
);
546 { /* Push aliases up by one and insert the original name at the front. */
548 unsigned len
= 1; /* Have NULL element already allocated. */
549 for (r
= aliases
; *r
; r
++)
551 /* This is essentially
552 XRETALLOC (aliases, len + 1, const_string);
553 except that MSVC warns without the cast to `void *'. */
554 aliases
= (const_string
*) xrealloc ((void *) aliases
,
555 (len
+ 1) * sizeof(const_string
));
556 for (i
= len
; i
> 0; i
--) {
557 aliases
[i
] = aliases
[i
- 1];
563 for (r
= aliases
; !done
&& *r
; r
++) {
564 const_string ctry
= *r
;
566 /* We have an ls-R db. Look up `try'. */
567 orig_dirs
= db_dirs
= hash_lookup (kpse
->db
, ctry
);
569 ret
= XTALLOC1 (str_list_type
);
570 *ret
= str_list_init ();
572 /* For each filename found, see if it matches the path element. For
573 example, if we have .../cx/cmr10.300pk and .../ricoh/cmr10.300pk,
574 and the path looks like .../cx, we don't want the ricoh file. */
575 while (!done
&& db_dirs
&& *db_dirs
) {
576 string db_file
= concat (*db_dirs
, ctry
);
577 boolean matched
= match (db_file
, path_elt
);
580 if (KPATHSEA_DEBUG_P (KPSE_DEBUG_SEARCH
))
581 DEBUGF3 ("db:match(%s,%s) = %d\n", db_file
, path_elt
, matched
);
584 /* We got a hit in the database. Now see if the file actually
585 exists, possibly under an alias. */
588 if (kpathsea_readable_file (kpse
, db_file
)) {
594 free (db_file
); /* `db_file' wasn't on disk. */
596 /* The hit in the DB doesn't exist in disk. Now try all its
597 aliases. For example, suppose we have a hierarchy on CD,
598 thus `mf.bas', but ls-R contains `mf.base'. Find it anyway.
599 Could probably work around this with aliases, but
600 this is pretty easy and shouldn't hurt. The upshot is that
601 if one of the aliases actually exists, we use that. */
602 for (a
= aliases
+ 1; *a
&& !found
; a
++) {
603 string atry
= concat (*db_dirs
, *a
);
604 if (kpathsea_readable_file (kpse
, atry
))
611 /* If we have a real file, add it to the list, maybe done. */
613 str_list_add (ret
, found
);
617 } else { /* no match in the db */
622 /* On to the next directory, if any. */
626 /* This is just the space for the pointers, not the strings. */
627 if (orig_dirs
&& *orig_dirs
)
631 free ((void *) aliases
);
633 /* If we had to break up NAME, free the TEMP_STR. */
641 kpathsea_db_search_list (kpathsea kpse
, string
* names
,
642 const_string path_elt
, boolean all
)
644 const_string
*db_dirs
, *orig_dirs
;
645 const_string last_slash
, name
, path
;
646 string temp_str
= NULL
;
649 const_string
*aliases
, *r
;
651 str_list_type
*ret
= NULL
;
652 boolean relevant
= false;
654 /* If we failed to build the database (or if this is the recursive
655 call to build the db path), quit. */
656 if (kpse
->db
.buckets
== NULL
)
659 /* Don't bother doing any lookups if this `path_elt' isn't covered by
660 any of database directories. We do this not so much because the
661 extra couple of hash lookups matter -- they don't -- but rather
662 because we want to return NULL in this case, so path_search can
663 know to do a disk search. */
664 for (e
= 0; !relevant
&& e
< STR_LIST_LENGTH (kpse
->db_dir_list
); e
++) {
665 relevant
= elt_in_db (STR_LIST_ELT (kpse
->db_dir_list
, e
), path_elt
);
671 ret
= XTALLOC1 (str_list_type
);
672 *ret
= str_list_init ();
674 /* Handle each name. */
675 for (n
= 0; !done
&& names
[n
]; n
++) {
678 /* Absolute names should have been caught in our caller. */
679 if (kpathsea_absolute_p(kpse
, name
, true))
682 /* When tex-glyph.c calls us looking for, e.g., dpi600/cmr10.pk, we
683 won't find it unless we change NAME to just `cmr10.pk' and append
684 `/dpi600' to PATH_ELT. We are justified in using a literal `/'
685 here, since that's what tex-glyph.c unconditionally uses in
686 DPI_BITMAP_SPEC. But don't do anything if the / begins NAME; that
687 should never happen. */
688 last_slash
= strrchr (name
, '/');
689 if (last_slash
&& last_slash
!= name
) {
690 unsigned len
= last_slash
- name
+ 1;
691 string dir_part
= (string
)xmalloc (len
);
692 strncpy (dir_part
, name
, len
- 1);
693 dir_part
[len
- 1] = 0;
694 path
= temp_str
= concat3 (path_elt
, "/", dir_part
);
695 name
= last_slash
+ 1;
701 /* If we have aliases for this name, use them. */
702 if (kpse
->alias_db
.buckets
)
703 aliases
= hash_lookup (kpse
->alias_db
, name
);
708 aliases
= XTALLOC1 (const_string
);
711 { /* Push aliases up by one and insert the original name at front. */
713 unsigned len
= 1; /* Have NULL element already allocated. */
714 for (r
= aliases
; *r
; r
++)
716 aliases
= (const_string
*) xrealloc ((void *) aliases
,
717 (len
+ 1) * sizeof(const_string
));
718 for (i
= len
; i
> 0; i
--) {
719 aliases
[i
] = aliases
[i
- 1];
724 for (r
= aliases
; !done
&& *r
; r
++) {
725 const_string ctry
= *r
;
727 /* We have an ls-R db. Look up `try'. */
728 orig_dirs
= db_dirs
= hash_lookup (kpse
->db
, ctry
);
730 /* For each filename found, see if it matches the path element. For
731 example, if we have .../cx/cmr10.300pk and .../ricoh/cmr10.300pk,
732 and the path looks like .../cx, we don't want the ricoh file. */
733 while (!done
&& db_dirs
&& *db_dirs
) {
734 string db_file
= concat (*db_dirs
, ctry
);
735 boolean matched
= match (db_file
, path
);
738 if (KPATHSEA_DEBUG_P (KPSE_DEBUG_SEARCH
))
739 DEBUGF3 ("db:match(%s,%s) = %d\n", db_file
, path
, matched
);
742 /* We got a hit in the database. Now see if the file actually
743 exists, possibly under an alias. */
746 if (kpathsea_readable_file (kpse
, db_file
)) {
752 free (db_file
); /* `db_file' wasn't on disk. */
754 /* The hit in the DB doesn't exist in disk. Now try all its
755 aliases. For example, suppose we have a hierarchy on CD,
756 thus `mf.bas', but ls-R contains `mf.base'. Find it anyway.
757 Could probably work around this with aliases, but
758 this is pretty easy and shouldn't hurt. The upshot is that
759 if one of the aliases actually exists, we use that. */
760 for (a
= aliases
+ 1; *a
&& !found
; a
++) {
761 string atry
= concat (*db_dirs
, *a
);
762 if (kpathsea_readable_file (kpse
, atry
))
769 /* If we have a real file, add it to the list, maybe done. */
771 str_list_add (ret
, found
);
775 } else { /* no match in the db */
779 /* On to the next directory, if any. */
783 /* This is just the space for the pointers, not the strings. */
784 if (orig_dirs
&& *orig_dirs
)
788 free ((void *) aliases
);