系统调用"打开"无法使用O_CREAT标志创建文件

时间:2016-06-25 08:57:03

标签: c linux system-calls

我必须使用linux的系统调用来完成练习:

  1. 打开文件" testinput.txt" (已存在于工作目录中,不为空)
  2. 打开文件" testoutput.txt" (不在工作目录中)
  3. 复制testoutput中的testinput内容
  4. 关闭两个文件
  5. 我发现我可以使用系统调用打开文件open可以打开输入文件(标记O_RDONLY)和输出文件(标记O_CREAT | O_WRONLY)。

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

    Errno说代码2 ="没有这样的文件或目录" (显然,我要求创建文件)。我做错了什么?

    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

1 个答案:

答案 0 :(得分:3)

我在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

让它发挥作用。