Attaching once more, fixed git message.
Pavel
>From bbe2a9d9aa0a4cef52084c6ed597c2279db544f5 Mon Sep 17 00:00:00 2001
From: Pavel Raiskup <[email protected]>
Date: Thu, 16 Jun 2016 13:42:13 +0200
Subject: [PATCH] modules, include: fix path-search issues
When 'm4' directory occurred in M4PATH or current directory
(happens very often with autotooled packages), the module loader -
while searching for 'm4.so', ended up with 'Is a directory' error
message.
Expanding 'include(Makefile)' failed before when M4PATH was set,
because in that case the current working directory was not
in module path.
* m4/path.c (try_prefixes): New function.
(m4_path_search): De-duplicate suffix trying by try_prefixes.
(m4__include_init): Always prepend current directory.
* tests/testsuite.at (AT_CHECK_M4): Filter out test output
dependant on user's setup.
* tests/options.at: Adjust expected stderr output.
* tests/others.at: As we now return really the _first_ errno
occured during path searching, we need to adjust expected error
output.
* doc/m4.texi: likewise.
---
doc/m4.texi | 2 +
m4/path.c | 126 ++++++++++++++++++++++++++++-------------------------
tests/options.at | 6 ++-
tests/others.at | 8 ++--
tests/testsuite.at | 1 +
5 files changed, 77 insertions(+), 66 deletions(-)
diff --git a/doc/m4.texi b/doc/m4.texi
index ba1b157..7f0d375 100644
--- a/doc/m4.texi
+++ b/doc/m4.texi
@@ -4683,6 +4683,8 @@
@comment options: -dip
@example
$ @kbd{m4 -dip -I doc/examples}
+@error{}m4debug: path search for 'm4' found 'm4.so'
+@error{}m4debug: path search for 'gnu' found 'gnu.so'
@error{}m4debug: input read from 'stdin'
define(`foo', `m4wrap(`wrapped text
')dnl')
diff --git a/m4/path.c b/m4/path.c
index ef743a3..a1ff090 100644
--- a/m4/path.c
+++ b/m4/path.c
@@ -182,6 +182,63 @@ m4_add_include_directory (m4 *context, const char *dir, bool prepend)
#endif
}
+/* Search for m4 module in DIRNAME directory. Try to test _all_ SUFFIXES with
+ FILENAME; use the first combination which seems to be correct m4 module. If
+ the FILENAME is absolute path, DIRNAME shall be NULL. */
+static char *
+try_suffixes (m4 *context, const char *dirname, const char *filename,
+ size_t max_suffix_len, const char **suffixes)
+{
+ int e = 0, i;
+ char *filepath = dirname ? file_name_concat (dirname, filename, NULL)
+ : strdup (filename);
+ size_t mem = strlen (filepath);
+ filepath = xrealloc (filepath, mem + max_suffix_len + 1);
+
+#if TRUNCATE_FILENAME
+ filepath = path_truncate (filepath);
+ mem = strlen (filepath); /* recalculate length after truncation */
+#endif
+
+#ifdef DEBUG_INCL
+ xfprintf (stderr, "path_search (%s) -- trying %s\n", filename, filepath);
+#endif
+
+ /* If search fails, we'll use the errno we got from the first unsuccessful
+ try. */
+ for (i = 0; suffixes && suffixes[i]; !i && (e = errno), ++i)
+ {
+ struct stat st;
+ int rc;
+ strcpy (filepath + mem, suffixes[i]);
+
+ /* Use stat() here rather than access() because access does not give us
+ S_ISDIR(st.st_mode) info. Choosing a module which we have no
+ privileges to open is not problem because dlopening later will fail
+ anyway with a understandable error. */
+ if (stat (filepath, &st))
+ continue;
+
+ if (S_ISREG (st.st_mode))
+ {
+ m4_debug_message (context, M4_DEBUG_TRACE_PATH,
+ _("path search for %s found %s"),
+ quotearg_style (locale_quoting_style, filename),
+ quotearg_n_style (1, locale_quoting_style,
+ filepath));
+ return filepath;
+ }
+
+ if (S_ISDIR (st.st_mode))
+ errno = EISDIR;
+ }
+ free (filepath);
+
+ /* No such file. */
+ errno = e;
+ return NULL;
+}
+
/* Search for FILENAME according to -B options, `.', -I options, then
M4PATH environment. If successful, return the open file, and if
@@ -220,69 +277,18 @@ m4_path_search (m4 *context, const char *filename, const char **suffixes)
/* If file is absolute, or if we are not searching a path, a single
lookup will do the trick. */
if (IS_ABSOLUTE_FILE_NAME (filename))
- {
- size_t mem = strlen (filename);
-
- /* Try appending each of the suffixes we were given. */
- filepath = strncpy (xmalloc (mem + max_suffix_len +1), filename, mem +1);
-#if TRUNCATE_FILENAME
- filepath = path_truncate (filepath);
- mem = strlen (filepath); /* recalculate length after truncation */
-#endif
- for (i = 0; suffixes && suffixes[i]; ++i)
- {
- strcpy (filepath + mem, suffixes[i]);
- if (access (filepath, R_OK) == 0)
- return filepath;
-
- /* If search fails, we'll use the error we got from the first
- access (usually with no suffix). */
- if (i == 0)
- e = errno;
- }
- free (filepath);
+ return try_suffixes (context, NULL, filename, max_suffix_len, suffixes);
- /* No such file. */
- errno = e;
- return NULL;
- }
-
- for (incl = m4__get_search_path (context)->list;
- incl != NULL; incl = incl->next)
+ for (incl = m4__get_search_path (context)->list, i = 0;
+ incl != NULL; incl = incl->next, ++i)
{
- char *pathname = file_name_concat (incl->dir, filename, NULL);
- size_t mem = strlen (pathname);
-
-#ifdef DEBUG_INCL
- xfprintf (stderr, "path_search (%s) -- trying %s\n", filename, pathname);
-#endif
-
- if (access (pathname, R_OK) == 0)
- {
- m4_debug_message (context, M4_DEBUG_TRACE_PATH,
- _("path search for %s found %s"),
- quotearg_style (locale_quoting_style, filename),
- quotearg_n_style (1, locale_quoting_style, pathname));
- return pathname;
- }
- else if (!incl->len)
- /* Capture errno only when searching `.'. */
- e = errno;
+ char *pathname = try_suffixes (context, incl->dir, filename,
+ max_suffix_len, suffixes);
+ if (pathname)
+ return pathname;
- filepath = strncpy (xmalloc (mem + max_suffix_len +1), pathname, mem +1);
- free (pathname);
-#if TRUNCATE_FILENAME
- filepath = path_truncate (filepath);
- mem = strlen (filepath); /* recalculate length after truncation */
-#endif
-
- for (i = 0; suffixes && suffixes[i]; ++i)
- {
- strcpy (filepath + mem, suffixes[i]);
- if (access (filepath, R_OK) == 0)
- return filepath;
- }
- free (filepath);
+ if (i == 0)
+ e = errno;
}
errno = e;
diff --git a/tests/options.at b/tests/options.at
index 7084207..8fa19b6 100644
--- a/tests/options.at
+++ b/tests/options.at
@@ -423,10 +423,12 @@ m4debug: input from m4wrap exhausted
dnl Test all flags.
AT_CHECK_M4([-dV in], [0], [[3
0
-]], [[m4debug: module m4: opening file
+]], [[m4debug: path search for 'm4' found 'm4.so'
+m4debug: module m4: opening file
m4debug: module m4: init hook called
m4debug: module m4: opened
m4debug: module m4: builtins loaded
+m4debug: path search for 'gnu' found 'gnu.so'
m4debug: module gnu: opening file
m4debug: module gnu: init hook called
m4debug: module gnu: opened
@@ -701,7 +703,7 @@ AT_CHECK_M4([-I post -B pre in], [1],
[[in pre/foo
in ./bar
in post/blah
-]], [[m4:in:3: include: cannot open file 'bad': No such file or directory
+]], [[m4:in:3: include: cannot open file 'bad': Too many levels of symbolic links
]])
AT_CLEANUP
diff --git a/tests/others.at b/tests/others.at
index 9c7a0c6..507ef78 100644
--- a/tests/others.at
+++ b/tests/others.at
@@ -144,15 +144,15 @@ AT_DATA([in3.m4],
AT_CHECK_M4([in1.m4/], [1], [], [stderr])
dnl mingw fails with EINVAL rather than the expected ENOTDIR
-AT_CHECK([$SED 's/Invalid argument/Not a directory/' stderr], [0],
-[[m4: cannot open file 'in1.m4/': Not a directory
+AT_CHECK([$SED 's/Invalid argument/No such file or directory/' stderr], [0],
+[[m4: cannot open file 'in1.m4/': No such file or directory
]])
AT_CHECK_M4([in1.m4], [1], [[
]], [stderr])
dnl mingw fails with EINVAL rather than the expected ENOTDIR
-AT_CHECK([$SED 's/Invalid argument/Not a directory/' stderr], [0],
-[[m4:in1.m4:1: include: cannot open file 'in2.m4/': Not a directory
+AT_CHECK([$SED 's/Invalid argument/No such file or directory/' stderr], [0],
+[[m4:in1.m4:1: include: cannot open file 'in2.m4/': No such file or directory
]])
AT_CHECK_M4([in2.m4], [0], [[
diff --git a/tests/testsuite.at b/tests/testsuite.at
index a7cdfc4..20246e2 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -89,6 +89,7 @@ m4_case([$4], [], [], [ignore], [],
/^m4debug: module/s/opening file.*/opening file/
s/\(cannot open module [^:]*\):.*/\1/
s/Bad file number/Bad file descriptor/
+ s|search for \([^ ]*\) found '\''.*\/\([^\.]*\.so\)|search for \1 found '\''\2|
s/^m4:.* option .*/m4: bad option/
' stderr >&2]], [0], [], [$4])])
])
--
2.7.4
_______________________________________________
M4-patches mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/m4-patches