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. MT【130】Heilbronn问题

    (清华THUSSAT,多选题) 平面上 4 个不同点 \(P_1,P_2,P_3,P_4\),在每两个点之间连接线段得到 6 条线段. 记 \[L=\max_{1\leq i<j\leq 4}| ...

  2. 【转】rt-thread的位图调度算法分析

    序言 期待读者 本文期待读者有C语言编程基础,后文中要分析代码,对其中的一些C语言中的简单语句不会介绍,但是并不要求读者有过多的C基础,比如指针和链表等不会要求太多,后面在分析代码时,会附带地介绍相关 ...

  3. 洛谷 P2389 电脑班的裁员 解题报告

    题意: 给定一段长为N的序列,选取其中的至多M段使这些子段和最大. 当N=1000时,我们可以采用动态规划解法 令\(dp[i][j][k]\)代表当前选至位置\(i\)处于第\(j\)段当前是否选取 ...

  4. 响应式开发(五)-----Bootstrap CSS----------Bootstrap 网格系统

    如果我们看过一些bootstrap的框架,经常看到col-sm-3等样式class. Bootstrap 提供了一套响应式.移动设备优先的流式网格系统,随着屏幕或视口(viewport)尺寸的增加,系 ...

  5. 目标检测应用化之web页面(YOLO、SSD等)

    在caffe源码目录下的examples下面有个web_demo演示代码,其使用python搭建了Flask web服务器进行ImageNet图像分类的演示. 首先安装python的依赖库:pip i ...

  6. Python中__init__.py文件的作用详解

    转自http://www.jb51.net/article/92863.htm Python中__init__.py文件的作用详解 http://www.jb51.net/article/86580. ...

  7. 【Asp.net入门02】搭建Asp.net开发环境

    本节主要讲解: 什么是asp.net asp.net开发和运行环境介绍 1.什么是ASP.NET Asp.net不是一种编程语言,而是一种开发技术.我们可以利用这种技术所提供的类库,使用C#或者VB编 ...

  8. Java入门:注册模块的实现

    1.主活动图 用户选择注册选项,进入注册界面,开始输入注册信息,到最后完成注册.具体的活动图如下: 以上活动图中,矩形框里的操作不是在一个类里面实现的,而是通过Form类和UserService类来实 ...

  9. 利用Snapshot快速跨Region迁移服务器

    当你需要对现有的网站进行跨区域迁移,或者是部署DR Site的时候,又不希望重新部署应用,有什么好办法呢?其实你可以利用Azure的磁盘snapshot进行磁盘级的复制,这样可以减少很多部署应用的时间 ...

  10. Python 函数01

    Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也 ...