作者:下家山
如何确定即将访问的文件是否有访问权限
怎么知道那个rwx属于u,哪个属于g,那个属于o?
所以,第一个属于u【usr】,第二个属于g【group】,第三个属于o【other】
问题:如果没有交互界面如何通过程序代码检查某个文件的访问权限?
access():判断是否具有存取文件的权限
相关函数
stat,open,chmod,chown,setuid,setgid
表头文件
#include
定义函数
int access(const char * pathname, int mode);
函数说明
access()会检查是否可以读/写某一已存在的文件。
参数mode有几种情况组合, R_OK,W_OK,X_OK 和F_OK。R_OK,W_OK与X_OK用来检查文件是否具有读取、写入和执行的权限。F_OK则是用来判断该文件是否存在。由于access()只作权限的核查,并不理会文件形态或文件内容,因此,如果一目录表示为“可写入”,表示可以在该目录中建立新文件等操作,而非意味此目录可以被当做文件处理。例如,你会发现DOS的文件都具有“可执行”权限,但用execve()执行时则会失败。
返回值
若所有欲查核的权限都通过了检查则返回0值,表示成功,只要有一权限被禁止则返回-1。
错误代码
EACCESS 参数pathname 所指定的文件不符合所要求测试的权限。
EROFS 欲测试写入权限的文件存在于只读文件系统内。
EFAULT 参数pathname指针超出可存取内存空间。
EINVAL 参数mode 不正确。
ENAMETOOLONG 参数pathname太长。
ENOTDIR 参数pathname为一目录。
ENOMEM 核心内存不足
ELOOP 参数pathname有过多符号连接问题。
EIO I/O 存取错误。
附加说明
使用access()作用户认证方面的判断要特别小心,例如在access()后再做open()的空文件可能会造成系统安全上的问题。
执行结果
答案是u
ln【小写的l,不是大写的i】
链接有两种:
一种被称为硬链接(Hard Link);硬链接ln ** **,没有参数-s, 它会在你选定的位置上生成一个和源文件大小相同的文件;
另外一种被称为符号链接(Symbol link),也叫软链接。
建立硬链接时,链接文件和被链接文件必须位于同一个文件系统中,并且不能建立指向目录的硬链接。而对于符号链接,则不存在这个问题。默认情况下,ln产生硬链接。
Ln -s src_file file_ln
练习:用touch建立一个文件www,然后用echo把1234567890重定向到www,再建立一个www的软连接和硬链接,做删除原文件,追加原文件内容的实验,看软硬连接的变化
2.4.1 函数原型:
执行结果:
【ctrl+D】结束cat > test
int stat(const char *restrict pathname, struct stat *restrict buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *restrict pathname, struct stat *restrict buf);
#include
#include
4.3 功能
int stat(const char *restrict pathname, struct stat *restrict buf);
提供文件名字,获取文件对应属性。感觉一般是文件没有打开的时候这样操作。
int fstat(int filedes, struct stat *buf);
通过文件描述符获取文件对应的属性。文件打开后这样操作
int lstat(const char *restrict pathname, struct stat *restrict buf);
连接文件
第一个参数:
文件路径或文件描述符【pathname&filedes】
给定一个pathname,stat函数返回一个与此命名文件有关的信息结构,fstat函数获得已在描述符filedes上打开的文件的有关信息。lstat函数类似于stat,但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息。
第二个参数:
是个指针,它指向一个描述相关文件详细信息的结构。这些函数填写由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; //伟建内容对应的块数量
};
可以通过上面提供的函数,返回一个结构体,保存着文件的信息。
4.5 返回值
三个函数的返回:若成功则为0,若出错则为-1
错误代码:
ENOENT 参数file_name指定的文件不存在
ENOTDIR 路径中的目录存在但却非真正的目录
ELOOP 欲打开的文件有过多符号连接问题,上限为16符号连接
EFAULT 参数buf为无效指针,指向无法存在的内存空间
EACCESS 存取文件时被拒绝
ENOMEM 核心内存不足
ENAMETOOLONG 参数file_name的路径名称太长
stat结构中最常用到的属性是st_mode(文件的类型及文件的访问权限)、st_nlink(硬链接数,表示有几个链接到该文件上)、st_uid、st_gid、st_size(以字节为单位的文件长度,只对普通文件、目录文件和符号连接有意义)、st_atime、st_mtime、st_ctime。
我们曾一再提到Unix系统中一切皆可视为文件,不过细而化之的话又可以分为多种类型,那么在程序中如何去对文件类型进行判别呢?这就需要用到下表中所示的一些宏:
宏
作用
S_ISREG()
测试是否为普通文件,不是返回0
S_ISDIR()
#define S_ISDIR(m) (((m) & 0170000) == (0040000))
测试是否为目录文件
S_ISCHR()
测试是否为字符特殊文件
S_ISBLK()
测试是否为块特殊文件
S_ISFIFO()
测试是否为FIFO文件
S_ISLNK()
测试是否为链接文件
S_ISSOCK()
测试是否为socket文件
S_ISUID()
测试是否设置了“设置-用户-ID”位
S_ISGID()
测试是否设置了“设置-组-ID”位
运行结果
为什么?
执行结果
检查到了链接文件