[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
invalid assumption of m4/getcwd-path-max.m4
From: |
Eric Blake |
Subject: |
invalid assumption of m4/getcwd-path-max.m4 |
Date: |
Fri, 25 Mar 2005 23:19:50 +0000 |
Right now, m4/getcwd-path-max.m4 of coreutils 5.3.0 or CVS is overly
pessimistic, and the test program returns 2 (interpreted as getcwd does not
even partially work) if it fails to mkdir or chdir to the ever-growing
pathname. This unnecessarily penalizes cygwin, where PATH_MAX is 259 [1] and
NAME_MAX is 255 [2], and where it is not possible, even with relative paths, to
ever exceed PATH_MAX for the absolute name of the file [3]. Therefore,
cygwin's getcwd() always succeeds [4] if given a large enough buffer (or if you
let it malloc), but running configure fails to detect this and has pwd(1)
resort to the (sometimes orders of magnitude) slower stat . / readdir .. loop
[5].
This is a regression from the 5.2.1 coreutils, where getcwd() was always
trusted. I worked around it in the cygwin build of 5.3.0 by priming the
config.cache with gl_cv_func_getcwd_path_max=yes. But it would be nicer if
configure could gracefully detect that the system cannot possibly mkdir() or
creat() a filename, relative or absolute, whose the absolute name would exceed
PATH_MAX. In that case, it is provable that getcwd() cannot fail when the
working directory is longer than PATH_MAX (since it is trivially true that the
working directory name can't be that long if that filename can't be created).
--
Eric Blake
[1] Cygwin uses 259 because Microsoft documents that the ASCII versions of
their syscalls are limited to 260 characters, including the trailing nul. Why
they subtract 1, since POSIX allows PATH_MAX to include the trailing nul, is
beyond me. Technically, Windows NT and later running NTFS supports pathnames
up to 32k, using the Unicode version of Windows syscalls and the \\?\ prefix,
but cygwin does not support this because it must also run on Windows 95 and FAT.
Furthermore, cygwin's definition of 259 is misleading - it is currently the
maximum length of the underlying absolute Windows path. Therefore, if the path
'/' maps to 'c:\cygwin\', while '/cygdrive/c' maps to 'c:\' (a common case in
the default cygwin installation), then the pathname / occupies more characters
(10) than /cygdrive/c (3)! This is further compounded by cygwin managed
mounts, which allow one to represent case sensitivity and otherwise invalid
characters in DOS filenames (such as \n) by expanding the offending characters
into %xx sequences. Thus, on a managed mount, it is possible for `touch a' to
succeed but `touch A' to fail with ENAMETOOLONG, because A expands to %41.
Therefore, cygwin does not even always satisfy the POSIX-mandated minimum
acceptable PATH_MAX of 256 in <limits.h>, let alone the XSI-mandated minimum of
1024.
[2] Actually, cygwin doesn't (yet) define NAME_MAX, but Microsoft documents
that Windows limits it to 255, equal to the XSI-mandated minimum, because of
the format of NTFS and FAT. And on managed mounts, it can be reduced to 85
(still greater than the POSIX minimum of 14), due to the %xx expansion going on.
[3] To make sure that it is not a cygwin-imposed limitation that could be
patched, I also tried using relative pathnames to the native Windows API of
CreateDirectory and SetCurrentDirectory (ASCII versions), and still get
ERROR_FILENAME_EXCED_RANGE when the CreateDirectory would exceed 260 characters
in the absolute pathname. Technically, someone could patch cygwin on NTFS by
allowing a PATH_MAX of 1024 that applies to the POSIX names (/ has length 1,
/cygdrive/c has length 11) rather than the underlying Windows name, and by
switching to using the Unicode API; and if that is done then relative paths
could generate files with POSIX absolute names longer than PATH_MAX, up to the
32k limit of the Windows absolute path name. But that PATH_MAX would be a lie
on FAT systems, and would still have the oddities where different POSIX names
of the same length expand to different length Windows names, so I doubt it will
happen any time soon.
[4] Windows has the property, allowed by POSIX, that a directory can't be
deleted or renamed if any process has it as its current working directory, so
unlike systems where unlink("..") can succeed, cygwin will never have an
invalid working directory.
[5] When the current directory is /cygdrive, getpwd() is practically
instantaneous (it doesn't even have to use a Windows system call); but
readdir() causes more than 26 syscalls to scan each possible drive letter, and
causes an annoying grinding noise and momentary freeze of the entire system
while checking each floppy drive to see if a disk is present.
- invalid assumption of m4/getcwd-path-max.m4,
Eric Blake <=