我编写了以下代码来尝试在Linux上创建一个具有0777模式的目录:
#include <sys/stat.h>
#include <sys/types.h>
int main () {
mkdir("/tmp/mkdir-test", 0777);
return 0;
}
但实际上,新目录有0755模式。
# stat /tmp/mkdir-test
File: `/tmp/mkdir-test'
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 802h/2050d Inode: 1772304 Links: 2
Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2016-09-27 20:23:54.000000000 -0700
Modify: 2016-09-27 20:23:54.000000000 -0700
Change: 2016-09-27 20:23:54.000000000 -0700
有人能解释一下吗?该程序如何创建一个真正的0777模式目录?
在shell中运行umask
;它会报告022
。
umask
设置的位。在单线程程序中,真正设置0777
权限的一种方法是与umask()
连接:
mode_t old_mask = umask(0);
mkdir("/tmp/mkdir-test", 0777);
umask(old_mask);
保留当前设置,除非您确定需要覆盖它。然而,这在多线程程序中是危险的,因为umask
值是全局的每个进程,而不是每个线程(感谢Peter Cordes指出这一点)。
chmod()
,这样做对于多线程程序也是安全的:
const char *dirname = "/tmp/mkdir-test";
mode_t target_mode = 0777;
if (mkdir(dirname, 0) == 0)
chmod(dirname, target_mode);
chmod()
函数设置的权限不受umask
值的影响。
调用mkdir()
的权限最好设置为0
,如下图所示;它将始终可靠地工作,并且不会通过修改umask
值来影响其他线程。或者,如果您愿意,也可以在调用mkdir()
时使用所需的目标权限(这个答案的前一个版本建议这样做,使用0777
作为硬编码的目标权限)。
const char *dirname = "/tmp/mkdir-test";
mode_t target_mode = 0777;
if (mkdir(dirname, target_mode) == 0)
chmod(dirname, target_mode);
如果您使用这种习惯用法,传递给mkdir()
的模式与传递给chmod()
的模式相同,或者不那么宽松,这一点很重要- 0
比任何其他模式都不那么宽松(并且总是有效)。如果在对mkdir()
的调用中使用更宽松的模式,则在mkdir()
和chmod()
调用之间存在TOCTOU(检查时间,使用时间)样式的漏洞,在此期间,某人(某些进程)可能以宽松的权限进入目录并造成破坏;这可能存在安全风险。
请注意,umask()
是一个非常简单的系统调用,因此也非常快速(作为系统调用,与open()
, mkdir()
或chmod()
等重量级系统调用相比)。