stat,fstat,lstat分别获取不同文件的stat结构信息
文件类型有7种:
(1)普通文件(2)目录文件(3)块设备(4)字符设备(5)Socket(6)FIFO(7)符号链接
设置用户ID和设置组ID
通常一个进程的有效用户ID和有效用户ID为实际用户ID和实际组ID,但是如果一个进程设置了设置用户ID,那么有效用户ID为文件所有者ID,有效组ID为文件组ID
验证:首先创建一个文件
touch newfile chown root newfile sudo chmod 600 newfile //设置文件所有者可读
#include <fcntl.h> #include <stdio.h> void sys_error(char *message) { printf("%s\n", message); } int main() { int fd; if ((fd = open("./newfile", O_RDONLY) == -1)) { sys_error("open error"); } else { printf("open for reading\n"); } return 0; }
gcc getNewFile.c
sudo chown root ./a.out
./a.out会得到open error,因为此时./a.out的有效用户ID还是xcszbdnl
现在改变权限位,设置设置用户ID changeType.c
#include <fcntl.h> #include <sys/stat.h> #include <stdio.h> void sys_error(char *message) { printf("%s\n", message); } int main() { struct stat buf; if (stat("./a.out", &buf) == -1) { sys_error("stat error"); } if (chmod("./a.out", (buf.st_mode | S_ISUID)) < 0) { sys_error("chmod error for ./a.out"); } return 0; }
gcc changeType.c -o change
sudo ./change 因为./a.out的文件所有者ID为root,要改变./a.out的权限位必须是root才能改变
ll ./a.out 发现已经设置设置用户ID位
./a.out
open for reading,发现已经可以打开了。umask创建文件屏蔽字,如果该位被屏蔽,那么即使设置了也没有用
umask.c
#include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #define RWRWRW (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) void sys_error(char *message) { printf("%s\n", message); } int main() { umask(0); int fd; if ((fd = open("test_1", O_CREAT | O_WRONLY | O_TRUNC, RWRWRW)) == -1) { sys_error("create test_1 error"); } umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if ((fd = open("test_2", O_CREAT | O_WRONLY | O_TRUNC, RWRWRW)) == -1) { sys_error("create test_2 error"); } return 0; }
ll test_1 test_2 //发现test_1所有用户都有读写权限,而test_2只有文件所有者有,因为其他位被屏蔽了
黏住位:
现在如果一个目录设置了黏住位的话说明只有满足以下条件的用户才能够删除该目录下的文件:
(1)该用户为超级用户
(2)该用户拥有此文件
(3)该用户拥有此目录
目录/tmp是设置黏住位的典型候选者,任何用户都可以在此目录下创建文件,但是不能删除别人的文件。
chown, fchown, lchown更改文件用户ID和组ID
文件长度,可以从st_size读得。只对普通文件有效。
getSize.c
#include <sys/stat.h> #include <stdio.h> void sys_ret(char *message) { printf("%s\n", message); } int main(int argc, char *argv[]) { int i; struct stat buf; for (i = 0; i < argc; i++) { if (stat(argv[i], &buf) == -1) { sys_ret("stat error"); } else if (!S_ISREG(buf.st_mode)) { sys_ret("not regular file"); } else { printf("%s:%ld\n", argv[i], buf.st_size); } } return 0; }
gcc getSize.c
./a.out /etc/ ./fork.c ./newfile