如何将字符串权限转换为mode_t类型

How to convert string permission to mode_t type

提问人:programme3219873 提问时间:7/18/2022 最后编辑:Jonathan Lefflerprogramme3219873 更新时间:7/18/2022 访问量:774

问:

我正在编写一个更改文件权限的程序。权限将通过命令行参数作为 a 传递,然后转换为 type 并提供给 chmod()。char *mode_t

如何将字符串权限/模式更改为 ?mode_t

例如,给定一个字符串 aka 如何更改为 ?4777rwsrwxrwx4777mode_t

C 文件 权限 chmod stat

评论

1赞 Jonathan Leffler 7/18/2022
安全问题:该模式是一组愚蠢的权限,可以对任何文件进行设置。它允许任何人编写他们选择的任何代码,并以程序所有者的身份运行它——这是灾难的根源。我认为 SUID(和 SGID)程序永远不应该被任何人写入;当然不是业主以外的任何人。但这与你的问题无关。(某些系统可能会应用额外的约束,但在基于 POSIX 的经典系统下,模式非常危险。47774777
1赞 Jonathan Leffler 7/18/2022
转换 chmod 命令支持的符号“更改模式”选项比处理纯数字模式要困难得多。
0赞 programme3219873 7/18/2022
感谢您的关注,我同意这是一组危险的权限,但我只是为了举个例子而使用它。在现实生活中,我一定会更加小心

答:

2赞 paddy 7/18/2022 #1

可以通过调用 strtol 并提供作为基数来解析字符串以提取八进制值:8

int mode = strtol(str, NULL, 8);

为了安全起见,您可能需要进行一些额外的健全性检查:

// Extract file mode from a string, with sanity checks.
// Returns non-zero on success. 
int string_to_filemode(const char* str, mode_t* mode)
{
    char* end = NULL;
    *mode = (mode_t)strtol(str, &end, 8);
    if (!end) return 0;
    while(isspace(*end)) end++;
    return *end == '\0' && (unsigned)*mode < 010000;
}

下面是一个使用它的示例:

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

#include <sys/stat.h>

int string_to_filemode(const char* str, mode_t* mode)
{
    char* end = NULL;
    *mode = (mode_t)strtol(str, &end, 8);
    if (!end) return 0;
    while(isspace(*end)) end++;
    return *end == '\0' && (unsigned)*mode < 010000;
}

int main(int argc, char *argv[])
{
    for (int i = 1; i < argc; i++)
    {
        mode_t mode;
        if (string_to_filemode(argv[i], &mode))
            printf("Mode: str=%s val=%04o\n", argv[i], mode);
        else
            printf("Invalid mode: %s\n", argv[i]);
    }
    return 0;
}

使用命令行参数调用时的输出:4777 644 1000 11232 91 abc -1

Mode: str=4777 val=4777
Mode: str=644 val=0644
Mode: str=1000 val=1000
Invalid mode: 11232
Invalid mode: 91
Invalid mode: abc
Invalid mode: -1

现场演示:https://godbolt.org/z/4nhW9G9jM

评论

0赞 programme3219873 7/18/2022
做什么?我认为它会检查字符串中的第一个非整数字符是否是 OR AKA 一个不是的值,我认为?if (!end)NULL\0true
1赞 paddy 7/18/2022
!end等效于 。它与字符串中的字符无关。这是一个指针测试。end == NULL