C4 文件和目錄:APUE 筆記

C4: 文件和目錄

  本章主要討論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   };

 1 函數stat、fstat、fstatat、lstat

  獲取文件屬性,頭文件 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返回文件名相關的文件屬性
  •   fstat返回文件描述符相關的文件屬性
  •   lastat與符號連接有關,若是輸入參數文件名是一個文件連接,則返回符號連接的信息,而非文件信息
  •   fstatat爲相對一個打開目錄,flag參數控制是否跟隨一個符號連接

2 文件類型

  對應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)函數

 3 設置用戶ID和組ID

  注意,此爲進程屬性。測試

  一般,進程的有效用戶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.*/

4 文件訪問權限

   stat結構的st_mode也包含了文件的訪問權限。文件都有9個訪問權限位,stat.h中定義爲9個宏,以下圖:

  上圖前3行,用戶指文件全部者。用u表示用戶,g表示組,o表示其餘,與chmod命令保持一致。

  文件權限規則:

  •   執行權限:名字路徑中的任一目錄,包括它可能隱含的當前工做目錄都應有執行權限。其中,目錄讀權限指的是訪問目錄內容(讀目錄文件列表),目錄執行權限指的是搜索(經過該目錄)
  •   讀權限:是否可以打開文件進行讀操做
  •   寫權限:是否可以打開文件進行寫操做。若是open中對一個文件制定O_TRUNK,則必須對該文件具備寫權限
  •   如需建立一個新文件,則必須對文件所在目錄具備寫權限和執行權限
  •   如需刪除一個文件,則必須對文件所在目錄具備寫權限和執行權限,對文件自己不須要有讀寫權限

  文件有擁有者ID  st_uid和擁有者組ID st_gid,此爲文件屬性。

  進程有有效ID和組ID。

  訪問文件時,兩組ID進行判斷,以爲進程是否擁有文件使用權。規則爲:

  •   若進程的有效用戶ID是0(超級用戶),則容許訪問
  •   若進程的有效ID等於文件全部者ID,則容許訪問
  •   若進程的組ID等於文件全部者組ID,則容許訪問
  •   其餘用戶的訪問權限位被設置,則容許訪問,不然拒絕

  建立新文件時

  •   新文件的用戶ID設置爲進程有效用戶ID
  •   新文件的組ID能夠設置爲進程的有效組ID,或者是所在目錄的組ID,依賴系統

5 函數access和faccessat

  按照進程實際用戶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。

6 函數umask

  爲進程設置文件模式建立屏蔽字,並返回以前的值。頭文件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按位或運算得來。

7 函數chmod、fchmod、fchmodat

  更改現有文件的訪問權限,頭文件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是下圖所示常量的按位或。

8 函數chown、fchown、fchownat、lchown

  用於改變文件的用戶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不變。

9 文件長度

  stat結構成員st_size表示以字節爲單位的文件長度,此字段對普通文件、目錄文件、符號連接有效。

10 函數truncate文件截斷

  能夠改變文件長度,頭文件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;

 

11 函數link、linkat、unlink、unlinkat、remove

  建立一個指向現有文件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,能夠保證臨時文件在程序奔潰時也能夠被刪除。

 

12 函數rename、renameat

  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;

 

13 符號連接

  符號連接比i節點的連接更加靈活,有如下兩個緣由:

  •  i節點連接一般要求連接和文件在同一文件系統
  •  一般只有超級用戶才能建立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;

 

 

14 文件時間

  stat結構有3個時間:

  • struct timespec st_atim; /* Time of last access. */            文件訪問時間
  • struct timespec st_mtim; /* Time of last modification. */   文件修改時間,指的是文件內容被修改
  • struct timespec st_ctim; /* Time of last status change. */    i節點狀態變動時間,節點最後修改時間,如訪問權限、用戶ID、連接數等

  文件訪問時間和修改時間能夠用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數組參數的第一個元素包含訪問時間,第二個參數包含修改時間。

  •   若是times是空指針,則設置訪問時間和修改時間爲當前時間
  •   若是times數組的任一元素tv_nsec爲UTIME_NOW,則忽略tv_sec字段,時間戳設置爲當前時間
  •   若是times數組的任一元素tv_nsec爲UTIME_OMIT,則忽略tv_sec字段,時間戳保持不變
  •   若是times數組的任一元素tv_nsec不是UTIME_OMIT和TIME_NOW,則設置時間戳爲tv_sec和tv_nsec

 

15 目錄操做:建立、刪除、讀取、切換

  使用函數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));

 

  注意:

  •   建立目錄至少應該指定一個執行權限位
  •   rmdir只能刪除空目錄

  對某一目錄具備訪問權限的任一用戶均可以讀目錄,可是隻有內核才能夠寫目錄。目錄操做頭文件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;
相關文章
相關標籤/搜索