1 /* readable.c: check if a filename is a readable non-directory file.
3 Copyright 1993, 1995, 1996, 2008 Karl Berry.
4 Copyright 1998, 1999, 2000, 2001, 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-stat.h>
21 #include <kpathsea/pathsearch.h>
22 #include <kpathsea/readable.h>
23 #include <kpathsea/tex-hush.h>
24 #include <kpathsea/truncate.h>
27 /* If access can read FN, run stat (assigning to stat buffer ST) and
28 check that fn is not a directory. Don't check for just being a
29 regular file, as it is potentially useful to read fifo's or some
33 /* `stat' is way too expensive for such a simple job. */
34 #define READABLE(fn, st) \
35 (access (fn, R_OK) == 0 && access (fn, D_OK) == -1)
37 /* Warning: st must be an unsigned int under Win32 */
39 READABLE(const_string fn, unsigned int st)
41 if ((st = GetFileAttributes(fn)) != 0xFFFFFFFF) {
45 switch(GetLastError()) {
46 case ERROR_BUFFER_OVERFLOW:
49 case ERROR_ACCESS_DENIED:
53 errno = EIO; /* meaningless, will make ret=NULL later */
57 return ((st != 0xFFFFFFFF) &&
58 !(st & FILE_ATTRIBUTE_DIRECTORY));
61 #define READABLE(fn, st) \
62 (access (fn, R_OK) == 0 && stat (fn, &(st)) == 0 && !S_ISDIR (st.st_mode))
65 /* POSIX invented the brain-damage of not necessarily truncating
66 filename components; the system's behavior is defined by the value of
67 the symbol _POSIX_NO_TRUNC, but you can't change it dynamically!
69 Generic const return warning. See extend-fname.c. */
72 kpse_readable_file P1C(const_string, name)
82 kpse_normalize_path((string)name);
83 if (READABLE (name, st)) {
86 } else if (errno == ENAMETOOLONG) {
87 ret = kpse_truncate_filename (name);
89 /* Perhaps some other error will occur with the truncated name, so
90 let's call access again. */
91 if (!READABLE (ret, st)) { /* Failed. */
92 if (ret != name) free (ret);
95 #endif /* ENAMETOOLONG */
96 } else { /* Some other error. */
97 if (errno == EACCES) { /* Maybe warn them if permissions are bad. */
98 if (!kpse_tex_hush ("readable")) {