只说安卓5.0以上:
faccessat&access:(判断文件使用权限的函数)
调用open函数时,是以有效用户而不是实际用户的身份去验证进程对要打开的文件的读写权限。但是有时候我们想知道的是实际用户而非有效用户对某一文件的权限,此时就要用到access函数。
函数原型:int access(const char* pathname, int mode);
int faccessat(int fd, const char* pathname, int mode, int flag);
所需库:#include<unistd.h>
返回值:如果文件具有指定的访问权限,则函数返回0;如果文件不存在或者不能访问指定的权限,则返回-1。
先说简单的access函数,pathname是文件的路径名+文件名,指定要测试的文件;mode则指明测试哪种权限,实际上有4种:
F_OK 值为0,判断文件是否存在
R_OK 值为4,判断对文件是否有读权限
W_OK 值为2,判断对文件是否有写权限
X_OK 值为1,判断对文件是否有读写权限
对于后三种情况,可以用“或”的方法将多种情况合在一起测试,比如R_OK | W_OK就代表测试进程对文件的读写权限。
对于faccessat函数,其用fd来指定目录,mode的含义不变,而flag可以指定是判断有效用户的权限还是实际用户的权限。
如果flag的值是AF_EACCESS(值为0x200)的话,判断的是有效用户的权限;
如果flag的值是0的话,则跟access一样,判断的是实际用户的权限。
当判断有权限时,返回0,否则返回-1.
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
void err_sys(char *);
void err_sys(char *err_txt)
{
printf("%s\n",err_txt);
exit(1);
}
int main(int argc, char* argv[])
{
// access 以实际用户ID测试进程的访问权限
printf("euid = %d,egid = %d,uid = %d, gid = %d\n",geteuid(), getegid(), getuid(), getgid());
if (argc != 2)
err_sys("you should input: %s file_name\n",argv[0]);
//判断实际用户的权限
if(access(argv[1], R_OK | W_OK) < 0)
printf("access error for RW!\n");
else
printf("access OK for RW!\n");
//以有效用户身份打开文件
if(open(argv[1], O_RDWR) < 0)
printf("open error for RW");
else
printf("open ok for RW");
return 0;
}
__openat&open:
(打开文件的函数,__openat类似open)
#include <fcntl.h>
int open(const char *path, int oflag, mode_t mode);
int openat(int fd, const char *path, int oflag, mode_t mode );
相同点:
当传给函数的路径名是绝对路径时,二者无区别.(openat()自动忽略第一个参数fd)
不同点:
当传给函数的是相对路径时,如果openat()函数的第一个参数fd是常量AT_FDCWD时,则其后的第二个参数路径名是以当前工作目录为基址的;否则以fd指定的目录文件描述符为基址。
目录文件描述符的取得通常分为两步,先用opendir()函数获得对应的DIR结构的目录指针,再使用int dirfd(DIR*)函数将其转换成目录描述符,此时就可以作为openat()函数的第一个参数使用了。
使用方法:
1,打开采用绝对路径表示的文件/home/leon/test.c,如果文件不存在就创建它。
下面是两种函数写法
fd = open("/home/leon/test.c", O_RDWR | O_CREAT, 0640);
fd = openat(anything, "/home/leon/test.c", O_RDWR | O_CREAT, 0640);
2,打开采用相对路径表示的文件
fd = open("./test.c", O_RDWR | O_CREAT, 0640);
fd = openat( AT_FDCWD, O_RDWR | O_CREAT, 0640);
chmod&fchmod&fchmodat
(修改权限等函数)
chmod、fchmod和fchmodat这3个函数使我们可以更改现有文件的访问权限。函数的原型为:
#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);
chmod函数在指定的文件上进行操作,而fchmod函数则对已打开的文件进行操作。
fchmodat函数与chmod函数在下面两种情况下是相同的:
一种是pathname参数为绝对路径,另一种是fd参数取值为AT_FDCWD而pathname参数为相对路径。否则,fchmodat计算相对于目录(由fd参数指向)的pathname。flag参数可以用于改变fchmodat的行为,
当设置了AT_SYMLINK_NOFOLLOW标志时,fchmodat并不会跟随符号链接。为了改变一个文件的权限位,进程的有效用
户ID必须等于文件的所有者ID,或者该进程必须具有超级用户权限。
stat&fstat&fstatat&lstat&fstatfs64
#include <sys/stat.h>
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(int fd,const char *restrict pathname,struct stat *restrict buf,int flag);
给出pathname,stat函数将返回与此命名文件有关的信息结构。fstat函数获得在描述符fd上打开的有关信息。
lstat返回该符号链接的有关信息,而不是由该符号链接引用的文件的信息。fstatat函数为一个相对于当前打开目录(由fd参数指向)的路径名返回文件统计信息,flag参数控制着是否跟随着一个符号链接。当AT_SYMLINK_N
OFOLLOW标志被设置时,fstatat不会跟随符号链接,而是返回符号链接本身的信息。否则,在默认情况下,返回的是符号链接所指向的实际文件的信息。如果fd参数的值是AT_FDCWD,并且pathname参数是一个相对路径名,fstatat会计算相对于当前目录的pathname参数。如果pathname是一个绝对路径,fd参数就会被忽略。这两种情况下
,根据flag的取值,fstatat的作用就跟stat或lstat一样。第2个参数buf是一个指针,它指向一个必须提供的结构。函数来填充由buf指向的结构。
rename&renameat
文件或目录可以用rename函数或者renameat函数进行重命名。
两个函数的返回值:若成功,返回0;若出错,返回-1.
#include <stdio.h>
int rename(const char * oldname, const char * newname);
int renameat(int oldfd, const char *oldname, int newfd, const char *newpath);
区别不大参数不同而已
mkdir&mkdirat
这两个函数创建一个新的空目录。其中 . 和 . . 目录是自动创建的。
mkdirat函数与mkdir函数类似。当fd参数具有特殊值AT_FDCWD或者pathname参数指定了绝对路径时,mkdir和mkdirat完全一样。
mknodat
(mknod的一个子函数,创建文件的)
函数类型为
int mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev);
truncate
(文件截断,用于截断文件的size字节大小,截断之后 size 后面的所有字符被删除。)
函数原型
int truncate(const char *path,off_t length);
int ftruncate(int fd,off_t length);
link&linkat
(文件创建一个新名字,其实可以理解为创建了一个新的文件项【即inode】(文件名不同),指向了与之前的文件相同的数据块(内容相同)。)
readlinkat
#include <unistd.h>
ssize_t readlink(const char *path, char *buf, size_t bufsiz);
eadlink()会将参数path的符号链接内容存储到参数buf所指的内存空间,返回的内容不是以\000作字符串结尾,但会将字符串的字符数返回,这使得添加\000变得简单。若参数bufsiz小于符号连接的内容长度,过长的内容会被截断,如果 readlink 第一个参数指向一个文件而不是符号链接时,readlink 设 置errno 为 EINVAL 并返回 -1。 readlink()函数组合了open()、read()和close()的所有操作。
返回值 :执行成功则返回字符串的字符数,失败返回-1, 错误代码存于errno
执行成功则返回ssize_t
错误代码:
EACCESS 取文件时被拒绝,权限不够
EINVAL 参数bufsiz为负数
EIO O存取错误
ELOOP 欲打开的文件有过多符号连接问题
ENAMETOOLONG 参数path的路径名称太长
ENOENT 参数path所指定的文件不存在
ENOMEM 核心内存不足
ENOTDIR 参数path路径中的目录存在但却非真正的目录
参考:
https://www.cnblogs.com/zhangjiansheng/p/8430080.html
https://blog.csdn.net/liangzc1124/article/details/83475246
https://www.cnblogs.com/XNQC1314/p/9241415.html
https://blog.csdn.net/Spring__Rider/article/details/80753824
https://blog.csdn.net/The_perfect_world/article/details/89310891
https://www.cnblogs.com/xxswkl/p/10848274.html
网友评论