UNIX文件的信息
stat, fstst, lstat - get file status
1. stat, fstat和lstat
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
-
- int stat(const char *path, struct stat *buf);
- int fstat(int fd, struct stat *buf);
- int lstat(const char *path, struct stat *buf);
stat() stats the file pointed to by path and fills in buf.
lstat() is identical to stat(), except that if path is a sym‐
bolic link, then the link itself is stat-ed, not the file that
it refers to.
fstat() is identical to stat(), except that the file to be
stat-ed is specified by the file descriptor fd.
- 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.used for regular file or symbolic link */
- 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 */
- };
2.文件类型:可以由sys/stat.h中相应宏判断。这些宏基本都是mode和S_IFxx相&得到结果。
(1).普通文件:内核并不区分文本文件还是二进制文件。对普通文件的解释由处理该文件的应用程序进行。由S_ISREG()宏来判断。
(2).目录文件:只有内核才能写目录文件。由S_ISDIR()宏来判断。
(3).块特殊文件:提供对带缓冲的设备的访问。每次访问以固定长度的单位进行。由S_ISCHR()宏来判断。
(4).字特殊文件:提供对不带缓冲的设备的访问。每次访问长度可变。系统中只有这两种设备类型。由S_ISBLK()宏来判断。
(5).FIFO:这种类型文件用于进程间通信,有时候也称为命名管道。由S_ISFIFO()宏来判断。
(6).嵌套字socket:这种文件类型用于进程键的网络通信。也可以用于一台host上进程之间的非网络通信。由S_ISSOCK()宏来判断。
(7).符号链接:这种文件类型指向另一个文件。由S_ISLNK()宏来判断。
POSIX.1允许实现IPC对象表示为文件,同样可以由宏来判断S_TYPEPEISMQ()消息队列,S_TYPEISSEM信号量和S_TYPEISSHM()共享存储。
3. 文件访问权限
stat中的st_uid和st_gid:实际用户ID和实际组ID标识文件究竟属于谁。有效用户ID以及附加组ID决定了我们的文件访问呢权限。通常两者相等,但在文件模式字中设置一个特殊标志:当执行此文件时,其进程的有效用户ID设置为文件所有者的ID(st_uid)。与此类似,设置另一个特殊标志:当执行此文件时,其进程的有效用户组ID设置为文件所有者组的ID(st_gid)。
例如/etc/passwd,/etc/shadow文件所有者是root,只有root才对/etc/passwd,/etc/shadow有写权限。而passwd允许任何一个用户改变自己的密码。因此需要设置passwd的setuid位以保证执行该程序的进程有root权限区更改相关文件。
规则:
(1).open with O_TRUNC必须对文件有写权限。
(2).创建一个文件必须对所在目录有写和执行权限,同样删除一个文件必须对文件的目录有写和执行权限(不需要对该文件有写和执行权限)。
(3).如果对该文件使用任意exec函数,必须对该文件有执行权限外还要保证该文件是一个普通文件。
每次打开,创建和删除一个文件,内核就进行文件访问权限的测试,而这种测试可能涉及文件的所有者,有效ID(有效用户和有效组ID)以及附加组ID(如果支持的话)。内核测试的顺序是:
a).如果进程有效用户ID是0,则允许所有权限。
b).若进程的有效用户ID等于文件的所有者ID,那么根据文件所有者的访问权限来判断。
c).若进程的有效组ID或进程的附加组ID之一等于文件的组ID,那么根据文件所有者组的访问权限来判断。
d).最后根据其他用户的适当访问权限判断。
对于其中任意一步满足(无论权限允许还是拒绝),那么不进行下面的测试。
创建新文件:新文件的用户ID设置为进程的有效用户ID,而组ID可以为以下二者之一:新文件的组ID可以是进程的有效组ID或为所在目录的组ID。(Linux ext2/3可以在mount的时候设置)
4.umask, access, chmod, fchmod, chown, fchown, lchown系统调用:略。注:在linux中只有root才能使用chown指令更改用户ID,但是组ID可以更改为进程的有效组ID(前提是当前进程拥有此文件)。
5.sticky bit:如果一个可执行文件的这一位被设置了,那么该程序第一次执行并结束时,其程序的正文部分(机器指令部分)的一个副本仍被保存在交换区,使得下次执行该程序时能较快地将其装入内存区。交换区占用连续磁盘空间,可将它视为连续文件。而且一个程序的正文部分在交换区也是连续存放的,相比一般的UNIX文件系统,文件的各数据块是随机存放的。所以对于常用的应用程序常常设置它们所在文件的sticky bit。但是对于UNIX系统大多数都配置有虚拟存储系统和快速文件系统不再需要这种技术。
对目录设置sticky bit,则只有对该目录具有写权限的用户在满足下列条件之一的情况下才能删除和更名目录下的文件:拥有此文件,拥有此目录或是超级用户。目录/tmp和/var/spool/uucppublic是设置sticky bit的典型候选者,任何用户都可在这两个目录中创建文件。任一用户对这两个目录的权限通常都是读写执行兼具。但是用户不能删除或者更名属于其他人的文件,为此这两个目录的文件模式都设置了sticky bit。
Reference documentation:
Linux Programmer's Manual STAT(2)
APUE