zoukankan      html  css  js  c++  java
  • 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。

     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个函数区别:

    •   stat返回文件名相关的文件属性
    •   fstat返回文件描述符相关的文件属性
    •   lastat与符号链接有关,如果输入参数文件名是一个文件链接,则返回符号链接的信息,而非文件信息
    •   fstatat为相对一个打开目录,flag参数控制是否跟随一个符号链接

    2 文件类型

      对应stat结构的字段 __mode_t  st_mode; /* File mode. */

      UNIX的文件类型有以下几种:

    类型  类型识别宏 释义
    普通文件 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和组ID

      19 __uid_t st_uid; /* User ID of the file's owner. */

      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;

      opencreat创建新临时文件后,立即调用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;
  • 相关阅读:
    select在各个浏览器中的兼容性问题
    pc打开手机站提示切换为手机屏幕
    图片预加载
    div盒子水平垂直居中的方法
    如何检测该浏览器为微信浏览器
    小箭头的写法,z-index在ie7显示混乱问题
    微信a标签不跳转
    css font简写规则
    windows环境cmd下执行jar
    docker制作镜像步骤
  • 原文地址:https://www.cnblogs.com/hgwang/p/9617863.html
Copyright © 2011-2022 走看看