Copy files into a directory using call systems

Viewed 32

I have a program that take two files Source and Destination.
I am trying to Copies the SOURCE file to the DESTINATION file. If DESTINATION does not exist, it is created. If DESTINATION exists and is a file, it is overwritten. If DESTINATION exists and is a directory, the source files will be copied there.

How can i copy the source file into the destination directory using calls system ?

What i tried :

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "checksum.h"

int main (int argc, char *argv[])
{
    if (argc < 3) {
        fprintf(stderr, "Usage: lcp [-b taille] source... destination\n");
        exit(1);
    }

    int fd1 = open(argv[1], O_RDONLY, 0644); //0644 — owner can read or write, group and others can only read; or something more restrictive).
    if (fd1 < 0)
    {
        fprintf(stderr, "%s: failed to open file %s for reading\n", argv[0], argv[1]);
        return 1;
    }
    int fd2 = open(argv[2], O_RDWR|O_CREAT);  
    if (fd2 < 0)
    {
        fprintf(stderr, "%s: failed to open file %s for reading and writing\n", argv[0], argv[2]);
        return 1;
    }

    close(fd1);  
    close(fd2);  
    return 0;  
}
1 Answers

You just need a loop that does a read on a buffer and a write of that buffer.

Note that most of the time if you ask read to get (e.g.) 100 bytes, it will do so for most files. It may return less than that, particularly if the file size is not a multiple of 100. So, we must account for "short" reads (and errors). Likewise for write

Here is the refactored code. It is annotated:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
//#include "checksum.h"

// xread -- read in data (account for short reads and errors)
// RETURNS: number of bytes read
ssize_t
xread(int fd,void *buf,size_t buflen)
{
    unsigned char *bp = buf;
    ssize_t curlen;
    ssize_t totlen = 0;

    // continue reading until end of buffer or read error
    for (;  buflen > 0;  buflen -= curlen, totlen += curlen) {
        // read next chunk
        // NOTE: curlen may be less than buflen
        curlen = read(fd,&bp[totlen],buflen);

        // got an EOF
        if (curlen == 0)
            break;

        // read error
        if (curlen < 0) {
            // handle interruptions from signals
            if (errno == EINTR)
                continue;
            perror("xread");
            exit(1);
        }
    }

    return totlen;
}

// xwrite -- write out data (account for short reads and errors)
// RETURNS: number of bytes written
ssize_t
xwrite(int fd,const void *buf,size_t buflen)
{
    const unsigned char *bp = buf;
    ssize_t curlen;
    ssize_t totlen = 0;

    // continue writing until end of buffer or write error
    for (;  buflen > 0;  buflen -= curlen, totlen += curlen) {
        // write next chunk
        // NOTE: curlen may be less than buflen
        curlen = write(fd,&bp[totlen],buflen);

        // got EOF (NOTE: this should _never_ happen)
        if (curlen == 0)
            break;

        // write error
        if (curlen < 0) {
            // handle interruptions from signals
            if (errno == EINTR)
                continue;
            perror("xwrite");
            exit(1);
        }
    }

    return totlen;
}

int
main(int argc, char *argv[])
{
    if (argc < 3) {
        fprintf(stderr, "Usage: lcp [-b taille] source... destination\n");
        exit(1);
    }

    // 0644 — owner can read or write, group and others can only read; or
    // something more restrictive).
    int fd1 = open(argv[1], O_RDONLY, 0644);
    if (fd1 < 0) {
        fprintf(stderr, "%s: failed to open file %s for reading\n",
            argv[0], argv[1]);
        return 1;
    }

    int fd2 = open(argv[2], O_RDWR | O_CREAT, 0644);
    if (fd2 < 0) {
        fprintf(stderr, "%s: failed to open file %s for reading and writing\n",
            argv[0], argv[2]);
        return 1;
    }

    // loop through file and copy bytes
    unsigned char buf[64 * 1024];
    while (1) {
        ssize_t rlen = xread(fd1,buf,sizeof(buf));
        if (rlen <= 0)
            break;
        xwrite(fd2,buf,rlen);
    }

    close(fd1);
    close(fd2);

    return 0;
}

Note: As Andrew pointed out, the open with O_CREAT needs a mode argument

Related