天天看点

UNIX环境高级编程-第4章-4.8-4.104.8 函数umask4.9 函数chmod,fchmod,fchmodat4.10 粘连位

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",)<){
    printf("新文件创建失败\n");
  }else{
    printf("新文件创建的权限值一定是:0404\n");
  }
  return ;
}
           

//结果如下:

[email protected]:~/桌面$ ./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();
  struct stat st;
  printf("旧的文件模式掩码:%04o\n",old);
  int fd1,fd2;
  if((fd1=open("a.txt",O_WRONLY|O_CREAT|O_TRUNC,))<){
    printf("文件a.txt打开写失败\n");
  }else if(stat("a.txt",&st)<){
    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)<){
      printf("更改a.txt的权限失败\n");
    }else if(stat("a.txt",&st)<){
      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",,)<){//man手册中说AT_SYMLINK_NOFOLLOW并没有实现
    printf("更改符号链接s234.txt的权限失败\n");
  }else if(stat("s234.txt",&st)<){
    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)<){
      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 ;
}
           

//验证的结果如下:

[email protected]:~/桌面$ ./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等目录,任何用户都拥有对该目录的读写执行权限,但是尽管如此,一个普通用户不应该能够删除或者重命名该目录下其他用户的文件,之所以只讨论删除和重命名,是因为这些权限通常是由目录权限决定的,但是其他权限是目录下的文件本身的权限决定的。

测试结果如下:
[email protected]:/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
[email protected]:/home/xcl/桌面$ mv ppp/xcl.txt ppp/xcl1.txt
mv: 无法将"ppp/xcl.txt" 移动至"ppp/xcl1.txt": 不允许的操作
[email protected]:/home/xcl/桌面$ rm ppp/xcl.txt
rm:是否删除有写保护的普通空文件 "ppp/xcl.txt"? y
rm: 无法删除"ppp/xcl.txt": 不允许的操作
      

继续阅读