Bug 221331 - [PATCH] update for unlink(2) manpage
Summary: [PATCH] update for unlink(2) manpage
Status: Open
Alias: None
Product: Documentation
Classification: Unclassified
Component: Manual Pages (show other bugs)
Version: Latest
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-bugs mailing list
URL:
Keywords: easy, patch
Depends on:
Blocks:
 
Reported: 2017-08-08 11:13 UTC by fehmi noyan isi
Modified: 2019-11-08 09:17 UTC (History)
3 users (show)

See Also:


Attachments
patch for the unlink(2) man page update (389 bytes, patch)
2017-08-08 11:13 UTC, fehmi noyan isi
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description fehmi noyan isi 2017-08-08 11:13:41 UTC
Created attachment 185149 [details]
patch for the unlink(2) man page update

unlink(2) manpage states both EISDIR and EPERM are returned if the user attempts to remove a directory. 

unlink(2) function calls kern_unlinkat(), which does not return EISDIR in any case. [1]

Also, POSIX standard states that EPERM should be returned when unlinking a directory and EISDIR is only used by Linux Standard Base (LSB).[1]

As the proof of concept, the code below shows only EPERM is returned while attempting to unlink a directory;

~/code/test/unlink_test % ls -l
total 40
drwxr-xr-x  2 fnoyanisi  fnoyanisi   512 Aug  8 22:00 dummy/
-rwxr-xr-x  1 fnoyanisi  fnoyanisi  9135 Aug  8 22:03 unlink_test*
-rw-r--r--  1 fnoyanisi  fnoyanisi   222 Aug  8 22:25 unlink_test.c
~/code/test/unlink_test % cat unlink_test.c 
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main(int argc, char **argv){
    
    if (unlinkat(argv[1])!=0)
        printf("Error %d : %s\n",errno, strerror(errno));

    return 0;
}
~/code/test/unlink_test % ./unlink_test dummy
Error 1 : Operation not permitted
~/code/test/unlink_test % 

With the attached patch file, the line which is in the ERRORS section and states that [EISDIR] is returned by unlink(2) when unlinking a directory is removed from the manual page.

unlink.2.fni -> working copy
unlink.2 -> unlink(2) manpage from revision 321776

Diff file was generated with the command below
diff -u unlink.2 unlink.2.fni > unlink.2.diff

Subversion revision details for the original unlink(2) manpage

/usr/src % svn info       
Path: .
Working Copy Root Path: /usr/src
URL: svn://svn.freebsd.org/base/release/11.1.0
Relative URL: ^/release/11.1.0
Repository Root: svn://svn.freebsd.org/base
Repository UUID: ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
Revision: 321776
Node Kind: directory
Schedule: normal
Last Changed Author: gjb
Last Changed Rev: 321354
Last Changed Date: 2017-07-22 08:55:38 +1200 (Sat, 22 Jul 2017)

[1] https://svnweb.freebsd.org/base/release/11.0.1/sys/kern/vfs_syscalls.c?revision=306421&view=markup#l1728
[2] http://pubs.opengroup.org/onlinepubs/9699919799/
Comment 1 WHR 2019-11-08 09:17:22 UTC
There was a case that unlink(2) may return EISDIR.

Function kern_unlinkat calls namei(9) to find the parent directory of the file; it will return EISDIR if the requested path was '/'.

Since '/' isn't a real link (but '/.' and '/..'), it can't be unlinked anyways.

Test:

# cat unlink.c 
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv) {
        if(argc != 2) {
                fprintf(stderr, "Usage: %s <path>\n", argv[0]);
                return -1;
        }
        if(unlink(argv[1]) < 0) {
                perror(argv[1]);
                return 1;
        }
        return 0;
}
# gcc -Wall -O1 unlink.c -o unlink
# ./unlink /etc/
/etc/: Operation not permitted
# ./unlink /.
/.: Operation not permitted
# ./unlink /
/: Is a directory