使用 O_APPEND 的 open() 不更新 EOF

open() using O_APPEND does not update EOF

我正在写一份dup()函数(我正在为Linuxapi学习一本书)。

我有一个名为 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 ?

我不是在寻找解决方法,我有兴趣找出 error/problem 的原因。

  1. 文件已经更新为:

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

    bash> cat xxx
    Hello, World
    Kostasbash>
    

注意:bash>是你的提示符,有时你的提示符可能包含carrier return,这会将光标放在行首,考虑这种情况

输出提示前:

    bash> cat xxx
    Hello, World
    Kostas
          ^cursor here

运营商之后return:

    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。