文件I/O(二)

本文轉載自實驗樓:文件I/O(二)

stat 的使用

Linux有個命令,ls -l,效果如下:

$ ls -l
-rw-rw-r-- 1 shiyanlou shiyanlou 978 Sep 19 02:13 hello.c

這個命令能顯示文件的類型、操作權限、硬鏈接數量、屬主、所屬組、大小、修改時間、文件名。它是怎么獲得這些信息,這一節我們將撥開迷霧。

stat 的基本使用

系統調用stat的作用是獲取文件的各個屬性。
需要包含的頭文件:

  • <sys/types.h>
  • <sys/stat.h>
  • <unistd.h>

函數原型:

int stat(const char \* path, struct stat \* buf)

功能:查看文件或目錄屬性。將參數path所指的文件的屬性,復制到參數buf所指的結構中。
參數:

  • path:要查看屬性的文件或目錄的全路徑名稱。
  • buf:指向用于存放屬性的結構體。stat成功調用后,buf的各個字段將存放各個屬性。
  • struct stat是系統頭文件中定義的結構體,定義如下:
struct stat {
    dev_t       st_dev;
    ino_t       st_ino;
    mode_t      st_mode;
    nlink_t     st_nlink;
    uid_t       st_uid;
    gid_t       st_gid;
    dev_t       st_rdev;
    off_t       st_size;
    blksize_t   st_blksize;
    blkcnt_t    st_blocks;
    time_t      st_atime;
    time_t      st_mtime;
    time_t      st_ctime;
};
  • st_ino:節點號
  • st_mode:文件類型和文件訪問權限被編碼在該字段中
  • st_nlink:硬連接數
  • st_uid:屬主的用戶ID
  • st_gid:所屬組的組ID
  • st_rdev:設備文件的主、次設備號編碼在該字段中
  • st_size:文件的大小
  • st_mtime:文件最后被修改時間
    返回值:成功返回0;失敗返回-1
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    struct stat     buf;
    if(argc != 2) { 
        printf("Usage: stat <pathname>"); 
        exit(-1); 
    }
    if(stat(argv[1], &buf) != 0) { 
        printf("stat error."); 
        exit(-1); 
    }
    printf("#i-node:    %ld\n", buf.st_ino);
    printf("#link:      %d\n", buf.st_nlink);
    printf("UID:        %d\n", buf.st_uid);
    printf("GID:        %d\n", buf.st_gid);
    printf("Size        %ld\n", buf.st_size);
    exit(0);
}
文件類型的判定

上一小節中struct stat中有個字段為st_mode,可用來獲取文件類型和文件訪問權限,我們將陸續學到從該字段解碼我們需要的文件信息
st_mode中文件類型宏定義

宏定義 文件類型
S_ISREG() 普通文件
S_ISDIR() 目錄文件
S_ISCHR() 字符設備文件
S_ISBLK() 塊設備文件
S_ISFIFO() 有名管道文件
S_ISLNK() 軟連接(符號鏈接)文件
S_ISSOCK() 套接字文件

我們修改上面的例子:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    struct stat buf;
    char * file_mode;
    if(argc != 2) {
        printf("Usage: stat <pathname>\n"); 
        exit(-1); 
    }
    if(stat(argv[1], &buf) != 0) {
        printf("stat error.\n"); 
        exit(-1); 
    }
    if (S_ISREG(buf.st_mode))
        file_mode = "-";
    else if (S_ISDIR(buf.st_mode))
        file_mode = "d";
    else if (S_ISCHR(buf.st_mode))
        file_mode = "c";
    else if(S_ISBLK(buf.st_mode))
        file_mode = "b";
    printf("#i-node:    %ld\n", buf.st_ino);
    printf("#link:      %d\n", buf.st_nlink);
    printf("UID:        %d\n", buf.st_uid);
    printf("GID:        %d\n", buf.st_gid);
    printf("Size        %ld\n", buf.st_size);
    printf("mode: %s\n", file_mode);
    exit(0);
}
文件權限的判定

文件類型與許可設定被一起編碼在st_mode字段中,同上面一樣,我們也需要一組由系統提供的宏來完成解碼。

宏定義 文件類型
S_ISUID 執行時,設置用戶ID
S_ISGID 執行時,設置組ID
S_ISVTX 保存正文
S_IRWXU 擁有者的讀、寫和執行權限
S_IRUSR 擁有者的讀權限
S_IWUSR 擁有者的寫權限
S_IXUSR 擁有者的執行權限
S_IRWXG 用戶組的讀、寫和執行權限
S_IRGRP 用戶組的讀權限
S_IWGRP 用戶組的寫權限
S_IRWXO 其它讀、寫、執行權限
S_IROTH 其它讀權限
S_IWOTH 其它寫權限
S_IXOTH 其它執行權限

目錄操作

當目標是目錄而不是文件的時候,ls -l的結果會顯示目錄下所有子條目的信息,怎么去遍歷整個目錄呢?

打開目錄

需要包含的頭文件:

  • <sys/types.h>
  • <dirent.h>

函數原型:

DIR * opendir(const char * name)

功能:opendir()用來打開參數name指定的目錄,并返回DIR *形態的目錄流
返回值:成功返回目錄流;失敗返回NULL

讀取目錄

函數原型:

struct dirent * readdir(DIR * dir)

功能:readdir()返回參數dir目錄流的下一個子條目(子目錄或子文件)
返回值: 成功返回結構體指向的指針,錯誤或以讀完目錄,返回NULL
函數執行成功返回的結構體原型如下:

struct dirent {
   ino_t   d_ino;
   off_t   d_off;
   unsigned short  d_reclen;
   unsigned char   d_type;
   char    d_name[256];
};

其中 d_name字段,是存放子條目的名稱

關閉目錄

函數原型:

int closedir(DIR * dir)

功能:closedir()關閉dir所指的目錄流
返回值:成功返回0;失敗返回-1,錯誤原因在errno中

我們來學習一個綜合的例子吧:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
int main(int argc, char *argv[])
{
    DIR *dp;
    struct dirent *entp;
    if (argc != 2) {
        printf("usage: showdir dirname\n");
        exit(0);
    }
    if ((dp = opendir(argv[1])) == NULL) {
        perror("opendir");
        exit(-1);
    }
    while ((entp = readdir(dp)) != NULL)
        printf("%s\n", entp->d_name);

    closedir(dp);
    return 0;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容