【问题标题】:Why does open() create my file with the wrong permissions?为什么 open() 使用错误的权限创建我的文件?
【发布时间】:2011-01-15 18:08:12
【问题描述】:

我正在尝试从一个文件中读取一些文本并使用open()read()write() 将其写入另一个文件。

这是我的open() 用于写入文件(我想创建一个新文件并写入其中):

fOut = open ("test-1", O_RDWR | O_CREAT | O_SYNC);

这是将文件权限设置为我根本不理解的东西。这是ls -l的输出:

---------T 1 chaitanya chaitanya 0 2010-02-11 09:38 test-1

连读权限都被锁定了。我试着搜索这个,但找不到任何东西。 奇怪的是,write() 仍然成功地将数据写入文件。

另外,如果我执行 'chmod 777 test-1',一切都会重新开始正常工作。

有人可以让我知道我在公开电话中哪里出了问题吗?

谢谢!

下面我贴了完整的程序供大家参考:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main () {

    char buffer[512], ch;

    int fIn, fOut, i;
    ssize_t bytes;
    FILE *fp = NULL;

    //open a file
    fIn = open ("test", O_RDONLY);
    if (fIn == -1) {
        printf("\nfailed to open file.");
        return 1;
    }

    //read from file
    bytes =  read (fIn, buffer, sizeof(buffer));
    //and close it
    close (fIn);

    printf("\nSuccessfully read %d bytes.\n", bytes);

    //Create a new file
    fOut = open ("test-1", O_RDWR | O_CREAT | O_SYNC);

    printf("\nThese are the permissions for test-1\n");
    fflush(stdout);
    system("ls -l test-1");

    //write to it and close it.
    write (fOut, buffer, bytes);
    close (fOut);


    //write is somehow locking even the read permission to the file. Change it.
    system("chmod 777 test-1");

    fp = fopen ("test-1", "r");
    if (fp == NULL) {
        printf("\nCan't open test-1");
        return 1;
    }

    while (1)
    {
        ch = fgetc(fp);
        if (ch == EOF)
            break;
        printf("\n%c", ch);
    }

    fclose (fp);

    return 0;
}

【问题讨论】:

  • 你可能不需要777权限;您可能最多只需要 666,而且通常您也不需要公共写权限。您不希望人们执行您的数据文件。

标签: c unix file-io


【解决方案1】:

open() 接受第三个参数,即权限集,即

open(filename, O_RDWR|O_CREAT, 0666)

0666 是一个八进制数,即 6 中的每一个对应三个权限位

6 = rw

7 = rwx

前三位是所有者权限,后三位是组权限,接下来是世界 第一个数字 - 代表文件或目录。 (0 - 文件,d - 目录) 这里我们使用 0 表示文件

这是一个典型的陷阱。编译器允许您保留权限参数,因为当您打开现有文件时,权限位没有意义。但是,当您在创建文件时忘记了参数时,您会获得一组随机的权限,例如0000 在你的情况下 (---)。

【讨论】:

  • 为了完整性,八进制 4 = r
  • @Adam Liss: hex 4 = octal 4。八进制便于权限,因为每组 3 位组成一个权限单元和一个八进制数字。 0644 = 0x1A4,但是以八进制表示的权限比以十六进制表示要容易得多。 (部分经验,但主要是适当的位分组)。
  • 0666 通常是一个很好的设置,即使您不打算让“其他”能够写入它。 umask 通常设置为 0022,即删除除所有者之外的所有人的写权限。
  • 我不明白最后一个参数是如何获得的,手册页上没有这个?
【解决方案2】:

阅读http://linux.die.net/man/2/open,您似乎错过了打开的mode参数:

当 O_CREAT 在标志中时必须指定模式,否则将被忽略。 参数 mode 指定在创建新文件时使用的权限。

【讨论】:

    【解决方案3】:

    这个问题最近帮助了我,所以我想尽自己的一份力量来更深入地了解正在发生的事情。如前所述,您缺少open() 的第三个参数。但是,您看到的权限不是随机的。他们来自堆栈。看下面的代码sn -p:

        asm("push $0");
        asm("push $0");
        asm("push $0");
        fd = open("base", O_RDWR|O_CREAT);
    

    注意以下结果:

        ----------. 1 user user 4 Feb 26 08:21 base
    

    我们把第一次push改成1,即执行权限:

        asm("push $1;push $0;push $0");
        fd = open("base", O_RDWR|O_CREAT);
    

    我们得到:

        ---------x. 1 user user 4 Feb 26 08:25 base
    

    把push改成4,即读权限,把另外两个值弄乱了:

        asm("push $4;push $5;push $6");
        fd = open("base", O_RDWR|O_CREAT);
    

    我们得到:

        -------r--. 1 user user 4 Feb 26 08:27 base
    

    因此,我们可以看到从堆栈中弹出的第三个值(第一次推送)才是真正重要的。最后,为了好玩,我们可以尝试 5 和 50,分别得到:

        -------r-x. 1 user user 4 Feb 26 08:27 base
        ----rw----. 1 user user 4 Feb 26 08:28 base
    

    希望这会增加一些清晰度!

    【讨论】:

    • 抱歉,让 C 使用该版本的 open 是什么意思?来自手册页:“在标志中指定 O_CREAT 时必须提供此参数;如果未指定 O_CREAT,则忽略模式。有效权限由进程的 umask 以通常方式修改:创建文件的权限是(模式和〜umask)。”参数在堆栈上传递;通过使用内联汇编手动设置堆栈,我们可以演示看似“随机”的权限来自何处。
    【解决方案4】:

    您可以在使用open();系统调用之前调用umask(0);系统调用来正确设置您的选择权限。

    【讨论】:

    • 值得指出的是,umask out 对整个过程都有影响,因此在多线程程序中存在竞争条件的风险
    【解决方案5】:

    其实umask()只是过滤权限,并没有设置权限。典型的umask() 值是0002(“不要放弃对世界的写权限”),如果open( "file", O_CREAT, 0777) 中的模式值授予所有权限,则生成的文件将具有775 作为其权限。

    【讨论】:

      【解决方案6】:

      与问题不严格相关,但接受的答案可以使用这个澄清点:

      rwx 与其数值表示之间存在关系,可以通过将字母的存在视为二进制 1,将其不存在视为二进制 0。

      例如

      rwx  <-->  111 (binary) <-->  7 (octal)
      
      r--  <-->  100 (binary) <-->  4 (octal)
      
      -wx  <-->  011 (binary) <-->  3 (octal) 
      

      作为进一步的补充,您现在可以考虑使用 chmod 命令:

      chmod 777 文件名.extension --> rwxrwxrwx 权限

      777 <--> 111 111 111 <--> rwx rwx rwx
      

      或者:chmod 654 filename.extension --> rw-r-x-r--

      654 <--> 110 101 100 <--> rw- r-x r--
      

      希望这是有用的!

      【讨论】:

        【解决方案7】:

        这是一个旧线程,但我认为人们应该注意“sys/stat.h”库。这包括一堆用于设置权限位的符号常量。

        例如:打开一个为用户启用读/写权限的文件

        #include <fcntl.h>
        #include <sys/stat.h>
        
        open("Your/File/Path", O_RDWR | O_CREAT, S_IWUSR | S_IRUSR);
        

        在哪里:

        S_IWUSR // Sets the Users Write bit
        S_IRUSR // Sets the Users Read bit
        

        这个库包括一堆其他的,我不会在这里一一列出,但你可以阅读它们here

        当然,您可以输入八进制值来设置这些位,但是有些人可能会认为这是不好的编码习惯。

        【讨论】:

        • 我认为您所说的是一般主观的东西,问题是即使在设置权限之后我们也看不到权限位设置。这适用于 stdlb api 或系统 api。
        • @BhupeshPant 问题询问为什么文件的权限位被设置为“---------T 1 chaitanya chaitanya 0 2010-02-11 09:38 test-1 " 即为什么文件没有设置权限位。在他的公开电话中,即)“fOut = open ("test-1", O_RDWR | O_CREAT | O_SYNC);"他有 O_CREAT 标志,如果文件“test-1”不存在,它将创建它。假设是这种情况(文件是在 open 调用中创建的),他还必须指定与文件关联的权限位。他稍后在代码中通过对 chmod 的系统调用更正了这一点。
        猜你喜欢
        • 2017-09-14
        • 2018-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-29
        • 2012-04-15
        • 1970-01-01
        相关资源
        最近更新 更多