1. 由于符号链接的存在,当使用以名字引用文件的函数时,就应当要了解函数是否处理符号链接了,也即该函数是否跟随符号链接到达它所链接的文件。相关函数总结如下:
1,当路径名是符号连接时,出错返回的函数有:mkdir、mkinfo、mknod和rmdir;
2,chown是否跟随符号链接取决于实现;
3,跟随符号链接的函数:access、chdir、chmod、creat、exec、link、open、opendir、
pathconf、stat、truncate;
4,不跟随符号链接的函数:lchown、lstat、readlink、remove、rename、unlink。
5,其中,如果同时用O_CREAT和O_EXCL两者调用open函数,如果路径名为符号
链接,open将出错返回,并将errno设置为EEXIST。其意图是阻塞一个安全性漏洞,
使具有特权的进程不会被诱骗对不适当的文件进行写操作。
2. symlink和readlink函数:
头文件 | #include<unistd.h> |
函数功能 | 创建/读取一个符号链接 |
函数原型 | int symlink( const char* actualpath, const char* sympath); ssize_t readlink( const char*restrict pathname,char*restrict buf, size_t bufsize); |
参数 | actualpath:要创建符号链接的文件名; sympath:创建的符号链接名; pathname:要读取的链接文件名; buf:存放读取的内容; |
返回值 | symlink:成功返回0;出错返回-1; readlink:返回读入buf的字节数; |
注 | symlink函数创建了一个指向actualpath的新目录项,在创建此符号链接时,并不要求actualpath已经存在,并且,actualpath和sympath不需要位于同一文件系统中。 open函数跟随符号链接,所以需要有一种方法打开符号链接本身,并读该链接中的名字。readlink()会将参数path的符号连接内容存到参数buf所指的内存空间,在buf中返回的符号链接的内容不以NULL作字符串结尾。若参数bufsiz小于符号连接的内容长度,过长的内容会被截断。readlink函数组合了open、read和close的所有操作。 |
3. 每个文件保持有三个时间字段,如下表:
注意修改时间(st_mtime)和更改状态时间( st_ctime)之间的区别。修改时间是文件内容最后一次被修改的时间。更改状态时间是该文件的i节点最后一次被修改的时间。注意,系统并不保存对一个i节点的最后一次存取时间,所以access和stat函数并不更改这三个时间中任何一个。- u选择项使其用存取时间排序,- c选择项则使其用更改状态时间排序。如下表,link函数是指其第二个参数的父目录:
1. utime函数:更改文件的访问和修改时间。
头文件 | #include<utime.h> |
函数功能 | 更改文件的访问和修改时间 |
函数原型 | int utime( const char* pathname, const struct utimbuf* times); |
参数 | pathname:文件名; times:存放更改后的访问和修改时间; |
返回值 | 成功返回0;失败返回-1; |
struct utimbuf
{
time_t:actime;//访问时间;
time_t:modtime;//修改时间
}
此结构中的两个时间值是日历时间。这是自1970年1月1日,00:00:00以来国际标准 时间所经过的秒数。
此函数的操作以及执行它所要求的优先权取决于times参数是否是NULL 。
(1) 如果times是一个空指针,则存取时间和修改时间两者都设置为当前时间。为了执 行此操作必须满足下列两条件之一:( a )进程的有效用户ID必须等于该文件的所有者 ID,( b )进程对该文件必须具有写许可权。
(2) 如果times是非空指针,则存取时间和修改时间被设置为times所指向的结构中的值。 此时,进程的有效用户ID必须等于该文件的所有者ID,或者进程必须是一个超级用户 进程。对文件只具有写许可权是不够的。
注意,我们不能对更改状态时间st_ctime指定一个值,当调用utime函数时,此字段被 自动更新。
2. mkdir和rmdir函数:创建/删除一个目录。
头文件 | mkdir:#include<sys/stat.h> rmdir:#include<unistd.h> |
函数功能 | 创建/删除一个空目录 |
函数原型 | int mkdir( const char* pathname, mode_t mode); int rmdir( const char*pathname); |
参数 | pathname:文件名; mode:文件存取权限; |
返回值 | 成功返回0;失败返回-1; |
此函数创建一个新的空目录。.和..目录项是自动创建的。所指定的文件存取许可权mode 由进程的文件方式创建屏蔽字修改。
常见的错误是指定与文件相同的mode(只指定读、写许可权)。但是,对于目录通常至 少要设置1个执行许可权位,以允许存取该目录中的文件名。
如果此调用使目录的连接计数成为0,并且也没有其他进程打开此目录,则释放由此目 录占用的空间。如果在连接计数达到0时,有一个或几个进程打开了此目录,则在此函 数返回前删除最后一个连接及.和..项。另外,在此目录中不能再创建新文件。但是在最 后一个进程关闭它之前并不释放此目录(即使某些进程打开该目录,它们在此目录下, 也不能执行其他操作,因为为使rmdir函数成功执行,该目录必须是空的)。
3. 读目录:对某个目录具有存取许可权的任一用户都可读该目录,但是只有内核才能写目录(防止文件系统发生混乱)。一个目录的写许可权位和执行许可权位决定了在该目录中能否创建新文件以及删除文件,它们并不表示能否写目录本身。UNIX现在包含了一套与读目录有关的例程,它们是POXIS.1的一部分。很多实现阻止应用程序使用read函数读取目录的内容,从而进一步将应用程序与目录格式中与实现相关的细节隔离开。
功能 | 打开一个目录。 |
头文件 | #include < dirent.h> |
函数原形 | DIR *opendir(const char *name) |
参数: | name 目录名 |
返回值: | NULL 遇到错误 |
| DIR * 打开成功,返回一个指向目录的指针 |
功能: | 关闭一个目录. |
头文件: | #include < dirent.h> |
函数原形: | int closedir(DIR *dir) |
参数: | dir 指向目录的指针 |
返回值: | -1 遇到错误 |
| 0 关闭成功 |
功能: | 读取目录内容。 |
头文件: | #include <dirent.h> |
函数原形: | struct dirent* readdir(DIR*dp) |
参数: | dp:指向目录的指针 |
返回值: | NULL 若在目录结尾或出错返回NULL |
| struct dirent* 打开成功 |
头文件 | #include<dirent.h> |
功能 | 设置参数dir 目录流目前的读取位置为原来开头的读取位置 |
函数原型 | void rewinddir( DIR*dp); |
参数 | dp:指向目录的指针 |
返回值 | 无 |
头文件 | #include<dirent.h> |
功能 | 获取与dp关联的目录中的当前位置 |
函数原型 | long telldir( DIR*dp); |
参数 | dp:指向目录的指针 |
返回值 | 与dp关联的目录中的当前位置 |
头文件 | #include<dirent.h> |
功能 | 设置与dp关联的目录流的当前读取位置 |
函数原型 | void seekdir( DIR*dp, long loc); |
参数 | dp:指向目录的指针; loc:代表距离目录开头的偏移量 |
返回值 | 无 |
telldir和seekdir函数不是基本POSIX.1标准的组成部分。它们是Single UNIX Specification中的XSI扩展。定义在头文件< dirent.h >中的dirent结构与实现有关。典 型实现至少包含下列两个成员:
struct dirent
{
ino_t d_ino;//i-node number
char d_name[NAME_MAX+1];//null-terminated filename
}
因为文件名是以NULL字符结束的,所以在头文件中如何定义数组d_name并无多大关系。DIR结构是一个内部结构,它由这四个函数用来保存正被读的目录的有关信息。其作用类似于FILE结构。FILE结构由标准I / O库维护。由opendir返回的指向DIR结构的指针由另外5个函数使用。opendir执行初始化操作,使第一个readdir读目录中的第一个目录项。目录中各目录项的顺序与实现有关。它们通常并不按字母顺序排列。
4. chdir、fchdir和getcwd函数:当前工作目录是进程的一个属性,起始目录则是登录名的一个属性。进程调用chdir或fchdir函数可以更改当前工作目录。因为当前工作目录是一个进程的属性,所以它只影响调用chdir的进程本身,而不影响其他进程。
头文件 | #include<unistd.h> |
功能 | 更改当前工作目录 |
函数原型 | int chdir( const char*pathname); int fchdir( int filedes); |
参数 | pathname:更改后的工作目录; fieldes:文件描述符 |
返回值 | 成功返回0;出错返回-1 |
头文件 | #include<unistd.h> |
功能 | 获取当前工作路径的绝对路径名 |
函数原型 | char* getcwd( char*buf, size_t size); |
参数 | buf:缓冲地址,保存得到的绝对路径名; size:buf的长度 |
返回值 | 指向绝对路径名的指针;出错,返回NULL; |
注: | buf必须有足够的长度以容纳绝对路径名再加上一个null终止字符,否则返回出错。 |
当一个应用程序需要在文件系统中返回到其工作的起点时,getcwd很有用。在更改工作目录之前,可以调用getcwd函数先将其保存起来。完成处理后,就可以将从getcwd获得的路径名作为调用参数传送给chdir,这样就返回到了文件系统中的起点。fchdir提供了一种更便捷的方法。在更换到文件系统的不同位置前,可以使用open打开当前工作目录,然后保存文件描述符。希望返回到原工作目录时,只要简单地将该文件描述符传递给fchdir。
5. st_dev和st_rdev这两个字段经常引起混淆。有关规则如下:
1,每个文件系统都由其主、次设备号而为人所知。设备号所用的数据类型是基本系统 数据类型dev_t。主设备号表示设备驱动程序,有时编码为与其通信的外设板;次设备 号标示特定的子设备。如一个磁盘经常包含若干个文件系统。在同一磁盘驱动器上的各 文件系统通常具有相同的主设备号,但它们的次设备号却不同。
2,我们通常可以使用两个大多数实现都定义的宏:major和minor来