link函数:
#include <unistd.h>
int link(const char *oldpath, const char *newpath);
此函数创建一个新目录项 newpath,它引用现存文件 existingpath。如若newpath已经存在,则返
回出错。
创建新目录项以及增加连接计数应当是个原子操作
只有超级用户进程可以创建指向一个目录的新连接。其理由是这样做可能在文件系统中形
成循环,大多数处理文件系统的公用程序都不能处理这种情况( 4 . 1 6节将说明一个由符号连接
引入的循环的例子)。
unlink函数:
#include <unistd.h>
int unlink(const char *pathname);
此函数删除目录项,并将由pathname所引用的文件的连接计数减 1。如果该文件还有其他连接,
则仍可通过其他连接存取该文件的数据。如果出错,则不对该文件作任何更改。
我们在前面已经提及,为了解除对文件的连接,必须对包含该目录项的目录具有写和执行
许可权。正如4.10节所述,如果对该目录设置了粘住位,则对该目录必须具有写许可权,并且
具备下面三个条件之一:
• 拥有该文件。
• 拥有该目录。
• 具有超级用户优先权。
只有当连接计数达到 0时,该文件的内容才可被删除。另一个条件也阻止删除文件的内容
——只要有进程打开了该文件,其内容也不能删除。关闭一个文件时,内核首先检查使该文件
打开的进程计数。如果该计数达到 0,然后内核检查其连接计数,如果这也是 0,那么就删除该
文件的内容。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ourhdr.h"
int main (void)
{
if (open ("tempfile", O_RDWR | O_CREAT) < 0)
err_sys("open error");
if (unlink ("tempfile") < 0)
err_sys("unlink error");
printf ("file unlinked\n");
sleep (15);
printf ("done\n");
exit (0);
}
unlink的这种特性经常被程序用来确保即使是在程序崩溃时,它所创建的临时文件也不会
遗留下来。进程用open或creat创建一个文件,然后立即调用unlink。因为该文件仍旧是打开的,
所以不会将其内容删除。只有当进程关闭该文件或终止时(在这种情况下,内核关闭该进程所
打开的全部文件),该文件的内容才被删除。
如果pathname是符号连接,那么unlink涉及的是符号连接而不是由该连接所引用的文件。
超级用户可以调用带参数pathname的unlink指定一个目录,但是通常不使用这种方式,而
使用函数rmdir。我们将在4.20节中说明rmdir函数。
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
根据oldname是指文件还是目录,有两种情况要加以说明。我们也应说明如果 newname已
经存在将会发生什么。
(1) 如果oldname说明一个文件而不是目录,那么为该文件更名。在这种情况下,如果
newname已存在,则它不能引用一个目录。如果 newname已存在,而且不是一个目录,则先将
该目录项删除然后将oldname更名为newname。对包含oldname的目录以及包含newname的目录,
调用进程必须具有写许可权,因为将更改这两个目录。
(2) 如若oldname说明一个目录,那么为该目录更名。如果 newname已存在,则它必须引用
一个目录,而且该目录应当是空目录(空目录指的是该目录中只有 . 和.. 项)。如果newname存
在(而且是一个空目录),则先将其删除,然后将 oldname更名为newname。另外,当为一个目
录更名时, newname 不能包含 oldname作为其路径前缀。例如,不能将 /usr/foo 更名为
/usr/foo /testdir,因为老名字( /usr/foo)是新名字的路径前缀,因而不能将其删除。
(3) 作为一个特例,如果 oldname和newname引用同一文件,则函数不做任何更改而成功返
回。
如若newname已经存在,则调用进程需要对其有写许可权(如同删除情况一样)。另外,
调用进程将删除oldname目录项,并可能要创建 newname目录项,所以它需要对包含 oldname及
包含newname的目录具有写和执行许可权。