3 文件和目录
3.1 stat、fstat、lstat 函数
#include <sys/types.h>
#include <sys/stat.h>
//三个函数的返回:若成功则为 0,若出错则为-1
int stat(const char *pathname, struct stat *buf) ;
int fstat(int filedes,struct stat * buf) ;
int lstat(const char *pathname, struct stat * buf) ;
给定一个pathname,stat函数返回一个与此命名文件有关的信息结构, fstat函数获得已在描述符filedes上打开的文件的有关信息。lstat函数类似于stat,但是当命名的文件是一个符号连接时, lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息。
struct stat
{
mode_t st_mode; /* file type & mode(permissions) */
ino_t st_ino; /* i-node number (serial number) */
dev_t st_dev; /* device number (filesystem) */
dev_t st_rdev; /* device number for special files */
nlink_t st_nlink /* number of links */
uid_t st_uid; /* user id of owner */
gid_t st_gid; /* group id of owner */
off_t st_size; /* size in bytes, for regular files */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* timer of last file status change */
long st_blksize; /* best I/O block size */
long st_blocks; /* number of 512-byte block allocated */
}
3.2 文件类型
(1)普通文件(regular file)。这是最常见的文件类型,这种文件包含了某种形式的数据。
(2)目录文件(directory file)。这种文件包含了其他文件的名字以及指向与这些文件有关信 息的指针。对一个目录文件具有读许可权的任一进程都可以读该目录的内容,但只有内核可以写目录文件。
(3)字符特殊文件(character special file)。这种文件用于系统中某些类型的设备。
(4)块特殊文件(block special file)。这种文件典型地用于磁盘设备。系统中的所有设备或者 是字符特殊文件,或者是块特殊文件。
(5)FIFO。这种文件用于进程间的通信,有时也将其称为命名管道。
(6)套接字(socket )。这种文件用于进程间的网络通信。套接口也可用于在一台宿主机上的 进程之间的非网络通信。
(7)符号连接(symbolic link)。这种文件指向另一个文件。
宏确定文件类型:
宏 | 文件类型 |
S_ISREG() | 普通文件 |
S_ISDIR() | 目录文件 |
S_ISCHR() | 字符特殊文件 |
S_ISBLK() | 块特殊文件 |
S_ISFIFO() | 管道或FIFO |
S_ISLNK() | 符号连接 |
S_ISSOCK() | 套接字 |
3.3 文件存储许可权
st_mode值也包含了对文件的存取许可权位。每个文件有9个存取许可权位,可将它们分成三类:
st_mode屏蔽 | 意 义 |
S_IRUSR | 用户-读 |
S_IWUSR | 用户-写 |
S_IXUSR | 用户-执行 |
S_IRGRP | 组-读 |
S_IWGRP | 组-写 |
S_IXGRP | 组-执行 |
S_IROTH | 其他-读 |
S_IWOTH | 其他-写 |
S_IXOTH | 其他-执行 |
3.4 access函数
access函数是按实际用户ID和实际组ID进行存取许可权测试的。
#include <unistd.h>
//返回:若成功则为0,若出错则为-1
int access(const char *pathname, int mode) ;
其中,mode是表中所列常数的逐位或运算。
mode | 说 明 |
R_OK | 测试读许可权 |
W_OK | 测试写许可权 |
X_OK | 测试执行许可权 |
F_OK | 测试文件是否存在 |
3.5 umask函数
umask函数为进程设置文件方式创建屏蔽字,并返回以前的值。
#include <sys/types.h>
#include <sys/stat.h>
//返回:以前的文件方式创建屏蔽字
mode_t umask(mode_t cmask) ;
3.6 chmod和fchmod函数
这两个函数使我们可以更改现存文件的存取许可权。
#include <sys/types.h>
#include <sys/stat.h>
//两个函数返回:若成功则为0,若出错则为-1
int chmod(const char * pathname, mode_t mode) ;
int fchmod(int filedes, mode_t mode) ;
chmod函数在指定的文件上进行操作,而fchmod函数则对已打开的文件进行操作。
3.7 chown, fchown和lchown函数
chown函数可用于更改文件的用户ID和组ID.
#include <sys/types.h>
#include <unistd.h>
//三个函数返回:若成功则为 0,若出错则为-1
int chown(const char *pathname, uid_t owner, gid_t group) ;
int fchown(int filedes, uid_t owner, gid_t group) ;
int lchown(const char *pathname, uid_t owner, gid_t group) ;
除了所引用的文件是符号连接以外,这三个函数的操作相类似。在符号连接情况下, lchown更 改符号连接本身的所有者,而不是该符号连接所指向的文件。
3.8 文件长度
stat结构的成员st_size包含了以字节为单位的该文件的长度。此字段只对普通文件、目录文件和符号连接有意义。
对于普通文件,其文件长度可以是0,在读这种文件时,将得到文件结束指示。
对于目录,文件长度通常是一个数,例如16或512的整倍数。
对于符号连接,文件长度是在文件名中的实际字节数。
3.9 文件截短
有时我们需要在文件尾端处截去一些数据以缩短文件。将一个文件的长度截短为0是一个 特例,用O_TRUNC标志可以做到这一点。为了截短文件可以调用函数 truncate和ftruncate。
#include <sys/types.h>
#include <unistd.h>
//两个函数返回;若成功则为 0,若出错则为-1
int truncate(const char *pathname, off_t length) ;
int ftruncate(int filedes, off_t length) ;
这两个函数将由路径名 pathname或打开文件描述符 filedes指定的一个现存文件的长度截短为 length。如果该文件以前的长度大于 length,则超过length以外的数据就不再能存取。如果以前的长度短于length,则其后果与系统有关。如果某个实现的处理是扩展该文件,则在以前的文件尾端和新的文件尾端之间的数据将读作0。
3.10 文件系统
可以把一个磁盘分成一个或多个分区。每个分区可以包含一个文件系统。
i节点是固定长度的记录项,它包含有关文件的信息。
如果在忽略自举块和超级块情况下更仔细地观察文件系统,则可以得到下图中所示的情况。
3.11 link,unlink,remove和rename函数
任何一个文件可以有多个目录项指向其 i节点。创建一个向现存文件连接的方法是使用link函数。
#include <unistd.h>
//返回:若成功则为0,若出错则为-1
int link(const char *existingpath, const char * newpath) ;
此函数创建一个新目录项newpath,它引用现存文件existingpath。如若newpath已经存在,则返 回出错。
为了删除一个现存的目录项,可以调用unlink函数。
#include <unistd.h>
//返回:若成功则为0,若出错则为-1
int unlink(const char *pathname) ;
此函数删除目录项,并将由pathname所引用的文件的连接计数减1。如果该文件还有其他连接, 则仍可通过其他连接存取该文件的数据。如果出错,则不对该文件作任何更改。
可以用 remove函数解除对一个文件或目录的连接。对于文件, remove的功能与 unlink相同。对于目录,remove的功能与rmdir相同。
#include <stdio.h>
//返回:若成功则为0,若出错则为-1
int remove(const char *pathname) ;
文件或目录用rename函数更名。
#include <stdio.h>
//返回:若成功则为0,若出错则为-1
int rename(const char * oldname, const char * newname) ;
3.12 符号链接
符号连接是对一个文件的间接指针,它与上一节所述的硬连接有所不同,硬连接直接指向文件和目录的i节点。引进符号连接的原因是为了避免硬连接的一些限制:
- 硬连接通常要求连接和 文件位于同一文件系统中。
- 只有超级用户才能创建到目录的硬连接。对符号连接以及它指 向什么没有文件系统限制,任何用户都可创建指向目录的符号连接。符号连接一般用于将一个 文件或整个目录结构移到系统中其他某个位置。
3.13 symlink和readlink函数
symlink函数创建一个符号连接。
#include <unistd.h>
//返回:若成功则为0,若出错则为-1
int symlink(const char * actualpath, const char * sympath) ;
readlink函数提供了一种方法打开该连接本身,并读该连接中的名字。
#include <unistd.h>
//返回:若成功则为读的字节数,若出错则为- 1
int readlink(const char * pathname, char * buf, int bufsize) ;
3.14 文件的时间
每个文件保持有三个时间字段。
字段 | 说 明 | 例 子 | ls ( 1 )选择项 |
st_atime | 文件数据的最后存取时间 | r e ad | - u |
st_mtime | 文件数据的最后修改时间 | w r i te | 缺省 |
st_ctime | i节点状态的最后更改时间 | chmod, chown |
3.15 utime函数
一个文件的存取和修改时间可以用utime函数更改。
#include <sys/types.h>
#include <utime.h>
//返回:若成功则为0,若出错则为-1
int utime(const char * pathname, const struct utimbuf * times) ;
此函数所使用的结构是:
struct utimbuf {
time_t actime; /*access time*/
time_t modtime; /*modification time*/
}
3.16 mkdir和rmdir函数
用mkdir函数创建目录,用rmdir函数删除目录。
#include <sys/types.h>
#include <sys/stat.h>
//返回:若成功则为0,若出错则为-1
int mkdir(const char * pathname, mode_t mode) ;
//返回:若成功则为0,若出错则为-
int rmdir(const char * pathname) ;
3.17 读目录
#include <sys/types.h>
#include <dirent.h>
//返回:若成功则为指针,若出错则为NULL
DIR *opendir(const char * pathname) ;
//返回:若成功则为指针,若在目录尾或出错则为NULL
struct dirent *readdir(DIR * dp) ;
void rewinddir(DIR * dp) ;
//返回:若成功则为0,若出错则为-1
int closedir(DIR * dp) ;
定义在头文件<dirent.h>中的dirent结构与实现有关。这个结构至少包含 下列两个成员:
struct dirent {
ino_t d_ino; /*i-node number*/
char d_name[NAME_MAX + 1]; /*null-terminated filename*/
}