This is the mail archive of the mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: cygwin's unlink

On Tue, Oct 26, 1999 at 02:01:10PM -0600, Steve Jorgensen wrote:
>Anyway, in the case where the file is truely a directory, under all
>unix systems we've tried, unlink returns and error, and we proceed with
>the recursive directory removal, but under cygwin it returns success
>(even though nothing is removed), and our code returns success without
>removing the directory.  Is this a limitation in the underlying windows
>unlink, or a bug in cygwin?

From: Chris Faylor <>
> When I try this I get a "Permission denied" error.  It should be a
> "Is a directory error" though.  I've changed the sources here so
> this should be fixed in the next snapshot.

Finally,  J. J. Farrell <> says:
> Before you fix that (he says, probably too late) ...
> This one's a bit complex. First off: under POSIX.1 it is
> implementation-defined whether or not unlink() works on
> directories. This means that Steve's algorithm is wrong,
> since what he saw as a bug in cygwin's unlink() is perfectly
> valid behaviour for a POSIX.1 system. The fact that POSIX
> allows it suggests that at least one UNIX implementation
> behaved that way when POSIX.1 was drawn up, and future ones
> are allowed to if they wish (though rmdir() is the preferred
> interface).
> Secondly: in the case where the implementation does not
> support unlink() on directories, the required error value
> is EPERM which would result in a "Permission denied" error.
> From the XPG3 documentation (which is aligned with POSIX.1):
>  [EPERM] The file named by path is a directory, and either
>          the calling process does not have appropriate
>          privileges, or the implementation prohibits using
>          unlink() on directories.

It appears that unlink() applied to a directory does not work (which is
consistent with POSIX.1), but returns success.  It seems that POSIX.1
requires EPERM to be returned if unlink() does not work, so Steve's
algorithm relying on an unsuccessful unlink() of a directory returning
an error is probably OK, although perhaps it would be more robust to
do a stat() first to determine if it is a directory.

A historical note as to why I think that POSIX.1 allows unlink() to maybe
work on directories, and the reason for the EPERM error (instead of EISDIR
which might seem more sensible) is that originally Unix did not have a
rmdir() system call.  Directories were removed by the /bin/rmdir command,
which was suid to root.  As root, it was possible to use the unlink() call
to remove a directory.  Of course, you had to remove "directory/.." first,
to keep the reference count of the parent directory correct, and to ensure
that there were no files in the directory being removed.  So, since unlink()
would simply remove the hard link, but did not adjust reference counts in
the filesystem, it was not safe to let just anyone make the call, so if
you weren't root, you got the EPERM error.

Making a directory (since there was no mkdir() system call) was done via a
call to mknod() to create a directory type file, then link() calls to create
"." and ".." in the new directory.

This meant that to create or delete a directory, a normal user program had to
do a fork() and exec() of /bin/mkdir or /bin/rmdir, which was somewhat
inconvenient, but because these programs made several system calls to
perform their tasks, there were race conditions that could occur with other
processes creating files in a directory /bin/rmdir was removing and had
already verified was empty, etc.  By making mkdir() and rmdir() system calls,
they can be made atomic removing race conditions and making the file system
a little more stable.

marcus hall

Want to unsubscribe from this list?
Send a message to

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]