is there any POSIX way through fstat() to check whether a file is a symbolic link or not?

强颜欢笑 提交于 2019-12-09 21:01:25

问题


Is there any POSIX way through fstat(2) to check whether a file is a symbolic link or not?

There is flag O_NOFOLLOW in open(2) which can check it, however, it's not POSIX.

There is S_ISLNK in fstat(2), which is said in man fstat:

   The S_ISLNK() and S_ISSOCK() macros are not in POSIX.1-1996,
   but both are present in POSIX.1-2001; the former is from SVID
   4, the latter from SUSv2.

and the compile will fail on my machine.

Also, there is another S_IFLNK in lstat(2), however, it won't work with fstat(2) (which will follow the link to the file referred to).


回答1:


No.

It's not true that fstat follows symlinks. Instead, open follows symlinks. Once you get to fstat, it is too late and the information is gone.

Tell us why you need to know, and we can help with that problem. (Open another question.)

How files work:

Here is some pseudo-C / shell code:

system("echo 'Hello, World!' >A.txt");
system("ln A.txt B.txt");
system("ln -s A.txt C.txt");

fdes = open("C.txt");
unlink("A.txt");
unlink("C.txt");
data = read(fdes);
write(stdout, data);

The result: your program prints "Hello, world!". The state of the world looks like this:

+--Application--+    +--Kernel--+    +-------Disk-------+
|               |    |          |    |                  |
|  fdes --------------> file ---------> inode #973 <-------+
|               |    |          |    |  "Hello World!"  |  |
+---------------+    +----------+    |                  |  |
                                     |  directory ---------+
                                     |  "B.txt"         |
                                     |                  |
                                     +------------------+

As far as the kernel is concerned, the file open is "inode #973". The data structure in kernel memory has some additional information such as the current position, but it does NOT know the path. The kernel is not expected to know that information.

If you asked the kernel what the path is, it could say "you have B.txt" open. But you never opened "B.txt", you opened "C.txt" which was a symlink to "A.txt", and both "A.txt" and "C.txt" have been deleted (they were just names to begin with).

Simple analogy:

You get a phone call from an old friend. He asks, "Did I look up your number in the phone directory, did I memorize it, or did I have to ask someone for your number?"

You have no way of knowing the answer. All you know is who is on the other end of the line. Just like an open file doesn't store information about what it was named (hard link or symbolic link), it just has information about permissions and data.

The solution: Just use lstat (yes, there is a race condition). If you didn't open the file yourself (e.g., you get it from a parent process or you get it over a socket), then it's more or less impossible to know if it was opened through a symbolic link.



来源:https://stackoverflow.com/questions/8875663/is-there-any-posix-way-through-fstat-to-check-whether-a-file-is-a-symbolic-lin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!