本章主要討論stat函數及其返回信息,經過修改stat結構字段,瞭解文件屬性。數組
struct stat結構定義以下:網絡
1 struct stat 2 { 3 __dev_t st_dev; /* Device. */ 4 #ifndef __x86_64__ 5 unsigned short int __pad1; 6 #endif 7 #if defined __x86_64__ || !defined __USE_FILE_OFFSET64 8 __ino_t st_ino; /* File serial number. */ 9 #else 10 __ino_t __st_ino; /* 32bit file serial number. */ 11 #endif 12 #ifndef __x86_64__ 13 __mode_t st_mode; /* File mode. */ 14 __nlink_t st_nlink; /* Link count. */ 15 #else 16 __nlink_t st_nlink; /* Link count. */ 17 __mode_t st_mode; /* File mode. */ 18 #endif 19 __uid_t st_uid; /* User ID of the file's owner. */ 20 __gid_t st_gid; /* Group ID of the file's group.*/ 21 #ifdef __x86_64__ 22 int __pad0; 23 #endif 24 __dev_t st_rdev; /* Device number, if device. */ 25 #ifndef __x86_64__ 26 unsigned short int __pad2; 27 #endif 28 #if defined __x86_64__ || !defined __USE_FILE_OFFSET64 29 __off_t st_size; /* Size of file, in bytes. */ 30 #else 31 __off64_t st_size; /* Size of file, in bytes. */ 32 #endif 33 __blksize_t st_blksize; /* Optimal block size for I/O. */ 34 #if defined __x86_64__ || !defined __USE_FILE_OFFSET64 35 __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ 36 #else 37 __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ 38 #endif 39 #ifdef __USE_XOPEN2K8 40 /* Nanosecond resolution timestamps are stored in a format 41 equivalent to 'struct timespec'. This is the type used 42 whenever possible but the Unix namespace rules do not allow the 43 identifier 'timespec' to appear in the <sys/stat.h> header. 44 Therefore we have to handle the use of this header in strictly 45 standard-compliant sources special. */ 46 struct timespec st_atim; /* Time of last access. */ 47 struct timespec st_mtim; /* Time of last modification. */ 48 struct timespec st_ctim; /* Time of last status change. */ 49 # define st_atime st_atim.tv_sec /* Backward compatibility. */ 50 # define st_mtime st_mtim.tv_sec 51 # define st_ctime st_ctim.tv_sec 52 #else 53 __time_t st_atime; /* Time of last access. */ 54 __syscall_ulong_t st_atimensec; /* Nscecs of last access. */ 55 __time_t st_mtime; /* Time of last modification. */ 56 __syscall_ulong_t st_mtimensec; /* Nsecs of last modification. */ 57 __time_t st_ctime; /* Time of last status change. */ 58 __syscall_ulong_t st_ctimensec; /* Nsecs of last status change. */ 59 #endif 60 #ifdef __x86_64__ 61 __syscall_slong_t __glibc_reserved[3]; 62 #else 63 # ifndef __USE_FILE_OFFSET64 64 unsigned long int __glibc_reserved4; 65 unsigned long int __glibc_reserved5; 66 # else 67 __ino64_t st_ino; /* File serial number. */ 68 # endif 69 #endif 70 };
獲取文件屬性,頭文件 sys/stat.h。成功返回0,失敗返回-1。app
1 /* Get file attributes for FILE and put them in BUF. */ 2 extern int stat (const char *__restrict __file, 3 struct stat *__restrict __buf) __THROW __nonnull ((1, 2)); 4 5 /* Get file attributes for the file, device, pipe, or socket 6 that file descriptor FD is open on and put them in BUF. */ 7 extern int fstat (int __fd, struct stat *__buf) __THROW __nonnull ((2)); 8 9 /* Get file attributes about FILE and put them in BUF. 10 If FILE is a symbolic link, do not follow it. */ 11 extern int lstat (const char *__restrict __file, 12 struct stat *__restrict __buf) __THROW __nonnull ((1, 2)); 13 14 /* Similar to stat, get the attributes for FILE and put them in BUF. 15 Relative path names are interpreted relative to FD unless FD is 16 AT_FDCWD. */ 17 # ifndef __USE_FILE_OFFSET64 18 extern int fstatat (int __fd, const char *__restrict __file, 19 struct stat *__restrict __buf, int __flag) 20 __THROW __nonnull ((2, 3));
以上4個函數區別:less
對應stat結構的字段 __mode_t st_mode; /* File mode. */socket
UNIX的文件類型有如下幾種:ide
類型 | 類型識別宏 | 釋義 |
普通文件 | S_ISREG() | 文本或者二進制文件 |
目錄文件 | S_ISDIR() | 目錄 |
塊特殊文件 | S_ISBLK() | 此類型文件提供對設備帶緩衝的訪問 |
字符特殊文件 | S_ISCHR() | 此類型文件提供對設備不帶緩衝的訪問 |
FIFO | S_ISFIFO() | 進程間通訊,也稱管道 |
套接字 | S_ISSOCK() | 網絡通訊 |
符號連接 | S_ISLINK() | 此類型文件指向另外一個文件 |
用法爲S_ISREG(stat.st_mode)函數
注意,此爲進程屬性。測試
一般,進程的有效用戶ID就是實際用戶ID,有效組ID就是實際組ID。stat中的兩個ID是文件擁有者ID和組IDui
19 __uid_t st_uid; /* User ID of the file's owner. */ this
20 __gid_t st_gid; /* Group ID of the file's group.*/
stat結構的st_mode也包含了文件的訪問權限。文件都有9個訪問權限位,stat.h中定義爲9個宏,以下圖:
上圖前3行,用戶指文件全部者。用u表示用戶,g表示組,o表示其餘,與chmod命令保持一致。
文件權限規則:
文件有擁有者ID st_uid和擁有者組ID st_gid,此爲文件屬性。
進程有有效ID和組ID。
訪問文件時,兩組ID進行判斷,以爲進程是否擁有文件使用權。規則爲:
建立新文件時
按照進程實際用戶ID和實際組ID進行訪問權限測試文件權限,頭文件 unistd.h。成功返回0,失敗返回-1
1 /* Test for access to NAME using the real UID and real GID. */ 2 extern int access (const char *__name, int __type) __THROW __nonnull ((1)); 3 4 /* Test for access to FILE relative to the directory FD is open on. 5 If AT_EACCESS is set in FLAG, then use effective IDs like `eaccess', 6 otherwise use real IDs like `access'. */ 7 extern int faccessat (int __fd, const char *__file, int __type, int __flag)
操做類型爲:
操做類型 | 說明 |
F_OK | 測試文件是否存在 |
R_OK | 測試讀權限 |
W_OK | 測試寫權限 |
X_OK | 測試執行權限 |
faccessat函數,若是flag設置爲AT_EACCESS,訪問檢查用的是調用有效用戶ID和有效組ID,而不是實際用戶ID和實際組ID。
爲進程設置文件模式建立屏蔽字,並返回以前的值。頭文件sys/stat.h,返回以前的文件屏蔽字
1 /* Set the file creation mask of the current process to MASK, 2 and return the old creation mask. */ 3 4 extern __mode_t umask (__mode_t __mask) __THROW;
參數mask爲表4-4按位或運算得來。
更改現有文件的訪問權限,頭文件sys/stat.h。成功返回0,失敗返回-1。
1 /* Set file access permissions for FILE to MODE. 2 If FILE is a symbolic link, this affects its target instead. */ 3 extern int chmod (const char *__file, __mode_t __mode) 4 __THROW __nonnull ((1)); 5 6 /* Set file access permissions of the file FD is open on to MODE. */ 7 #if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED 8 extern int fchmod (int __fd, __mode_t __mode) __THROW; 9 #endif 10 11 /* Set file access permissions of FILE relative to 12 the directory FD is open on. */ 13 extern int fchmodat (int __fd, const char *__file, __mode_t __mode, 14 int __flag) 15 __THROW __nonnull ((2)) __wur;
參數mode是下圖所示常量的按位或。
用於改變文件的用戶ID和組ID,頭文件 unistd.h。成功返回0,失敗返回-1。
1 /* Change the owner and group of FILE. */ 2 extern int chown (const char *__file, __uid_t __owner, __gid_t __group) 3 __THROW __nonnull ((1)) __wur; 4 5 /* Change the owner and group of the file that FD is open on. */ 6 extern int fchown (int __fd, __uid_t __owner, __gid_t __group) __THROW __wur; 7 8 /* Change the owner and group of FILE relative to the directory FD is open 9 on. */ 10 extern int fchownat (int __fd, const char *__file, __uid_t __owner, 11 __gid_t __group, int __flag) 12 __THROW __nonnull ((2)) __wur; 13 14 /* Change owner and group of FILE, if it is a symbolic 15 link the ownership of the symbolic link is changed. */ 16 extern int lchown (const char *__file, __uid_t __owner, __gid_t __group) 17 __THROW __nonnull ((1)) __wur;
若是兩個參數中任意一個是-1,則對於ID不變。
stat結構成員st_size表示以字節爲單位的文件長度,此字段對普通文件、目錄文件、符號連接有效。
能夠改變文件長度,頭文件unistd.h。成功返回0,失敗返回-1。
1 /* Truncate FILE to LENGTH bytes. */ 2 # ifndef __USE_FILE_OFFSET64 3 extern int truncate (const char *__file, __off_t __length) 4 __THROW __nonnull ((1)) __wur;
建立一個指向現有文件i節點的連接,頭文件unistd.h。成功返回0,失敗返回-1。
這種連接方式,直接指向文件i節點,使得文件i節點上的連接計數__nlink_t st_nlink; /* Link count. */增長。
1 /* Make a link to FROM named TO. */ 2 extern int link (const char *__from, const char *__to) __THROW __nonnull ((1, 2)) __wur; 3 4 /* Like link but relative paths in TO and FROM are interpreted relative 5 to FROMFD and TOFD respectively. */ 6 extern int linkat (int __fromfd, const char *__from, int __tofd, const char *__to, int __flags) 7 __THROW __nonnull ((2, 4)) __wu
unlink能夠刪除一個現有目錄項,將所引文件的連接計數減1。成功返回0,失敗返回-1。
1 /* Remove the link NAME. */ 2 extern int unlink (const char *__name) __THROW __nonnull ((1)); 3 4 /* Remove the link NAME relative to FD. */ 5 extern int unlinkat (int __fd, const char *__name, int __flag) 6 __THROW __nonnull ((2));
只有文件的連接計數達到0,文件的內容才能夠被刪除。
若是unlinkat的參數flag被設置爲AT_REMOVEDIR時,unlinkat函數能夠相似rmdir同樣刪除目錄。
remove函數解除對一個文件或者目錄的連接,頭文件stdio.h。成功返回0,失敗返回-1。
對於文件,remove的功能與unlink相似。對於目錄,remove的功能與rmdir相似。
1 /* Remove file FILENAME. */ 2 3 extern int remove (const char *__filename) __THROW;
open\creat建立新臨時文件後,當即調用unlink,能夠保證臨時文件在程序奔潰時也能夠被刪除。
rename、renameat可用於對文件或者目錄重命名,頭文件stdio.h。成功返回0,失敗返回-1。
1 /* Rename file OLD to NEW. */ 2 extern int rename (const char *__old, const char *__new) __THROW; 3 4 /* Rename file OLD relative to OLDFD to NEW relative to NEWFD. */ 5 extern int renameat (int __oldfd, const char *__old, int __newfd, const char *__new) __THROW;
符號連接比i節點的連接更加靈活,有如下兩個緣由:
能夠用symlink或symlinkat函數建立一個符號連接,頭文件unistd.h。成功返回0,失敗返回-1。
1 /* Make a symbolic link to FROM named TO. */ 2 extern int symlink (const char *__from, const char *__to) 3 __THROW __nonnull ((1, 2)) __wur; 4 5 /* Like symlink but a relative path in TO is interpreted relative to TOFD. */ 6 extern int symlinkat (const char *__from, int __tofd, 7 const char *__to) __THROW __nonnull ((1, 3)) __wur;
函數建立一個指向from文件路徑的新目錄項to。
因爲open方法訪問符號連接時,將訪問到符號連接引用的文件。爲了訪問符號連接自己,須要使用readlink和readlinkat函數,頭文件unistd.h。成功返回讀取的字節數,失敗返回-1。
1 /* Read the contents of the symbolic link PATH into no more than 2 LEN bytes of BUF. The contents are not null-terminated. 3 Returns the number of characters read, or -1 for errors. */ 4 extern ssize_t readlink (const char *__restrict __path, 5 char *__restrict __buf, size_t __len) 6 __THROW __nonnull ((1, 2)) __wur; 7 8 /* Like readlink but a relative PATH is interpreted relative to FD. */ 9 extern ssize_t readlinkat (int __fd, const char *__restrict __path, 10 char *__restrict __buf, size_t __len) 11 __THROW __nonnull ((2, 3)) __wur;
stat結構有3個時間:
文件訪問時間和修改時間能夠用futimens和utimensat函數更改,頭文件sys/stat.h。成功返回0,失敗返回-1。
1 /* Set file access and modification times of the file associated with FD. */ 2 extern int futimens (int __fd, const struct timespec __times[2]) __THROW; 3 4 /* Set file access and modification times relative to directory file 5 descriptor. */ 6 extern int utimensat (int __fd, const char *__path, const struct timespec __times[2], int __flags) __THROW __nonnull ((2));
timespec結構定義爲:
1 struct timespec 2 { 3 __time_t tv_sec; /* Seconds. */ 4 __syscall_slong_t tv_nsec; /* Nanoseconds. */ 5 };
函數futimens數組參數的第一個元素包含訪問時間,第二個參數包含修改時間。
使用函數mkdir、mkdirat、rmdir能夠建立或者刪除目錄,頭文件sys/stat.h。成功返回0,失敗返回-1。
1 /* Create a new directory named PATH, with permission bits MODE. */ 2 extern int mkdir (const char *__path, __mode_t __mode) 3 __THROW __nonnull ((1)); 4 5 /* Like mkdir, create a new directory with permission bits MODE. But 6 interpret relative PATH names relative to the directory associated 7 with FD. */ 8 extern int mkdirat (int __fd, const char *__path, __mode_t __mode) 9 __THROW __nonnull ((2)); 10 11 /* Remove the directory PATH. */ 12 extern int rmdir (const char *__path) __THROW __nonnull ((1));
注意:
對某一目錄具備訪問權限的任一用戶均可以讀目錄,可是隻有內核才能夠寫目錄。目錄操做頭文件dirent.h。
1 /* Open a directory stream on NAME. 2 Return a DIR stream on the directory, or NULL if it could not be opened. 3 This function is a possible cancellation point and therefore not 4 marked with __THROW. */ 5 extern DIR *opendir (const char *__name) __nonnull ((1)); 6 7 8 /* Same as opendir, but open the stream on the file descriptor FD. 9 This function is a possible cancellation point and therefore not 10 marked with __THROW. */ 11 extern DIR *fdopendir (int __fd); 12 13 14 /* Read a directory entry from DIRP. Return a pointer to a `struct 15 dirent' describing the entry, or NULL for EOF or error. The 16 storage returned may be overwritten by a later readdir call on the 17 same DIR stream. 18 If the Large File Support API is selected we have to use the 19 appropriate interface. 20 This function is a possible cancellation point and therefore not 21 marked with __THROW. */ 22 extern struct dirent *readdir (DIR *__dirp) __nonnull ((1)); 23 24 25 /* Rewind DIRP to the beginning of the directory. */ 26 extern void rewinddir (DIR *__dirp) __THROW __nonnull ((1)); 27 28 29 /* Close the directory stream DIRP. 30 Return 0 if successful, -1 if not. 31 This function is a possible cancellation point and therefore not 32 marked with __THROW. */ 33 extern int closedir (DIR *__dirp) __nonnull ((1)); 34 35 36 /* Return the current position of DIRP. */ 37 extern long int telldir (DIR *__dirp) __THROW __nonnull ((1)); 38 39 40 /* Seek to position POS on DIRP. */ 41 extern void seekdir (DIR *__dirp, long int __pos) __THROW __nonnull ((1));
每一個進程都有一個初始工做目錄。起始目錄是登陸名的屬性,而當前工做目錄是進程的屬性。
使用chdir能夠切換當前工做目錄,頭文件unistd.h。成功返回0,失敗返回-1。
1 /* Change the process's working directory to PATH. */ 2 extern int chdir (const char *__path) __THROW __nonnull ((1)) __wur; 3 4 /* Change the process's working directory to the one FD is open on. */ 5 extern int fchdir (int __fd) __THROW __wur;
使用getcwd能夠獲取當前工做目錄,頭文件unistd.h。成功返回0,失敗返回-1。
1 /* Get the pathname of the current working directory, 2 and put it in SIZE bytes of BUF. Returns NULL if the 3 directory couldn't be determined or SIZE was too small. 4 If successful, returns BUF. In GNU, if BUF is NULL, 5 an array is allocated with `malloc'; the array is SIZE 6 bytes long, unless SIZE == 0, in which case it is as 7 big as necessary. */ 8 extern char *getcwd (char *__buf, size_t __size) __THROW __wur;