一:文件相关属性
stat,lstat,fstat1 函数都是获取文件(普通文件,目录,管道,socket,字符,块()的属性。函数原型#include <sys/stat.h>
#include <sys/stat.h>
int stat(constchar *restrict pathname, struct stat *restrict buf);提供文件名字,获取文件对应属性。
int fstat(intfiledes, struct stat *buf);通过文件描述符获取文件对应的属性。
int lstat(constchar *restrict pathname, struct stat *restrict buf);连接文件描述命,获取文件属性,当文件是一个符号链接时返回该符号链接的有关信息,而不是由该符号链接引用的文件的信息。
文件对应的属性
struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //伟建内容对应的块数量
};
二.文件相关权限
和一个进程相关的ID有:
1)实际用户ID 实际组ID : 标识空间我们是谁, 登录时取自口令文件登录项,登录会话期间一直不变,超级用户可改变
2)有效用户ID 有效组ID : 决定了我们的文件访问权限,也就是用来测试本进程对某些文件的访问权限
3)保存的设置用户ID,设置组ID: 执行一个程序时包含了有效用户ID 和有效组ID的副本
ps: 通常 有效用户ID等于实际用户ID,有效组ID等于实际组ID ,当执行一个文件时, 如果文件设置了设置用户ID位或设置用户组ID位 即SUID SGID 则情况不同
文件模式字中的设置用户ID:当执行此文件时,将进程的有效用户ID设置为文件所有者的用户ID;
文件模式字中的设置组ID:当执行此文件是,将进程的有效组ID设置为此文件的组所有者ID,
列如:若文件的所有者是超级用户,而且设置了该文件的设置用户ID, 当其他用户进程执行此文件程序时,则该进程具体有超级用户特权,而管执行此文件的用户ID是谁,UNIX中的passwd就是一个列子;
进程每次打开文件时, 内核进行的访问权限测试:
1) 如果进程的有效用户ID是0(超级用户), 则允许访问
2) 若进程有效用户ID等于文件所有者ID, 则根据文件所有者所设置的权限访问
3) 如进程的有效组ID或进程的附加组ID之一等于文件的组ID(即文件的实际组ID) , 那么进程对文件的权限为文件所有组所设置的权限
4) 若其他用户适当权限被设置 则进程此文件的权限为文件的其他访问权限
从上面可以看出,内核对进程文件的权限测试主要是针对 进程的有效用户ID来进行测试的, 也就是说, 如果有效用户ID 等于文件所有者ID 那么我(打开文件的进程) 就是文件的所有者 拥有文件所有者所拥有的权限, 如果不是文件的所有者 就再测试进程有效组ID...
三.新文件和新目录的所有权
1. 新文件的用户ID设置成进程的有效用户ID
2. 新文件的组ID两种情况:
(1) 新文件的组ID是进程的有效组ID
(2) 如果新文件的组ID所在目录的设置组ID位 设置了的话, 新文件的组ID将设为目录的组ID (这设置组ID位这里的作用与权限测试的时候有点类似)
3. 其他:
(1). mkdir 函数自动的传递了目录的设置组ID位
(2) access 函数是用实际用户ID和实际组ID来进行访问权限的测试的, 如果你只想测试下实际用户所拥有的权限 ,就可以使用这个函数了。
umask 函数: 为进程设置文件模式创建屏蔽字
#include <sys/stat.h>
mode_t umask(mode_t cmask);(返回以前的文件模式创建屏蔽字, 少数几个没有出错返回的函数)
文件创建屏蔽字:在进程创建一个新文件或新目录时,就一定会使用文件模式创建屏蔽字,open, creat函数的mode参数即指定新文件的访问权限位。
实例:创建两个文件,创建第一个时,umask值为0,创建第二个是,umask值禁止所有组合其他用户的访问权限;
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
int main(void)
{
umask(0);
if(creat("foo", RWRWRW) < 0)
{
printf("creat error:%s\n", strerror(errno));
exit(1);
}
umask(S_IWGRP|S_IRGRP|S_IROTH|S_IWOTH);
if(creat("bar", RWRWRW) < 0)
{
printf("creat error:%s\n", strerror(errno));
exit(1);
}
exit(0);
}
执行效果:
四.文件的其他操作
chmo,fchmod 函数:更改现有文件的访问权限:
#include <sys/stat.h>
int chmod(const char *pathname, mode_tmode);
int fchmod(int fileds, mode_t mode);(成功返回0, 出错返回-1)
chmod在指定的文件上操作,fchmod在已打开的文件进行操作
chown, fchown, lchown函数:更改文件用户ID和组ID
int chown(const char *pathname, uid_towner, gid_t group);
int fchown(int filedse, uid_t, owner,gid_t group);
int lchown(const char* pathname, uid_towner, gid_t group);
三个函数成功返回0, 出错返回-1;
link,symlink函数:创建一个指向现有文件的链接;
#include <unistd.h>
int link(const char*existpath, const char* newpath);
创建了一个指向existpath的硬链接newpath
int symlink(const char*actualpath, const char* sympath);
创建了一个指向actualpath的符号连接 sympathy
两个函数成功返回0, 出错返回-1
硬链接和符号连接:
1) 硬链接直接指向文件的i节点,符号链接指向一个文件的间接指针
2) 硬链接通常要求链接和文件位于同一个文件系统中
3) 只有超级用户才呢过创建指向目录的硬链接