#include
//成功返回0,失败返回-1.
int stat(const char *restrict pathname, struct stat *restrict buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *restrict pathname, struct stat *restrict buf);
int fstatat(const char *restrict pathname, struct stat *restrict buf, int flag);
【1】
【1】UNIX常用几种文件类型:
(1)普通文件(regular file)
(2)目录文件(directory file):包含其他文件名字和指向 这些文件相关信息 的指针。
(3)块特殊文件(block special file):提供对设备带缓冲的访问,每次以固定长度为单位进行。
(4)字符特殊文件(character special file):提供对设备不带缓冲的访问,每次进行长度可变。
(5)套接字(socket):用于进程之间的网络通信或同一宿主机上进程的非网络通信。
(7)符号链接(symbolic link):指向另一文件。
【2】文件类型包含在stat结构的st_mode成员中,可用宏确认文件类型:
【3】一般直接用lstat,因为stat无法观察到符号链接。
【1】所有类型的文件都有访问权限(而不是只有普通文件)。
【2】每个文件有9个访问权限位,可以分成3类:
st_mode屏蔽 | 屏蔽位 | 含义 |
---|---|---|
S_IRWXU | 0700 | 用户读写执行 |
S_IRUSR | 0400 | 用户读 |
S_IWUSR | 0200 | 用户写 |
S_IXUSR | 0100 | 用户执行 |
S_IRWXG | 0070 | 组读写执行 |
S_IRGRP | 0040 | 组读 |
S_IWGRP | 0020 | 组写 |
S_IXGRP | 0010 | 组执行 |
S_IRWXO | 0007 | 其他读写执行 |
S_IROTH | 0004 | 其他读 |
S_IWOTH | 0002 | 其他写 |
S_IXOTH | 0001 | 其他执行 |
【3】用户指文件所有者(owner)。
【4】打开文件夹中的文件需要对当前文件夹有执行权限。
【5】为了在open函数对一个文件指定O_TRUNC标志,必须对该文件有写权限。
【6】为了创建新文件和删除文件,必须对对应目录有些权限和执行权限,而不需要对文件有权限。
【7】所有者ID是文件的性质,进程的有效ID和附属组ID是进程的性质。每次打开、创建和删除文件时,内核会以组的有效ID和有效组ID为基础对文件访问权限测试,过程如下:
①若进程的有效用户ID是0(超级用户),允许;
②若进程的有效用户ID等于文件的所有者ID(即进程拥有此文件),若所有者适当的访问权限位被设置(读操作则用户读应为1,写操作则用户写应为1,执行文件则用户执行位应为1),则允许访问。
③进程有效组ID或进程附属组ID之一等于文件的组ID,若组适当的访问权限位被设置,则允许访问。
④其他用户适当的访问权限位被设置,则允许访问。
【8】文件访问权限就是 st_mode 位图中的低 9 位。
大家都知道,在 Linux 系统中文件的权限分为 3 个组:文件属主权限、文件属组权限、其它用户权限,而每个组又分为 4 种权限:读取®、写入(w)、执行(x)、无权(-)。
所以在使用 ls(1) -l 命令时可以得到类似 -rwx-r-xr-x 的权限标志,这个标志就是这样来的。
【1】新文件的组ID取决于它所在的目录的设置组ID位是否被设置。若设置,则新文件的组ID取决于目录的组ID,否则为进程的有效组ID。
【1】有时进程也希望按其实际用户ID和实际组ID来测试其访问能力。access和faccessat函数就是按实际用户ID和实际组ID进行访问权限测试的(测试过程与4【6】相同,仅仅是将有效换成实际)。
#include
//成功返回0,失败返回-1
int access(const char *pathname, int mode);
int faccessat(int fd, const char *pathname, int mode, int flag);
【2】
mode | 说明 |
---|---|
F_OK | 测试文件是否存在 |
R_OK | 测试读权限 |
W_OK | 测试写权限 |
X_OK | 测试执行权限 |
【3】在pathnome为绝对路径 或者 fd取值为AT_FDCWD而pathname参数为相对路径 情况下,两个函数是相同的。 否则,faccessat计算相对于(fd参数指向的)打开目录的pathname。
【4】flag用来改变faccessat的行为。若为AT_EACCESS则检查用有效ID而非实际ID。
【5】chmod u+s [文件名],为文件增加用户(u)写(s)权限。
#include
【1】参数cmask是由4-6列出的9个常量中的若干个或构成,open和creat的mode参数也如此。可以用按位或运算符指定多个模式:
st_mode屏蔽 | 屏蔽位 | 含义 |
---|---|---|
S_IRWXU | 0700 | 用户读写执行 |
S_IRUSR | 0400 | 用户读 |
S_IWUSR | 0200 | 用户写 |
S_IXUSR | 0100 | 用户执行 |
S_IRWXG | 0070 | 组读写执行 |
S_IRGRP | 0040 | 组读 |
S_IWGRP | 0020 | 组写 |
S_IXGRP | 0010 | 组执行 |
S_IRWXO | 0007 | 其他读写执行 |
S_IROTH | 0004 | 其他读 |
S_IWOTH | 0002 | 其他写 |
S_IXOTH | 0001 | 其他执行 |
【2】cmask中的权限会被关闭;
【3】最终权限为 mode & ~umask。
【4】umask 值越大,权限越低。
这三个函数使我们可以更改先有文件的访问权限
#include
//成功返回0,失败返回-1
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);
【1】chmod对指定文件进行操作
【2】fchmod对已打开的文件进行操作
【3】当pathname为绝对路径或fd取值为AT_FDCWD而pathname为相对路径时,fchmodat与chmod相同,否则fchmodat计算相对于(fd指向的)打开目录的pathname。
【4】当flag为AT_SYMLINK_NOFOLLOW时,fchmodat不跟随符号链接。
【5】进程的邮箱用户ID必须等于文件的所有者ID或拥有超级用户权限,才可以改变文件权限位。
【6】mode的文件访问权限位比4-6多6个,如下:
st_mode屏蔽 | 屏蔽位 | 含义 |
---|---|---|
S_ISUID | 执行时设置用户ID | |
S_ISGID | 执行时设置组ID | |
S_ISVTX | 保存正文(粘着位) | |
S_IRWXU | 0700 | 用户读写执行 |
S_IRUSR | 0400 | 用户读 |
S_IWUSR | 0200 | 用户写 |
S_IXUSR | 0100 | 用户执行 |
S_IRWXG | 0070 | 组读写执行 |
S_IRGRP | 0040 | 组读 |
S_IWGRP | 0020 | 组写 |
S_IXGRP | 0010 | 组执行 |
S_IRWXO | 0007 | 其他读写执行 |
S_IROTH | 0004 | 其他读 |
S_IWOTH | 0002 | 其他写 |
S_IXOTH | 0001 | 其他执行 |
举例使用:
if(stat("foo", &statbuf)<0)
err_sys("stat error for foo")
//打开执行时设置组ID且关闭组执行
if(chmod("foo", (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0)
err_sys("chmod error for foo“)
【7】解释S_ISUID和S_ISGID: 默认情况下创建目录/文件时, 使用当前进程的gid 来设置目录和文件的属主,例如有目录/opt/tmp 其属组(不是属主) 为wwwgroup, 用户user1 对这个目录有写权限.
有进程以user1为EUID, group1 为EGUID运行, 在/opt/tmp/ 目录下创建了目录 dir1
则/opt/tmp/dir1 在默认情况下属组为group1
如果/opt/tmp 目录S_ISGID置位, 则上例中, 创建出来的目录/opt/tmp/dir1 属组为wwwgroup, 且S_ISGID 被置位.
以下函数用于更改文件的用户ID和组ID。函数之间的区别与之前基本相同,按照fun、ffun、ffunat、lfun规律。
#include
int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int fd, uid owner, gid_t group);
int fchownat(int fd, const char *pathname, uid owner, gid_t group)
int lchown(onst char *pathname, uid_t owner, gid_t group);
【1】只能超级用户进程使用,普通用户不仅无法修改别人文件的所有者,也无权修改自己文件的所有者。(不确定?)
【1】stat结构中st_size以字节为单位,只对普通文件、目录文件和符号链接有意义。
【2】目录一般是一个数的整数倍,符号链接是文件名的实际字节数(如usr/lib为7)
【3】空洞是设置的偏移量超过文件尾端并写入数据造成的,文件长度依然是正常值(du -s查看),但显示所使用磁盘空间总量会较大(ls -l查看)。若实际程序复制这个文件,则空洞会被填满。