Copy content from one file to another in C

Given one txt file Im trying to make a C program that copy the content of that into other which name is passed by arguments.The program must read blocks of 512 bytes from the source file and write the bytes read in the destination file.

My attempt:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include<fcntl.h>

int main(int argc, char* argv[]){
    if(argc < 2){
        printf("ERROR: Missing arguments\n");
        exit(1);    
    }

    int fdo, fdd;

    if((fdo = open(argv[1], O_RDONLY)) == -1){
        printf("ERROR: Origin file %s can not be opened\n", argv[1]);
        exit(1);
    }

    if(fdd = open(argv[2], O_CREAT | O_TRUNC, 0666) == -1){
        printf("ERROR: Dest. file %s can not be opened\n", argv[2]);
        exit(1);
    } 

    char buff[512];
    size_t n_bytes;

    while((n_bytes = read(fdo,buff,512)) > 0){
        if(write(fdd,buff,n_bytes) < 0){
            printf("Can not write buffer content in %s \n", argv[2]);
            exit(1);
        }
    }

    if(n_bytes < 0){
        printf("Can not read %s file \n", argv[1]);
        exit(1);
    }

    close(fdo);
    close(fdd);

    return 0;
}

The content of the file test.txt is:

abcdef
1890

And their permissions are:

usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ ls -l
total 32
-rwxrwxr-x 1 usuarioso usuarioso 17048 nov 23 16:15 copyrf
-rw-rw-r-- 1 usuarioso usuarioso   774 nov 23 16:39 copyrf.c
-rw-rw-r-- 1 usuarioso usuarioso    12 nov 23 16:52 test.txt

However when I execute it I get the following:

usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ gcc -o copyrf copyrf.c
usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ ./copyrf test.txt test1.txt
abcdef
1890
usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ ls -l
total 28
-rwxrwxr-x 1 usuarioso usuarioso 17008 nov 23 17:00 copyrf
-rw-rw-r-- 1 usuarioso usuarioso   771 nov 23 16:59 copyrf.c
-rw-rw-rw- 1 usuarioso usuarioso     0 nov 23 17:00 test1.txt
-rw-rw-r-- 1 usuarioso usuarioso    12 nov 23 16:52 test.txt
usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ cat test1.txt
usuarioso@usuarioso-virtualbox:~/Documentos/SO 2022/pr2/API de ficheros y directorios$ 

i.e the file test1.txt is created but is empty and the content of the file test.txt is printed in console.

What am I missing?

>Solution :

Clang’s gcc points out the problem pretty well:

$ gcc temp.c
temp.c:19:12: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
    if(fdd = open(argv[2], O_CREAT | O_TRUNC, 0666) == -1){
       ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
temp.c:19:12: note: place parentheses around the assignment to silence this warning
    if(fdd = open(argv[2], O_CREAT | O_TRUNC, 0666) == -1){
           ^
       (                                                 )
temp.c:19:12: note: use '==' to turn this assignment into an equality comparison
    if(fdd = open(argv[2], O_CREAT | O_TRUNC, 0666) == -1){
       ^
           ==

… in particular, fdd is being set to the result of (open(...) == -1), i.e. to 1 if the open() call returned -1, or to 0 if the open() call returned any other value. Since neither 0 nor 1 is the value of the file-descriptor returned by open(), your subsequent calls to write(fdd, ...) are using an invalid file-descriptor value and therefore failing.

The fix would be to add parentheses as you did for your first/open-for-read open() call, making it like this instead:

if((fdd = open(argv[2], O_CREAT | O_TRUNC, 0666)) == -1){

In addition to that, you need to add O_WRONLY to the oflag argument of your second call to open(), otherwise fdd will not be allowed to write to the file.

Leave a Reply