This is the mail archive of the
cygwin-developers
mailing list for the Cygwin project.
Re: findutils support in 1.7.0
- From: Eric Blake <ebb9 at byu dot net>
- To: cygwin-developers at cygwin dot com
- Date: Sat, 26 Apr 2008 06:14:41 -0600
- Subject: Re: findutils support in 1.7.0
- References: <48129F17.5000707@byu.net> <20080426083905.GA3023@calimero.vinschen.de>
According to Corinna Vinschen on 4/26/2008 2:39 AM:
[moving to -devel]
Also, it looks like long path names are currently
quadratic in behavior,
Dunno about that. Right now the path is converted from multibyte
to wchar and vice versa a couple of times more often than necessary,
probably, but it shouldn't be quadratic. Do you have a simple(tm)
testcase to reproduce?
http://git.sv.gnu.org/gitweb/?p=gnulib.git;a=blob;f=m4/getcwd-path-max.m4;h=5e6d58b;hb=bb037ad
--
Don't work too hard, make some time for fun as well!
Eric Blake ebb9@byu.net
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#ifndef AT_FDCWD
# define AT_FDCWD 0
#endif
#ifdef ENAMETOOLONG
# define is_ENAMETOOLONG(x) ((x) == ENAMETOOLONG)
#else
# define is_ENAMETOOLONG(x) 0
#endif
/* Don't get link errors because mkdir is redefined to rpl_mkdir. */
#undef mkdir
#ifndef S_IRWXU
# define S_IRWXU 0700
#endif
/* The length of this name must be 8. */
#define DIR_NAME "confdir3"
#define DIR_NAME_LEN 8
#define DIR_NAME_SIZE (DIR_NAME_LEN + 1)
/* The length of "../". */
#define DOTDOTSLASH_LEN 3
/* Leftover bytes in the buffer, to work around library or OS bugs. */
#define BUF_SLOP 20
int
main ()
{
#ifndef PATH_MAX
/* The Hurd doesn't define this, so getcwd can't exhibit the bug --
at least not on a local file system. And if we were to start worrying
about remote file systems, we'd have to enable the wrapper function
all of the time, just to be safe. That's not worth the cost. */
exit (0);
#elif ((INT_MAX / (DIR_NAME_SIZE / DOTDOTSLASH_LEN + 1) \
- DIR_NAME_SIZE - BUF_SLOP) \
<= PATH_MAX)
/* FIXME: Assuming there's a system for which this is true,
this should be done in a compile test. */
exit (0);
#else
char buf[PATH_MAX * (DIR_NAME_SIZE / DOTDOTSLASH_LEN + 1)
+ DIR_NAME_SIZE + BUF_SLOP];
char *cwd = getcwd (buf, PATH_MAX);
size_t initial_cwd_len;
size_t cwd_len;
int fail = 0;
size_t n_chdirs = 0;
if (cwd == NULL)
exit (1);
cwd_len = initial_cwd_len = strlen (cwd);
while (1)
{
size_t dotdot_max = PATH_MAX * (DIR_NAME_SIZE / DOTDOTSLASH_LEN);
char *c = NULL;
cwd_len += DIR_NAME_SIZE;
/* If mkdir or chdir fails, it could be that this system cannot create
any file with an absolute name longer than PATH_MAX, such as cygwin.
If so, leave fail as 0, because the current working directory can't
be too long for getcwd if it can't even be created. For other
errors, be pessimistic and consider that as a failure, too. */
if (mkdir (DIR_NAME, S_IRWXU) < 0 || chdir (DIR_NAME) < 0)
{
if (! (errno == ERANGE || is_ENAMETOOLONG (errno)))
fail = 2;
break;
}
if (PATH_MAX <= cwd_len && cwd_len < PATH_MAX + DIR_NAME_SIZE)
{
c = getcwd (buf, PATH_MAX);
if (!c && errno == ENOENT)
{
fail = 1;
break;
}
if (c || ! (errno == ERANGE || is_ENAMETOOLONG (errno)))
{
fail = 2;
break;
}
}
if (dotdot_max <= cwd_len - initial_cwd_len)
{
if (dotdot_max + DIR_NAME_SIZE < cwd_len - initial_cwd_len)
break;
c = getcwd (buf, cwd_len + 1);
if (!c)
{
if (! (errno == ERANGE || errno == ENOENT
|| is_ENAMETOOLONG (errno)))
{
fail = 2;
break;
}
if (AT_FDCWD || errno == ERANGE || errno == ENOENT)
{
fail = 1;
break;
}
}
}
if (c && strlen (c) != cwd_len)
{
fail = 2;
break;
}
++n_chdirs;
}
/* Leaving behind such a deep directory is not polite.
So clean up here, right away, even though the driving
shell script would also clean up. */
{
size_t i;
/* Try rmdir first, in case the chdir failed. */
rmdir (DIR_NAME);
for (i = 0; i <= n_chdirs; i++)
{
if (chdir ("..") < 0)
break;
if (rmdir (DIR_NAME) != 0)
break;
}
}
exit (fail);
#endif