summaryrefslogtreecommitdiff
path: root/Build/source/texk/kpathsea/readable.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/kpathsea/readable.c')
-rw-r--r--Build/source/texk/kpathsea/readable.c60
1 files changed, 41 insertions, 19 deletions
diff --git a/Build/source/texk/kpathsea/readable.c b/Build/source/texk/kpathsea/readable.c
index c32b2302d15..d62957e5ba0 100644
--- a/Build/source/texk/kpathsea/readable.c
+++ b/Build/source/texk/kpathsea/readable.c
@@ -17,11 +17,13 @@
along with this library; if not, see <http://www.gnu.org/licenses/>. */
#include <kpathsea/config.h>
+#include <kpathsea/c-namemx.h>
+#include <kpathsea/c-pathch.h>
+#include <kpathsea/c-pathmx.h>
#include <kpathsea/c-stat.h>
#include <kpathsea/pathsearch.h>
#include <kpathsea/readable.h>
#include <kpathsea/tex-hush.h>
-#include <kpathsea/truncate.h>
/* If access can read FN, run stat (assigning to stat buffer ST) and
@@ -62,38 +64,59 @@ READABLE(const_string fn, unsigned int 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!
-
- We may or may not return NAME. It's up to the caller not to assume
- the return value is modifiable. */
-
+ the symbol _POSIX_NO_TRUNC, but you can't change it dynamically! */
string
-kpathsea_readable_file (kpathsea kpse, const_string name)
+kpathsea_readable_file (kpathsea kpse, string name)
{
- string ret;
-
#ifdef WIN32
unsigned int st = 0;
#else /* ! WIN32 */
struct stat st;
#endif
- kpathsea_normalize_path(kpse, (string)name);
+ kpathsea_normalize_path (kpse, name);
if (READABLE (name, st)) {
- ret = (string) name;
+ return name;
#ifdef ENAMETOOLONG
} else if (errno == ENAMETOOLONG) {
- ret = kpathsea_truncate_filename (kpse, name);
+ /* Truncate any too-long components in NAME. */
+ unsigned c_len = 0; /* Length of current component. */
+ char *s = name; /* Position in current component. */
+ char *t = name; /* End of allowed length. */
+
+ for (; *s; s++) {
+ if (c_len <= NAME_MAX)
+ t = s;
+#if defined(WIN32)
+ if (IS_KANJI (s)) {
+ s++;
+ c_len += 2;
+ continue;
+ }
+#endif
+ if (IS_DIR_SEP (*s) || IS_DEVICE_SEP (*s)) {
+ if (c_len > NAME_MAX) {
+ /* Truncate if past the max for a component. */
+ memmove (t, s, strlen (s) + 1);
+ s = t;
+ }
+ /* At a directory delimiter, reset component length. */
+ c_len = 0;
+ } else
+ c_len++;
+ }
+ if (c_len > NAME_MAX)
+ /* Truncate if past the max for last component. */
+ *t = 0;
/* 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;
- }
+ if (READABLE (name, st)) /* Success. */
+ return name;
#endif /* ENAMETOOLONG */
} else { /* Some other error. */
if (errno == EACCES) { /* Maybe warn them if permissions are bad. */
@@ -101,14 +124,13 @@ kpathsea_readable_file (kpathsea kpse, const_string name)
perror (name);
}
}
- ret = NULL;
}
- return ret;
+ return NULL;
}
#if defined (KPSE_COMPAT_API)
string
-kpse_readable_file (const_string name)
+kpse_readable_file (string name)
{
return kpathsea_readable_file (kpse_def, name);
}