Linux 文件权限修改:chmod、fchmod 与 fchmodat
在 Unix/Linux 系统中,修改现有文件的访问权限主要依赖三个系统调用:chmod、fchmod 和 fchmodat。它们分别基于路径名、文件描述符以及带标志的路径名进行操作。
函数原型
#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, mode_t mode, int flag);
这三个函数的返回值逻辑一致:成功时返回 0,出错时返回 -1 并设置 errno。
核心区别与行为
- chmod:直接通过文件路径名操作。适用于已知完整路径的场景。
- fchmod:针对已打开的文件描述符(fd)操作。这在处理临时文件或避免路径竞争时非常有用。
- fchmodat:功能最灵活。当
pathname为绝对路径,或fd为AT_FDCWD且pathname为相对路径时,其行为等同于chmod。否则,它会将pathname视为相对于fd指向目录的相对路径。此外,flag参数允许控制符号链接的处理方式,例如设置AT_SYMLINK_NOFOLLOW可防止跟随符号链接,从而安全地修改链接本身的属性而非目标文件。
权限位与模式设置
要改变文件的权限位,进程的有效用户 ID(EUID)必须等于文件的所有者 ID,或者该进程需具备超级用户(root)权限。
mode 参数通常由多个常量按位或组成。除了标准的读、写、执行权限外,还包含几个特殊位:
- S_ISUID / S_ISGID:设置用户/组 ID 位。
- S_ISVTX:保存正文位(Sticky Bit),常用于目录。
- S_IRWXU / S_IRWXG / S_IRWXO:用户、组、其他用户的读写执行组合掩码。
在实际使用中,我们既可以像设置 bar 文件那样直接指定绝对权限值,也可以像处理 foo 文件那样先通过 stat 获取当前权限,修改后再应用。例如,显式开启组 ID 位的同时关闭组执行位, 输出中对应的权限字符会显示为 (表示设置了 SGID 但无执行权)。

