On 10/12/2015 02:00 PM, Jonathan Leffler wrote:
1. Has anyone else seen anything similar on El Capitan?
2. Does anyone have an idea how to get rid of the trashed directories?
3. How can we modify the test so it doesn't fail catastrophically like
this on El Capitan?
4. Do I need to report a bug to Apple separately from this report to
GNU Tar?
For (4), OS X is clearly busted here. A user-mode application shouldn't
be able to create a directory that 'rm -fr' can't remove. Please feel
free to report the bug to Apple. The problem will occur with many GNU
tools' installation procedure, as they're all using Gnulib and Gnulib
tries to check for getcwd bugs like this one.
For (2) I suggest using coreutils; 'rm -fr directory should do the trick
if you're using GNU rm.
For (3) we need to figure out why the test doesn't clean up after itself
on El Capitan. It's supposed to. Please compile and run the attached
test program in a place where you don't mind having long directory
chains. On my GNU/Linux host, I can do something like this:
gcc t.c
strace ./a.out
and the 'strace' output contains the following, showing that the test
program cleans up after itself. Please find out why it's not doing so
under El Capitan. OS X lacks strace, but you can use a debugger or
dtruss or whatever your favorite tool is. Thanks.
mkdir("confdir-14B---", 0700) = 0
chdir("confdir-14B---") = 0
mkdir("confdir-14B---", 0700) = 0
chdir("confdir-14B---") = 0
...
mkdir("confdir-14B---", 0700) = 0
chdir("confdir-14B---") = 0
getcwd(0x1736010, 4096) = -1 ENAMETOOLONG (File name too
long)
[a whole bunch of other stuff, which eventually succeeds. Now comes
cleanup time....]
rmdir("confdir-14B---") = -1 ENOENT (No such file or
directory)
chdir("..") = 0
rmdir("confdir-14B---") = 0
chdir("..") = 0
...
chdir("..") = 0
rmdir("confdir-14B---") = 0
exit_group(0) = ?
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
/* Arrange to define PATH_MAX, like "pathmax.h" does. */
#include <unistd.h>
#include <limits.h>
#include <sys/param.h>
#if !defined PATH_MAX && defined MAXPATHLEN
# define PATH_MAX MAXPATHLEN
#endif
#ifndef S_IRWXU
# define S_IRWXU 0700
#endif
/* This size is chosen to be larger than PATH_MAX (4k), yet smaller than
the 16kB pagesize on ia64 linux. Those conditions make the code below
trigger a bug in glibc's getcwd implementation before 2.4.90-10. */
#define TARGET_LEN (5 * 1024)
int
main (void)
{
char *cwd;
size_t initial_cwd_len;
int fail = 0;
cwd = getcwd (NULL, 0);
if (cwd == NULL)
return 2;
initial_cwd_len = strlen (cwd);
free (cwd);
if (1)
{
static char const dir_name[] = "confdir-14B---";
size_t desired_depth = ((TARGET_LEN - 1 - initial_cwd_len)
/ sizeof dir_name);
size_t d;
for (d = 0; d < desired_depth; d++)
{
if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0)
{
if (! (errno == ERANGE || errno == ENAMETOOLONG
|| errno == ENOENT))
fail = 3; /* Unable to construct deep hierarchy. */
break;
}
}
/* If libc has the bug in question, this invocation of getcwd
results in a failed assertion. */
cwd = getcwd (NULL, 0);
if (cwd == NULL)
fail = 4; /* getcwd didn't assert, but it failed for a long name
where the answer could have been learned. */
free (cwd);
/* Call rmdir first, in case the above chdir failed. */
rmdir (dir_name);
while (0 < d--)
{
if (chdir ("..") < 0)
{
fail = 5;
break;
}
rmdir (dir_name);
}
}
return fail;
}