文件结构stat——
下面三个函数可以获取文件的状态信息:
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
stat函数指定文件路径,fstat指定文件描述符,lstat类似于stat,但对于符号链接文件来说,lstat获取的是符号链接文件本身的状态信息而非引用的那个文件的状态信息,stat是个结构体,如下:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
文件类型——
UNIX系统的文件类型包括普通文件、目录文件、块特殊文件、字符特殊文件、FIFO(命名管道)、套接字、符号链接,其中最主要的文件类型是普通文件。
文件权限——
每个文件都有9个访问权限位,分别是用户、组和其它的读、写和执行权限。与每个进程相关联的ID有诸多个,分别是实际用户ID、实际组ID、有效用户ID、有效组ID、附加组ID、保存的设置用户ID、保存的设置组ID。创建一个新文件时,新文件的ID与当前进程的ID有关。下面的access函数是按实际用户ID和实际组ID进行访问权限测试的:
#include <unistd.h>
int access(const char *pathname, int mode);
创建文件时可以指定文件模式,与这个文件模式相关的有个屏蔽字,umask函数可以指定屏蔽字:
#include <sys/stat.h>
mode_t umask(mode_t cmask);
更改现有文件的访问权限可以使用下面两个函数:
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
更改现有文件的用户ID、组ID可以使用下面几个函数:
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, git_t group);
文件截短——
在创建文件时可以指定O_TRUNC将文件截短,下面的函数也可以做到:
#include <unistd.h>
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
粘住位——
S_ISVTX位被称为粘住位或保存文本位,如果一个可执行程序文件的这一位被设置了,那么在该程序第一次被执行并结束时,其程序正文部分的一个副本仍被保存在交换区,这使得下次执行该程序时能较快地将其装入内存区。其原因是交换区占用连续磁盘空间,可将它视为连续文件,而且一个程序的正文部分在交换区也是连续存放的,而在一般的UNIX文件系统中,文件的各数据块很可能是随机存放的,对于常用的应用程序,例如文本编辑器和C编辑器,我们常常设置它们所在文件的粘住位。现近较新的UNIX系统大多数都配置有虚拟存储系统以及快速文件系统,所以不再需要使用这种技术。
文件系统——
以传统的基于BSD的UNIX文件系统UFS为例,我们可以把一个磁盘分成一个或多个分区,每个分区可以包含一个文件系统。一个很重要的概念就是i节点,它包含了大多数与文件有关的信息:文件类型、文件访问权限位、文件长度和指向该文件所占用的数据块的指针等等。stat结构中的大多数信息都取自i节点。只有两项数据存放在目录项中:文件名和i节点编号。
文件链接——
链接分为符号链接和硬链接,前者是指向一个文件的间接指针,而后者直接指向文件的i节点。引入符号链接的原因是为了避开硬链接的一些限制:硬链接通常要求链接和文件位于同一文件系统中;只有超级用户才能创建指向目录的硬链接。既然符号链接可以指向目录,有可能引入循环,使用时这点需要注意。
任何一个文件可以有多个目录项指向i节点,创建一个指向现有文件的链接的方法是使用link函数:
#include <unistd.h>
int link(const char *oldpath, const char *newpath);
为了删除一个 现有的目录项,可以调用unlink函数:
#include <unistd.h>
int unlink(const char *pathname);
解除对一个文件或目录的链接也可以用remove函数:
#include <stdio.h>
int remove(const char *pathname);
文件名或目录用rename函数更名:
#include <stdio.h>
int rename(const char *oldname, const char *newname);
symlink函数创建一个符号链接:
#include <unistd.h>
int symlink(const char *oldpath, const char *newpath);
readlink函数打开符号链接并读取链接中的名字:
#include <unistd.h>
ssize_t readlink(const char *path, char *buf, size_t bufsize);
文件时间——
对每个文件保持有三个时间段,分别是文件数据的最后访问时间st_atime、文件数据的最后修改时间st_mtime和i节点状态的最后更改时间st_ctime。一个文件的访问和修改时间可以用utime函数更改:
#include <utime.h>
int utime(const char *filename, const struct utimbuf *times);
utimbuf结构如下:
struct utimbuf {
time_t actime; /* access time */
time_t modtime; /* modification time */
};
目录操作——
mkdir函数创建目录,rmdir函数删除空目录:
#include <syt/stat.h>
int mkdir(const char *pathname, mode_t mde);
#include <unistd.h>
int rmdir(const char *pathname);
读取目录可以使用下列函数:
#include <dirent.h>
DIR* opendir(const char *name);
DIR* fdopendir(int fd);
struct dirent* readdir(DIR *dirp);
void rewinddir(DIR *dirp);
int closedir(DIR *dirp);
int telldir(DIR *dirp);
void seekdir(DIR *dirp, long offset);
dirent结构如下:
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported
by all file system types */
char d_name[256]; /* filename */
};
下面两个函数可以更改当前工作目录:
#include <unistd.h>
int chdir(const char *path);
int fchdir(int fd);
getcwd获取当前工作目录:
#include <unistd.h>
char* getcwd(char *buf, size_t size);