系统调用“open”无法创建带有 O_CREAT 标志的文件

inc*_*cud 3 c linux system-calls

我必须使用 Linux 的系统调用完成一个练习:

  1. 打开文件“testinput.txt”(已存在于工作目录中,不为空)
  2. 打开文件“testoutput.txt”(工作目录中不存在)
  3. 将 testinput 的内容复制到 testoutput 中
  4. 关闭两个文件

我发现我可以使用系统调用打开文件,open既可以打开输入文件(flag O_RDONLY)又可以打开输出文件(flag O_CREAT | O_WRONLY)。

输入文件工作正常。输出文件没有。

Errno 表示代码 2 =“没有这样的文件或目录”(显然,我要求创建该文件)。我究竟做错了什么?

PS:为了强调我正在使用系统调用,我不是在调用函数,open(...)而是syscall(SYS_OPEN, ...)

outFileDesc = syscall(SYS_OPEN, "testoutput.txt", O_WRONLY | O_TRUNC | O_CREAT, 438);
if(outFileDesc == -1) {
    int code = errno;

    // gdb used here -> print code -> 2

    char str[] = "Unable to open \"testoutput.txt\"\n";
    syscall(SYS_WRITE, FILE_DESC_STDOUT, str, sizeof(str)/sizeof(char));
    syscall(SYS_CLOSE, inFileDesc);
    syscall(SYS_EXIT, 1);
    return 1;   
}
Run Code Online (Sandbox Code Playgroud)

整个代码:

#include <unistd.h>
#include <sys/syscall.h>
#include <errno.h>

/* file flags fcntl.h */
#define O_RDONLY    0x0000      /* open for reading only */
#define O_WRONLY    0x0001      /* open for writing only */
#define O_CREAT     0x0200      /* create if nonexistant */
#define O_TRUNC     0x0400      /* truncate to zero length */

#define FILE_DESC_STDOUT 1

#define SYS_EXIT 1
#define SYS_READ 3
#define SYS_WRITE 4
#define SYS_OPEN 5
#define SYS_CLOSE 6

#define IN_MESSAGE_LEN 9
#define OUT_MESSAGE_LEN 9

char inBuffer[IN_MESSAGE_LEN];
char outBuffer[OUT_MESSAGE_LEN];

int main (int argc, char *argv[])
{
    int inFileDesc, outFileDesc;

    // Apertura fine di input
    inFileDesc = syscall(SYS_OPEN, "testinput.txt", O_RDONLY, 438);
    if(inFileDesc == -1) {
        char str[] = "Unable to open \"testinput.txt\"\n";
        syscall(SYS_WRITE, FILE_DESC_STDOUT, str, sizeof(str)/sizeof(char));
        syscall(SYS_EXIT, 1);
        return 1;   
    }

    // Apertura fine di output
    outFileDesc = syscall(SYS_OPEN, "testoutput.txt", O_WRONLY | O_TRUNC | O_CREAT, 438);
    if(outFileDesc == -1) {
        int code = errno;

        char str[] = "Unable to open \"testoutput.txt\"\n";
        syscall(SYS_WRITE, FILE_DESC_STDOUT, str, sizeof(str)/sizeof(char));
        syscall(SYS_CLOSE, inFileDesc);
        syscall(SYS_EXIT, 1);
        return 1;   
    }

    // Travaso contenuto file di input in file di output
    int read, i;
    while((read = syscall(SYS_READ, inFileDesc, inBuffer, IN_MESSAGE_LEN)) != 0) {

        for(i = 0; i < IN_MESSAGE_LEN; i++) {
            outBuffer[i] = inBuffer[i];
        }

        syscall(SYS_WRITE, outFileDesc, outBuffer, OUT_MESSAGE_LEN);
    }

    syscall(SYS_CLOSE, inFileDesc);
    syscall(SYS_CLOSE, outFileDesc);

    syscall(SYS_EXIT, 0);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

执行截图

mel*_*ene 5

我运行你的代码strace并得到:

...
open("testinput.txt", O_RDONLY)         = 3
open("testoutput.txt", O_WRONLY|O_TRUNC|O_APPEND) = -1 ENOENT (No such file or directory)
//                                      ^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

即您对O_*标志的定义是错误的。

事实证明,有不止一件事是错误的:0x0200实际上是O_TRUNC(不是O_CREAT),并且0x0400实际上是O_APPEND(不是O_TRUNC)。

将其更改为

#define O_CREAT 0x0040
#define O_TRUNC 0x0200
Run Code Online (Sandbox Code Playgroud)

让它发挥作用。