CS 355 - Systems Programming:
Unix/Linux with C
How to Copy a File
Reference: Molay, Understanding Unix/Linux Programming, Chapter 2.6-2.8
The cp command
Our standard approach to studying a Unix system command:
What does cp do?
Typical usage of cp to copy a file:
cp source_file target_file
Read the manual:
$ man cp
CP(1) BSD General Commands Manual CP(1)
NAME
cp -- copy files
SYNOPSIS
cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file target_file
cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file ...
target_directory
DESCRIPTION
In the first synopsis form, the cp utility copies the contents of the
source_file to the target_file. In the second synopsis form, the con-
tents of each named source_file is copied to the destination
target_directory. The names of the files themselves are not changed. If
cp detects an attempt to copy a file to itself, the copy will fail.
. . .
How does cp do it?
cp uses two system calls in addition to open, read, and close:
Can I write cp?
The basic operation of cp:
open sourcefile for reading
open copyfile for writing
while not EOF
read from source to buffer
write from buffer to copy
close sourcefile
close copyfile
C source code for cp:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFFERSIZE 4096
#define COPYMODE 0644
int main(int ac, char *av[])
{
int in_fd, out_fd, n_chars;
char buf[BUFFERSIZE];
/* check arguments */
if (ac != 3){
fprintf(stderr, "usage: %s source destination\n", *av);
return 1;
}
/* open files */
if ((in_fd=open(av[1], O_RDONLY)) == -1) {
perror("Cannot open source file");
return 1;
}
if ((out_fd=creat( av[2], COPYMODE)) == -1) {
perror("Cannot creat destination file");
return 1;
}
/* copy files */
while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0)
if (write(out_fd, buf, n_chars) != n_chars) {
perror("Write error");
return 1;
}
if (n_chars == -1) {
perror("read error");
return 1;
}
/* close files */
if (close(in_fd) == -1 || close(out_fd) == -1) {
perror("Error closing file(s) ");
return 1;
}
return 0;
}
Buffering
Consider the effect of the buffer size (BUFFERSIZE) on the number of read and write system calls. System calls are time consuming because jumping into and out of kernel takes time. The CPU runs in supervisor mode with a special stack and memory environment when executing kernel code and runs in user mode when executing user code.
Kernel buffering keeps copies of disk blocks in memory to reduce the time needed to write the data to the physical disk. It makes disk I/O faster, but it does not eliminate the need for buffering at the user code level.