系统调用"open"无法使用O_CREAT标志创建文件。

3

我需要使用Linux的系统调用完成一个练习:

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

我发现可以使用系统调用open打开输入文件(标志O_RDONLY)和输出文件(标志O_CREAT | O_WRONLY)。

输入文件能正常工作。但输出文件不能。

错误代码是2 = “No such file or directory”(显然,我要求创建文件)。我做错了什么?

P.S.:为了强调我正在使用系统调用,我没有调用函数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;   
}

整个代码:

#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;
}

Screenshot of the execution


3
“438”是用非常奇怪的方式表示“0666”。 - melpomene
如果使用open()而不是通过syscall()来执行,你能够成功地创建(并写入)输出文件吗? - user707650
为什么不使用 #include <fcntl.h> - jxh
@melpomene 这段代码将由我的队友手动翻译成汇编语言,我不确定他知道如何用八进制写666。我太懒了,没有写注释并希望他检查如何制作,我解决了写十进制常数的问题。 - incud
@jxh 在汇编(gas)中,我们不知道如何包含C头文件,所以我们可能会直接写常量。为了让这段C代码与我们要编写的汇编类似,我决定直接写常量(出于同样的原因,我使用了syscall()代替open(),write()等函数)。 - incud
1个回答

5

我使用strace运行了你的代码,并得到了以下结果:

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

即,您关于O_*标志的定义是错误的。

事实证明,有不止一个问题: 0x0200 实际上是 O_TRUNC(而不是 O_CREAT),0x0400 实际上是 O_APPEND(而不是 O_TRUNC)。

将其更改为

#define O_CREAT 0x0040
#define O_TRUNC 0x0200

使其正常运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接