h#stat(),fstat(),fstatat(),lstat()
#include <sys/stat.h>
int stat(const char *restrict pathname,struct stat *restrict buf);
int fstat(int fd,struct stat *buf);
int lstat(const char *restrict pathname,struct stat *restrict buf);
int fstatat(int fd,const char restrict pathname,struct stat *restrict buf ,int flag);
//正确返回0,错误返回-1,
restrict关键字
restrict,C语言中的一种类型限定符(Type Qualifiers),用于告诉编译器,对象已经被指针所引用,不能通过除该指针外所有其他直接或间接的方式修改该对象的内容。
能帮助编译器进行更好的优化代码,生成更有效率的汇编代码.如 int *restrict ptr, ptr 指向的内存单元只能被 ptr 访问到,任何同样指向这个内存单元的其他指针都是未定义的,直白点就是无效指针。
struct stat *restrict
将会被用来填充的结构体。
给出pathname
参数,用参数给定的文件去填充传入的stat
结构。
而如果给出fd
则是用该文件描述符引用的文件,去填充结构体。
- stat()
使用指定的路径指向的文件信息,填充传入的结构体。 - fstat()
获取指定文件描述符绑定的文件的信息,填充传入的结构体。 - lstat()
当路径指定的文件是一个链接文件的时候,就填充该链接文件的信息。而不是所连接的源文件 - fstatat()
对路径指定的目录,返回目录的文件统计信息。如果存在链接文件,返回源文件。
fd存在特殊值AT_FDCWD
为当前目录,相对与当前目录。
struct stat
struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
timespec st_atime; //文件最后被访问的时间
timespec st_mtime; //文件内容最后被修改的时间
timespec st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //文件内容对应的块数量
};
ls -l
使用stat()
字段介绍
- mode_t 文件类型
普通文件:
目录文件:对于目录有读权限的任一进程都可以读取目录内容,但是只有内核可以直接写目录。必须使用这节的函数才能改变目录。
块特殊文件:提供对设备(磁盘)带缓冲的访问,每次访问以固定长度为单位。
字符特殊文件:对设备提供不带缓冲的访问
FIFO:管道文件,用于进程间的通信
套接字:用于进程间的通信
符号链接:这种文件指向另一个文件
对这些文件,有对应的函数来判断文件类型。
S_ISREG()
:普通文件
S_ISDIR()
:目录文件
S_ISCHR()
:字符特殊块
S_ISBLK()
:快特殊文件
S_ISRFIFO()
:管道FIFO
S_ISLNK()
:符号链接
S_ISSOCK()
:套接字
bool i = S_ISREG(buf.st_mode);
下面是IPC对象的文件,下面这些函数传入的是结构体的指针
S_TYPEISMQ()
:消息队列
S_TYPEISSEM()
:信号量
S_TYPEISSHM()
:共享存储对象
设置用户ID和设置组ID
实际ID:表示文件实际是那个用户的。
有效ID:表示谁对该文件有访问权限。
保存的设置ID:执行一个程序的时候,程序包含了有效的副本。
通常:有效** = 实际**
**代表:用户 组。
详细解释
- 实际**ID
是当前登录的用户ID。也是一个程序的执行者。
在登录系统的时候就已经设置了。也就是我们登录的用户名。 - 有效ID
这个名词是描述实际ID是否有操作某个文件和函数的权限。是否可以执行某个函数。
也就是说他描述实际用户和一个操作之间的关系。
可以这样理解:
程序在执行的时候,系统需要通过判断有效ID,来判断该程序对一个操作是否有权限。而这个有效ID通常适合实际**ID绑定的,因为我们就是用这个用户登录的程序执行的操作。
这个是和进程绑定的。 - 设置用户ID位
如果该位被设置为一个用户。
那么操作该文件或者相关函数的时候,他的有效**ID就会被设置成对应的用户。
这样,进程对某个操作的权限就不再是我们登录的那个用户了。
文件权限解释
- 第一位 -
第一位是文件类型
上面的文件第一位是-
表示是一个普通文件。还有其他的例如:
d
目录,l
链接文件,b
接口设备,c
串行端口设备 - 剩余部分三个一组
分别表示:文件所有者的权限,同用户组的权限,其他用户的权限。
第一个表示是否可读,第二个表示是否可写,第三个表示是否可执行
如果是对应的rwx
那么是又全部权限,否则用-
表示没有该项权限。
其中还有三个特殊权限s
,,
- SUID
当s
标志出现在文件所有者的x
位时,成为设置用户ID,有如下特点:
只对二进制程序有效
执行者需要对该程序有执行权限,也就是其他用户或者用户组具有执行权限
该权显只在程序执行过程中有效。
执行者将暂时获得该程序的所有者权限 - SGID
当s
标志出现在文件用户组的x
位时。
同上,只是程序执行者获得的是用户组的权限。
当对文件进行创建打开删除的时候,内核会对权限进行测试:
以此为,是否是root,是否是所有者,用户组,其他。
新文件和目录文件的所有权
当使用open
,creat
创建文件的时候,新文件的权限。
access()和faccessat()
测试运行程序的用户对指定的文件是否有相应的权限
#incldue <unistd.h>
int access(const char *pathname,int mode);
int faccess(int fd,const char *pathname,int mode,int mode,int flag);
//成功返回0
mode的取值:
- F_OK:测试文件是否存在
- R_OK:是否可度
- W_OK:可写
- X_OK:可执行
后一个函数的fd也是一个后面pathname
的起始路径。
flag设置为AT_EACCESS
则是检测其有效**ID(也就是会被s位影响)
umask()
为创建的新文件指定权限。和进程绑定
使用一组预处理变量,进行与运算的结果为参数,返回之前的权限
chmod(),fchmod(),fchmodat()
改变现有文件的权限
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd,mode_t mode);
int fchmodeat(int fd ,const char *pathname ,mode_t mode,int flag);
后者flag
来选择是否跟随符号链接。
chown(),fchown(),fchownat(),lchown()
改变文件的有所这,用户组。
格式化IO
#include <stdio.h>
int printf(cosnt char *restrict format,...);
int fprintf(FILE* fp,cosnt char *restrict format,...);
int dprintf(int fd,cosnt char *restrict format,...);
int sprintf(char *restrict buf,cosnt char *restrict format,...);
int snprintf(char *restrict buf,size_t n ,cosnt char *restrict format,...);
//成功返回输入的字节数,失败返回负数。
sprintf
可能导致buf越界,结束后在尾部加\0
snprintf
指定缓冲区长度,超出部分直接丢弃,且不会在尾部加\0
在其format
中可以有占位符:格式为:
%[标志][宽度][最少输出位数][参数长度]参数类型
- 标志
,
将整数按千分为分组字符,-
左对齐,+
带正负号,空格
第一位不是正负号加空格,#
指定转换进制,0
前导0补齐 - 最小宽度
小于指定宽度,前面加空格补齐, - 输出位数
精度以.开头加非负数字
字符串最大字节数直接数字开头 - 参数长度
应该是参数的sizeof
hh
1,h
2,l
4,ll
8,j
4,z
size_t,t
,L
long double - 占位符类型
d/i
有符号十进制,o
无符号八进制,u
无符号10进制,x/X
无符号16进制,f/F
双精度,e/E
指数格式双精度,g/G
,a/A
十六进制双精度,c
字符,s
字符串,p
指向void的指针,%
%字符,C/S
宽字符字符串。
网友评论