使用O_APPEND打开()不会更新EOF

时间:2017-07-28 12:47:51

标签: c linux dup

我正在撰写dup()函数的副本(我正在研究Linux api的一本书)。

我有一个名为temp.txt的文件,其中包含一行,其中包含以下字符串:Hello, World

以下是代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

//NAIVE IMPLEMENTATION
int dup_t(int old) {
    if(old == -1) {
        errno = EBADF;
        return -1;
    }

    int flags;
    flags = fcntl(old, F_GETFL);
    if(flags == - 1) {
        errno = EBADF;
        return -1;
    }

    int new;
    if((new = fcntl(old, F_DUPFD)) == - 1) {
        errno = EBADF;
        return - 1;
    }
    return new;
}

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

    if(argc == 1) {
        printf("Error, no arguments given\n");
        exit(-1);
    }

    int fd, cpfd;

    if((fd = open(&argv[1][0], O_RDWR | O_APPEND)) == -1) {
        printf("Error opening the file\n");
        exit(-1);
    }

    cpfd = dup_t(fd);
    if(cpfd == -1) {
        printf("Error dup_t()\n");
        exit(-1);
    }

    if(close(fd) == -1) {
        printf("Error closing fd\n");
        exit(-1);
    }

    if(write(cpfd, "kostas", 6) == - 1) {
        printf("Error writting\n");
        exit(-1);
    }

    if(close(fd) == -1) {
        printf("Error closing fd\n");
        exit(-1);
    }

    if(write(cpfd, "kostas", 6) == - 1) {
        printf("Error writting\n");
        exit(-1);
    }

    if(close(cpfd) == -1) {
        printf("Error closing cpfd\n");
        exit(-1);
    }
}

因此,通过成功运行./prog temp.txt,文件temp.txt必须包含以下字符串。 Hello, WorldKostas

通过运行命令cat temp.txt,我得到的输出是Hello, World,但是,如果我在nano这样的文本编辑器上打开文件,我会得到Hello, World(其次是一个包含kostas的新行。

为什么cat命令会产生错误的输出? 为什么在字符串Hello, World的末尾添加了新行?

我不是在寻找解决方法,我有兴趣找出错误/问题的原因。

1 个答案:

答案 0 :(得分:1)

  1. 该文件已更新为:

    Hello, World[eol]
    Kostas[no end-of-line here]
    
  2. cat将输出文件内容完全,这不会输出最终的eol,这是您的终端在cat之后显示的内容:

    bash> cat xxx
    Hello, World
    Kostasbash>
    
  3. 注意:bash>是您的提示,有时您的提示可能包含carrier return,这会将光标放在行的开头,请考虑这种情况

    在输出提示之前:

        bash> cat xxx
        Hello, World
        Kostas
              ^cursor here
    

    运营商返回后:

        bash> cat xxx
        Hello, World
        Kostas
        ^cursor here
    

    最后输出提示:

        bash> cat xxx
        Hello, World
        bash>
              ^cursor here
    

    因此,如果文件末尾没有eol,你的提示可能会覆盖cat的最后一行输出。

    顺便说一句:

    1. 使用vim打开文件时,左下角会显示[noeol],表示文件末尾没有eol的文件
    2. 使用zsh时,如果最后一个命令最后没有输出eol,则显示%,zsh将输出额外的eol。