4.7 函数access和faccessat

当一个进程使用了设置用户ID和设置组ID作为另一个用户(或者组)运行时,这时候有效用户(组)ID和实际用户(组)ID不一样,但进程仍然希望测试实际用户(组)ID的访问能力。这时候就可以使用access和faccessat。测试步骤同4.5节一样,但将有效改为实际

#include <unistd.h>
int access(const char *pathname,int mode);
int faccessat(int fd,const char*pathname,int mode,int flag);
//两个函数的返回值:若成功烦怒I0;若出错,返回-1

其中,如果测试文件是否已经存在,mode就为F_OK;否则mode是图4-7中所列常量的按位或。

flag参数可以用于改变faccessat的行为,如果flag设置为AT_EACCESS,访问检查用的是调用进程的有效用户ID和有效组ID,而不是实际用户ID和实际组ID。

4.8 函数umask

umask函数为进程设置文件模式创建屏蔽字,并返回之前的值。

#include <sys/stat.h>
mode_t umask(mode_t cmask);

其中,参数cmask是由图4-6中列出的9个常量中的若干个按位"或“构成的。

在文件模式创建屏蔽字中为1的位,在文件mode中的相应位一定被关闭。

看下面的例子:

首先将屏蔽位设为0,然后创建一个文件,发现默认创建的文件mode为u=rw,g=rw,o=rw(666)

harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ umask 0
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ umask -S
u=rwx,g=rwx,o=rwx
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ touch test.txt
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ ll test.txt
-rw-rw-rw- 1 harlan harlan 0 6月 5 21:02 test.txt

下面更新文件模式屏蔽字,并创建文件:

harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ umask 027
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ umask -S
u=rwx,g=rx,o=
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ touch test2.txt
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ ll test2.txt
-rw-r----- 1 harlan harlan 0 6月 5 21:05 test2.txt

因为group的x和other的rwx被屏蔽掉了,因此得到上面的结果。

umask值表示为8进制数,一位代表一种要屏蔽的权限,见下图所示:



注意: 用数字和符号表示文件模式屏蔽字的不同,数字中的1表示的是要屏蔽的权限,而符号中显示的是支持的权限。

4.9 函数chmod

chmod使得我们可以更改现有文件的访问权限。

#include <sys/stat.h>
int chmod(const char*pathname,mode_t name);
成功返回0;出错返回-1

为了改变一个文件的权限位,进程的有效用户ID必须等于文件的所有者ID,或者该用户必须具有超级用户权限。

疑问:可读可写可执行权限和chmod有关系么?

答:没有任何关系。

看下面一个简单的例子,创建一个其他用户可读可写可执行的文件所有者为root的文件:

harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ ll chmod.txt
-rw-r--rwx 1 root root 0 6月 5 21:16 chmod.txt

在harlan用户下创建下面的程序:

#include <fcntl.h>
#include <stdio.h>
int main(void)
{
struct stat statbuf;
if(stat("chmod.txt",&statbuf)<0)
printf("stat error!\n");
int rv = chmod("chmod.txt",statbuf.st_mode & ~S_IRWXO);//remove the other's read write and execute
if(rv < 0)
{
printf("chmod error!\n");
}
return 0;
}

上面的程序尝试在harlan用户下来修改chmod.txt文件的权限位,harlan用户对chmod.txt是可读可写可执行的。但是它不能修改此文件的权限位,结果打印:

harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ ./a.out
chmod error!

参数mode是图4-11中所示的常量的按位或:

注意:chmod函数修改的是i节点最近一次被更改的时间,而并不是最后修改文件内容的时间。

注意:如果新文件的组ID不等于进程的有效组ID或者进程附属组ID中的一个,并且进程没有超级用户权限,那么设置组ID位会被自动关闭。在linux3.2.0中,如果没有超级用户权限的进程写一个文件,则设置用户ID位和设置组ID位会被自动清除。看下面的例子:

对于文件chmod.txt,我们同时设置了设置用户ID和设置组ID,

harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ ll chmod.txt
-rwSr-srwx 1 root root 4 6月 5 22:16 chmod.txt

写一段代码来用普通用户权限写这个文件

#include <fcntl.h>
#include <stdio.h> void PrintSetUserID(unsigned int st_mode)
{
if(st_mode&S_ISUID)
{
printf("set-user-ID is 1.\n");
}
else
{
printf("set-user-ID is 0.\n");
}
} void PrintSetGroupID(unsigned int st_mode)
{
if(st_mode&S_ISGID)
{
printf("set-group-ID is 1.\n");
}
else
{
printf("set-group-ID is 0.\n");
}
}
void ClearSetUserID_SetGroupID()
{ struct stat statbuf;
if(stat("chmod.txt",&statbuf)<0)
printf("stat error!-");
else
{
PrintSetUserID(statbuf.st_mode);
PrintSetGroupID(statbuf.st_mode);
}
int fd = open("chmod.txt",O_RDWR);
ssize_t num = write(fd,"test",4);
printf("write num:%d\n",(int)num);
if(stat("chmod.txt",&statbuf)<0)
printf("stat error!--\n");
else
{
PrintSetUserID(statbuf.st_mode);
PrintSetGroupID(statbuf.st_mode);
}
}
int main(void)
{
ClearSetUserID_SetGroupID();
return 0;
}

运行结果:

harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ ./a.out
set-user-ID is 1.
set-group-ID is 1.
write num:4
set-user-ID is 0.
set-group-ID is 0.

4.10 粘着位

  • 对于文件的粘着位,因为现今的UNIX系统大多都配置了虚拟存储系统以及快速文件系统,所以不再需要这个设置。
  • 对于目录的粘着位,如果你为一个目录设置了粘着位,只有对该目录具有写权限的用户并且满足下列条件之一,才能删除或重命名该目录下的文件:
    1. 拥有此文件;
    2. 拥有此目录;
    3. 是超级用户。

看下面的例子:

harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ mkdir dir
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ chmod 777 dir
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ ll
...
drwxrwsrwx 2 harlan harlan 0 6月 5 22:47 dir
...
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ chmod o+t dir
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ ll
...
drwxrwsrwt 2 harlan harlan 0 6月 5 22:47 dir
...

疑问:粘着位和其他写是否同时存在?见下面的代码:

#include <fcntl.h>
#include <stdio.h> void main()
{
struct stat statbuf;
if(stat("dir",&statbuf))
printf("stat error!\n"); if(statbuf.st_mode & S_ISVTX)
{
printf("sticky bit is set!\n");
} if(statbuf.st_mode & S_IXOTH)
{
printf("other execute bit is set!\n");
}
}

输出结果为:

harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ ./a.out
sticky bit is set!
other execute bit is set!

可见是可以同时存在的。同时存在和只存在黏着位的显示有什么区别呢?见下面的例子:

harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ chmod 776 dir
drwxrwsrw- 2 harlan harlan 0 6月 5 22:47 dir
harlan@DESKTOP-KU8C3K5:/github/APUE/chapter_4/myexamples$ chmod o+t dir
drwxrwsrwT 2 harlan harlan 0 6月 5 22:47 dir

可见如果只有粘着位其它的第三位为大写的T,如果是小写表示粘着位+可执行。

/var/tmp 目录设置了粘着位+任意用户的可读可写可执行

harlan@DESKTOP-KU8C3K5:/var$ ll
总用量 12
drwxr-xr-x 2 root root 0 4月 11 2014 backups
drwxr-xr-x 2 root root 0 3月 30 14:52 cache
drwxrwxrwt 2 root root 0 3月 30 14:52 crash
drwxr-xr-x 2 root root 0 4月 27 22:17 lib
drwxrwsr-x 2 root staff 0 4月 11 2014 local
lrwxrwxrwx 1 root root 9 3月 30 14:50 lock -> /run/lock
drwxrwxr-x 2 root syslog 0 5月 1 21:38 log
drwxrwsr-x 2 root mail 0 3月 30 14:50 mail
drwxr-xr-x 2 root root 0 3月 30 14:50 opt
lrwxrwxrwx 1 root root 4 3月 30 14:50 run -> /run
drwxr-xr-x 2 root root 0 3月 30 14:50 spool
drwxrwxrwt 2 root root 0 6月 5 22:28 tmp

我们用root用户在tmp目录下面创建一个文件:

root@DESKTOP-KU8C3K5:/var/tmp# ll
总用量 4
drwxrwxrwt 2 root root 0 6月 5 22:28 ./
drwxr-xr-x 2 root root 0 3月 30 14:53 ../
-rw-r--r-- 1 root root 0 6月 5 22:28 test.txt

尝试在harlan用户下删除:

harlan@DESKTOP-KU8C3K5:/var/tmp$ rm test.txt
rm:是否删除有写保护的普通空文件 "test.txt"? y
rm: 无法删除"test.txt": 不允许的操作

虽然harlan用户对这个目录具有写权限,但因为所在目录设置了粘着位,并且不满足上述任意三个条件之一,因此不讷讷个删除文件。

APUE-文件和目录(二)函数access,mask,chmod和粘着位的更多相关文章

  1. windows中操作文件和目录的函数

    1.文件操作函数       CreateFile();//创建或打开文件      ReadFile();//从文件读      WriteFile();//向文件写      SetFilePoi ...

  2. linux C之判断文件或目录是否存在 access函数

    http://blog.sina.com.cn/s/blog_6a1837e90100uh5d.html access():判断是否具有存取文件的权限 相关函数    stat,open,chmod, ...

  3. [APUE]文件和目录(中)

    一.link.unlink.remove和rename 一个文件可以有多个目录项指向其i节点.使用link函数可以创建一个指向现存文件连接 #include <unistd.h> int ...

  4. [APUE]文件和目录(上)

    一.文件权限 1. 各种ID 我在读这一章时遇到了各种ID,根据名字完全不清楚什么意思,幸好看到了这篇文章,http://blog.csdn.net/ccjjnn19890720/article/de ...

  5. PHP 文件与目录操作函数总结

    >>>文件操作 打开 fopen();    打开文件 读取内容 fread();    从文件指针 handle 读取最多 length 个字节 readfile();    读入 ...

  6. APUE 文件和目录

    文件和目录 Unix 所有的文件都对应一个 struct stat,包含了一个文件所有的信息. #include <sys/stat.h> struct stat { mode_t st_ ...

  7. Linux系统对文件及目录的权限管理(chmod、chown)

    本文命令: 4 5 6 ls -l chmod chown 1.身份介绍 在linux系统中,对文件或目录来说访问者的身份有三种: ①.属主用户,拥有者(owner)文件的创建者 ②.属组用户,和文件 ...

  8. [APUE]文件和目录(下)

    一.mkdir和rmdir函数 #include <sys/types.h> #include <sys/stat.h> int mkdir(const char *pathn ...

  9. php 文件、目录操作函数

    目录 opendir readdir closedir mkdir rmdir  : 只能删除空目录 文件 filetype filesize is_file basename dirname pat ...

随机推荐

  1. SpringBoot项目部署进阶

    一.war包部署 通过“云开发”平台初始化的SpringBoot项目默认采用jar形式打包,这也是我们推荐的方式.但是,因为某些原因,软件需求方特别要求用war形式打包,我们该怎么做? 1.项目尚未开 ...

  2. 何登成大神对Innodb加锁的分析

    背景 MySQL/InnoDB的加锁分析,一直是一个比较困难的话题.我在工作过程中,经常会有同事咨询这方面的问题.同时,微博上也经常会收到MySQL锁相关的私信,让我帮助解决一些死锁的问题.本文,准备 ...

  3. [CF1110H]Modest Substrings

    description CodeForces 定义一个正整数\(x\)是合适的当且仅当\(l\le x\le r\),其中\(l,r\le 10^{800}\). 找到一个长度为\(n\)的数字串,使 ...

  4. 一些说明&其他奇奇怪怪的东西

    NOIP考完了,这篇博客彻底咕了.

  5. Xpack集成LDAP

    支持两种配置方式: The ldap realm supports two modes of operation, a user search mode and a mode with specifi ...

  6. java堆溢出

    java堆是用来存储对象实例的:只要不断创建对象,GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,当对象数量达到最大堆的容量限制的时候就会产生内存溢出异常.异常对战信息为OutOf ...

  7. java类加载详解

    1,类的加载过程: JVM将类加载过程分为三个步骤:装载(load),链接(link)和初始化(initialize),其中链接又分为三个步骤: 验证(varification),准备(Prepara ...

  8. 【loj2586】【APIO2018】选圆圈

    题目 有 \(n\) 个圆$c_1,c_2, \cdots , c_n $,执行如下的操作: 找到剩下的半径最大的圆删除并删除所有和它有交的其他并没有被删除的圆: 求每个圆是被那个圆删除的: $1 \ ...

  9. Web前端之Javascript详解20180330

    一.javascript概述 javascript是基于对象和事件的脚本语言. 特点: 1.安全性(不允许直接访问本地硬盘(因为是被远程的浏览器解释)),它可以做的就是信息的动态交互 2.跨平台性(只 ...

  10. 【转】了解CNN

    摘要 过去几年,深度学习在解决诸如视觉识别.语音识别和自然语言处理等很多问题方面都表现出色.在不同类型的神经网络当中,卷积神经网络是得到最深入研究的.早期由于缺乏训练数据和计算能力,要在不产生过拟合的 ...