Linux 4.2.0
link, linkat - make a new name for a file
在之前的章节,我们知道一个文件可以有多个dirctory entries
指向它的i-node
。我们可以使用link , linkat
来创建已经存在文件的链接(link)
原型如下:
#include <unistd.h>
int link(const char *oldpath, const char *newpath);
#include <fcntl.h> /* Definition of AT_* constants */
#include <unistd.h>
int linkat(int olddirfd, const char *oldpath,
int newdirfd, const char *newpath, int flags);
//Return: 0 if OK, -1 on error
link
link() creates a new link (also known as a hard link
) to an existing file.
If newpath
exists, it will not be overwritten.
This new name may be used exactly as the old one for any operation;both names refer to the same file (and so have the same permissions and ownership) and it is impossible to tell which name was the “original”.
linkat
Thelinkat()
system call operates in exactly the same way as link()
, except for the differences described here.:
If the pathname given in
oldpath
is relative, then it is interpreted relative to the directory referred to by the file descriptorolddirfd
(rather than relative to the current working directory of the calling process, as is done by link() for a relative pathname).If oldpath is relative and olddirfd is the special value AT_FDCWD, then oldpath is interpreted relative to the current working directory of the calling process (
like link()
).If oldpath is absolute, then olddirfd is ignored.
The interpretation of
newpath
is as foroldpath
, except that a relative pathname is interpreted relative to the directory referred to by the file descriptornewdirfd
.
flags argument
如果flag是AT_SYMLINK_FOLLOW
,创建的link
是用于symbolic link
指向的目标。如果flag
被清除,则link
用于symblic link
本身。
Besides
directory entry
的新建和link count
的增加必须是原子操作。
大部分实现都需要路径名在同一个文件系统上,尽管POSIX.1允许实现支持link
能跨越文件系统。支持创建directories
的hard link(硬链接)
的实现,都只能让超级用户进行该项操作。这条限制(constraint)是因为hard link
可能在文件系统中造成循环(loops),这是文件系统不法处理的。(在4.17节我们会展示symbolic link的loop实例)。因此,许多文件系统不允许(目录)directories
的硬链接(hard link)。
unlink, unlinkat - delete a name and possibly the file it refers to
原型:
#include <unistd.h>
int unlink(const char *pathname);
#include <fcntl.h> /* Definition of AT_* constants */
#include <unistd.h>
int unlinkat(int dirfd, const char *pathname, int flags);
//both Return: 0 if OK, -1 on error
这些系统调用会移除目录条目(directory entry
)并且减少pathename
引用的文件的链接数目link count
。如果文件还有其他的链接(link),文件的内容还可以通过其他链接访问。如果产生error
,文件不会发生变化。
As mentioned earlier, to unlink a file, we must have write permission
and execute permission
in the directory containing the directory entry, as it is the directory entry that we will be removing. Also, as mentioned in Section 4.10, if the sticky bit
is set in this directory we must have write permission
for the directory and meet one of the following criteria:
• Own the file
• Own the directory
• Have superuser privileges
仅仅当link count
达到0,文件的内容才会被删除。另一种阻止文件内容被删除的条件就是,一些进程open
了该文件,文件的内容也不会被删除。当某文件被关闭了(closed),内核会先确定打开(open
)该文件的进程数量,如果为0,此时内核会继续确定link count
,如果还为0,文件内容被删除。
unlinat
pathname
为相对路径,unlinkat
会将其看做fd
开的目录的相对路径。
如果fd
值为AT_FDCWD
时,pathname
就是相对路径,相对于调用进程的当前工作目录。如果pathname
是绝对路径,fd
直接被忽略。
flag
用于改变unlinkat
默认行为。
1. AT_REMOVEDIR
: 用于删除目录,类似于使用rmdir
命令。
2. clear: unlinkat
操作和unlink
一致。
Example
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main()
{
if(open("tempfile", O_RDWR|O_CREAT, S_IRWXO) < 0)
{
fprintf(stderr, "open file error %s\n", strerror(errno));
exit(-1);
}
if(unlink("tempfile") < 0)
{
fprintf(stderr, "unlink file error %s\n", strerror(errno));
exit(-1);
}
printf("file unlinked\n");
sleep(15);
printf("done\n");
return 0;
}
sleep(15),用于睡眠15s,定义在unistd中。
This property of unlink is often used by a program to ensure that a temporary file it creates won’t be left around in case the program crashes. The process creates a file using either open
or creat
and then immediately calls unlink
. The file is not deleted, however, because it is still open. Only when the process either closes the file or terminates, which causes the kernel to close all its open files, is the file deleted.
If pathname
is a symbolic link
, unlink
removes the symbolic link, not the file referenced by the link. There is no function to remove the file referenced by a symbolic link given the name of the link.
The superuser can call unlink
with pathname specifying a directory if the file system supports it, but the function rmdir
should be used instead to unlink a directory. We describe the rmdir
function in Section 4.21.
remove
We can also unlink a file or a directory
with the remove
function. For a file, remove is identical to unlink. For a directory, remove is identical to rmdir
.
remove - remove a file or directory
#include <stdio.h>
int remove(const char *pathname);
//Returns: 0 if OK, -1 on error