14

I want to rewrite the "cp" command of Linux. So this program will work like #./a.out originalfile copiedfile. I can open the file, create new file but can't write the new file. Nothing is written. What could be the reason?

The current C code is:

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main(int argc,char *aa[]){ int fd,fd1; char buffer[100]; if(argc!=3){ printf("Usage : ./a.out <original> <copy> \n"); return -1; } fd=open(aa[1],O_RDONLY,S_IRUSR); if(fd==-1){ printf("file not found.\n"); return -1; } fd1=open(aa[2],O_CREAT | O_WRONLY,S_IRUSR); if(fd1!=-1){ printf("file is created.\n"); } ssize_t n; while(n=read(fd,buffer,50)){ write(fd1,buffer,n); printf("..writing..\n"); } close(fd); close(fd1); } 
4
  • 2
    Unused variable fd2; don't forget to check that write writes everything you expected it to; don't use assignments as conditions (use GCC -Wall); it is still better to return a value from main() though C99 (mistakenly) permits you to leave the return off main(). Your error message for fd1 is incorrect; you don't exit when it fails on fd1. You could use sizeof(buffer) in the read instead of 50 which is half the size of your buffer. Errors are classically written to stderr, not stdout. Your loop runs into problems if the read fails (negative value) as opposed to returning nothing. Commented Jan 5, 2010 at 19:18
  • Just copied and pasted your code onto my machine, compiled with gcc and it works fine. Commented Jan 5, 2010 at 19:47
  • 1
    Oh, something miracle happened. Because of your comment, I tried to move the file to another place and tested again. It WORKS!!! Thank you so much. Commented Jan 5, 2010 at 21:26
  • Perhaps if you changed the conditional check after the destination file open so that if it failed you printed (to stderr, of course) the errno and error message, you would have a better idea of exactly why nothing is written. Good C programming practice is to always check system calls for error returns. Commented Jan 5, 2010 at 21:56

4 Answers 4

18

You need to write() the read() data into the new file:

ssize_t nrd; int fd; int fd1; fd = open(aa[1], O_RDONLY); fd1 = open(aa[2], O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); while (nrd = read(fd,buffer,50)) { write(fd1,buffer,nrd); } close(fd); close(fd1); 

Update: added the proper opens...

Btw, the O_CREAT can be OR'd (O_CREAT | O_WRONLY). You are actually opening too many file handles. Just do the open once.

Sign up to request clarification or add additional context in comments.

5 Comments

Hi, thanks for the reply. I edited my post with new code. I tried as you said but still not working. Nothing is written to new file. Please help me!
I'm sorry but still not working. I put some string inside the while loop and it showed that while loop worked only once. :(
Yeah, my code isn't perfect, but its a good nudge in the right direction. Keep playing with it. Like Jonathan says in his comment on your post, you have quite a few issues with the code. You'll want to check the read() return for == 0. Also You need to probably use sizeof(buffer) instead of 50. But I was just trying to give a helpful nudge, not take away the fun/frustration of finding the answer by yourself.
I agree with you but sometimes you know, we don't have enough time to find out the answers ourself. Actually, I always find the solutions out by myself but for this problem, I'm having exam tomorrow. I already spent hours for this problem. Thanks for the help anyway!
@Devyn Usually when someone doesn't have time to complete a task, they pay someone else to do it. I wish I could get free programming when I get too much work to do. :)
14

First of all, the code you wrote isn't portable, even if you get it to work. Why use OS-specific functions when there is a perfectly platform-independent way of doing it? Here's a version that uses just a single header file and is portable to any platform that implements the C standard library.

#include <stdio.h> int main(int argc, char **argv) { FILE* sourceFile; FILE* destFile; char buf[50]; int numBytes; if(argc!=3) { printf("Usage: fcopy source destination\n"); return 1; } sourceFile = fopen(argv[1], "rb"); destFile = fopen(argv[2], "wb"); if(sourceFile==NULL) { printf("Could not open source file\n"); return 2; } if(destFile==NULL) { printf("Could not open destination file\n"); return 3; } while(numBytes=fread(buf, 1, 50, sourceFile)) { fwrite(buf, 1, numBytes, destFile); } fclose(sourceFile); fclose(destFile); return 0; } 

EDIT: The glibc reference has this to say:

In general, you should stick with using streams rather than file descriptors, unless there is some specific operation you want to do that can only be done on a file descriptor. If you are a beginning programmer and aren't sure what functions to use, we suggest that you concentrate on the formatted input functions (see Formatted Input) and formatted output functions (see Formatted Output).

If you are concerned about portability of your programs to systems other than GNU, you should also be aware that file descriptors are not as portable as streams. You can expect any system running ISO C to support streams, but non-GNU systems may not support file descriptors at all, or may only implement a subset of the GNU functions that operate on file descriptors. Most of the file descriptor functions in the GNU library are included in the POSIX.1 standard, however.

4 Comments

I think you make a good point about using streams... (I didnt down vote you), but I'll upvote you back to zero.
The downvote itself doesn't bother me at all, it's the why that I'm interested in. Feedback, whether positive or negative, helps me improve myself. If I can do that while (hopefully) helping someone else at the same time, nothing like it.
I didn't downvote too. Your solution isn't "perfect" - as you probably know - but I am going to upvote. Just to enforce the downvoter to explain the reason.
Yes, I do know that the solution isn't perfect. This was something I hacked up during a break and is meant to be illustrative rather than production quality...
3

You have to do write in the same loop as read.

Comments

2

You have to allocate the buffer with mallock, and give the read write the pointer to it.

#include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main(){ ssize_t nrd; int fd; int fd1; char* buffer = malloc(100*sizeof(char)); fd = open("bli.txt", O_RDONLY); fd1 = open("bla.txt", O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); while (nrd = read(fd,buffer,sizeof(buffer))) { write(fd1,buffer,nrd); } close(fd); close(fd1); free(buffer); return 0; } 

Make sure that the rad file exists and contains something. It's not perfect but it works.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.