linux下创建文件的文件权限问题
今天发现创建文件的权限和自己规定的权限不一致,了解到了权限掩码的问题,这里总结一下。
首先权限掩码umask是chmod配套的,总共为4位(gid/uid,属主,组权,其它用户的权限),不过通常我们都只用到后面3个,第一个是特殊的权限位,暂时没有很了解。比如chmod 0777 file 就代表给file设置属主、组内用户、其他用户分别是rwx、rwx、rwx的权限。
在我的ubuntu15.04下,umask默认是0002,可以用umask指令查看,加上参数-S会更加易懂:
掩码,顾名思义,是用来掩盖了一些bit,这些bit在这里就表示权限,比如从上面的图我们可以看到0002就是掩盖了其他用户的w权限(o=rx),因为2在二进制是010,我们创建文件时候规定的文件权限***是要和掩码的反码按位相与的,这样才可以屏蔽掉某个位。比如创建文件的时候指定了0666,那么0666 & ~0002 = 0664,最终建立的文件权限为 rw-rw-r--。
另外,linux下(不包含权限掩码umask)规定了文件的默认权限是0666(去除了执行权限x可以减少非常多的攻击,因为很多病毒文件如果创建出来没有执行权限的话,就失去了意义),目录的默认权限是0777。所以,我们如果新建一个文件,文件权限还要和权限掩码umask按位相与,即0666 & ~0002 = 0664(我的电脑上),最后得到的0664(rw-rw-r--)才是文件的真正权限,同理,创建一个目录(0777 & ~0002 = 0775,即rwxrwxr-x)也一样:
我们可以用umask命令来改变权限掩码的值,相应的,我们创建的文件也会要和umask按位相与,会少相对应的部分权限:
相应的,c也有个umask函数,我们用c也可以查看和改变umask的值,但是,修改的仅仅是调用umask()这个函数的进程的值,也就是其余的umask值不变,我们可以用shell命令umask查看一下,会发现umask还是原来的值,所以在c语言里面调用的umask只会改变调用进程的umask。查看man帮助手册可以知道,fork出来的子进程也会继承父进程的umask,也就是说父进程如果修改了权限掩码为0001,那么fork得到的子进程将会和父进程保持一直的权限掩码0001而不是系统的0002或者0022。
当我们用c语言的open(linux的系统函数)来创建一个新文件的时候(即第二个参数指定O_CREAT),我们一定要指明第三个参数的权限是什么,默认的权限并不是linux默认的0666,所以不指定的话我也不知道是什么(感觉每次创建的都不一样?)。因此,保险起见,我们在用open创建一个文件的时候,就按照自己的需求(没有的话就按照linux默认的0666)指定创建的文件权限,而制定了这个权限以后,还要和当前进程的权限掩码按位相与,这样才会得到最终的文件权限。
O_CREAT
If the file exists, this flag has no effect except as noted under O_EXCL below. Otherwise, the file is created; the user ID of the file is set to the effective user ID of the process; the group ID of the file is set to the group ID of the file's parent directory or to the effective group ID of the process; and the access permission bits (see <sys/stat.h>) of the file mode are set to the value of the third argument taken as type mode_t modified as follows: a bitwise-AND is performed on the file-mode bits and the corresponding bits in the complement of the process' file mode creation mask. Thus, all bits in the file mode whose corresponding bit in the file mode creation mask is set are cleared. When bits other than the file permission bits are set, the effect is unspecified. The third argument does not affect whether the file is open for reading, writing or for both.