/*
如上节所述,任何一个文件可以有多个目录项指向其i节点,创建一个指向现有文件的链接的方法是使用link函数
#include <unistd.h>
int link(const char *existingpath,const char *newpath);
返回值:若成功则返回0,若出粗则返回-1
次函数创建一个新目录项newpath,它引用现有的文件existingpath.如果newpath已经存在,则返回出错,只创建newpath中的最后一个分量,路径中的其
他部分应当已经存在,创建新目录项以及增加链接计数应当是个原子操作,最然posix.1允许实现支持文件系统的链接,但是大多数实现要求这两个路径名
在同一个文件系统中。如果实现支持创建指向一个目录的硬链接,那么也仅限于超级用户可以这么做。其理由是这样做可能在文件系统中形成循环,大多数
处理文件系统的实用程序都不能处理这种情况。因此很多文件系统实现不允许对于目录的硬链接
为了删除一个现有的目录项,可以调用unlink函数
#include <unistd.h>
int unlink(const char *pathname);
若成功则返回0,若出错则返回-1,此函数删除目录项,并将由pathname所引用文件的链接计数-1,如果还有指向该文件的其他链接,则仍可通过其他链接访
问该文件的数据。如果出错,则不对该文件做任何更改。
我们在前面已经提到,为了解除对文件的链接,必须对包含该目录项的目录具有写和执行权限,如果对该目录设置了粘住位,则对该目录必须具有写权限,
并且具备下列三个条件之一。
× 拥有该文件
× 拥有该目录
× 具有超级用户特权
只有当链接计数达到0时,该文件的内容才可被删除。另一个条件也会阻止删除文件内容——只要有进程打开了该文件,其内容也是不能删除的
关闭一个文件时,内核首先检查打开该文件的进程数。如果该数达到0,然后内核检查其链接数,如果这个数也是0,那么就删除该文件的内容
unlink的这种性质经常被程序用来确保即使在该程序崩溃时,它所创建的临时文件也不会保留下来,进程用open或creat创建一个文件,然后立即调用unl
ink.因为该文件仍旧是打开的,所以不会将其删除。只有当进程关闭该文件或终止时(在这种情况下,内核会关闭该进程打开的全部文件),该文件的内
容才会被删除,如果pathname是符号链接,那么unlink删除该符号链接,而不会删除由该链接所引用的文件。给出符号链接名情况下,没有一个函数能删
除由该链接所引用的文件
我们也可以用remove函数解除对一个文件或目录的链接,对于文件remove的功能和unlinke相同。对于目录,remove的功能与rmdir相同。
#include <stdio.h>
int remove(const char *pathname);
返回值:若成功则返回0,若出错则返回-1
对文件或目录进行更名。
#include <stdio.h>
int rename(const char *oldname,const char *newname);
若成功则返回0,若错误则返回-1
根据oldname是指文件还是指目录,有几种情况要加以说明,我们应说明如果newname已经存在将会发生什么
(1) 如果oldname指的是一个文件而不是一个目录,那么为该符号或链接更名,在这种情况下,如果newname已经存在,则它不能引用一个目录,如果ne
wname已经存在,而且不是一个目录,则先将该目录项删除然后将oldname更名为newname,对包含oldname的目录以及包含newname的目录,调用进程必须具
有写权限,因为将更改这两个目录。
*/
#include "apue.h"
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
// print a message and return to caller.caller specifies "errnoflag"
static void err_doit(int errnoflag,int error,const char *fmt,va_list ap)
{
char buf[MAXLINE];
vsnprintf(buf,MAXLINE,fmt,ap);
if(errnoflag)
snprintf(buf+strlen(buf),MAXLINE-strlen(buf),": %s",strerror(error));
strcat(buf,"\n");
fflush(stdout);
fputs(buf,stderr);
fflush(NULL);
}
void err_sys(const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
err_doit(1,errno,fmt,ap);
va_end(ap);
exit(1);
}
int main(void)
{
if(open("tempfile",O_RDWR) < 0)
err_sys("open error");
if(unlink("tempfile") < 0)
err_sys("file unliked");
printf("file unlinked\n");
sleep(15);
printf("done\n");
exit(0);
}
如上节所述,任何一个文件可以有多个目录项指向其i节点,创建一个指向现有文件的链接的方法是使用link函数
#include <unistd.h>
int link(const char *existingpath,const char *newpath);
返回值:若成功则返回0,若出粗则返回-1
次函数创建一个新目录项newpath,它引用现有的文件existingpath.如果newpath已经存在,则返回出错,只创建newpath中的最后一个分量,路径中的其
他部分应当已经存在,创建新目录项以及增加链接计数应当是个原子操作,最然posix.1允许实现支持文件系统的链接,但是大多数实现要求这两个路径名
在同一个文件系统中。如果实现支持创建指向一个目录的硬链接,那么也仅限于超级用户可以这么做。其理由是这样做可能在文件系统中形成循环,大多数
处理文件系统的实用程序都不能处理这种情况。因此很多文件系统实现不允许对于目录的硬链接
为了删除一个现有的目录项,可以调用unlink函数
#include <unistd.h>
int unlink(const char *pathname);
若成功则返回0,若出错则返回-1,此函数删除目录项,并将由pathname所引用文件的链接计数-1,如果还有指向该文件的其他链接,则仍可通过其他链接访
问该文件的数据。如果出错,则不对该文件做任何更改。
我们在前面已经提到,为了解除对文件的链接,必须对包含该目录项的目录具有写和执行权限,如果对该目录设置了粘住位,则对该目录必须具有写权限,
并且具备下列三个条件之一。
× 拥有该文件
× 拥有该目录
× 具有超级用户特权
只有当链接计数达到0时,该文件的内容才可被删除。另一个条件也会阻止删除文件内容——只要有进程打开了该文件,其内容也是不能删除的
关闭一个文件时,内核首先检查打开该文件的进程数。如果该数达到0,然后内核检查其链接数,如果这个数也是0,那么就删除该文件的内容
unlink的这种性质经常被程序用来确保即使在该程序崩溃时,它所创建的临时文件也不会保留下来,进程用open或creat创建一个文件,然后立即调用unl
ink.因为该文件仍旧是打开的,所以不会将其删除。只有当进程关闭该文件或终止时(在这种情况下,内核会关闭该进程打开的全部文件),该文件的内
容才会被删除,如果pathname是符号链接,那么unlink删除该符号链接,而不会删除由该链接所引用的文件。给出符号链接名情况下,没有一个函数能删
除由该链接所引用的文件
我们也可以用remove函数解除对一个文件或目录的链接,对于文件remove的功能和unlinke相同。对于目录,remove的功能与rmdir相同。
#include <stdio.h>
int remove(const char *pathname);
返回值:若成功则返回0,若出错则返回-1
对文件或目录进行更名。
#include <stdio.h>
int rename(const char *oldname,const char *newname);
若成功则返回0,若错误则返回-1
根据oldname是指文件还是指目录,有几种情况要加以说明,我们应说明如果newname已经存在将会发生什么
(1) 如果oldname指的是一个文件而不是一个目录,那么为该符号或链接更名,在这种情况下,如果newname已经存在,则它不能引用一个目录,如果ne
wname已经存在,而且不是一个目录,则先将该目录项删除然后将oldname更名为newname,对包含oldname的目录以及包含newname的目录,调用进程必须具
有写权限,因为将更改这两个目录。
*/
#include "apue.h"
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
// print a message and return to caller.caller specifies "errnoflag"
static void err_doit(int errnoflag,int error,const char *fmt,va_list ap)
{
char buf[MAXLINE];
vsnprintf(buf,MAXLINE,fmt,ap);
if(errnoflag)
snprintf(buf+strlen(buf),MAXLINE-strlen(buf),": %s",strerror(error));
strcat(buf,"\n");
fflush(stdout);
fputs(buf,stderr);
fflush(NULL);
}
void err_sys(const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
err_doit(1,errno,fmt,ap);
va_end(ap);
exit(1);
}
int main(void)
{
if(open("tempfile",O_RDWR) < 0)
err_sys("open error");
if(unlink("tempfile") < 0)
err_sys("file unliked");
printf("file unlinked\n");
sleep(15);
printf("done\n");
exit(0);
}