diff options
| author | akiyamn | 2020-09-08 23:33:53 +1000 |
|---|---|---|
| committer | akiyamn | 2020-09-08 23:33:53 +1000 |
| commit | cc006cf8239efd4f30925a1cefb0e408db3ffe0d (patch) | |
| tree | 1c4999b0556ba9bf442be9c489600cff6715c5fb /fileutil.c | |
| parent | a74edeb738198cbe7945fa3682da6e7030c13ce9 (diff) | |
| download | fit2100_ass1-cc006cf8239efd4f30925a1cefb0e408db3ffe0d.tar.gz fit2100_ass1-cc006cf8239efd4f30925a1cefb0e408db3ffe0d.zip | |
Commented a lot
Diffstat (limited to 'fileutil.c')
| -rw-r--r-- | fileutil.c | 92 |
1 files changed, 66 insertions, 26 deletions
@@ -4,7 +4,7 @@ * Alexander Occhipinti * Student ID: 29994705 * Created: 3 Sep 2020 - * Last Modified: 7 Sep 2020 + * Last Modified: 8 Sep 2020 * * fileutil is a program which is a utility for files. It combines the functionality of cat cp and mv. * This program allows you to copy the contents of a given file to stdout or to a another file. @@ -34,11 +34,12 @@ void to_stderr(char *string) { write(2, string, strlen(string)); } + /* - * Prints the contents of a given file (provided a path) to stdout. - * Returns nothing. + * Given a file path and open() flags, open a file + * Catches openning errors, prints an error to stderr when an error occurs and exits + * Returns a file descriptor of the open file. Needs to be closed afterwards. */ - int open_file(char *path, int flags){ // Read the input file int fd; @@ -47,11 +48,18 @@ int open_file(char *path, int flags){ to_stderr(path); to_stderr(" could not be opened: "); to_stderr(strerror(error)); - exit(1); // Exit if an error occurs + // Exit (with 1) if an error occurs, with error 2 if the file exists and can not be overwriten + if (errno == EEXIST) exit(2) : exit(1); } return fd; } +/* + * Given a source file descriptor open for reading, + * put all of its contents in the destination file descriptor open for writing. + * + * Useful for transferring data between files or stdin/stdout/stderr +*/ void file_into_file(int source_fd, int dest_fd){ int bytes_read; char buffer[FILE_BUF_SIZE]; @@ -61,6 +69,10 @@ void file_into_file(int source_fd, int dest_fd){ } +/* + * Prints the contents of a given file (provided a path) to stdout. + * Returns nothing. +*/ void print_file(char *read_path) { int read_fd; read_fd = open_file(read_path, O_RDONLY); @@ -68,20 +80,31 @@ void print_file(char *read_path) { close(read_fd); } +/* + * Copy a file from the read_path to the write_path, prints an error to stderr and quits if + * there is an error with opening. Overwrites the target file only if bool overwrite is true, throws an error otherwise. + * +*/ void copy_file(char *read_path, char *write_path, bool overwrite) { int read_fd, write_fd; int write_flags = O_WRONLY | O_CREAT | O_TRUNC; - if (!overwrite) write_flags |= O_EXCL; + if (!overwrite) write_flags |= O_EXCL; // Add no-clobber flag if not allowed to overwrite + // Open both files read_fd = open_file(read_path, O_RDONLY); write_fd = open_file(write_path, write_flags); - file_into_file(read_fd, write_fd); + file_into_file(read_fd, write_fd); // Write one file into the other + // Close both files close(read_fd); close(write_fd); } +/* + * Provided a string of an absolute path, returns a pointer to the same string representing + * a string of just the filename. +*/ char* get_filename(char *full_path){ char* filename = strrchr(full_path, '/'); // Find the string after the last occurence of a '/' if (!filename) return full_path; // If there are no slashes, the whole path is already a filename @@ -89,30 +112,46 @@ char* get_filename(char *full_path){ } +/* +* Returns true if the provided string is a UNIX style absolute path (starts with '/'), false otherwise +*/ bool is_a_path(char* string) { return (strlen(string) == 0) ? false : string[0] == '/'; } +/* + * Copies a file given the path `file_path`, into the directory of path string `dir_path` + * Moves the file rather than copies it (i.e. remove the original file) if `move` is true + * Overwrites the target file if it exists if `overwrite` is true +*/ void copy_into_dir(char *file_path, char *dir_path, bool move, bool overwrite){ char* filename; char* new_path; size_t new_path_len; + // Construct the absolute path of the new file in the directory specified, allocate memory filename = get_filename(file_path); new_path_len = strlen(dir_path) + strlen(filename) + 1; new_path = (char *) malloc(new_path_len); - + // Combine/concat the parts of the new filename strcpy(new_path, dir_path); strcat(new_path, "/"); strcat(new_path, filename); + copy_file(file_path, new_path, overwrite); - if (move) unlink(file_path); + if (move) unlink(file_path); // Delete the original if `move` is specified to_stdout("Copy successful\n"); free(new_path); } +/* + * Given argc and argv (number of program arguments and the program arguments) provided from main, + * create an `arguments_t` type struct containing all of the information about the arguments. + * If the given arguments are invalid, the `.valid` attribute of the return value is false. +*/ arguments_t parse_arguments(int argc, char **argv){ + // Create a fresh arguments_t struct arguments_t args = { .src_index = -1, .dir_index = -1, @@ -122,6 +161,7 @@ arguments_t parse_arguments(int argc, char **argv){ .dir_flag = false }; + // Go through each argument, find the defined flags and store then in the struct for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-d") == 0) { args.dir_flag = true; @@ -133,57 +173,57 @@ arguments_t parse_arguments(int argc, char **argv){ } } - if (argc > 1 && is_a_path(argv[1])) args.src_index = 1; + // Determine if the source path is either not provided or the first argument + if (argc > 1 && is_a_path(argv[1])) args.src_index = 1; + // Is a valid combination of flags provided? bool correct_flags = (args.move_flag || args.force_flag) ? args.dir_flag : true; - bool correct_directory = false; + // Is the -d tag followed by a path? + bool correct_directory = false; if (args.dir_index < argc) { correct_directory = (args.dir_flag) ? is_a_path(argv[args.dir_index]) : true; } + // Combine all conditions for a valid set of arguments args.valid = correct_flags && correct_directory && (argc >= MIN_NUM_OF_ARGS) && (argc <= MAX_NUM_OF_ARGS); - return args; } +/* + * Given an arguments_t struct of the program's arguments, execute the correct suprogram + * (i.e. move, copy or print to stdout) +*/ void execute_subprogram(arguments_t args, char *argv[]) { + + // Abort program if invalid arguments specified if (!args.valid) { to_stderr("Invalid arguments given.\n"); exit(1); } + // Set the source_path to the default read path if it's not defined char *source_path = (args.src_index == -1 ) ? DEFAULT_READ_PATH : argv[args.src_index]; char *dir_path; - if (args.dir_flag){ + if (args.dir_flag){ // Copy/move a file into a directory dir_path = argv[args.dir_index]; copy_into_dir(source_path, dir_path, args.move_flag, args.force_flag); } else { - print_file(source_path); + print_file(source_path); // Print a file } } - - - - - +// Main int main(int argc, char *argv[]) { arguments_t args = parse_arguments(argc, argv); - if (!args.valid) { - to_stderr("Invalid arguments provided."); - return 1; - } else { - execute_subprogram(args, argv); - } - + execute_subprogram(args, argv); return 0; } |
