#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#include <errno.h>

#include <string.h>

/* if this is defined then append to file if it exists */

#define COPY_APPEND

#define BUFFER_SIZE 256

int main ( int argc , char ** args )

{

if ( argc != 3 )

{

fprintf ( stderr , "ERROR: argument(s) missing!

" ) ;

return - 1 ;

}

int in = open ( args [ 1 ] , O_RDONLY ) ;

if ( in == - 1 )

{

fprintf ( stderr , "ERROR: could not open %s!

" , args [ 1 ] ) ;

return - 1 ;

}

#ifdef COPY_APPEND

int out = open ( args [ 2 ] , O_CREAT | O_WRONLY | O_APPEND , 0644 ) ;

#elif

int out = open ( args [ 2 ] , O_CREAT | O_WRONLY , 0644 ) ;

#endif

if ( out == - 1 )

{

fprintf ( stderr , "ERROR: could not open %s!

" , args [ 2 ] ) ;

return - 1 ;

}

char buffer [ BUFFER_SIZE ] ;

int ret ;

while ( ( ret = read ( in , buffer , BUFFER_SIZE ) ) > 0 )

{

if ( write ( out , buffer , ret ) <= 0 )

fprintf ( stderr , "ERROR: %s

" , strerror ( errno ) ) ;

}

close ( in ) ;

close ( out ) ;

return 0 ;

}

/* The buffer size in this case should be as big as possible, because everytime the buffer is full,

the kernel makes a context switch so we can write the buffer to the out file.

If the buffer size is 1 Byte, we would need to make 1000 context switches if we had

a 1000 Byte file. Therefore we should create the buffer size as big as possible for

the computer. */

/* lseek with offset 0 is needed to jump to the beginning of the file. After I found the

end of the file, I jumped back with lseek offset 0. */

/* 5a) opens a file for write/read and jumps to the end of the file. Then it writes something.

5b) opens a file for append/write/read and then it writes something.