4.8 函数umask
至此,我们已经说明了与每个文件相关的9个权限访问位,在此基础上,我们可以说明每个进程相关的文件模式创建屏蔽字umask值。
#include<sys/stat.h>
mode_t umask(mode_t cmask);
该函数为进程设置新的文件模式屏蔽字,并且返回原来的文件模式屏蔽字,在文件模式屏蔽字中为1的位,在文件st_mode中的相应位一定关闭。
//编写一个程序验证umask函数的使用
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
int main(int argc,char**argv){
//禁用所有用户的写和执行权限
mode_t old=umask(S_IWUSR|S_IXUSR|S_IWGRP|S_IXGRP|S_IWOTH|S_IXOTH);
printf("旧的文件创建权限掩码值是:%04o\n",old);
//创建一个文件
if(creat("fff.txt",0707)<0){
printf("新文件创建失败\n");
}else{
printf("新文件创建的权限值一定是:0404\n");
}
return 0;
}
//结果如下:
xcl@xcl:~/桌面$ ./main
旧的文件创建权限掩码值是:0002
新文件创建的权限值一定是:0404
4.9 函数chmod,fchmod,fchmodat
#include<sys/stat.h>
int chmod(const char*pathname,mode_t mode);
int fchmod(int fd,mode_t mode);
int fchmodat(int fd,const char*pathname,mode_t mode,int flag);
这些函数可以更改文件的权限,flag可以更改fchmodat的行为,当flag取值为AT_SYMLINK_NOFOLLOW的时候,fchmodat并不会跟踪符号链接,即chmod,fchmodat默认是跟踪符号链接。
mode参数可以取值为以下宏定义的按位取或运算: S_ISUID 设置UID位 S_ISGID 设置GID位 S_ISVTX 粘连位 S_IRUSR 所有者读 S_IWUSR 所有者写 S_IXUSR 所有者执行 S_IRGRP 属组读 S_IWGRP 属组写 S_IXGRP 属组执行 S_IROTH 其他用户读 S_IWOTH 其他用户写 S_IXOTH 其他用户执行 经过查看man手册,Linux并没有实现fchmodat函数的flag=AT_SYMLINK_NOFOLLOW标志。原文是: fchmodat(): AT_SYMLINK_NOFOLLOW If pathname is a symbolic link, do not dereference it: instead operate on the link itself. This flag is not currently implemented.
//编写程序,验证chmod,fchmodat函数,其中chmod删除用户读权限,fchmod设置属主读,属组读,其他用户读权限,并且fchmod设置AT_SYMLINK_NOFOLLOW。
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
int main(int argc,char**argv){
mode_t old=umask(0333);
struct stat st;
printf("旧的文件模式掩码:%04o\n",old);
int fd1,fd2;
if((fd1=open("a.txt",O_WRONLY|O_CREAT|O_TRUNC,0444))<0){
printf("文件a.txt打开写失败\n");
}else if(stat("a.txt",&st)<0){
printf("获取文件a.txt的权限失败\n");
}else{
printf("-------------文件a.txt的属性是----------------------------\n");
printf("属主权限:%04o\n",st.st_mode&S_IRWXU);
printf("属组权限:%04o\n",st.st_mode&S_IRWXG);
printf("其他用户权限:%04o\n",st.st_mode&S_IRWXO);
printf("-------------将a.txt的属主读权限禁用----------------------\n");
if(chmod("a.txt",st.st_mode&~S_IRUSR)<0){
printf("更改a.txt的权限失败\n");
}else if(stat("a.txt",&st)<0){
printf("获取a.txt的权限失败\n");
}else{
printf("-----------重新获取a.txt的属主权限----------------------\n");
printf("属主权限:%04o\n",st.st_mode&S_IRWXU);
printf("属组权限:%04o\n",st.st_mode&S_IRWXG);
printf("其他用户权限:%04o\n",st.st_mode&S_IRWXO);
}
}
printf("\n");
if(fchmodat(AT_FDCWD,"s234.txt",0444,0)<0){//man手册中说AT_SYMLINK_NOFOLLOW并没有实现
printf("更改符号链接s234.txt的权限失败\n");
}else if(stat("s234.txt",&st)<0){
printf("获取符号链接指向文件的权限失败\n");
}else{
printf("------------------更改符号链接s234.txt指向的文件的权限0444----------------------------\n");
printf("------------------符号链接s234.txt指向的文件现在的权限是------------------------\n");
printf("属主权限:%04o\n",st.st_mode&S_IRWXU);
printf("属组权限:%04o\n",st.st_mode&S_IRWXG);
printf("其他用户权限:%04o\n",st.st_mode&S_IRWXO);
if(lstat("s234.txt",&st)<0){
printf("获取符号链接s234.txt本身的信息失败\n");
}else{
printf("------------------符号链接s234.txt本身的权限是------------------------------\n");
printf("属主权限:%04o\n",st.st_mode&S_IRWXU);
printf("属组权限:%04o\n",st.st_mode&S_IRWXG);
printf("其他用户权限:%04o\n",st.st_mode&S_IRWXO);
}
}
return 0;
}
//验证的结果如下:
xcl@xcl:~/桌面$ ./main
旧的文件模式掩码:0002
文件a.txt的属性是—————————-
属主权限:0400
属组权限:0040
其他用户权限:0004
将a.txt的属主读权限禁用———————-
重新获取a.txt的属主权限———————-
属主权限:0000
属组权限:0040
其他用户权限:0004
更改符号链接s234.txt指向的文件的权限0444—————————-
符号链接s234.txt指向的文件现在的权限是————————
属主权限:0400
属组权限:0040
其他用户权限:0004
符号链接s234.txt本身的权限是——————————
属主权限:0700
属组权限:0070
其他用户权限:0007
4.10 粘连位
S_ISVTX是粘连位,粘连位的起源有一段有趣的历史,现在SUS扩展了粘连位的使用,如果对一个目录设置了粘连位,只有对该目录具有写权限,并且满足下列之一条件,才能删除或重命名该目录下的文件: 拥有此文件 拥有此目录 拥有超级管理员权限 粘连位典型的作用是:对于一个公共目录如/var,/var/tmp等目录,任何用户都拥有对该目录的读写执行权限,但是尽管如此,一个普通用户不应该能够删除或者重命名该目录下其他用户的文件,之所以只讨论删除和重命名,是因为这些权限通常是由目录权限决定的,但是其他权限是目录下的文件本身的权限决定的。 测试结果如下: oracle@xcl:/home/xcl/桌面$ ll ppp 总用量 36 drwxrwxrwt 2 xcl xcl 4096 6月 9 21:44 ./ drwxr-xr-x 4 xcl xcl 16384 6月 9 21:42 ../ -rw-rw-r-- 1 oracle oracle 0 6月 9 21:43 oracle1.txt -rw-rw-r-- 1 xcl xcl 0 6月 9 21:43 xcl.txt oracle@xcl:/home/xcl/桌面$ mv ppp/xcl.txt ppp/xcl1.txt mv: 无法将"ppp/xcl.txt" 移动至"ppp/xcl1.txt": 不允许的操作 oracle@xcl:/home/xcl/桌面$ rm ppp/xcl.txt rm:是否删除有写保护的普通空文件 "ppp/xcl.txt"? y rm: 无法删除"ppp/xcl.txt": 不允许的操作