-1

I am writing a copy of the dup() function (I am studying a book for the Linux api).

I have a file named temp.txt which contains one line with the following string: Hello, World.

Here is the code:

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

So, by running ./prog temp.txt successfully, the file temp.txt must contain the following string. Hello, WorldKostas

By running the command cat temp.txt the output I get is Hello, World, but, if I open the file on a text editor like nano I get Hello, World (followed by a new line which contains) kostas.

Why does the cat command produce an incorrect output? Why is there a new line added at the end of the string Hello, World ?

I am not looking for a workaround, I am interested in finding out the reason of the error/problem.

KostasRim
  • 2,053
  • 1
  • 16
  • 32
  • You can create your initial temp.txt file without the end-of-line character using `echo -n "Hello, World" > temp.txt`. – Ian Abbott Jul 28 '17 at 13:10
  • `EOF` is a macro used by C standard library functions, not a flag and not really stored in the file, nor part of the Linux API (hence `-1` from `read`, etc.). – too honest for this site Jul 28 '17 at 13:16
  • 2
    @KostasRim: 1) Don't assume who comments is also a downvoter. 2) Even if, it is at the discretion of the user whether he sees your question a DV candidate or not. Either way, complaining about a DV to a commenter is alwas contraproductive: If he is, he might next time not leave a comment, but silently DV; I don't think this is what you really want. If not, the DVer will not read the complaint and the commenter might consider a DV just for the false accusation. Just my thoughts. – too honest for this site Jul 28 '17 at 17:39

1 Answers1

1
  1. The file has already been updated to:

    Hello, World[eol]
    Kostas[no end-of-line here]
    
  2. cat will output the file content exactly, which wont output final eol, this is what your terminal show after cat:

    bash> cat xxx
    Hello, World
    Kostasbash>
    

NOTE: bash> is your prompt, sometimes your prompt may contains carrier return, which will put cursor at the beginning of the line, consider this situation

Before output prompt:

    bash> cat xxx
    Hello, World
    Kostas
          ^cursor here

After carrier return:

    bash> cat xxx
    Hello, World
    Kostas
    ^cursor here

Finally output prompt:

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

So, your prompt may overwrite the last line of output of cat if no eol at the end of the file.

BTW:

  1. When using vim opening a file, [noeol] will shown at bottom left to indicate a file without eol at the end of the file
  2. When using zsh, an % will shown if last command doesn't output eol at the end, and zsh will output an extra eol.
Zang MingJie
  • 5,164
  • 1
  • 14
  • 27
  • My terminal name is `kostas` so it was indeed overnighting that name. The only difference on the terminal was an extra `s` added to `kostas`. It was something like `kostass`. Such a small detail which I didn't even notice. Thanks for your answer. – KostasRim Jul 28 '17 at 16:50