Coreutils (mv) bug

Eric Blake
Fri Jun 24 14:06:00 GMT 2005

Hash: SHA1

According to Christopher Faylor on 6/23/2005 1:11 PM:
> Since managed mounts are rare you could solve 99% of the problems by
> doing what I mentioned.  Just don't do it for managed mounts.

Is there an easy way to see if a filename belongs to a managed mount?

Also, as a thought process, would supressing the .exe magic on a managed
mount may make sense, since the sole purpose of managed mounts is to be
more unix-like where what you type is what you get?  This would mean that
on a managed mount, you always get ENOENT if you request "foo" when only
"foo.exe" exists from the user's perspective.  To be useful for invoking
utilities, executables would then have to default to compiling "foo"
instead of "foo.exe" from the user's perspective, requiring a tweak to gcc
to see if it is outputting to a managed mount.  Also, it might make more
sense for the managed mount code to hide a single .exe extension, kind of
like the .lnk extension of symlinks is hidden everywhere else.  And if the
user really wants a .exe extension on a managed mount, the filename
mangler would have to modify it so that it can tell the difference between
hidden .exe and what the user typed.  It may also involve some tweaks to
autoconf/automake, which would have to learn that on managed mounts,
$(EXEEXT) should be empty.  But this has all been a thought experiment,

In the meantime, back in reality land, I noticed another bug in readlink()
- - on a symlink, it sets errno to ENOTDIR even though it succeeds.  Also,
the trailing . trick does not work on symlinks the way I expected (whether
it is dangling or not), but fortunately a trailing .lnk comes to the
rescue.  Therefore, after several hours of tinkering, I came up with the
following test which should be a 100% reliable way to see if file exists
as spelled or had an .exe appended (myjoin() should be an obvious helper

if (readlink(file, NULL, 0) < 0)
  { /* not a symlink */
    if (errno == EINVAL)
      { /* but is an existing file or dir */
        if (access(myjoin(file, "."), F_OK) == 0)
          /* non symlink, spelled "file" */;
          /* non symlink, spelled "file.exe" */;
      /* does not exist under any spelling */;
  { /* symlink exists */
    if (readlink(myjoin(file, ".lnk"), NULL, 0) == 0)
      /* symlink, dangling or targetted, spelled "file" */;
      /* symlink, dangling or targetted, spelled "file.exe" */;

Any comments from anyone agreeing with my logic?  Obviously, because this
is not atomic, it can experience random mis-diagnoses if some other task
is hitting the same directory, but that is a common problem to all cygwin
file operations.  And it doesn't work on managed mounts, so if that ever
becomes a FAQ, I'll know what to look for.

Now to apply it to coreutils, and see if this more accurate snooping for
.exe magic can fix the recent mv, ln, install, and cp issues.

- --
Life is short - so eat dessert first!

Eric Blake   
Version: GnuPG v1.4.0 (Cygwin)
Comment: Public key at
Comment: Using GnuPG with Thunderbird -


Unsubscribe info:
Problem reports:

More information about the Cygwin mailing list