C4: 文件和目录

  本章主要讨论stat函数及其返回信息,通过修改stat结构字段,了解文件属性。

  struct stat结构定义如下:

 struct stat
{
__dev_t st_dev; /* Device. */
#ifndef __x86_64__
unsigned short int __pad1;
#endif
#if defined __x86_64__ || !defined __USE_FILE_OFFSET64
__ino_t st_ino; /* File serial number. */
#else
__ino_t __st_ino; /* 32bit file serial number. */
#endif
#ifndef __x86_64__
__mode_t st_mode; /* File mode. */
__nlink_t st_nlink; /* Link count. */
#else
__nlink_t st_nlink; /* Link count. */
__mode_t st_mode; /* File mode. */
#endif
__uid_t st_uid; /* User ID of the file's owner. */
__gid_t st_gid; /* Group ID of the file's group.*/
#ifdef __x86_64__
int __pad0;
#endif
__dev_t st_rdev; /* Device number, if device. */
#ifndef __x86_64__
unsigned short int __pad2;
#endif
#if defined __x86_64__ || !defined __USE_FILE_OFFSET64
__off_t st_size; /* Size of file, in bytes. */
#else
__off64_t st_size; /* Size of file, in bytes. */
#endif
__blksize_t st_blksize; /* Optimal block size for I/O. */
#if defined __x86_64__ || !defined __USE_FILE_OFFSET64
__blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */
#else
__blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
#endif
#ifdef __USE_XOPEN2K8
/* Nanosecond resolution timestamps are stored in a format
equivalent to 'struct timespec'. This is the type used
whenever possible but the Unix namespace rules do not allow the
identifier 'timespec' to appear in the <sys/stat.h> header.
Therefore we have to handle the use of this header in strictly
standard-compliant sources special. */
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. */
# define st_atime st_atim.tv_sec /* Backward compatibility. */
# define st_mtime st_mtim.tv_sec
# define st_ctime st_ctim.tv_sec
#else
__time_t st_atime; /* Time of last access. */
__syscall_ulong_t st_atimensec; /* Nscecs of last access. */
__time_t st_mtime; /* Time of last modification. */
__syscall_ulong_t st_mtimensec; /* Nsecs of last modification. */
__time_t st_ctime; /* Time of last status change. */
__syscall_ulong_t st_ctimensec; /* Nsecs of last status change. */
#endif
#ifdef __x86_64__
__syscall_slong_t __glibc_reserved[];
#else
# ifndef __USE_FILE_OFFSET64
unsigned long int __glibc_reserved4;
unsigned long int __glibc_reserved5;
# else
__ino64_t st_ino; /* File serial number. */
# endif
#endif
};

1 函数stat、fstat、fstatat、lstat

  获取文件属性,头文件 sys/stat.h。成功返回0,失败返回-1。

 /* Get file attributes for FILE and put them in BUF.  */
extern int stat (const char *__restrict __file,
struct stat *__restrict __buf) __THROW __nonnull ((, )); /* Get file attributes for the file, device, pipe, or socket
that file descriptor FD is open on and put them in BUF. */
extern int fstat (int __fd, struct stat *__buf) __THROW __nonnull (()); /* Get file attributes about FILE and put them in BUF.
If FILE is a symbolic link, do not follow it. */
extern int lstat (const char *__restrict __file,
struct stat *__restrict __buf) __THROW __nonnull ((, )); /* Similar to stat, get the attributes for FILE and put them in BUF.
Relative path names are interpreted relative to FD unless FD is
AT_FDCWD. */
# ifndef __USE_FILE_OFFSET64
extern int fstatat (int __fd, const char *__restrict __file,
struct stat *__restrict __buf, int __flag)
__THROW __nonnull ((, ));

  以上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

 /* Test for access to NAME using the real UID and real GID.  */
extern int access (const char *__name, int __type) __THROW __nonnull (()); /* Test for access to FILE relative to the directory FD is open on.
If AT_EACCESS is set in FLAG, then use effective IDs like `eaccess',
otherwise use real IDs like `access'. */
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,返回之前的文件屏蔽字

 /* Set the file creation mask of the current process to MASK,
and return the old creation mask. */ extern __mode_t umask (__mode_t __mask) __THROW;

  参数mask为表4-4按位或运算得来。

7 函数chmod、fchmod、fchmodat

  更改现有文件的访问权限,头文件sys/stat.h。成功返回0,失败返回-1。

 /* Set file access permissions for FILE to MODE.
If FILE is a symbolic link, this affects its target instead. */
extern int chmod (const char *__file, __mode_t __mode)
__THROW __nonnull (()); /* Set file access permissions of the file FD is open on to MODE. */
#if defined __USE_POSIX199309 || defined __USE_XOPEN_EXTENDED
extern int fchmod (int __fd, __mode_t __mode) __THROW;
#endif /* Set file access permissions of FILE relative to
the directory FD is open on. */
extern int fchmodat (int __fd, const char *__file, __mode_t __mode,
int __flag)
__THROW __nonnull (()) __wur;

  参数mode是下图所示常量的按位或。

8 函数chown、fchown、fchownat、lchown

  用于改变文件的用户ID和组ID,头文件 unistd.h。成功返回0,失败返回-1。

 /* Change the owner and group of FILE.  */
extern int chown (const char *__file, __uid_t __owner, __gid_t __group)
__THROW __nonnull (()) __wur; /* Change the owner and group of the file that FD is open on. */
extern int fchown (int __fd, __uid_t __owner, __gid_t __group) __THROW __wur; /* Change the owner and group of FILE relative to the directory FD is open
on. */
extern int fchownat (int __fd, const char *__file, __uid_t __owner,
__gid_t __group, int __flag)
__THROW __nonnull (()) __wur; /* Change owner and group of FILE, if it is a symbolic
link the ownership of the symbolic link is changed. */
extern int lchown (const char *__file, __uid_t __owner, __gid_t __group)
__THROW __nonnull (()) __wur;

  如果两个参数中任意一个是-1,则对于ID不变。

9 文件长度

  stat结构成员st_size表示以字节为单位的文件长度,此字段对普通文件、目录文件、符号链接有效。

10 函数truncate文件截断

  可以改变文件长度,头文件unistd.h。成功返回0,失败返回-1。

 /* Truncate FILE to LENGTH bytes.  */
# ifndef __USE_FILE_OFFSET64
extern int truncate (const char *__file, __off_t __length)
__THROW __nonnull (()) __wur;

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

  创建一个指向现有文件i节点的链接,头文件unistd.h。成功返回0,失败返回-1。

  这种链接方式,直接指向文件i节点,使得文件i节点上的链接计数__nlink_t st_nlink; /* Link count. */增加。

 /* Make a link to FROM named TO.  */
extern int link (const char *__from, const char *__to) __THROW __nonnull ((, )) __wur; /* Like link but relative paths in TO and FROM are interpreted relative
to FROMFD and TOFD respectively. */
extern int linkat (int __fromfd, const char *__from, int __tofd, const char *__to, int __flags)
__THROW __nonnull ((, )) __wu  

  unlink可以删除一个现有目录项,将所引文件的链接计数减1。成功返回0,失败返回-1。

 /* Remove the link NAME.  */
extern int unlink (const char *__name) __THROW __nonnull (()); /* Remove the link NAME relative to FD. */
extern int unlinkat (int __fd, const char *__name, int __flag)
__THROW __nonnull (());

  只有文件的链接计数达到0,文件的内容才可以被删除。

  如果unlinkat的参数flag被设置为AT_REMOVEDIR时,unlinkat函数可以类似rmdir一样删除目录。

  remove函数解除对一个文件或者目录的链接,头文件stdio.h。成功返回0,失败返回-1。

  对于文件,remove的功能与unlink类似。对于目录,remove的功能与rmdir类似。

 /* Remove file FILENAME.  */

 extern int remove (const char *__filename) __THROW;

  open\creat创建新临时文件后,立即调用unlink,可以保证临时文件在程序奔溃时也可以被删除。

12 函数rename、renameat

  rename、renameat可用于对文件或者目录重命名,头文件stdio.h。成功返回0,失败返回-1。

 /* Rename file OLD to NEW.  */
extern int rename (const char *__old, const char *__new) __THROW; /* Rename file OLD relative to OLDFD to NEW relative to NEWFD. */
extern int renameat (int __oldfd, const char *__old, int __newfd, const char *__new) __THROW;

13 符号链接

  符号链接比i节点的链接更加灵活,有以下两个原因:

  •  i节点链接通常要求链接和文件在同一文件系统
  •  通常只有超级用户才能创建i节点的链接  

  可以用symlink或symlinkat函数创建一个符号链接,头文件unistd.h。成功返回0,失败返回-1。

 /* Make a symbolic link to FROM named TO.  */
extern int symlink (const char *__from, const char *__to)
__THROW __nonnull ((, )) __wur; /* Like symlink but a relative path in TO is interpreted relative to TOFD. */
extern int symlinkat (const char *__from, int __tofd,
const char *__to) __THROW __nonnull ((, )) __wur;

  函数创建一个指向from文件路径的新目录项to。

  由于open方法访问符号链接时,将访问到符号链接引用的文件。为了访问符号链接本身,需要使用readlink和readlinkat函数,头文件unistd.h。成功返回读取的字节数,失败返回-1。

 /* Read the contents of the symbolic link PATH into no more than
LEN bytes of BUF. The contents are not null-terminated.
Returns the number of characters read, or -1 for errors. */
extern ssize_t readlink (const char *__restrict __path,
char *__restrict __buf, size_t __len)
__THROW __nonnull ((, )) __wur; /* Like readlink but a relative PATH is interpreted relative to FD. */
extern ssize_t readlinkat (int __fd, const char *__restrict __path,
char *__restrict __buf, size_t __len)
__THROW __nonnull ((, )) __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。

 /* Set file access and modification times of the file associated with FD.  */
extern int futimens (int __fd, const struct timespec __times[]) __THROW; /* Set file access and modification times relative to directory file
descriptor. */
extern int utimensat (int __fd, const char *__path, const struct timespec __times[], int __flags) __THROW __nonnull (());

  timespec结构定义为:

 struct timespec
{
__time_t tv_sec; /* Seconds. */
__syscall_slong_t tv_nsec; /* Nanoseconds. */
};

  函数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。

 /* Create a new directory named PATH, with permission bits MODE.  */
extern int mkdir (const char *__path, __mode_t __mode)
__THROW __nonnull (()); /* Like mkdir, create a new directory with permission bits MODE. But
interpret relative PATH names relative to the directory associated
with FD. */
extern int mkdirat (int __fd, const char *__path, __mode_t __mode)
__THROW __nonnull (()); /* Remove the directory PATH. */
extern int rmdir (const char *__path) __THROW __nonnull (());

  注意:

  •   创建目录至少应该指定一个执行权限位
  •   rmdir只能删除空目录

  对某一目录具有访问权限的任一用户都可以读目录,但是只有内核才可以写目录。目录操作头文件dirent.h。

 /* Open a directory stream on NAME.
Return a DIR stream on the directory, or NULL if it could not be opened.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern DIR *opendir (const char *__name) __nonnull (()); /* Same as opendir, but open the stream on the file descriptor FD.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern DIR *fdopendir (int __fd); /* Read a directory entry from DIRP. Return a pointer to a `struct
dirent' describing the entry, or NULL for EOF or error. The
storage returned may be overwritten by a later readdir call on the
same DIR stream.
If the Large File Support API is selected we have to use the
appropriate interface.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern struct dirent *readdir (DIR *__dirp) __nonnull (()); /* Rewind DIRP to the beginning of the directory. */
extern void rewinddir (DIR *__dirp) __THROW __nonnull (()); /* Close the directory stream DIRP.
Return 0 if successful, -1 if not.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern int closedir (DIR *__dirp) __nonnull (()); /* Return the current position of DIRP. */
extern long int telldir (DIR *__dirp) __THROW __nonnull (()); /* Seek to position POS on DIRP. */
extern void seekdir (DIR *__dirp, long int __pos) __THROW __nonnull (());

  每个进程都有一个初始工作目录。起始目录是登录名的属性,而当前工作目录是进程的属性。

  使用chdir可以切换当前工作目录,头文件unistd.h。成功返回0,失败返回-1。

 /* Change the process's working directory to PATH.  */
extern int chdir (const char *__path) __THROW __nonnull (()) __wur; /* Change the process's working directory to the one FD is open on. */
extern int fchdir (int __fd) __THROW __wur;

  使用getcwd可以获取当前工作目录,头文件unistd.h。成功返回0,失败返回-1。

 /* Get the pathname of the current working directory,
and put it in SIZE bytes of BUF. Returns NULL if the
directory couldn't be determined or SIZE was too small.
If successful, returns BUF. In GNU, if BUF is NULL,
an array is allocated with `malloc'; the array is SIZE
bytes long, unless SIZE == 0, in which case it is as
big as necessary. */
extern char *getcwd (char *__buf, size_t __size) __THROW __wur;

C4 文件和目录:APUE 笔记的更多相关文章

  1. linux文件权限目录配置笔记

    ###linux 文件权限目录配置笔记 ---------- 多人多任务环境 linux 一般将文件可存取的身份分为三个类别:owner group others Permission deny ls ...

  2. linux文件与目录管理笔记

    ### Linux文件与目录管理 ---------- 绝对路径: / 相对路径:不以/开头的 当前目录 . 上一个工作目录 - 用户主目录 ~ root账户的主目录是/root 其他用户是/home ...

  3. C3 文件IO:APUE 笔记

    C3:文件IO 1 引言 本章描述的函数被成为不带缓冲的IO,涉及5个函数:open.read.write.lseek.close. 文件控制:dup.sync.fsync.fdatasync.fcn ...

  4. apue学习笔记(第四章 文件和目录)

    本章将描述文件系统的其他特性和文件的性质. 函数stat.fstat.fstatat和lstat #include <sys/stat.h> int stat(const char *re ...

  5. APUE 学习笔记(三) 文件和目录

    1. 文件类型 文件类型信息包含在 struct stat 里的 st_mode 成员 (1)普通文件,unix内核并不区分文本文件和二进制文件 (2)目录文件,这种文件包含了其他文件的名字以及指向这 ...

  6. APUE学习笔记3——文件和目录

    1 简介 之前学习了执行I/O操作的基本函数,主要是围绕普通文件I/O的打开.读或写.下面继续学习Unix文件系统的其他特征和文件的基本性质.我们将从stat函数开始,了解stat结构所代表的文件属性 ...

  7. 《UNIX环境高级编程》(APUE) 笔记第四章 - 文件和目录

    4 - 文件和目录 1. 函数 stat.fstat.fstatat 和 lstat #inlcude <sys/stat.h> int stat(const char *restrict ...

  8. emacs 新手笔记(四) —— 使用 dired 完成一些简单的文件和目录操作

    ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287 据说熟悉了 dired,就可以在 emacs 下轻松管理文件和目录了,甚至不再需要 shell 和桌面操作. ...

  9. (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

随机推荐

  1. Python(并发编程进程)

    并发编程 二.多进程 要让Python程序实现多进程(multiprocessing),我们先了解操作系统的相关知识. Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊.普通的函 ...

  2. OCR技术浅探:特征提取(1)

    研究背景 关于光学字符识别(Optical Character Recognition, 下面都简称OCR),是指将图像上的文字转化为计算机可编辑的文字内容,众多的研究人员对相关的技术研究已久,也有不 ...

  3. HTTP中的header头解析说明

    HTTP的头信息比较多,这里根据实际例子作出说明.下面图片是访问 http://kccdzz.com 的一个HTTP请求的header信息,可以看出Headers主要分为Response Header ...

  4. Git添加本地项目出现fatal: unable to get credential storage lock: File exists

    把本地项目初始化之后上传到github上出现问题:fatal: unable to get credential storage lock: File exists 解决办法:是因为我上传用的git帐 ...

  5. TQ2440系统介绍入门 、linux系统目录结构

    TQ2440开发板系统安装步骤: 1.先用JTAG线安装BIOS到开发板.下载BIOS,NOR/NAND开关选在NOR位置. 2.linux安装步骤: (1).格式化分区 (2).安装BIOS---& ...

  6. Boinformatics-2018-10-1-目录

    1.基因分析 --Using standard microbiome reference groups to simplify beta-diversity analyses and facilita ...

  7. windows批处理初学贴出一些命令

    在cmd窗口中复制时,右键选标记,然后再选择此时选择区域就变白了.然后要么直接拖到要粘贴的地方,要么直接按回车存到剪贴板里. 1.循环导入文件夹下面的文件到数据库中 cd /d D:/Program ...

  8. css图片上悬浮文字(丝带效果)实现

    首先看效果 思路:1.去掉“丝带“菱角使用的是overflow: hidden; 2.通过z-index降低图片的优先级或者调高“丝带”优先级来实现覆盖效果(z-index需要写在有position的 ...

  9. 数据库连接池libzdb

    官网:http://www.tildeslash.com/libzdb/ A small, easy to use Open Source Database Connection Pool Libra ...

  10. Django-RestFrameWork之分页 视图 路由 渲染器

    目录 一.分页 二.视图 三.路由 四.渲染器 一.分页 试问如果当数据量特别大的时候,你是怎么解决分页的? 方式a.记录当前访问页数的数据id 方式b.最多显示120页等 方式c.只显示上一页,下一 ...