C Error Handling Challenge: The "Robust File Copier"
Your goal is to create a program that reads the content of one file and writes it into another. However, unlike a basic tutorial program, this one must be bulletproof. You must anticipate every possible failure point.
The Mission: Secure Data Transfer
You will write a program that takes a source filename and a destination filename. You must implement specific error-checking logic at every step of the execution.
Challenge Requirements
To complete this challenge successfully, your program must implement the following four pillars of error handling:
- 1. File Existence Check: Attempt to open the source file. If it doesn't exist, use
perror() to print a descriptive error and exit with EXIT_FAILURE.
- 2. Permission & Disk Check: Attempt to open the destination file for writing. If the disk is full or the file is read-only, use
strerror(errno) to print the exact system reason for failure.
- 3. Dynamic Buffer Allocation: Instead of a fixed array, use
malloc() to create a buffer (e.g., 1024 bytes). You must check if malloc returns NULL.
- 4. Clean Shutdown: Ensure that no matter where an error occurs, all open files are closed and all allocated memory is freed before the program terminates. No memory leaks allowed!
Starter Template
Use this structure to begin. Focus on replacing the comments with actual error-checking logic.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *src, *dest;
char *buffer;
// Task 1: Open source file and check for errors
src = fopen("source.txt", "r");
if (!src) { /* Handle error here */ }
// Task 2: Allocate memory for buffer and check for NULL
buffer = malloc(1024);
if (!buffer) { /* Handle error and close src */ }
// Task 3: Open destination and check for errors
// Task 4: Copy data and Clean up
return EXIT_SUCCESS;
}
Advanced Bonus Objectives
- Custom Error Codes: Create an
enum of custom error codes (e.g., ERR_FILE_NOT_FOUND, ERR_MEMORY_FULL) and return them instead of just 1.
- Math Safety: If you are calculating the percentage of the file copied, implement a check to prevent Division by Zero if the source file is empty (0 bytes).
- Signal Handling: Use
signal.h to catch a Ctrl+C (SIGINT) and print a "Cleanup and Exiting" message before the program dies.
Critical Error Handling Table
| Potential Failure |
C Detection Method |
Recovery Action |
| Source File Missing |
if (src == NULL) |
Print error and stop. |
| Out of RAM |
if (buffer == NULL) |
Close files, free partial, exit. |
| Disk Full during Write |
Check return of fwrite |
Delete partial file, report errno. |
Technical Tip: When an error occurs halfway through your program, remember the Cascade Cleanup. If you opened a file and then malloc failed, you must close that file before exiting. Professional code often uses goto cleanup; at the end of the function to handle this in one place.