File System (fs) Project
COP-3402
Table of Contents
1. Overview
In this project, you will implement a variation of the cp
command called mycp
.
2. Input
USAGE: ./mycp source_file target_file
The program should be called mycp
. It takes two arguments: source_file
is an existing, regular file; and target_file
is either an existing file or a non-existent file but in an existing directory. The source and destination should not be the same file.
3. Input validation
Report errors via exit codes passed to the exit
library call, e.g., exit(5)
terminates the program with exit code 1
.
Error messages are optional, but should only be written to stderr, not to stdout, which will be used for program output, i.e., use fprintf(stderr, ...)
instead of printf
.
3.1. Number of arguments
Exit with exit code 3
if there are not two arguments (remember that argc
will be 3, since it includes the name of the program itself). A useful error message is to print the usage instructions, e.g.,
fprintf(stderr, "USAGE: ./mvplus source_file target_file\n");
3.2. Source file
Exit with exit code 4
if source_file
does not exist or cannot be opened for any other reason, i.e., if stat
fails.
Exit with exit code 5
if source_file
is not a regular file, i.e., check that (statbuf.st_mode & S_IFMT)
is S_IFREG
, where statbuf
is the result of the call to stat
.
3.3. Syscall Errors
For any other system calls that fail, use exit code EXIT_FAILURE
, which is defined in stdlib.h
.
3.4. Exit code precedence
If an input violates multiple exit codes, only the lowest-numbered exit code should be produced. Consider EXIT_FAILURE to be the lowest-numbered exit code.
3.5. Checking for the same file
It is not required to check that the source and destination are the same file, thought it may be one part of a bonus project extension. What can we look at to see whether two paths are referring to the same file (same as determined by the file system)?
4. Output
When running successfully, the program should exit with the success exit code (0 or EXIT_SUCCESS), which is the default exit code returned by main. The destination file should be a different file that has the exact same byte contents as the source file. If the destination file exists, it should be overwritten. If it doesn't exist, then it should be created. No directories should be created; it is an error if the destination file is in a non-existent directory.
5. System call and library references
Do not use helper libraries or other simplified calls to achieve similar results as functions below. Just use the syscalls below for these aspects of the project.
Symbol | Reference | Reading |
---|---|---|
stat() | man 2 stat |
LPI 15.1 |
struct stat | man 2 stat |
|
st_mode | man 7 inode |
|
open() | man 2 open |
LPI 4.1 |
read() | man 2 read |
|
write() | man 2 write |
|
close() | man 2 close |
|
perror() | man 3 perror |
LPI 3.4 |
exit(EXIT_FAILURE) | man 3 exit |
man
is the command-line manual.- LPI is The Linux Program Interface book.
- Knowledge of memory management and string processing is assumed.
6. Building and running the tool
Create a Makefile that will build your project and give the resulting program the name mycp
. See the hello project for an example Makefile.
Your project must be buildable with make
and runnable with ./mycp
, both from the root of your repo, i.e.,
make ./mycp
Automated grading will build and run your tool this way and only this way.
7. Submitting your project
7.1. git
setup
Be sure to complete the git exercise before attempting this project.
Create a new local repository, following the directions in the git exercise (including the git --set-upstream
last step) and set the local and remote repository URLs to be the following locations:
Local repository | ~/cop3402spring25/fs |
Remote repository | gitolite3@eustis3.eecs.ucf.edu:cop3402/$USER/fs |
7.2. Self-check
See the hello project for instructions on cloning a project from the grading server.
8. Grading
The test cases used to grade the project are listed below. Scripts to run the the odd-numbered test cases are provided publicly, while the even-numbered test cases are private.
To use the automated tests, first download them, e.g.,
cd ~/cop3402spring25/fs wget https://www.cs.ucf.edu/~gazzillo/teaching/cop3402spring25/files/fs_public_tests.tar tar -xvf fs_public_tests.tar
To run a test case, e.g., tests/03-threeargs.sh
, use the following bash command from the root of your local repository directory:
bash tests/03-threeargs.sh $(readlink -f mycp)
This runs the bash script, passing in the absolute path to your program, which is what $(readlink -f mycp)
does.
8.1. Test cases
# | Short Name | Description | Expected Output |
---|---|---|---|
1 | noargs | Call mycp with no arguments. | It should fail with the appropriate exit code. |
2 | onearg | Call mycp with one argument. | It should fail with the appropriate exit code. |
3 | threeargs | Call mycp with three arguments. | It should fail with the appropriate exit code. |
4 | missingsource | Call mycp with a source file that does not exist. | It should fail with the appropriate exit code. |
5 | dirsource | Pass a directory as the source file. | It should fail with the appropriate exit code. |
6 | destdirnotexist | The source file exists but the destination file is in a directory that does not exist. | It should fail with the appropriate exit code for a failed syscall. |
7 | destisdir | Use a directory as the target file. | It should fail with the appropriate exit code. |
8 | emptysourcedest | The source and destination files both exist and are empty. | After running, the destination file should exist. |
9 | sourceemptydestnotexist | Use an empty source file and provide a destination file that does not exist but will be in an existing directory. | After running, the destination file should exist and be empty. |
10 | sourcedestnotexist | The source exists and is non-empty, but the destination does not exist (but is targeting an existing directory). | After running, the destination file should exist and contain the contents of the source file. |
11 | sourcedestexistshorter | The source file exists and is non-empty and the destination exists and contains fewer bytes than the source. | After running, the destination should exist and contain the exact contents of the source file. |
12 | sourcedestexistlonger | The source file exists and is non-empty and the destination exists, is non-empty, and is longer than the source file. | After running, the destination should exist and contain only the contents of the source file (none of the contents of the destination file). |
13 | sourcedestdirexistlonger | The source is an existing file and the destination file is in a different directory and is larger than the destination file. | After running, the destination should exist and contain the exact contents of the source file. |
9. Bonus project ideas
- Create a version of the copy that avoids a race condition where a component of the target path is changed during the open. See the manpages for open(2) and openat2(2)
- If the directory (or directories) in the target file do not exist, create them first.
- Add a command-line flag that provides an option to avoid overwriting an existing file or other features similar to cp's -i, -u, or -n. See the manpage for cp(1).
- Come up with your own extension or change and propose it.
10. Grading schema
Criterion | Points |
---|---|
The git repo exists | 1 |
The program is written, builds, and runs as described here | 1 |
Tests pass, prorated by the number of test cases passing | 6 |
TOTAL | 8 |