c - 使用 O_CREAT 调用 open() 的默认模式是什么以及如何在打开/创建文件时正确设置它

标签 c linux io system

我正在尝试使用 I/O 系统调用重新创建 fopen() 的基本功能。我想以某种方式“为使用 O_CREAT 的 open() 调用设置默认模式”但是我不确定如何去做。它并不完美,但这是我到目前为止所拥有的。

MYFILE * myfopen(const char * path, const char * mode){
MYFILE *fp = (MYFILE *)malloc(sizeof(MYFILE)); //EDITED
int fd;
  switch(mode[0]){
            case 'r':
                    fd=open(path, O_RDONLY | O_CREAT, 0440);
                    break;
            case 'w':
                    fd=open(path, O_WRONLY | O_CREAT | O_TRUNC, 0220);
                    break;
            default:
                    fd=open(path, O_RDWR | O_CREAT | O_TRUNC, 0660);
  }

 if(fd < 0){
     return NULL;
 }

 fp->fileD=fd;
 fp->offset=0;
 return fp;
} 

fileD 将是 open 调用返回的文件描述符。我认为其余的是不言自明的。

它可以编译,但是当我尝试运行它时出现“段错误”错误。此函数也无法打开新文件并将文件描述符关联到它。

我认为段错误可能在此处:

int myfputc(int c, MYFILE * fp){

 if(write(fp->fileD, &c, 1) == -1){
    return 1;
 }
 ++fp->offset; //how to gain access to the current offset of the stream?
 return 0;
}

我尝试重新创建 fputc 的地方。

这是 MYFILE 结构:

typedef struct {
    int fileD; // descriptor
    int bufferSz; // buffer size
    int bufferCh; // # of bytes in stream
    int offset; //current offset position
    int errorF; // error flag
    int EOFF; // EOF flag

} MYFILE;

最佳答案

文件权限可能应该是 0644,也可能是 0666(或者可能是 0640/0660,以拒绝其他人访问,同时允许您的组访问),无论您创建的文件是用于读取还是写入。您通常不应该包含执行权限(您也没有)。我愿意支持更少的组权限(不写组对我来说似乎很好)。当当前进程具有 0444 或更严格的写权限时,您甚至可以为每个其他进程将文件设置为只读。但标准将使用 0666 并让 umask 删除权限。

您可能会注意到,如果您未能打开该文件,您的代码就会泄漏。您应该在返回错误路径之前 free(fp);

请注意,您没有设置结构中的所有字段,也没有设置 malloc(),因此这些字段中存在随机垃圾。奇怪的是,尽管有缓冲区大小,但看不到缓冲区。


这段代码对我有用。它稍微清理了您的 myfopen() 函数,但除此之外,它运行时不会崩溃。我认为您的问题出在其他代码中。

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

typedef struct
{
    int fileD; // descriptor
    int bufferSz; // buffer size
    int bufferCh; // # of bytes in stream
    int offset; // current offset position
    int errorF; // error flag
    int EOFF; // EOF flag
} MYFILE;

static
MYFILE *myfopen(const char *path, const char *mode)
{
    MYFILE *fp = (MYFILE *)malloc(sizeof(*fp));
    int fd;
    switch (mode[0])
    {
    case 'r':
        fd = open(path, O_RDONLY | O_CREAT, 0640);
        break;
    case 'w':
        fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
        break;
    default:
        fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0640);
        break;
    }

    if (fd < 0)
    {
        free(fp);
        return NULL;
    }

    fp->fileD = fd;
    fp->offset = 0;
    fp->bufferSz = 0;
    fp->bufferCh = 0;
    fp->errorF = 0;
    fp->EOFF = 0;
    return fp;
}

static
int myfputc(int c, MYFILE *fp)
{
    if (write(fp->fileD, &c, 1) == -1)
    {
        return 1;
    }
    ++fp->offset; // how to gain access to the current offset of the stream?
    return 0;
}

int main(void)
{
    MYFILE *fp = myfopen("./test.txt", "w");
    if (fp != 0)
    {
        const char *src = "The text!\n";
        while (*src != '\0')
            myfputc(*src++, fp);
    }
    return 0;
}

结果:

$ ls -l test.txt
-rw-r-----  1 jleffler  staff  10 Feb 15 19:11 test.txt
$ cat test.txt
The text!
$ 

关于c - 使用 O_CREAT 调用 open() 的默认模式是什么以及如何在打开/创建文件时正确设置它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28533553/

相关文章:

c - 编码维吉尼亚密码时c中的段错误

c - 对 mprotect 的调用太多

c - 你如何在c中使用 float 作为指数

linux - 用于非阻塞、面向行的套接字 I/O 的 C++ 库?

c - 与线程相关的错误文件描述符

c - 引用 fgets,\0 如何合并到普通文本文件中

c - 如何在C中将数组写入文件

多线程上的困惑

c++ - 使用制表符和空格读入文件

linux - ^[ :blank:] does not match dot in sed