目录
文件属性
这里主要通过 stat
结构的成员来了解文件属性,通过各种系统调用方法来获取或修改 stat
包含的属性
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 */
};
字段属性
stat获取
stat
结构信息可以通过以下方法获取
#include <sys/stat.h>
int stat(const char *pathname, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
- stat()返回所命名文件的相关信息
- lstat()与stat()类似,当文件是符号链接时,那么该方法返回的事符号链接自身(stat()返回的是符号指向实际的文件)
- fstat()返回以某个打开的文件描述符所指的文件的相关信息
stat()和lstat()需要有
pathname
父目录的执行权限;fstat()只要给提供有效的文件描述符,就可以调用成功
获取stat结构示例
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
for (int i = 1; i < argc; ++i)
{
struct stat st;
if (stat(argv[i], &st) != 0)
{
printf("stat failed!\n");
continue;
}
printf("dev:\t%lu\n", st.st_dev);
printf("ino:\t%lu\n", st.st_ino);
printf("mode:\t%d\n", st.st_mode);
printf("nlink:\t%lu\n", st.st_nlink);
printf("uid:\t%d\n", st.st_uid);
printf("gid:\t%d\n", st.st_gid);
printf("rdev:\t%lu\n", st.st_rdev);
printf("size:\t%lu\n", st.st_size);
printf("blksize:\t%lu\n", st.st_blksize);
printf("blocks:\t%lu\n", st.st_blocks);
printf("atime:\t%ld\n", st.st_atime);
printf("mtime:\t%ld\n", st.st_mtime);
printf("ctime:\t%ld\n", st.st_ctime);
}
return 0;
}
设备ID和i节点号
st_dev
字段标识文件所驻留的设备st_ino
字段包含了文件i节点号
使用上面两者,可在所有文件系统中唯一标识某个文件
如果针对的设备是i节点,那么 st_rdev
字段包含设备的主、辅ID
使用宏 major()
和 minor()
可以提取dev_t值的主、辅ID
major、minor原型
unsigned int major(dev_t dev);
unsigned int minor(dev_t dev);
文件所有权
st_uid
和 st_gid
字段分别标识文件所有者(用户ID)和所属组(组ID)
链接数
st_nlink
字段包含了指向文件链接数(硬链接)
文件类型及权限
st_mode
字段内含位掩码,标识文件类型和指定文件权限的双重作用
<---文件类型---><------------------ 权限 ----------------------->
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | | U | G | T | R | W | X | R | W | X | R | W | X |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
可以直接通过 (statbuf.st_mode & S_IFMT) == S_IFREG
判断文件类型,也可以通过下面测试宏来直接检查。
检查文件类型的宏
常量 | 测试宏 | 文件类型 |
---|---|---|
S_IFREG | S_ISREG() | 普通文件 |
S_IFDIR | S_ISDIR() | 目录 |
S_IFCHR | S_ISCHR() | 字符设备 |
S_IFBLK | S_ISBLK() | 块设备 |
S_IFIFO | S_ISFIFO() | FIFO或管道 |
S_IFSOCK | S_ISSOCK() | 套接字 |
S_IFLNK | S_ISLNK() | 符号链接 |
文件权限
UGT 分别表示设置用户ID、设置组ID、粘贴位
rwx 分别表示读、写、执行权限,上面的9个rwx权限位分别表示所属用户、所属组、其他用户的权限
常量 | 其他值 | 权限位 |
---|---|---|
S_ISUID | 04000 | Set-user-ID |
S_ISGID | 02000 | Set-group-ID |
S_ISVTX | 01000 | Sticky |
S_IRUSR | 04000 | User-read |
S_IWUSR | 02000 | User-write |
S_IXUSR | 01000 | User-execute |
S_IRGRP | 04000 | Group-read |
S_IWGRP | 02000 | Group-write |
S_IXGRP | 01000 | Group-execute |
S_IROTH | 04000 | Other-read |
S_IWOTH | 02000 | Other-write |
S_IXOTH | 01000 | Other-execute |
目录的权限说明
- 读权限:可列出目录之下的内容
- 写权限:可在目录内创建、删除文件
- 可执行权限:可访问目录中的文件
文件大小
st_size
字段表示文件的字节数,对于符号链接,表示链接所指路径名的长度;对于共享内存对象,表示对象的大小。
st_blocks
字段表示分配给文件的总块数,块大小为512字节,其中包括了指针块所分配的空间
st_blksize
字段表示文件系统上文件进行I/O操作时的最优块大小;若I/O所采用的块大小小于该值,被视为低效
文件时间戳
st_atime
: 上次访问时间st_mtime
: 上次修改时间st_ctime
: 上次文件状态发生改变的时间(i节点信息被修改就是状态发生改变)
文件属性修改方法
文件所有权
#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
int lchown(const char *pathname, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
- chown()改变由pathname参数命名的文件的所有权
- lchown()同上,区别pathname为符号链接时,则改变链接本身(chown改变的是链接所指文件)
- fchown()同上,传入的参数是文件描述符
如果只是打算修改用户ID或组ID之一,只需要将另一个改为-1即可
文件权限
检查文件访问权限
#include <unistd.h>
int access(const char *pathname, int mode);
若参数pathname为符号链接,access()将对其解引用
mode是常量按位或的位掩码。满足权限则返回0, 否则返回-1
常量 | 描述 |
---|---|
F_OK | 文件存在 |
R_OK | 文件可读 |
W_OK | 文件可写 |
X_OK | 文件可执行 |
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
- chmod()更改pathname参数所指文件的权限,如果是符号链接,则修改符号链接所指向的文件权限
- fchmod()功能同上,修改的是文件描述符所指的文件权限
文件链接数
修改文件连接数的方法有很多,比如创建新文件(create()
)、创建硬连接(link()
)、删除文件、删除硬连接(unlink
)等等,都可以改变文件的链接数目,当链接数目为0的时候,就会把文件彻底删掉
mkdir()
, rmdir()
是对目录的创建和删除方法,同样也改变目录的链接数(目录没有硬连接)
文件时间戳
#include <sys/stat.h>
int utime(const char*pathname, const struct utimbuf *buf);
int utimes(const char*pathname, const struct timeval tv[2]);
int futimens(int fd, const struct timespec time[2]);
int lutimes(const char *pathname, const struct timeval tv[2]);
- utime()如果buf为null,将文件上次访问时间和修改时间设置为当前时间,否则按照buf结构的相应字段去修改时间
- utimes()可以用微秒的精度来指定时间值
- futimes()可以使用文件描述符来修改时间(其他功能和utimes一样)
- lutimes()与utimes()的区别就是如果文件是符号链接,lutimes()修改的是符号链接本身
参考
- UNIX环境高级编程
- Linux/UNIX系统编程手册(上册)
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 245292011@qq.com