Download raw body.
openat(2) is mostly useless, sadly
Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> > From: "Theo de Raadt" <deraadt@openbsd.org>
> > Date: Fri, 30 May 2025 19:17:46 -0600
> >
> > Steffen Nurpmeso <steffen@sdaoden.eu> wrote:
> >
> > > I would not use ENOTTY for F_BELOW on !DIR, maybe ENOTDIR is
> > > better.
> >
> > >From errno(2) manpage:
> >
> > 20 ENOTDIR Not a directory. A component of the specified pathname
> > existed, but it was not a directory, when a directory was
> > expected.
> >
> > F_BELOW is fcntl(2).
> >
> > int
> > fcntl(int fd, int cmd, ...);
> >
> > But there is no pathname. Yes it is partly vague, but then grep the whole
> > tree for ENOTDIR and always anticipates a pathname at a higher level.
>
> Note that openat(2) says:
>
> [ENOTDIR] The path argument specifies a relative path and the fd
> argument is a valid file descriptor but it does not
> reference a directory.
>
> So here ENOTDIR does apply to a file descriptor.
That is in the openat(2) page, where there is a pathname.
But fcntl() has no pathname.
However, it looks like this has been used for non-pathname circumstances before:
int
sys_fchdir(struct proc *p, void *v, register_t *retval)
...
if (fp->f_type != DTYPE_VNODE || vp->v_type != VDIR) {
FRELE(fp, p);
return (ENOTDIR);
}
And fchdir(2) says:
[ENOTDIR] The file descriptor does not reference a directory.
Checking other manual pages in a sloppy way,
grep 'file desc' * | grep 'directory'
access.2:the directory associated with file descriptor
access.2:argument is a valid file descriptor but it does not reference a directory.
chdir.2:The file descriptor does not reference a directory.
chmod.2:argument is a valid file descriptor but it does not reference a directory.
chown.2:the directory associated with file descriptor
chown.2:argument is a valid file descriptor but it does not reference a directory.
chroot.2:Passing directory file descriptors via
link.2:is a valid file descriptor but it does not reference a directory.
mkdir.2:the directory associated with file descriptor
mkdir.2:argument is a valid file descriptor but it does not reference a directory.
mkfifo.2:the directory associated with file descriptor
mkfifo.2:argument is a valid file descriptor but it does not reference a directory.
mknod.2:the directory associated with file descriptor
mknod.2:argument is a valid file descriptor but it does not reference a directory.
open.2:the directory associated with file descriptor
open.2:argument is a valid file descriptor but it does not reference a directory.
pathconf.2:argument is a valid file descriptor but it does not reference a directory.
readlink.2:the directory associated with file descriptor
readlink.2:argument is a valid file descriptor but it does not reference a directory.
rename.2:is a valid file descriptor but it does not reference a directory.
stat.2:the directory associated with file descriptor
stat.2:argument is a valid file descriptor but it does not reference a directory.
symlink.2:the directory associated with file descriptor
symlink.2:argument is a valid file descriptor but it does not reference a directory.
unlink.2:the directory associated with file descriptor
unlink.2:argument is a valid file descriptor but it does not reference a directory.
utimes.2:the directory associated with file descriptor
utimes.2:argument is a valid file descriptor but it does not reference a directory.
Some of these follow the form
[ENOTDIR] The path argument specifies a relative path and the fd
argument is a valid file descriptor but it does not
reference a directory.
I think this would be a good diff to intro(2) to explain the situation that
we had a few ENOTDIR related to non-pathname conditions, but the openat()
family of calls has greatly expanded the situation.
Index: intro.2
===================================================================
RCS file: /cvs/src/lib/libc/sys/intro.2,v
diff -u -p -u -r1.73 intro.2
--- intro.2 19 Dec 2022 18:13:50 -0000 1.73
+++ intro.2 31 May 2025 15:03:24 -0000
@@ -159,8 +159,9 @@ A hard link to a file on another file sy
An attempt was made to apply an inappropriate function to a device,
for example, trying to read a write-only device such as a printer.
.It Er 20 ENOTDIR Em "Not a directory" .
-A component of the specified pathname existed, but it was
+A file descriptor or a component of the specified pathname existed, but it was
not a directory, when a directory was expected.
+.Pp
.It Er 21 EISDIR Em "Is a directory" .
An attempt was made to open a directory with write mode specified.
.It Er 22 EINVAL Em "Invalid argument" .
Then, we can use ENOTDIR for a condition in fcntl(2).
openat(2) is mostly useless, sadly