天天看點

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": 不允許的操作
      

繼續閱讀