Unix/Linux编程-文件和目录(一)

文件和目录(一)

4.1 4个stat函数

#include <sys/stat.h>

int  stat(const char *pathname, struct stat *buf);

int  fstat(int fd, struct stat *buf);

int  lstat(const char *pathname, struct stat *buf);

int fstatat(int fd, const char *pathname,struct stat *buf, int flag);

返回值:成功返回0,错处返回-1


(1) stat函数将于此路径名的文件有关信息保存在buf指向的缓冲区中。
(2) fstat函数获取已打开描述符fd上相关信息。
(3) lstat函数返回该符号链接的有关信息,而不是由该符号链接引用的文件的信息。
(4) fstatat函数为一个相对于当前打开目录的路径名返回的文件信息。flag参数控制着是否跟随这一个符号链接。当标志设置为AT_SYMLINK_NOFOLLOW时,则不会跟随符号链接。

4.2 stat结构体

struct stat {

              dev_t     st_dev;     /* ID of device containing file */

              ino_t     st_ino;     /* inode number */

              mode_t    st_mode;    /* protection */

              nlink_t   st_nlink;   /* number of hard links */

              uid_t     st_uid;     /* user ID of owner */

              gid_t     st_gid;     /* group ID of owner */

              dev_t     st_rdev;    /* device ID (if special file) */

              off_t     st_size;    /* total size, in bytes */

              blksize_t st_blksize; /* blocksize for file system I/O */

              blkcnt_t  st_blocks;  /* number of 512B blocks allocated */

              time_t    st_atime;   /* time of last access */

              time_t    st_mtime;   /* time of last modification */

              time_t    st_ctime;   /* time of last status change */

           };


4.3 文件类型

Unix/Linux系统中,文件有7种类型:
(1) 普通文件(regular file)。至于普通文件是文本文件还是二进制数据,对于内核而言没有区别,关键在于解释这个文件的应用程序。
(2) 目录文件(directory file)。这种文件包含了其他文件的名字以及指向与这些文件有关信息的指针。
(3) 块特殊文件(block special file)。这种类型的文件提供对设备带缓冲的访问,每次访问以固定长度为单位进行。
(4) 字符特殊文件(character special file)。这种类型的文件提供对设备不带缓冲的访问,每次访问长度可变。
(5) FIFO。用于进程间通信,也叫管道(pipe)。
(6) 套接字(socket)。这种类型的文件用于进程间的网络通信。
(7) 符号链接(symbolic link)。这种类型的文件指向另一个文件。


文件类型信息保存在stat结构的st_mode成员中,可以使用下面的宏来确定文件类型。

文件类型

S_ISREG()

普通文件

S_ISDIR()

目录文件

S_ISCHR()

字符特殊文件

S_ISBLK()

块特殊文件

S_ISFIFO()

FIFO或管道

S_ISLNK()

符号链接

S_ISSOCK()

套接字

早期的Unix版本并不提供S_ISxxx宏,需要将sd_mode与屏蔽字S_IFMT位与运算,然后与名为S_IFxx的常量进行比较。
#define S_ISDIR (mode)  ( ( (mode)  &  S_IFMT) ) == S_IFDIR)

4.4 文件访问权限

4.4.1 文件的9个访问权限位

stat结构中的成员st_mode值也包含对了文件的访问权限为。每个文件有9个访问权限位:

st_mode屏蔽

含义

S_IRUSR

S_IWUSR

S_IXUSR

用户读

用户写

用户执行

S_IRGRP

S_IWGRP

S_IXGRP

组读

组写

组执行

S_IROTH

S_IWOTH

S_IXOTH

其他读

其他写

其他执行

(1) 目录的读权限和执行权限与普通文件的意义是不同的。对于目录,读权限允许我们获取该目录中所有文件名的列表。当一个目录是我们要访问文件的路径名的一个组成部分时,对该目录的执行权限使我们可通过该目录(也就是搜索该目录,寻找一个特定的文件名)。
(2) 对目录具有写权限和执行权限,才能在目录中创建一个文件。
(3) 如果要删除一个现有文件,必须对包含该文件的目录具有写权限和执行权限,但对该文件本身则不需要读、写权限。

4.4.2 内核文件访问权限测试

进程每次打开、创建或删除一个文件时,内核就进行文件访问权限测试:
(1) 若进程的有效用户ID是0(超级用户),则允许访问。
(2) 若进程的有效用户ID等于文件的所有者ID(也就是进程拥有此文件),那么如果所有者适当的访问权限为被设置,则允许访问,否则拒绝访问。
(3) 若进程的有效组ID或进程的附属组ID之一等于文件的组ID,那么如果适当的访问权限位被设置,则允许访问,否则拒绝访问。
(4) 若其他用户适当的访问权限为被设置,则允许访问,否则拒绝访问。

4.5 access和faccessat函数

当一个进程使用设置用户ID或设置组ID功能作为另一个用户(或组)运行时,希望按其实际用户ID和实际组ID来测试其访问权限,就需要使用access或faccessat函数。

#include <unistd.h>

int  access(const char *pathname, int mode);

int faccessat(int fd, const char *pathname, int mode, int flag);

返回值:成功返回0,错误返回-1

mode参数:

mode

说明

F_OK

测试文件是否存在(access函数)

R_OK

测试读权限

W_OK

测试写权限

X_OK

测试执行权限

flag参数可以用于改变faccessat函数的行为,如果flag设置为AT_EACCESS,访问检查用的是调用进程的有效用户ID和有效组ID,而不是实际用户ID和实际组ID。

4.6 umask函数

#include <sys/stat/h>

mode_t umask(mode_t cmask);

返回值:之前的文件模式创建屏蔽字

umask函数为进程设置文件模式创建屏蔽字,并返回之前的值。
cmask是4.4.1中列出的9个常量中的若干个按位或组成的。

4.7 更改文件访问权限:chmod、fchmod和fchmodat

#include <sys/stat.h>

int  chmod(const char *pathname, mode_t mode);

int  fchmod(int fd, mode_t mode);

int fchmodat(int fd,const char *pathname, mode_t mode,int flag);

返回值:成功返回0,出错返回-1

flag参数可以用于改变fchmodat的行为,当设置了AT_SYMLINK_NOFOLLOW标志时,不会跟随符号链接。为了改变一个文件的权限位,进程的有效用户ID必须等于文件的所有者ID,或者该进程必须具有超级用户权限。
参数mode所示常量的按位或:

mode

说明

S_ISUID

S_ISGID

S_ISVTX

执行时设置用户ID

执行时设置组ID

保存正文(粘着位)

S_IRWXU

S_IRUSR

S_IWUSR

S_IXUSR

用户读写执行

用户读

用户写

用户执行

S_IRWXG

S_IRGRP

S_IWGRP

S_IXGRP

组读写执行

组读

组写

组执行

S_IRWXO

S_IROTH

S_IWOTH

S_IXOTH

其他读写执行

其他读

其他写

其他执行

如果我们只想修改其中的某些权限位,先调用stat获得当前权限,然后修改他。

猜你喜欢

转载自blog.csdn.net/water_3700348/article/details/78259763