【APUE】文件和目錄

本文章將描述文件系統的其他特性和文件的性質。
1 stat、fstat、和lstat函數
    獲取文件的信息結構
    #include <sys/stat.h>
    int stat(const char *restrict pathname, struct stat * restrict buf);
    int fstat(int filedes, struct stat *buf);
    int lstat(const char *restrict pathname, struct stat * restrict buf);
    //若成功返回0,失敗返回-1

    stat函數獲取與此命名文件有關的信息結構
    fstat函數獲取在描述符filedes上打開的文件的有關的信息
    lstat與stat類似,但是當命名文件是一個符號鏈接的時候,lstat返回此符號連接的信息,而不是此符號連接所指向的文件的信息
    以下是stat結構體的結構
    struct stat {
        mode_t         st_mode;    // 文件類型和權限
        ino_t         st_ino;        // 文件的inode號
        dev_t        st_dev;        // 設備號
        dev_t        st_rdev;    // 特殊設備文件號
        nlink_t        st_nlink;    // 鏈接數
        uid_t        st_uid;        // 用戶ID號
        gid_t        st_gid;        // 用戶屬組ID號
        off_t        st_size;    // 普通文件對應的文件字節數
        time_t        st_atime;    // 文件最後被訪問的時間
        time_t         st_mtime;    // 文件最後被修改的時間
        time_t        st_ctime;    // 文件狀態最後被修改的時間
        blksize_t    st_blksize;    // 文件內容對應的塊大小
        blkcnt_t    st_blocks;    // 文件內容對應的塊數量
    };
2 文件類型
    文件類型包括以下幾種:
    (1)普通文件:最常見的類型,包含了某種形式的數據。
    (2)目錄文件:包含了其他文件的名字以及指向與這些文件有關的信息的指針。
    (3)塊特殊文件:這種類型的文件可以提供對設備帶緩衝的訪問(磁盤)。
    (4)字符特殊文件:這種類型的文件提供對設備不帶緩衝的訪問。
    (5)FIFO:這種類型的文件用於進程間通信,有時將其稱爲命名管道。
    (6)套接字:這種類型的文件用於進程間的網絡通信。
    (7)符號鏈接:這種文件類型指向一個文件。
    文件類型的信息保存在stat結構體的st_mode中,可以通過以下宏確定文件的類型
        S_ISREG()    //普通文件
        S_ISDIR()    //目錄文件
        S_ISCHR()    //字符特殊文件
        S_ISBLK()    //塊特殊文件
        S_ISFIFO()    //管道或FIFO
        S_ISLNK()    //符號鏈接
        S_ISSOCK()    //套接字
    POSIX.1允許實現進程間對象(IPC)。以下宏可以確定IPC對象的類型,這些宏的參數是指向stat結構的指針
        S_TYPEISMQ    //消息隊列
        S_TYPEISSEM    //信號量
        S_TYPEISSHM    //共享存儲對象
3 用戶ID和組ID
    一個進程通常包含多個ID
    實際用戶ID和實際組ID標識我們究竟是誰,這兩個字段在登錄的時候取自口令文件中的登錄項。
    有效用戶ID、有效組ID以及附加組ID決定了我們的文件訪問權限。
    保存的設置用戶ID和保存的組ID在執行一個程序時包含了有效用戶ID和組有效組ID的副本。
    在stat函數中,設置用戶ID位及設置組ID位都包含在st_mode值中。可以用S_ISUID()和S_ISGID()來測試。
2.4 文件的訪問權限
    所有的文件類型的文件都有訪問權限(access Permission)
    每個文件都有9個訪問權限
    S_IRUSR    //用戶-讀
    S_IWUSR    //用戶-寫
    S_IXUSR    //用戶-執行
    S_IRGRP    //組-讀
    S_IWGRP    //組-寫
    S_IXGRP    //組-執行
    S_IROTH    //其他-讀
    S_IWOTH    //其他-寫
    S_IXOTH    //其他-執行
    我們用名字打開任一類型的文件時,對該名字中包含的每一個目錄,包括它可能隱含的當前工作目錄都應具有執行權限。
    這就是爲什麼對於目錄其執行權限位常被稱爲搜索位的原因。
    進程在每次打開,創建和刪除一個文件的時候,內核就進行文件訪問權限的測試:
    1.若進程的有效用戶ID是0,則允許訪問。
    2.若進程的有效用戶ID等於文件的所有者ID,那麼,若所有者適當的訪問權限位被設置,則允許訪問,否則拒絕訪問。
    3.若進程的有效組ID或進程的附加組ID之一等於文件的組ID,那麼,若所有者適當的訪問權限位被設置,則允許訪問,否則拒絕訪問。
    4.若其他用戶適當的訪問權限位被設置,則允許訪問,否則拒絕訪問。
5 access函數
    按實際的用戶ID和實際組ID進行訪問權限測試
    #include <unistd.h>
    int access(const char *pathname, int mode);
    //成功返回0,失敗返回-1
6 umask函數
    爲進程設置文件模式創建屏蔽字
    #include <sys/stat.h>
    mode_t umask(mode_t cmask);
    //返回以前的文件模式創建屏蔽字,沒有出錯返回
    cmask是9個訪問權限位
7 chmod和fchmod函數
    改變文件的訪問權限
    #include <sys/stat.h>
    int chmod(const char *pathname, mode_t mode);
    int fchmod(int filedes, mode_t mode);
    //成功返回0,失敗返回-1
8 粘住位
    S_ISVTX位在早期的UNIX尚未使用分頁技術的早期版本中,被該位被稱之爲粘住位,當程序運行結束的時候,
    其程序的正文部分的一個副本仍被保存在交換區內,下一次執行該程序的時候,可以較快的裝入內存。
    現今的粘住位稱爲保存正文位,如果對一個目錄設置了粘住位,則只有滿足以下條件之一,纔可將其刪除:
        1.擁有此文件
        2.擁有此目錄
        3.是超級用戶
9 chown、fchown和lchown
    用於更改文件的用戶ID和組ID
    #include <unistd.h>
    int chown(const char *pathname, uid_t owner, gid_t group);
    int fchown(int filedes, uid_t owner, gid_t group);
    int lchown(const char *pathname, uid_t owner, gid_t group);
    //成功返回0,失敗返回-1
10 文件長度
    在unix環境下,文件長度只是文件的一個屬性,並不表徵佔用多少磁盤空間
    stat結構成員st_size表示以字節文單位的文件長度,此字段只針對與普通文件,目錄文件和符號鏈接有意義。
11 文件截短
    在文件尾端處截去一些數據以縮短文件。
    #include <unistd.h>
    int truncate(const char *pathname, off_t length);
    int ftruncate(int filedes, off_t length);
    //成功返回0,失敗返回-1
    以上兩個函數是把現有的文件截短爲length字節。
12 link、unlink、remove和rename
    #include <unistd.h>
    int link(const char *existingpath, const char *newpath);
    //創建一個指向現有文件的鏈接
    int unlink(const char *pathname);
    //刪除一個現有的目錄項
    int remove(const char *pathname);
    //解除對一個文件或目錄的鏈接
    int rename(const char *oldname, const char *newname);
    //對文件或目錄改名
13 symlink和readlink函數
    操作符號鏈接
    #include <unistd.h>
    int symlink(const char *actualpath, const char *sympath);
    //創建一個符號鏈接
    ssize_t readlink(const char * restrict pathname, char * restrict buf, size_t bufsize);
    //讀取一個符號鏈接
14 文件的時間
    對每個文件保持三個時間字段
    st_atime    //文件數據的最後訪問時間(read)
    st_mtime    //文件數據的最後修改時間(write)
    st_ctime    //i節點狀態的最後更改時間(chmod, chown)
    unix不記錄文件的創建時間
15 utime函數
    修改一個文件的訪問和修改時間
    #include <utime.h>
    int utime(const char *pathname, const struct utimbuf *time);
    
    struct utimbuf{
        time_t actime;
        time_t modtime;
    };
16 mkdir和rmdir函數
    創建和刪除目錄
    #include <sys/stat.h>
    int mkdir(const char * pathname, mode_t mode);
    int rmdir(const char * pathname);//只能刪除空目錄,目錄中只包括.和..
17 讀目錄
    #include <dirent.h>
    DIR *opendir(const char *pathname);
    //成功返回指針,失敗返回NULL
    struct dirent *readdir(DIR *dp);
    //成功返回指針,若在目錄結尾或者出錯返回NULL
    void rewinddir(DIR *dp);
    int closedir(DIR *dp);
    //成功返回0,失敗返回-1
    long telldir(DIR *dp);
    //返回與dp關聯的目錄中的當前位置
    void seekdir(DIR *dp, long loc);

    struct dirent {
        ino_t d_ino;
        char d_name[NAME_MAX + 1];
    };
18 chdir、fchdir和getcwd
    更改當前工作目錄
    #include <unistd.h>
    int chdir(const char *pathname);
    int fchdir(int filedes);
    //成功返回0, 失敗返回-1

    獲取當前工作目錄的完整的絕對路徑名
    #include <unistd.h>
    char * getcwd(char *buf, size_t size);
    //成功返回buf, 失敗返回NULL
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章