linux stat函式(獲取檔案詳細資訊)
阿新 • • 發佈:2019-02-06
函式原型 #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); 類似於stat.但是當命名的檔案是一個符號連結時,lstat返回該符號連結的有關資訊,而不是由該符號連結引用檔案 函式說明: 通過檔名filename獲取檔案資訊,並儲存在buf所指的結構體stat中返回值: 執行成功則返回0,失敗返回-1,錯誤程式碼存於errno 第二個引數是個指標,它指向一個我們應提供的結構。這些函式填寫由buf指向的結構。 該結構的實際定義可能所實施而有所不同,但其基本形式是:
struct stat { dev_t st_dev; //檔案的裝置編號 ino_t st_ino; //節點 mode_t st_mode; //檔案的型別和存取的許可權 nlink_t st_nlink; //連到該檔案的硬連線數目,剛建立的檔案值為1 uid_t st_uid; //使用者ID gid_t st_gid; //組ID dev_t st_rdev; //(裝置型別)若此檔案為裝置檔案,則為其裝置編號 off_t st_size; //檔案位元組數(檔案大小) unsigned long st_blksize; //塊大小(檔案系統的I/O 緩衝區大小) unsigned long st_blocks; //塊數 time_t st_atime; //最後一次訪問時間 time_t st_mtime; //最後一次修改時間 time_t st_ctime; //最後一次改變時間(指屬性) };
st_mode 則定義了下列數種情況:
S_IFMT 0170000 檔案型別的位遮罩 S_IFSOCK 0140000 scoket S_IFLNK 0120000 符號連線 S_IFREG 0100000 一般檔案 S_IFBLK 0060000 區塊裝置 S_IFDIR 0040000 目錄 S_IFCHR 0020000 字元裝置 S_IFIFO 0010000 先進先出 S_ISUID 04000 檔案的(set user-id on execution)位 S_ISGID 02000 檔案的(set group-id on execution)位 S_ISVTX 01000 檔案的sticky位 S_IRUSR(S_IREAD) 00400 檔案所有者具可讀取許可權 S_IWUSR(S_IWRITE)00200 檔案所有者具可寫入許可權 S_IXUSR(S_IEXEC) 00100 檔案所有者具可執行許可權 S_IRGRP 00040 使用者組具可讀取許可權 S_IWGRP 00020 使用者組具可寫入許可權 S_IXGRP 00010 使用者組具可執行許可權 S_IROTH 00004 其他使用者具可讀取許可權 S_IWOTH 00002 其他使用者具可寫入許可權 S_IXOTH 00001 其他使用者具可執行許可權
上述的檔案型別在POSIX中定義了檢查這些型別的巨集定義:
S_ISLNK (st_mode) 判斷是否為符號連線 S_ISREG (st_mode) 是否為一般檔案 S_ISDIR (st_mode) 是否為目錄 S_ISCHR (st_mode) 是否為字元裝置檔案 S_ISBLK (s3e) 是否為先進先出 S_ISSOCK (st_mode) 是否為socket
若一目錄具有sticky位(S_ISVTX),則表示在此目錄下的檔案只能被該檔案所有者、此目錄所有者或root來刪除或改名。
錯誤程式碼:
ENOENT 引數file_name指定的檔案不存在 ENOTDIR 路徑中的目錄存在但卻非真正的目錄 ELOOP 欲開啟的檔案有過多符號連線問題,上限為16符號連線 EFAULT 引數buf為無效指標,指向無法存在的記憶體空間 EACCESS 存取檔案時被拒絕 ENOMEM 核心記憶體不足 ENAMETOOLONG 引數file_name的路徑名稱太長
示例程式:
//============================================================================ // Name : stat.cpp // Author : Mars // Version : // Copyright : Your copyright notice // Description : //============================================================================ #include <stdio.h> #include <sys/types.h> #include <pwd.h> #include <sys/stat.h> #include <dirent.h> #include <time.h> #include <grp.h> #include <string.h> #include <unistd.h> bool get_file_info_stat(const char *file_name, char *line,struct stat *s_buff) { char date[16]; char mode[11] = "----------"; line[0]='\0'; struct passwd * pass_info = getpwuid(s_buff->st_uid); //通過使用者的uid查詢使用者的passwd資料 if(pass_info!=NULL) { //依引數gid指定的組識別碼逐一搜索組檔案,找到時便將該組的資料以group結構返回 struct group * group_info = getgrgid(s_buff->st_gid); if(group_info!=NULL) { int b_mask = s_buff->st_mode & S_IFMT; if(b_mask == S_IFDIR) { mode[0]='d'; } else if(b_mask == S_IFREG){ mode[0]='-'; } else { return false; } mode[1] = (s_buff->st_mode & S_IRUSR)?'r':'-'; mode[2] = (s_buff->st_mode & S_IWUSR)?'w':'-'; mode[3] = (s_buff->st_mode & S_IXUSR)?'x':'-'; mode[4] = (s_buff->st_mode & S_IRGRP)?'r':'-'; mode[5] = (s_buff->st_mode & S_IWGRP)?'w':'-'; mode[6] = (s_buff->st_mode & S_IXGRP)?'x':'-'; mode[7] = (s_buff->st_mode & S_IROTH)?'r':'-'; mode[8] = (s_buff->st_mode & S_IWOTH)?'w':'-'; mode[9] = (s_buff->st_mode & S_IXOTH)?'x':'-'; strftime(date,13,"%b %d %H:%M",localtime(&(s_buff->st_mtime))); sprintf(line,"%s %3d %-4s %-4s %8d %12s %s\n",mode,s_buff->st_nlink,pass_info->pw_name,group_info->gr_name,s_buff->st_size,date,file_name); return true; } } return false; } bool is_special_dir(const char *dir) { if(dir==NULL) return true; int len = strlen(dir); if(len>2) return false; if(dir[0]!='.') return false; if(len==1) return true; if(dir[1]=='.') return true; return false; } bool get_file_info(const char *file_name, char *line) { if(line==NULL) return false; struct stat s_buff; if(is_special_dir(file_name)) return false; int status = stat(file_name,&s_buff); //獲取檔案對應屬性 if(status==0) { return get_file_info_stat(file_name,line,&s_buff); } return false; } int main(int argc, char** argv) { char line[300]; char path[128] = {'\0'}; getcwd(path, 128); //獲取當前工作路徑 DIR* dir = opendir(path); //開啟目錄控制代碼 if(dir == NULL){ printf("opendir failed!"); return 1; } while(1) { struct dirent *d_next = readdir(dir); //讀取目錄 if(d_next==NULL) break; line[0]='\0'; if(get_file_info(d_next->d_name,line)) { printf("%s",line); } } }