APUE(4)---文件和目錄 (2)

7、函數umaskshell

  umask函數爲進程設置文件模式建立屏蔽字,並返回以前的值,這是少數幾個沒有出錯返回函數中的一個。其中cmask是9個常量(S_IR/W/XUSR、S_IR/W/XGRP、S_IR/W/XOTH)中的若干個按位「或」構成的。函數

#include<sys/stat.h>
mode_t umask(mode_t cmask);
//返回值:以前的文件模式建立屏蔽字
#include<apue.h>
#include<fcntl.h>

#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

int main(void)
{
    umask(0);
    if(creat("foo", RWRWRW) < 0)
    {
        err_sys("create error for foo");
    }

    umask(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
    if(creat("bar", RWRWRW) < 0)
    {
        err_sys("create error for bar");
    }
    exit(0);
}

4-9 umask函數實例ui

  UNIX系統的大多數用戶從不處理他們的umask值,一般在登陸時,由shell的啓動文件設置一次,而後再不改變。用戶能夠設置umask值以控制他們所建立文件的默認權限。umask的經常使用值:000(任何用戶都能讀寫文件)、002(阻止其餘用戶寫入你的文件)、022(阻止同組成員和其餘成員寫入你的文件)、027(阻止同組成員寫你的文件和其餘用戶讀、寫或執行你的文件)。spa

8、函數chmod、fchmod和fchmodatunix

#include <sys/stat.h>
int chmod(const char *pathname, mode_t mask);
int fchmode(int fd, mode_t mask);
int fchmodeat(int fd, char *pathname, mode_t mask);
//若成功,返回0;若出錯,返回-1

  這三個函數使咱們能夠更改現有文件的訪問權限,爲了改變一個文件的權限位,進程的有效用戶ID必須等於文件的全部者ID,或者該進程必須具備超級用戶權限。還須要注意的是chmode函數更新的知識i節點最近一次被更改的時間。按時間默認方式,ls -l列出的是最後修改文件內容的時間指針

#include <apue.h>
int main(void)
{
    struct stat statbuf;
    if(stat("foo", &statbuf) < 0)
    {
        err_sys("stat error for foo");
    }

    if(chmod("foo", statbuf.st_mode & ~S_IXGRP|S_ISGID) < 0)
    {
        err_sys("chmode error for foo");
    }

    if(chmod("bar", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
    {
        err_sys("chmode error for bar");
    }

    exit(0);
}

4-12 chmode函數實例code

9、函數chown、fchown、fchownat和lchownblog

#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int fchownat(int fd, const char *pathname, uid_t owner, gid_t group, int flag);
int lchown(const char *pathname, uid_t owner, gid_t group);

  這四個函數都是用於更改文件的用戶ID和組ID,若是兩個參數ower和group中的任意一個爲-1,則對應的ID不變。lchown和fchownat(設置了AT_SYNLINK_NOFOLLOW)更改符號鏈接自己,而不是更改符號鏈接所指向的文件的全部者。進程

10、文件長度和文件截斷rem

  stat結構成員st_size表示以字節爲單位的文件的長度,此字段只對普通文件、目錄文件和符號鏈接有意義。對於普通文件,長度能夠爲0;對於符號鏈接,文件長度實在文件名中的實際字節數。現今大多數現代的unix系統提供字段st_blksize和st_blocks。第一個是對文件I/O較合適的快長度;第二個是所分配的實際512字節塊塊數。咱們說起普通文件能夠包含空洞,其實際分配塊數可使用du -s來進行查看。

  將一個文件截斷爲0能夠在打開時使用O_TRUNC標誌,爲了階段文件能夠調用函數truncate和ftruncate。若length小於當前文件的長度,則截斷;若大於當前文件的長度,則填充0。

#include <unistd.h>
int truncate(const char *pathname, off_t length);
int ftruncate(int fd, off_t length);
//若成功,返回0;若失敗,返回-1

11、文件系統

4-13 磁盤、分區和文件系統

  咱們能夠把一個磁盤分紅一個或多個分區。每一個分區能夠包含一個文件系統。i節點是固定長度的記錄項,它包含大部分信息。

4-14 較詳細的柱面組的i節點和數據塊

1.途中有兩個目錄項指向同一個ijiedian。每一個i節點都有一個鏈接計數,其值是指向該i節點的目錄項數,只有當鏈接計算減小至0時,纔可刪除該文件。這就是爲何解除對一個文件的鏈接操做並不老是意味着釋放該文件佔用的磁盤塊的緣由。這也是爲何刪除一個目錄項的函數被稱之爲unlink而不是delete的緣由。

2.另一種鏈接類型稱爲符號鏈接(symbolic link)。符號鏈接文件的實際內容(在數據塊中)包含了該富豪連接所指向的文件的名字。

3.i節點包含了文件有關的全部信息:文件類型、文件訪問權限爲、文件的長度和只想文件數據塊的指針等。可是有兩項重要數據存放在目錄項中:文件名和i節點編號。

4.i節點編號是指向同一文件系統中相應i節點,一個目錄項不能只想另外一個文件系統的i節點,這就是爲何lb命令不能跨越文件系統的緣由。

5.當在不更新文件系統地狀況下爲一個文件重命名時,該文件的實際內容並未移動,只須要構造一個指向現有i節點的新目錄項,並刪除老目錄項,鏈接技術不會改變。

12、函數link、linkat、unlin、unlinkat和remove

#include <unistd.h>
int link(const char *existingpath, const char *newpath);
int linkat(int efd, const char *existingpath,  int nfd, const char *newpath, int flag);
//若成功,返回0;若失敗,返回-1

  建立一個只想現有文件的鏈接方法是使用link和linkat函數。當現有文件是符號鏈接時,有falg參數來控制linkat函數是建立指向現有符號鏈接的鏈接仍是建立指向現有符號鏈接所指向的文件的鏈接。若是在flag參數中設置了AT_SYMLINK_FOLLOW標誌,就建立指向符號鏈接目標的鏈接。建立新目錄項和增長鏈接計數應當是一個原子操做。

#include <unistd.h>
int unlink(const char *pathname);
int unlinkat(int fd, const char *pathname, int flag);

  上面兩個用於接觸對文件的鏈接,其權限要求:擁有該文件、擁有該目錄或者具備超級用戶權限。

#include <apue.h>
#include <fcntl.h>

int main(void)
{
    if(open("tempfile", O_RDWR) < 0)
    {
        err_sys("open error");
    }

    if(unlink("tempfile") < 0)
    {
        err_sys("unlink error");
    }

    printf("file unlinked\n");

    sleep(15);
    printf("done\n");
    exit(0);
}

4-16 打開一個文件,而後unlink

  unlink的這種特性常常被程序用來確保即便是在程序崩潰時,它所建立的臨時文件也不會遺留下來。進程用open或creat建立一個文件,而後當即調用unlink,由於該文件仍舊是打開的,因此不會將其內容刪除。只有當進程關閉或終止時,該文件的內容纔會被刪除。若是pathname是符號鏈接,那麼unlink刪除該符號鏈接,而不是刪除由該鏈接所引用的文件。

  咱們也能夠用remove函數接觸對一個文件或目錄的連接。對於文件,remove的功能與unlink相同;對於目錄,remove的功能與rmdir相同。

#include<stdio.h>
int remove(const char *pathname);
相關文章
相關標籤/搜索