Subject: Re: Linux emulation and mkdir with trailing /
To: Alan Barrett <apb@cequrux.com>
From: Bill Studenmund <wrstuden@zembu.com>
List: tech-kern
Date: 09/25/2000 11:13:21
On Mon, 25 Sep 2000, Alan Barrett wrote:
> If bar is a non-directory file, why would you expect to be able to
> open "bar/" (with a trailing slash)? What's the point of the trailing
> slash?
>
> I expect '/' to mark directories. My expectation is based on
> observing patterns of behaviour. The only use I know for slashes in a
> unix-like filesystem is to mark the root of the filesystem and to
> separate components where all components (except perhaps the last) are
> directory names. In my limited experience, I have never encountered
> any use for a trailing slash after a non-directory file name, nor seen
> anybody deliberately put trailing slashes after a non-directory file
> name. Whenever I have seen a slash in a filename, the slash has been
> used either to indicate the root of the filesystem, or to mark the
> thing before the slash as a directory. Whenever I have seen other
> people use trailing slashes in filenames on a unix-like system, those
> other people have intended to name a directory. I observe that I get
> errors from "touch foo/" and not from "touch foo" (if foo did not
> previously exist). I observe that "mv foo bar/" fails if bar does not
> exist as a directory. All this makes me expect that a trailing slash
> should be permitted on a directory name but illegal on a non-directory
> name.
>
> I might not have non-BSD historical precedent on my side, but I surely
> have the principle of least astonishment on my side. Allowing "bar/"
> to refer to a non-directory file is very astonishing to people
> familiar with the way '/' is usually used in filenames.
I agree with Alan here.
As I understand it, the desired behavior is
"mkdir /foo/bar/" will work when only /foo exists.
We don't need to hack mkdir to do this. A much cleaner way is to change
lookup(), since it after all is returning the error.
I think the code to change is:
/*
* If this was not the last component, or there were trailing
* slashes, then the name must exist.
*/
if (cnp->cn_flags & REQUIREDIR) {
error = ENOENT;
goto bad;
}
which is around line 465 of sys/kern/vfs_lookup.c. If we made it:
if ((cnp->cn_flags & REQUIREDIR) &&
(~cnp->cn_flags & (ISLASTCN & CREATE_DIR))) {
where CREATE_DIR is a new flag for namei. The logic is that if we are
creating a directory, and we have hit the last component and the name
doesn't exist, then it's ok to return what we've got (a locked parent
dir and a NULL vpp).
(We want to return an error if we require a directory (there were slashes
after this name) and we either aren't at the end of the name (ISLASTCN
isn't set) or someone tried to create a file which had a / at the end of
the name (CREATE_DIR not set since we aren't called by a directory-making
syscall).)
Thoughts?
Take care,
Bill