Bug 73301
Summary: | Documentation misses case of link, linkat, symlink, symlinkat giving ENOENT for a directory with a reference only held by a process | ||
---|---|---|---|
Product: | Documentation | Reporter: | Steven Stewart-Gallus (sstewartgallus00) |
Component: | man-pages | Assignee: | documentation_man-pages (documentation_man-pages) |
Status: | RESOLVED CODE_FIX | ||
Severity: | low | CC: | mtk.manpages |
Priority: | P1 | ||
Hardware: | All | ||
OS: | Linux | ||
Kernel Version: | Subsystem: | ||
Regression: | No | Bisected commit-id: |
Description
Steven Stewart-Gallus
2014-03-31 19:09:23 UTC
This problem also exists with link and linkat. Steven, (In reply to Steven Stewart-Gallus from comment #0) > The errors printed out by the following code on symlink and symlinkat are > missed by the documentation. > > #include <fcntl.h> > #include <stdio.h> > #include <sys/stat.h> > #include <sys/types.h> > #include <unistd.h> > > int main() { > if (-1 == mkdir("/tmp/temporary", S_IRWXU)) { > perror("mkdir"); > } > > int dir = open("/tmp/temporary", O_RDONLY | O_CLOEXEC); > if (-1 == dir) { > perror("open"); > } > > if (-1 == rmdir("/tmp/temporary")) { > perror("rmdir"); > } > > if (-1 == symlinkat("/", dir, "root")) { > perror("symlinkat"); > } So far, so good. > char template_text[] = "/proc/self/fd/XXXXXXXXXXX/root"; > sprintf(template_text, "/proc/self/fd/%i/root", dir); > if (-1 == symlink("/", template_text)) { > perror("symlink"); > } I'm a little puzzled, why would one want to make a symlink somewhere under /proc? > > return 0; > } > > The calls to symlink and symlinkat in this case give ENOENT errors. For symlinkat(), I can see the logic. You're trying to create a link relative to a directory that does not exist. Could the call reasonably do anything other than fail? > This > might also be a small oversight which is probably impossible to change now. > I wonder if the code thinks this is a dangling symbolic link (a case which > is mentioned by the documentation)? > > The POSIX standard issue 7 also seems to miss this corner case (although it > might simply be an omission of mentioning a system dependant case rather > than a bug for the POSIX standard). The specs in POSIX were driven from the Linux implementation effort, so I don;t think that your hypothesis there would fit. > I'm not sure how exactly one would explain this corner case in the > documentation. I'd be willing to give it a shot, but, first,I'm not sure what if anything to say about the symlink() case. Do you have a more realistic example of that case? On further reflection, this is not a problem with the documentation of
symlink, symlinkat, link and linkat but a problem with the
documentation of ENOENT and what a nonexisting directory actually
means.
I suppose how one might describe the situation is that when a
directory is unlinked from a filesystem (but still has process
references to it) it enters a zombie state where many filesystem calls
become inappropriate to use on it.
I'm not sure where such documentation should be placed. We already
have shm_overview(7), mq_overview(7) and such; and I think if we had a
dir_overview(7) that would be the perfect place to put this corner
case. dir_overview(7) might be too big project for not really any gain
though.
> I'd be willing to give it a shot, but, first,I'm not sure what if
> anything to say about the symlink() case. Do you have a more
> realistic example of that case?
Nope. People should probably be able to figure that out from the
description of the symlink case. I was just pointing it out for
completeness and I'd be fine if that case was omitted.
I've applied the patches below. diff --git a/man2/link.2 b/man2/link.2 index d5a697d..df2b9e2 100644 --- a/man2/link.2 +++ b/man2/link.2 @@ -291,6 +291,17 @@ file corresponding to a file descriptor created with See .BR open (2). .TP +.B ENOENT +.I oldpath +is a relative pathname and +.I olddirfd +refers to a directory that has been deleted, +or +.I newpath +is a relative pathname and +.I newdirfd +refers to a directory that has been deleted. +.TP .B ENOTDIR .I oldpath is relative and diff --git a/man2/symlink.2 b/man2/symlink.2 index a6cf6a7..8bd067f 100644 --- a/man2/symlink.2 +++ b/man2/symlink.2 @@ -210,6 +210,12 @@ The following additional errors can occur for .I newdirfd is not a valid file descriptor. .TP +.B ENOENT +.I linkpath +is a relative pathname and +.IR newdirfd +refers to a directory that has been deleted. +.TP .B ENOTDIR .I linkpath is relative and |