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.
This commit is contained in:
Zack Weinberg 2020-12-21 15:29:32 -05:00
parent 237519e6e7
commit ea9d7d9f1f
No known key found for this signature in database
GPG Key ID: 384F8E68AC65B0D5
2 changed files with 32 additions and 7 deletions

View File

@ -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

View File

@ -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