summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2020-12-21 15:29:32 -0500
committerZack Weinberg <zackw@panix.com>2020-12-23 14:06:07 -0500
commit616480956de06e32526775c8b7f8fd34d04238a5 (patch)
treef94e135ff6a3cb00f72bc8cbb9411c465cbea3ef
parent8118c2adc4dc0a7ee4f9616197d0e3db42f9a788 (diff)
downloadautoconf-616480956de06e32526775c8b7f8fd34d04238a5.tar.gz
autom4te: correct error message when we can’t create autom4te.cache.
While testing something else, I noticed that autom4te may print a nonsensical error message when it fails to create autom4te.cache, because it checks again whether the directory already exists before giving up, and this clobbers errno. Instead of doing (the perl equivalent of) test -d $cache || mkdir $cache || test -d $cache call mkdir unconditionally. If it fails with an errno code other than EEXIST, consider that a hard failure; if it fails with EEXIST, check whether the thing that exists is in fact a directory. (A symlink to a directory qualifies; I wouldn’t be surprised if people are moving autom4te.cache around with symlinks.) Either way, if we fail, report strerror(errno) from the original mkdir failure. Also, print the current working directory as part of the error message; this aids debugging when you’re working with a big hairy nested tree. * bin/autom4te.in: Don’t check whether autom4te.cache exists before attempting to create it. Only stat autom4te.cache if mkdir fails with EEXIST, otherwise fail immediately. Make sure to report the errno code from mkdir, not the subsequent stat (if any). Report the current working directory as part of the error message. * tests/tools.at: Verify that autom4te reports the actual reason when it fails to create autom4te.cache. Verify that failure to create autom4te.cache because that name exists, but isn’t a directory, is detected.
-rw-r--r--bin/autom4te.in19
-rw-r--r--tests/tools.at20
2 files changed, 32 insertions, 7 deletions
diff --git a/bin/autom4te.in b/bin/autom4te.in
index febcdeea..4c2b905c 100644
--- a/bin/autom4te.in
+++ b/bin/autom4te.in
@@ -1012,12 +1012,21 @@ if ($freeze)
exit $exit_code;
}
-# We need our cache directory. Don't fail with parallel creation.
-if (! -d "$cache")
+# Ensure the cache directory exists.
+if (! mkdir ($cache, 0755))
{
- mkdir "$cache", 0755
- or -d "$cache"
- or fatal "cannot create $cache: $!";
+ # Snapshot $! immediately, the next few operations may clobber it.
+ my $eexist = $!{EEXIST};
+ my $errmsg = "$!";
+
+ # If mkdir failed with EEXIST, that means the *name* $cache
+ # already exists, but it might be the wrong kind of file.
+ if (! $eexist || ! -d $cache)
+ {
+ require Cwd;
+ my $cwd = Cwd::cwd();
+ fatal "cannot create $cache in $cwd: $errmsg";
+ }
}
# Open the index for update, and lock it. autom4te handles several
diff --git a/tests/tools.at b/tests/tools.at
index d32ad362..49710202 100644
--- a/tests/tools.at
+++ b/tests/tools.at
@@ -1534,20 +1534,36 @@ end-language: "Autoconf-without-aclocal-m4"
# A failed redirection may cause a status of 2 with FreeBSD sh.
AT_CHECK([(: > sub/some-file) || exit 1 && exit 77], 1, [ignore], [ignore])
-# Failure to create cache directory.
+# Failure to create cache directory due to access permissions.
AT_CHECK_AUTOCONF([], [1], [ignore], [stderr])
AT_CHECK([grep 'cannot create .*autom4te.cache' stderr], [0], [ignore])
+AT_CHECK([grep ': Permission denied' stderr], [0], [ignore])
AT_CHECK([test -f configure], [1])
+# Failure to create cache directory due to something else in the way.
chmod u+w sub
+: > sub/autom4te.cache
+AT_CHECK_AUTOCONF([], [1], [ignore], [stderr])
+AT_CHECK([grep 'cannot create .*autom4te.cache' stderr], [0], [ignore])
+AT_CHECK([grep ': File exists' stderr], [0], [ignore])
+AT_CHECK([test -f configure], [1])
+
+# This time, creation should succeed.
+rm -f sub/autom4te.cache
AT_CHECK_AUTOCONF
+AT_CHECK([test -d sub/autom4te.cache])
rm -f configure sub/autom4te.cache/*
chmod a-w sub/autom4te.cache
# Failure to create a file in the cache directory.
AT_CHECK_AUTOCONF([], [1], [ignore], [stderr])
-AT_CHECK([grep 'cannot open.*autom4te.cache' stderr], [0], [ignore])
+AT_CHECK([grep 'cannot open .*autom4te.cache' stderr], [0], [ignore])
+AT_CHECK([test -f configure], [1])
+
+# If the directory already exists, that should be fine.
+chmod u+w sub/autom4te.cache
+AT_CHECK_AUTOCONF
AT_CLEANUP