[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 

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 

[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.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]