APUE-文件和目录(二)函数access,mask,chmod和粘着位

2024-04-07 12:48

本文主要是介绍APUE-文件和目录(二)函数access,mask,chmod和粘着位,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

bloglt_20170606074949.jpg

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中所列常量的按位或。

bloglt_20170605084828.jpg

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进制数,一位代表一种要屏蔽的权限,见下图所示:

bloglt_20170605210741.jpg
注意: 用数字和符号表示文件模式屏蔽字的不同,数字中的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 executeif(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中所示的常量的按位或:

bloglt_20170605212923.jpg

注意: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和粘着位的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/882636

相关文章

Python中help()和dir()函数的使用

《Python中help()和dir()函数的使用》我们经常需要查看某个对象(如模块、类、函数等)的属性和方法,Python提供了两个内置函数help()和dir(),它们可以帮助我们快速了解代... 目录1. 引言2. help() 函数2.1 作用2.2 使用方法2.3 示例(1) 查看内置函数的帮助(

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

Linux使用scp进行远程目录文件复制的详细步骤和示例

《Linux使用scp进行远程目录文件复制的详细步骤和示例》在Linux系统中,scp(安全复制协议)是一个使用SSH(安全外壳协议)进行文件和目录安全传输的命令,它允许在远程主机之间复制文件和目录,... 目录1. 什么是scp?2. 语法3. 示例示例 1: 复制本地目录到远程主机示例 2: 复制远程主

Python中bisect_left 函数实现高效插入与有序列表管理

《Python中bisect_left函数实现高效插入与有序列表管理》Python的bisect_left函数通过二分查找高效定位有序列表插入位置,与bisect_right的区别在于处理重复元素时... 目录一、bisect_left 基本介绍1.1 函数定义1.2 核心功能二、bisect_left 与

java中BigDecimal里面的subtract函数介绍及实现方法

《java中BigDecimal里面的subtract函数介绍及实现方法》在Java中实现减法操作需要根据数据类型选择不同方法,主要分为数值型减法和字符串减法两种场景,本文给大家介绍java中BigD... 目录Java中BigDecimal里面的subtract函数的意思?一、数值型减法(高精度计算)1.

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

C++类和对象之默认成员函数的使用解读

《C++类和对象之默认成员函数的使用解读》:本文主要介绍C++类和对象之默认成员函数的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、默认成员函数有哪些二、各默认成员函数详解默认构造函数析构函数拷贝构造函数拷贝赋值运算符三、默认成员函数的注意事项总结一

Python函数返回多个值的多种方法小结

《Python函数返回多个值的多种方法小结》在Python中,函数通常用于封装一段代码,使其可以重复调用,有时,我们希望一个函数能够返回多个值,Python提供了几种不同的方法来实现这一点,需要的朋友... 目录一、使用元组(Tuple):二、使用列表(list)三、使用字典(Dictionary)四、 使

PyTorch中cdist和sum函数使用示例详解

《PyTorch中cdist和sum函数使用示例详解》torch.cdist是PyTorch中用于计算**两个张量之间的成对距离(pairwisedistance)**的函数,常用于点云处理、图神经网... 目录基本语法输出示例1. 简单的 2D 欧几里得距离2. 批量形式(3D Tensor)3. 使用不

MySQL 字符串截取函数及用法详解

《MySQL字符串截取函数及用法详解》在MySQL中,字符串截取是常见的操作,主要用于从字符串中提取特定部分,MySQL提供了多种函数来实现这一功能,包括LEFT()、RIGHT()、SUBST... 目录mysql 字符串截取函数详解RIGHT(str, length):从右侧截取指定长度的字符SUBST