`

文件权限 ID 修改函数介绍

阅读更多
    在前面“设置用户 ID 和设置组 ID”一节中,我们介绍了与每个文件相关的 9 个访问权限位,在此基础上我们可以说明与每个进程相关联的文件模式创建屏蔽字。
    umask 函数为进程设置文件模式创建屏蔽字,并返回之前的值。
#include <sys/stat.h>

mode_t umask(mode_t cmask);       // cmask 是 9 个文件访问权限位常量的按位或
              /* 返回值:之前的文件模式创建屏蔽字 */

    在进程创建一个新文件或新目录时,就一定会使用文件模式创建屏蔽字。在文件模式创建屏蔽字中为 1 的位,在文件 mode 中的相应位就会被关闭。
    下例程序创建了两个文件,创建第一个时,umask 值为 0,创建第二个时,umask 值禁止了所有组和其他用户的访问权限。
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

#define RWRWRW (S_IRUSR |S_IWUSR |S_IRGRP |S_IWGRP |S_IROTH |S_IWOTH)

int main(void){
	umask(0);
	if(creat("foo", RWRWRW) < 0){
		printf("creat error for foo\n");
		exit(2);
	}
	umask(S_IRGRP |S_IWGRP |S_IROTH |S_IWOTH);
	if(creat("bar", RWRWRW) < 0){
		printf("creat error for bar\n");
		exit(2);
	}
	exit(0);
}

    执行结果如下(从中可看出更改子进程的文件模式创建屏蔽字不会影响父进程(常常为 shell )的屏蔽字):
$ umask                 # 先查看当前文件模式创建屏蔽字
0022
$ ./umaskDemo.out 
$ ls -l foo bar
-rw-------. 1 lei root 0 7月   2 23:55 bar
-rw-rw-rw-. 1 lei root 0 7月   2 23:55 foo
$ umask                 # 观察文件模式创建屏蔽字是否更改
0022

    尽管在登录时,shell 的启动文件会自行设置一次 umask 值,但当编写创建新文件的程序时,如果想确保指定的访问权限位已经激活,那么最好在进程运行时修改 umask 值,以免进程运行时有效的 umask 值关闭该权限位。

    更改 umask 值会影响所有随后的文件,如果想更改特定文件的访问权限,可使用 chmod 函数族。
#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, node_t mode, int flag);
                       /* 返回值:若成功,都返回 0;否则,都返回 -1 */

    chmod 函数在制定的文件上进行操作,而 fchmod 函数则对已打开的文件进行操作。fchmodat 函数与 chmod 函数在这两种情况下是相同的:一种是 pathname 参数为绝对路径,另一种是 fd 参数取值为 AT_FDCWD 而 pathname 为相对路径。否则,fchmodat 计算相对于打开目录(由 fd 指向)的 pathname。flag 参数可以改变 fchmodat 的行为,当设置了 AT_SYMLINK_NOFOLLOW 标志时,fchmodat 并不会跟随符号链接。
    要改变一个文件的权限位,进程的有效用户 ID 必须等于文件的所有者 ID,或者该进程必须具有超级用户权限。
    参数 mode 是下表中的常量(均位于头文件 <sys/stat.h> 中)的按位或:


    下面是使用 chmod 函数改变 umask 示例中生成的 foo 和 bar 文件的示例。
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

int main(void){
	struct stat statbuf;

	if(stat("foo", &statbuf) < 0){
		printf("stat error for foo\n");
		exit(2);
	}
	// turn on set-group-ID and turn off group-execute.
	if(chmod("foo",(statbuf.st_mode & ~S_IXGRP) |S_ISGID) < 0){
		printf("chmod error for foo\n");
		exit(2);
	}

	// set absolute mode to "rw-r--r--"
	if(chmod("bar", S_IRUSR |S_IWUSR |S_IRGRP |S_IROTH) < 0){
		printf("chmod error for bar\n");
		exit(2);
	}
	exit(0);
}

    执行结果:
$ ls -l foo bar        # 开始的文件权限位
-rw-------. 1 lei root 0 7月   3 23:39 bar
-rw-rw-rw-. 1 lei root 0 7月   3 23:39 foo
 
$ ./chmodDemo.out 
 
$ ls -l foo bar        # 改变后的文件权限位
-rw-r--r--. 1 lei root 0 7月   3 23:39 bar
-rw-rwSrw-. 1 lei root 0 7月   3 23:39 foo    # Solaris 中显示的是“l”而非“S”

    这里可看出,ls 命令列出的时间和日期并没有改变。这是因为 chmod 更新的只是 i 节点最近一次被更改的时间,而“ls -l”命令默认列出的是最后修改文件内容的时间。
    chmod 函数在下列条件下自动清除两个权限位。
    1、Solaris 等系统对用于普通文件的粘着位赋予了特殊含义(此时如果任何执行位都没有设置,那么操作系统就不会缓存文件内容),在这些系统上如果试图设置普通文件的粘着位(S_ISVTX),而又没有超级用户权限,那么 mode 中的粘着位会被自动关闭。
    2、新创建文件的组 ID 可能不是调用进程所属的组。特别地,当新文件的组 ID 不等于进程的有效组 ID 或者进程附属组 ID 中的一个,而且进程又没有超级用户权限,那么设置组 ID 位就被自动关闭。这就防止了用户创建一个设置组 ID 文件,而该文件是由并非该用户所属的组拥有的。
  
    下面再继续介绍用来更改文件的用户 ID 和组 ID 的 chown 函数族。
#include <unistd.h>

int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int fchownat(int fd, const char *pathname, uid_t owner, gid_t group, int flag);
int lchown(const char *pathname, uid_t, gid_t group);
                     /* 返回值:若成功,都返回 0;否则,都返回 -1 */

    其中,如果两个参数 owner 或 group 中的任意一个为 -1,则对应的 ID 不变。
    fchown 函数改变 fd 参数指向的打开文件的所有者,既然它在一个已打开的文件上操作,就不能用于改变符号链接的所有者。
    fchownat 函数与 chown 或者 lchown 函数在下面两种情况下是相同的:一种是 pathname 为绝对路径,另一种是 fd 参数取值为 AT_FDCWD 而 pathname 为相对路径。这两种情况下,如果 flag 设置了 AT_SYMLINK_NOFOLLOW 标志,fchownat 与 lchown 行为相同,如果 flag 清除了 AT_SYMLINK_NOFOLLOW 标志,则 fchownat 与 chown 行为相同。如果 fd 参数设置为打开目录的文件描述符,并且 pathname 是相对路径,fchownat 就计算相对于打开目录的 pathname。
    若 _POSIX_CHOWN_RESTRICTED 常量(它可选地定义在头文件 <unistd.h> 中,可以使用 pathconf 或 fpathconf 函数查询)对指定的文件生效,则 POSIX.1 规定:
    1、只有超级用户进程能更改该文件的用户 ID,以防用户改变其文件的所有者来摆脱磁盘空间限额的限制。
    2、如果进程拥有此文件(即其有效用户 ID 等于该文件的用户 ID),参数 owner 等于 -1 或文件的用户 ID,并且 group 参数等于进程的有效组 ID 或进程的附属组 ID 之一,则一个非超级用户进程可以更改该文件的组 ID。
    这意味着,当 _POSIX_CHOWN_RESTRICTED 有效时,不能更改其他用户文件的用户 ID,你可以更改你所拥有的文件的组 ID,但只能改到所属的组。如果这些函数由非超级用户进程调用,则在成功返回时,该文件的设置用户 ID 位和设置组 ID 位都将被清除。
  • 大小: 55.8 KB
分享到:
评论

相关推荐

    详细对比C语言中的chmod()函数和fchmod()函数

    C语言chmod()函数:修改文件权限 头文件: #include &lt;sys&gt; #include 定义函数: int chmod(const char * path, mode_t mode); 函数说明:chmod()会依参数mode 权限来更改参数path 指定文件的权限。 参数 mode ...

    精通WindowsAPI 函数 接口 编程实例

    15.4.2 msi文件的创建与修改工具orca.exe 474 15.4.3 准备工作 475 15.4.4 编辑表组 475 第16章 设备驱动管理与内核通信 476 16.1 设备管理 476 16.1.1 列举设备接口 477 16.1.2 监控设备的加载和卸载...

    精通Windows.API-函数、接口、编程实例.pdf

    15.4.2 msi文件的创建与修改工具orca.exe 474 15.4.3 准备工作 475 15.4.4 编辑表组 475 第16章 设备驱动管理与内核通信 476 16.1 设备管理 476 16.1.1 列举设备接口 477 16.1.2 监控设备的加载和卸载...

    上传媒资文件至视频点播(aliyun-sdk-vod-upload) .zip

    自定义上传进度回调函数:您可根据自已的业务场景重新定义不同事件处理的方式,只需要修改上传回调示例函数即可。 * * * 五、辅助媒资上传目前支持2种方式: * 1.上传本地文件,不支持断点续传,最大支持5GB的...

    Linux系统C语言编程连接MySql数据库实现的用户用户组色权限管理系统(图形界面)

    2、db_修改过(用户 角色 权限) 文件: 博客网址:https://blog.csdn.net/weixin_42167759/article/details/80848780 修改的问题: 1、新增用户时候id 改为最大id值加一,之前用的select查看出来的记录数加一,...

    rar压缩软件.rar

    此命令能和大多数压缩文件变量开关一起使用修改压缩文件参数。对于象 -cl, -cu, -tl 等没有专门命令的开关特别方便。 它不能重新压缩、解密或加密压缩文件数据,它不能整合或创建卷。如果 不和其它开关一起使用...

    UNIX期末试卷

    (2) 给出设置mylist.txt文件权限为仅对文件主具有读写权限的实现命令; (3) 给出设置query文件用户ID权限实现命令; (4) 给出用户zhang执行程序query的结果。 4、使用fork,exec以及wait函数构造简单的shell解释程序...

    detour 2.1

    ---- (2) 可以使用QueryProtectEx函数把存放指令的页面的权限更改为可读可写可执行,再改写其内容,从而修改正在运行的程序 ---- (3) 可以使用VirtualAllocEx从一个进程为另一正运行的进程分配虚存,再使用 ...

    KODExplorer 芒果云-资源管理器

    - 文件文件夹权限修改(右键——属性,即可修改) - 对话框加入ico,对应任务栏 - 右键等部分菜单效果优化 - 远程下载加入进度条,下载速度等信息 ####fix bug:(bug解决和程序优化) - 下载前判断当前目录可写 - ...

    PHP和MySQL Web开发第4版pdf以及源码

    2.8 使用其他有用的文件函数 2.8.1 查看文件是否存在:file_exists() 2.8.2 确定文件大小:filesize() 2.8.3 删除一个文件:unlink() 2.8.4 在文件中定位:rewind()、fseek()和ftell() 2.9 文件锁定 2.10 更好...

    PHP和MySQL WEB开发(第4版)

    2.8 使用其他有用的文件函数 2.8.1 查看文件是否存在:file_exists() 2.8.2 确定文件大小:filesize() 2.8.3 删除一个文件:unlink() 2.8.4 在文件中定位:rewind()、fseek()和ftell() 2.9 文件锁定 2.10 更好的方式...

Global site tag (gtag.js) - Google Analytics