The cp command is used to copy the contents of a file to another file, such that the target file has the same contents as the target file, but uses the name and directory specified by the user. For example, if I do the command cp file1 /user/scott/file2 the contents of file1 will be copied and created in the location /user/scott/file2.
To be able to implement this logic, we need to understand how to create and write to a file. The creat system call attempts to open a file for writing, creating the file if it doesn’t already exist. If there is already a file with the name provided, it will discard its contents, and allow for writing. When we create a file, we will also provide a permission set for the file. For example, creat(“test”,0644) will create a file named test with permission bits 0644. If the file test already exists, the permission bit set will not be altered in any way.
There is another system call to write files called write. This system call can be used after a file is opened. It allows you to write a buffer of n bytes to a provided file descriptor. Using this with our creat system call will allow us to write content to a file, creating the file if it doesn’t exist.
Now that we understand how to work with files, we can look at the general process flow of the cp command. The idea will be to implement the following logic:
- Open the source file to read.
- Open the copy file for writing, or create it if it doesn’t already exist.
- Read the source file into a buffer
- Write from the buffer to the copy file
- Close the source file and copy file
We will start by defining constants for the buffer size, and mode for our copy file. We will first check if the user-supplied a valid number of arguments, exiting if the number of arguments is not 2. From here, we first get the file descriptor related to opening the source file we are working with, using the open system call. Next, we use the creat system call to attempt to open or create the destination file, getting the file descriptor of the resulting file.
Once this is done, we read the buffer size into our buffer from the source file and write it to the destination file. We do this until we either cannot write to the destination file or have exhausted the source file. Once this is completed, we make sure we actually transferred the data, and close the files.
Testing this in our command line shows that we can copy test files successfully. Note that the system command cmp compares two files to determine if there are any differences. With our test, it returns nothing, meaning that the files are exactly similar, and our copy function worked successfully.