Using open(), read() and write() system calls to copy a file

Austin Heath Source

I'm having trouble using read(), write(), and open() to copy a file into a new directory. I'm able to create a new file with open() and I'm able to write to the terminal with write() but I was under the assumption that if I passed my int file descriptor from open to write, write would write to the specified file.

In addition to this, once I open a file the permissions are all funky and I can only open it as root. Each time I create a file, it's completely empty but I can see the entire file I just read be printed out in the terminal.

I've read through the man files for each system call but I'm still not grasping what the issue is here.

Here's my code:

void *scanFile( s_request *request )
{
    //TODO Print out all struct variables.
    pthread_mutex_lock(&mutex);

    int readFileReference;
    int writeFileReference;
    int bufferSize = request->bufferSize;
    int numberOfBytesRead = bufferSize;
    int *buffer[bufferSize];

    if ((readFileReference = open(request->file, O_RDONLY)) == -1)
    {
        printf("Failed to open file. Aborting.\n");
        exit(EXIT_FAILURE);
    }

    if ((writeFileReference = open("newfile.txt", O_CREAT | O_APPEND | O_RDWR) == -1))
    {
        printf("Failed to open write file. Aborting.\n");
        exit(EXIT_FAILURE);
    }

    while ((read(readFileReference, buffer, numberOfBytesRead)) != 0)
    {
        write(writeFileReference, buffer, bufferSize);
        bzero(buffer, bufferSize);
    }

    pthread_mutex_unlock(&mutex);
}

Fixed the issue:

Updated code:

void *scanFile( s_request *request )
{
    //TODO Print out all struct variables.
    pthread_mutex_lock(&mutex);

    int readFileReference;
    int writeFileReference;
    int bufferSize = request->bufferSize;
    int numberOfBytesRead = bufferSize;
    int *buffer[bufferSize];

    if ((readFileReference = open(request->file, O_RDONLY)) == -1)
    {
        printf("Failed to open file. Aborting.\n");
        exit(EXIT_FAILURE);
    }

    if ((writeFileReference = open("newfile.txt", O_CREAT | O_WRONLY, 0777)) == -1)
    {
        printf("Failed to open write file. Aborting.\n");
        exit(EXIT_FAILURE);
    }

    while ((read(readFileReference, buffer, numberOfBytesRead)) != 0)
    {
        write(writeFileReference, buffer, bufferSize);
        bzero(buffer, bufferSize);
    }

    close(writeFileReference);
    close(readFileReference);

    pthread_mutex_unlock(&mutex);
}
cpthreads

Answers

answered 11 months ago duskwuff #1

if ((writeFileReference = open("newfile.txt", O_CREAT | O_APPEND | O_RDWR) == -1))

You've got the parentheses wrong on this line. (It's correct on the readFileReference line.) What you want is:

if ((writeFileReference = open("newfile.txt", O_CREAT | O_APPEND | O_RDWR)) == -1)
                                                                         ^^^    ^^^

Your original version of that line was calling open(), performing a comparison to -1, then assigning the result of that comparison to writeFileReference.

Additionally:

  • As noted by Zan Lynx in a comment, you need to pass a permissions value to open() when creating a file. 0666 is typically correct -- it'll create the file as readable/writable. (It's modified by the process umask, so it'll end up creating the file as 0644 under a typical configuration.)

  • You need to save the return value from read somewhere and pass that as the third argument to write (instead of bufferSize). Otherwise, your program will write more bytes than were read, e.g. when copying small files.

  • Technically, you should be checking the return value from write(). Just like read(), it's not guaranteed to complete a full write every time it's called. (In practice, when working with regular files, it will always either complete the write or return an error, but there are some esoteric situations where this may not be the case.)

  • You don't need to bzero() the buffer after writing from it.

comments powered by Disqus