/* readable.c: check if a filename is a readable non-directory file. Copyright (C) 1993, 95, 96 Karl Berry. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include /* If access can read FN, run stat (assigning to stat buffer ST) and check that fn is not a directory. Don't check for just being a regular file, as it is potentially useful to read fifo's or some kinds of devices. */ #ifdef __DJGPP__ /* `stat' is way too expensive for such a simple job. */ #define READABLE(fn, st) \ (access (fn, R_OK) == 0 && access (fn, D_OK) == -1) #elif WIN32 #define READABLE(fn, st) \ (GetFileAttributes(fn) != 0xFFFFFFFF && \ !(GetFileAttributes(fn) & FILE_ATTRIBUTE_DIRECTORY)) #else #define READABLE(fn, st) \ (access (fn, R_OK) == 0 && stat (fn, &(st)) == 0 && !S_ISDIR (st.st_mode)) #endif /* POSIX invented the brain-damage of not necessarily truncating filename components; the system's behavior is defined by the value of the symbol _POSIX_NO_TRUNC, but you can't change it dynamically! Generic const return warning. See extend-fname.c. */ string kpse_readable_file P1C(const_string, name) { struct stat st; string ret; if (READABLE (name, st)) { ret = (string) name; #ifdef ENAMETOOLONG } else if (errno == ENAMETOOLONG) { ret = kpse_truncate_filename (name); /* Perhaps some other error will occur with the truncated name, so let's call access again. */ if (!READABLE (ret, st)) { /* Failed. */ if (ret != name) free (ret); ret = NULL; } #endif /* ENAMETOOLONG */ } else { /* Some other error. */ if (errno == EACCES) { /* Maybe warn them if permissions are bad. */ if (!kpse_tex_hush ("readable")) { perror (name); } } ret = NULL; } return ret; }