stat 系列函数返回与文件相关的信息结构
#include <sys/stat.h>
int stat(const char* path,struct stat* buf);
int fstat(int filedes,struct stat* buf);
int lstat(const char* path,struct stat* buf);
其中 fstat 通过文件描述符来获取文件信息,lstat 在读取符号连接文件时,获取符号连接文件本身的属性。
| 实际用户ID | 我们实际上是谁? |
| 实际组ID | |
| 有效用户ID | 用于文件访问权限检查 |
| 有效组ID | |
| 附加组ID | |
| 保存的设置用户ID | 由exec函数保存的有效用户ID |
| 保存的设置组ID | 由exec函数保存的有效用户组ID |
| 意义 | st_mode宏 |
|---|---|
| 用户-读 | S_IRUSR |
| 用户-写 | S_IWUSR |
| 用户-执行 | S_IXUSR |
| 组-读 | S_IRGRP |
| 组-写 | S_IWGRP |
| 组-执行 | S_IXGRP |
| 其他-读 | S_IROTH |
| 其他-写 | S_IWOTH |
| 其他-执行 | S_IXOTH |
默认情况下,进程使用有效用户ID/有效组ID来执行对文件的权限测试. 但也可以使用access函数来让进程根据 实际用户/组权限 进行测试:
#include <unistd.h>
int access (const char* path,int mode)
其中mode的可选值为:
| mode | 说明 |
|---|---|
| R_OK | 测试读权限 |
| W_OK | 测试写权限 |
| X_OK | 测试执行权限 |
| F_OK | 测试文件是否存在 |
umask函数为进程设置文件模式创建屏蔽字,并返回以前的值
#include <sys/stat.h>
mode_t umask(mode_t cmask);
其中cmask为访问权限那9个st_mode常量中的一个或多个的"或"构成
当使用create/open函数创建新文件时,即使mode参数中有设置某个参数,但若使用umask设置了屏蔽该权限,则创建的新文件也不会有该参数.
但umask可能会也可能不会修改由内核直接产生的core文件
#include <sys/stat.h>
int chmod(const char* path,mode_t mode);
int fchmod(int filedes,mode_t mode);
chmod函数在指定文件上进程操作,而fchmod函数则对已打开的文件进行操作
为了改变文件权限,进程的 有效ID 必须等于文件的所有者ID,或进程具有超级用户权限
| 意义 | st_mode宏 |
|---|---|
| 用户-读 | S_IRUSR |
| 用户-写 | S_IWUSR |
| 用户-执行 | S_IXUSR |
| 组-读 | S_IRGRP |
| 组-写 | S_IWGRP |
| 组-执行 | S_IXGRP |
| 其他-读 | S_IROTH |
| 其他-写 | S_IWOTH |
| 其他-执行 | S_IXOTH |
| 执行时设置用户ID | S_ISUID |
| 执行时设置组ID | S_ISGID |
| 设置粘住位 | S_ISVTX |
注意:由于新建文件的组ID可能时父目录的组ID,因此新创建的组ID可能并不是调用进程所示的组. 因此,为了安全,当新文件的组ID不属于进程的有效组ID或进程附加组ID中的一个,或进程没有超级用户权限时,那么设置组ID位会自动被关闭. 这就防止了用户创建一个设置组ID文件,而该文件是由并非该用户所属的组所拥有的.
若对一个可执行文件设置了粘住位,则该程序第一次执行并结束后,其程序的指令部分仍然会保存在交换区中,由于交换区占用连续的磁盘空间,因此下次载入该程序会更快一些.
若对一个目录设置了粘住位,则只有对该目录具有写权限的用户满足以下之一的条件时才允许或更名该目录下的文件
对目录设置粘住位的一个典型目录是/tmp目录,任何人都能够在其目录下创建文件,但用户不能删除/更名其他用户的文件.
#include <unistd.h>
int chown(const char* path,uid_t owner,gid_t group)
int fchown(int filedes,uid_t owner,gid_t group)
int lchown(const char* path,uid_t owner,gid_t group)
三者的区别类似stat,fstgat和lstat
若参数owner/group为-1,则表示对应ID不变.
空洞是由所设置的偏移量超过文件尾端,并写了数据后照成了.
文件中的空洞可能占有也可能不占用磁盘空间,但当复制该文件时,那么新文件会填满这些空洞.
#include <unistd.h>
int truncate(const char* path,off_t len);
int ftruncate(int filedes,off_t len);
若原文件的长度大于参数len,则超过len之前的数据就不能再访问.
若原文件的长度小于len,则实现效果与系统相关.
#include <unistd.h>
int link(const char* exist_path,const char *new_path);
#include <unistd.h>
int unlink(const char* path)
该函数删除目录项,并将由path所引用的文件的链接计数减1.
只有当链接计数为0时,该文件的内容才正真被删除.(注意: 若有进程打开了该文件,则即使该文件的链接计数为0,也不会真正释放磁盘空间. 只有当关闭该文件后,内核检查其链接数为0,才删除该文件内容. )
unlink的这种特性,可以用来创建临时文件: 进程创建临时文件后,立刻调用unlink. 该文件因为是打开的,所以内容不会被删除,但当进程退出时,该文件的内容被删除.
一般来说,参数path指向的是一个 文件 ,但若是超级用户权限,则参数path可以指向一个目录. 但通常应该使用rmdir函数代替.
#include <stdio.h>
int remove(const char* path)
若path为文件路径,则remove与unlink类似.
若path为目录路径,则remove与rmdir类型.
#include <stdio.h>
int rename(const char* oldname,const chaar* newname);
用open打开文件时,如果传递给open函数的路径指定了一个符号链接,那么open跟随链接找到所指向的文件. 若符号链接所指向的文件并不存在,则open返回出错.
#include <unistd.h>
int symlink(const char* actual_path,const char* sym_path)
创建一个指向actual_path的符号链接sym_path. 并不要求acutal_path已近存在
#include <unistd.h>
ssize_t readlink(const char* pathname,char* buf,size_t bufsize)
open函数会跟随符号链接打开其指向的实际文件 若要打开链接本身,则需要使用readlink函数
每个文件都保持有三个时间属性,它们的意义为:
| 字段 | 说明 | 例子 | ls命令选项 |
|---|---|---|---|
| st_atime | 文件数据的最后访问时间 | read | -u |
| st_mtime | 文件数据的最后修改时间 | write | 默认 |
| st_ctime | i节点状态的最后更改时间 | chmod,chown | -C |
注意:系统并不保存对一个i节点的最后一次访问时间.
#include <utime.h>
int utime(const char* path,const struct utimbuf* times);
struct utimbuf{
time_t actime; /* access time */
time_t modtime; /* modification time */
}
#include <sys/stat.h>
int mkdir(const char* path,mode_t mode);
指定的文件访问权限mode参数,会收到进程的文件模式创建屏蔽字的修改.
需要注意的是:对于目录, 一般至少要设置一个执行权限位 ,以允许访问该目录的文件名.
#include <unistd.h>
int rmdir(const char* path);
被删除的目录必须为空
#include <dirent.h>
DIR *opendir(const char* pathname);
struct dirent* readdir(DIR* dp);
void rewinddir(DIR* dp);
int closedir(DIR* dp);
long telldir(DIR* dp);
void seekdir(DIR* dp,long loc);
struct dirent{
ino_t d_ino;
char d_name[NAME_MAX + 1];
}
使用readdir读取目录中的目录项,目录中的各目录项的顺序与实现有关,它们通常并不按照字母顺序排列.
#include <unistd.h>
int chdir(const char* path);
int chdir(int filedes);
#include <unistd.h>
char* getcwd(char* buf,size_t size);

