1 函数stat,fstat,lstat,fstatat
#include<sys/stat.h>
int stat(const char* restrict pathname,struct stat *restrict buf);//1.pathname 文件路径 2.buf 一个文件类型的结构体指针
int fstat(int fd,struct stat *buf);//1.fd 已经打开的文件描述符 2.buf 与上述相同
int lstat(const char*restrict pathname,struct stat *restrict buf);//与 stat函数参数相同
int fstatat(int fd,const char* restrict pathname,struct stat *restrict buf,int flag);
1.stat函数 文件的类型赋值给buf
2.fstat与stat相同,但第一个参数不同,fstat的第一个参数为文件描述符
3.lstat与stat函数相同,但lstat如果遇到的文件的符号连接,他指向的是文件本身,而不是符号连接指向的文件
4.fstatat函数为一个相对于当前打开目录(由fd指出)的路径名返回文件统计信息。flag参数控制着是否跟随一个符号链接。当flag参数为AT_SYMLINK_NOFOLLOW标志被设置时,不会跟随符号链接,而是返回符号链接本身的信息。否则,返回的是符号链接指向的实际文件的信息。如果参数fd的值是AT_FDCWD, 并且pathname是一个相对路径名。则fstatat会计算相对于当前目录的pathname参数。如过pathname是个绝对路径,fd的参数就会被忽略.
下面是结构体 stat的定义
struct stat
{
mode_t st_mode;//文件类型
into_t st_ino;
dev_t st_dev;
dev_t st_rdev;
nlink_t st_nlink;//硬链接计数
uid_t st_uid;//文件所有者
gid_t st_gid;//文件组所有者
off_t st_size;
struct timespec st_atime;//文件数据最后的访问时间
struct timespec st_mtime;//文件数据最后的修改时间
struct timspec st_ctime;//i节点状态最后更改的时间
blksize_t st_blksize;//对文件IO 较合适的块长度
blkcnt_t st_blocks;//所分配的实际512字节块的块数 有的可能不是512字节,此值不使用移植
};
2.文件类型
文件类型信息包含在stat结构体的st_mode成员中.可以用下图中的宏确定文件类型,这些宏的参数都是stat结构体中的st_mode成员.
宏 | 文件类型 |
---|---|
S_ISREG() | 普通文件 |
S_ISDIR() | 目录文件 |
S_ISCHR() | 字符特殊文件 |
S_ISBLK() | 块特殊文件 |
S_ISFIFO() | 管道或FIFO |
S_ISLNK() | 符号链接 |
S_ISSOCK() | 套接字 |
下面的宏参数指向的是stat结构体
宏 | 对象的类型 |
---|---|
S_TYPEISMQ() | 消息队列 |
S_TYPEISSEM() | 信号量 |
S_TYPEISSHM() | 共享存储对象 |
3. 文件访问权限
文件访问权限值包含在了st_mode 这个里面。下面是其访问位
st_mode屏蔽 | 含义 |
---|---|
S_IRUSR | 用户读 |
S_IWUSR | 用户写 |
S_IXUSR | 用户执行 |
S_IRGRP | 组读 |
S_IWGRP | 组写 |
S_IXGRP | 组执行 |
S_IROTH | 其它读 |
S_IWOTH | 其它写 |
S_IXOTH | 其它执行 |
S_ISUID | 设置用户ID |
S_ISGID | 设置组ID |
4. 函数access和faccessat 测试实际用户权限
下面两个函数是用来测试实际用户ID和实际组ID是否对 文件拥有的权限.
#include<unistd.h>
int access(const char*pathname,int mode);//1. pathname 文件路径 2.mode 测试模式
int faccessat(int fd,const chat*pathname,int mode,int flag);//1. fd 文件描述符 2.pathname 文件路径 3.mode 访问模式 4.flag 额外的设置
1.access 可以用来测试 实际用户是否拥有mode权限。 mode的参数如下图,
2.faccessat 函数与access函数功能相同,但其可以指定fd为其实路径 .并且如果flag的参数设置为AT_EACCESS则访问监测的是调用进程的有效用户ID和有效组ID,而不是实际用户ID和实际组ID
说明 | mode |
---|---|
R_OK | 测试读权限 |
W_OK | 测试写权限 |
X_OK | 测试执行权限 |
5. 函数umask 创建屏蔽字
函数umask函数为进程设置文件模式创建屏蔽字,并且返回之前的值(这是少数没有出错返回函数中的一个).
#include<sys.stat.h>
mode_t umask(mode_t cmask);//1.文件的访问权限.
6. 新文件和目录的所有权限。
1.新文件的用户ID为进程的有效用户ID
2.新文件的组ID可以是进程的有效用户ID 也可以是所在目录的组ID。
7. 函数chmod,fchmod和fchmodat
下面三个函数用来改变 文件的访问权限
#include<sys/stat.h>
int chmod(const char*pathname,mode_t mode);//1. pathname 文件路径 2.mode 权限设置
int fchmod(int fd,mode_t mode);//1.fd 文件描述符 2.mode 权限设置
int fchmodat(int fd,const chat*pathname,mode_t mode,int flag);//1.fd 文件描述符 2.pthname 文件路径 3.mode 权限设置 4.flag fchmodat的模式
1.fchmodat 函数的最后一个参数flag如果设置为AT_SYMLINK_NOFOLLOW标志时候,将不会跟随符号连接
参数mode是图4-11中所表示的常量的按位或
mode | 说明 |
---|---|
S_ISUID | 执行时设置用户ID |
S_ISGID | 执行时设置组ID |
S_ISVTX | 保存正文(粘着位) |
################# | ##################################################################### |
S_IRWXU | 用户读写和执行 |
S_IRUSR | 用户读 |
S_IWUSR | 用户写 |
S_IXUSR | 用户执行 |
################ | ##################################################################### |
S_IRWXG | 组读写和执行 |
S_IRGRP | 组读 |
S_IWGRP | 组写 |
S_IXGRP | 组执行 |
################ | ##################################################################### |
S_IRWXO | 其它读写和执行 |
S_IROTH | 其它读 |
S_IWOTH | 其它写 |
S_IXOTH | 其它执行 |
8. 粘着位(保存正文位)
在现在的操作系统中,允许对一个目录设置粘着位,如果一个目录设置了粘着位,只有对目录具有写权限的用户并且满足下列条件之一。才可以对目录中的文件或目录删除或者重命名。
1.拥有此文件
2.拥有此目录
3.是超级用户
9. 函数chown,fchown,fchownat和lchown 修改用户所属
下面几个chown函数用于更改文件的用户ID和组ID。如果两个参数的owner或者group中的任意一个是-1,则对应的ID位不变。
#include<unistd.h>
int chown(const char*pathname,uid_t owenr,gid_t group);//1.pathnam 文件路径 2.owenr 新的用户id 3.group 新的组ID
int fchown(int fd,uid_t owenr,gid_t group);
int fchownat(int fd,const char*pathname,uid_t owner,gid_t group,int flag);
int lchown(const char* pathname,uid_t owern,gid_t group);
1.函数lchown和fchownat函数(flag设置了AT_SYMLINK_NOFOLLOW标志)时,引用的是符号链接本身
如果 _POSIX_CHOWN_RESTRICTED生效,则
1.只有超级用户可以更改文件的用户ID
2.如果进程拥有文件,(用户有效ID等于文件所有者ID),参数owner等于-1或者文件的用户ID。并且参数group等于进程的有效用户组ID或者进程附属组ID之一,那么非超级用户可以更改组ID
10. 文件截断函数 truncate和ftruncate
有时候我们需要在文件尾端截取一些数据,下面的函数可以做到这一点
#include<unsitd.h>
int truncate(const chat*pathname,off_t length);//1.pathname 文件路径 2.length 偏移量
int ftruncate(int fd,off_t length);//1.fd 已经打开的文件描述符 2.length 偏移量
1.这两个函数将一个现有文件长度截断为length.如果该文件以前的长度大于length 则length以外的数据不能访问。
2.如果以前的长度小于length,则文件长度将增加。相当于形成了一个文件空洞.
11. 硬链接函数 link,linkat,unlink,unlinkat
如下函数可以创建一个现有文件的硬链接.注意大部分文件系统不支持创建目录的硬链接
#incude<unistd.h>
int link(const chat*exisingpaht,const chat*newpath);//1.exisingpath 现有文件 2.newpath 新的目录项
int linkat(int efd,const chat*existingpath,int nfd,const chat*newpath,int flg);//1.efd 以前的目录打开文件描述符
2.existngpath 相对于efd的文件路径 3.nfd 现有的打开的目录文件描述符 4.newpath 相对于ndf新的文件目录 5.flg 相关选项
1.对于函数linkat 如果两个路径名中有任意一个是相对路径,则他们都通过相对应的文件描述符计算。
2.如果两个任意一个设置为 AT_FDCWD,则通过当前路径计算,
3.如果flg 设置了AT_SYMLINK_FLLOW标志 则创建指向目标链接,否则创建指向符号链接本身。
下面函数可以删除目录项
#include<unistd.h>
int unlink(const char*pathname);//1.pathname 文件路径
int unlinkat(int fd,const chat*pathname,int flag);//1.fd 文件描述符 2.pathname 相对于fd的路径 3.flag 选项
1.当函数unlinkat函数flag设置为AT_REMOVEDIT的时候,可以像rmdir函数一样删除目录
2.没有一个函数能够删除由符号链接所引用的文件.
12. 函数remove
#include<stdio.h>
int remove(const char*pathname);
1.当pahtname是文件时候,与unlink相同
2.当pathname是目录时,与rmdir相同
13. 函数 rename 和renameat 修改文件名称
文件和目录可以通过函数rename和renameat进行重命名
#include<stdio.h>
int rename(const char*oldname,const char*newname);//1.oldname 以前的文件名 2.newname 现在的文件名称
int renameat(int oldfd,const chat * oldname,int newfd,const char* newname);
1.如果oldname指向的是一个文件,如果newname已经存在但不是目录,则删除它覆盖。否则出错
2.如果oldname是一个目录.如果newname已经存在但是一个控目录,则覆盖。否则出错
3.如果oldname和newname是符号链接,则处理的是符号链接本身.
14. 符号连接 symlink,symlinkat,readlink,readlinkat.
符号连接是相对于一个文件的间接指针。硬连接直接指向文件的I节点。引入符号连接,就是为了避开硬链接的一些限制。
1.硬连接通常要求连接位于同一文件系统中.
2.只有超级用户才能创建指向用户的目录的硬链接。
#include<unistd.h>
int symlink(const char* actualpath,const char*sympaht);//1.被指向的目录项。 2.新的目录项
int symlinkat(const char* actualpath,int fd,const char*sympath);//1.被指向的目录项. 2.相对打开描述的引用目录。 3.新的目录项。
#include<unistd.h>
ssize_t readlink(const char*restrict pathname,char* restrict buf, size_t bufsize);
ssize_t readlinkat(int fd,const char*restrict,char*restrict buf,size_t bufsize );
1.这两个函数读取符号连接本身,并不跟随符号链接.
2.相当于组合了 open,read和close的所有操作.
15. 函数 futimens,utimensat和utimes
一个文件的访问和修改时间可以用以下几个函数更改. futimens和utimensat函数可以定纳秒级的精度的时间戳.
#include<sys/stat.h>
int futimens(int fd,const struct timespec times[2]);
int utimensat(int fd,const char*path,const struct timespec times[2],int flag);
int utimes(const char*pathname,const struct timecval times[2]);
1.这两个数组的第一个元素包含访问时间,第二个元素包含修改时间。
2.如果times参数是一个空指针,则访问时间和修改时间两者都设置为当前时间
3.如果times参数指向两个timespec结构数组,任一数组元素的tv_nsec字段的值为UTIME_NOW,相应的时间戳就设置为当前时间
4.utime对路径名进行操作.
16. 函数mkdir,mkdirat和rmdir
用mkdir和mkdirat函数创建目录,用rmdir函数删除目录
#include<sys/stat.h>
int mkdir(const char*pahtname,mode_t mode);//1.pahtname 目录路径 2.mode 权限
int mkdirat(int fd,const char*pahtname,mode_t mode);
int rmdir(const char*pathname);
1.mkdir和mkdirat创建目录
2.使用rmdir删除目录
17. 读目录操作
#include<dirent.h>
DIR* opendir(const char*pathname);//1.pathname 文件路径
DIR* fdopendir(int fd);//1.fd 已经打开的文件描述符
struct dirent*readdir(DIR *dp);//1.dp 读取文件目录
void rewinddir(DIR *dp);
int closedir(DIR *dp);//
long telldir(DIR *dp);
void seekdir(DIR *dp,long loc);
1.fdopendir 函数提供了一种把文件描述符转换成目录结构体的方法.
2.struct dirent 结构体至少提供两个成员 ino_t d_ino和 char d_name;
3.rewinddir将目录流回到初始位置
4.telldir函数返回当前目录读取到的位置
5.seekdir将目录流设置到该位置.
18. 修改工作目录 chdir,fchdir和getcwd
进程调用chdir或者fchdir函数可以更改当前工作目录
#include<unistd.h>
int chdir(const char *pathname);//1.pathname 新的工作目录路径
int fchdir(int fd);//打开的目录文件描述符
char * getcwd(char *buf,size_t size);//1.buf 缓冲区 2.size 缓冲区长度