文件属性操作
stat/lstat
int stat(const char *pathname, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);
stat穿透
lstat不穿透
两者主要的区别在于连接文件
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; // 文件的类型和存取权限
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; // 用户ID
gid_t st_gid; // 组ID
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; // 文件字节数
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* time of last access */
struct timespec st_mtim; // 最后一次修改时间
struct timespec st_ctim; /* time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
st_mode: 文件的类型和存取权限
S_IFMT 0170000 bit mask for the file type bit field
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
S_ISUID 04000 set-user-ID bit
S_ISGID 02000 set-group-ID bit (see below)
S_ISVTX 01000 sticky bit (see below)
S_IRWXU 00700 owner has read, write, and execute permission
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 group has read, write, and execute permission
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 others (not in group) have read, write, and execute permission
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
获取文件大小测试
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
struct stat st;
int ret = stat("haha.txt", &st);
if (ret == -1) {
perror("stat error");
exit(-1);
}
printf("file size = %d\n", (int)st.st_size);
return 0;
}
权限测试
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
struct stat st;
int ret = stat("haha.txt", &st);
if (ret == -1) {
perror("stat error");
exit(-1);
}
printf("file size = %d\n", (int)st.st_size);
// 文件类型 --> 判断是否是普通文件
if ((st.st_mode & S_IFMT) == S_IFREG) {
printf("这不是一个普通文件\n");
}
// 所有者对文件的操作
if (st.st_mode & S_IRUSR)
printf("读权限\n");
if (st.st_mode & S_IWUSR)
printf("写权限\n");
if (st.st_mode & S_IXUSR)
printf("执行权限\n");
return 0;
}
access
测试当前用户指定文件是否具有某种属性
当前用户, 使用哪个用户调用这个函数, 这个用户就是当前用户
int access(const char *pathname, int mode);
参数:
pathname: 文件名
mode: 4种权限 R_OK: 读; W_OK: 写; X_OK: 执行; F_OK: 文件是否存在
返回值:
0 有某种权限, 或者文件存在
-1 没有, 或文件不存在
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
if (argc < 2) {
printf("a.out filename\n");
}
int ret = access(argv[1], W_OK);
if (ret == -1) {
perror("access");
exit(1);
}
printf("You can write this file. \n");
return 0;
}
chmod
int chmod(const char *pathname, mode_t mode);
参数:
filename: 文件名
mode: 文件权限, 八进制数
修改文件所有者和所属组
#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
参数:
pathname:
owner: 整型值, 用户ID, 在/etc/passwd中
group: 组ID, 在/etc/group中
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char const *argv[])
{
if (argc < 3) {
printf("a.out filename mode\n");
}
int mode = strtol(argv[2], NULL, 8);
int ret = chmod(argv[1], mode);
if (ret == -1) {
perror("chmod");
exit(1);
}
ret = chown(argv[1], 1001, 1002);
if (ret == -1) {
perror("chown");
exit(1);
}
return 0;
}
truncate
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);
参数:
path: 文件名
length: 文件最终的大小, 和lseek拓展文件大小相比, 不需要最后写一个字符. 比原来小, 删除后边的buf; 比原来大, 拓展后面的部分添加\0, 显示@字符, 文件空洞
rename
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);