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?
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.