Summary: | ln(1): |ln -sF| never calls rmdir(2) on target_file == target_dir, only target_dir/basename | ||||||||
---|---|---|---|---|---|---|---|---|---|
Product: | Base System | Reporter: | Jan Beich <jbeich> | ||||||
Component: | bin | Assignee: | freebsd-bugs (Nobody) <bugs> | ||||||
Status: | New --- | ||||||||
Severity: | Affects Only Me | CC: | bycn82, glebius, joseph_stewart, ports | ||||||
Priority: | --- | ||||||||
Version: | CURRENT | ||||||||
Hardware: | Any | ||||||||
OS: | Any | ||||||||
Bug Depends on: | |||||||||
Bug Blocks: | 92149 | ||||||||
Attachments: |
|
Description
Jan Beich
2014-07-19 23:46:36 UTC
I checked the source code of the ln, I agree with him, something wrong there! the main logic are here. switch(argc) { case 0: usage(); /* NOTREACHED */ case 1: /* ln source */ exit(linkit(argv[0], ".", 1)); case 2: /* ln source target */ exit(linkit(argv[0], argv[1], 0)); default: ; } /* ln source1 source2 directory */ I did the below test with my explanation. root@FBHead:~ # uname -a FreeBSD FBHead 11.0-CURRENT FreeBSD 11.0-CURRENT #0 r268881: Sun Jul 20 01:32:21 UTC 2014 root@FBHead:/usr/obj/usr/src/sys/GENERIC amd64 Test1 root@FBHead:~ # ln -s -F usage: ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file [target_file] ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file ... target_dir link source_file target_file the argc==0, so show the usage. Test2 root@FBHead:~ # ln -s -F foo root@FBHead:~ # ls -al foo lrwxr-xr-x 1 root wheel 3 Jul 20 04:42 foo -> foo according to the logic, the argc==1, so it will call linkit(argv[0], ".", 1) so the result will be foo->foo, it will be useless, because it will delete the current foo and create the new foo soft link with link to itself!!! Test3 root@FBHead:~ # rm foo root@FBHead:~ # touch foo root@FBHead:~ # mkdir bar root@FBHead:~ # ln -s -F foo bar root@FBHead:~ # ls -al bar/foo lrwxr-xr-x 1 root wheel 3 Jul 20 04:47 bar/foo -> foo here the argc==2, so it will call linkit(argv[0], argv[1], 0) and the 3rd parameter "0" means the argv[1] is not a directory!! anyway, the result is not correct, Test4 root@FBHead:~ # ln -s -F foo1 foo2 bar in this case, the argc is not 0 1 2 , so it will be go to default: and continue, actually it will just loop the parameters and call linkit, the result will be same as previous one. all this are not make sense!!! the -F in the man page also bullshit! I think all this features are the same on other systems for example Linux or other BSD systems. because the code are not new created. already there for long long !!! anyway, I dont recommend to make changes in the source code immediately, but update the document first. make it clear about how it works. what do you guys think ? OK, I was wrong, I just got below from my CentOS. #touch foo1 #ls -s -f foo1 ln: `foo1' and `./foo1' are the same file So the conclusion is the "ln" command on CentOS is smarter than the one in FreeBSD. The flag -F was introduced solely for creating symlinks for directories. Hard links for a directory is not permitted in FreeBSD, so -s flag is needed (otherwise, -F is ignored). One should not use -F for non-directory source, it's meaningless indeed. Created attachment 144837 [details] improve manpage -f flag can replace a file with either symlink to file or directory and hardlink to file. -f already errors out if source_file is a directory and -F inherits that. But comment 3 still doesn't explain *why* -F is artifically limited to symlinks and only directories or behavior inconsistency if target_file is a directory. hadlink case $ echo >foo $ echo >bar $ ln -F foo bar vs. $ echo >foo $ mkdir bar $ ln -F foo bar symlink case $ echo >foo $ echo >bar $ ln -sF foo bar $ mkdir foo $ echo >bar $ ln -sF foo bar vs. $ mkdir foo $ mkdir bar $ ln -sF foo bar $ echo >foo $ mkdir bar $ ln -sF foo bar Let's remove some ambiguity in manpage such as when target file is a directory. Given current behavior its notion doesn't change from target directory and rmdir(2) is only called under it but not on the directory itself. Also, -F is not only an extension but incompatible with GNU ln. Created attachment 144841 [details]
improve manpage, v1.1
typos and drop basename(3) reference
Option isn't specific to FreeBSD. Mac OS X also supports it. |