/* * fileutil.c * * Alexander Occhipinti * Student ID: 29994705 * Created: 3 Sep 2020 * Last Modified: 7 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. * It also allows you to delete the original (i.e. mv) if you please. * */ #include #include #include #include #include #include "fileutil.h" /* * Prints a given string to stdout. Returns nothing. */ void to_stdout(char *string) { write(1, string, strlen(string)); } /* * Prints a given string to stderr. Returns nothing. */ void to_stderr(char *string) { write(2, string, strlen(string)); } /* * Prints the contents of a given file (provided a path) to stdout. * Returns nothing. */ int open_file(char *path, int flags){ // Read the input file int fd; if ((fd = open(path, flags, NEW_FILE_PERMS)) <= 2){ to_stderr(path); to_stderr(" could not be opened.\n"); exit(1); // Exit if an error occurs } return fd; } void file_into_file(int source_fd, int dest_fd){ int bytes_read; char buffer[FILE_BUF_SIZE]; while ((bytes_read = read(source_fd, buffer, FILE_BUF_SIZE))) { write(dest_fd, buffer, bytes_read); } } void print_file(char *read_path) { int read_fd; read_fd = open_file(read_path, O_RDONLY); file_into_file(read_fd, 1); close(read_fd); } 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; read_fd = open_file(read_path, O_RDONLY); write_fd = open_file(write_path, write_flags); file_into_file(read_fd, write_fd); close(read_fd); close(write_fd); } 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 return ++filename; // Return the filename without a leading slash } bool is_a_path(char* string) { return (strlen(string) == 0) ? false : string[0] == '/'; } void copy_into_dir(char *file_path, char *dir_path, bool move, bool overwrite){ char* filename; char* new_path; size_t new_path_len; filename = get_filename(file_path); new_path_len = strlen(dir_path) + strlen(filename) + 1; new_path = (char *) malloc(new_path_len); strcpy(new_path, dir_path); strcat(new_path, "/"); strcat(new_path, filename); copy_file(file_path, new_path, overwrite); if (move) unlink(file_path); to_stdout("Copy successful\n"); free(new_path); } arguments_t parse_arguments(int argc, char **argv){ arguments_t args = { .src_index = -1, .dir_index = -1, .valid = false, .move_flag = false, .force_flag = false, .dir_flag = false }; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-d") == 0) { args.dir_flag = true; args.dir_index = i+1; } else if (strcmp(argv[i], "-M") == 0) { args.move_flag = true; } else if (strcmp(argv[i], "-F") == 0) { args.force_flag = true; } } if (argc > 1 && is_a_path(argv[1])) args.src_index = 1; bool correct_flags = (args.move_flag || args.force_flag) ? args.dir_flag : true; bool correct_directory = false; if (args.dir_index < argc) { correct_directory = (args.dir_flag) ? is_a_path(argv[args.dir_index]) : true; } args.valid = correct_flags && correct_directory && (argc >= MIN_NUM_OF_ARGS) && (argc <= MAX_NUM_OF_ARGS); return args; } void execute_subprogram(arguments_t args, char *argv[]) { if (!args.valid) { to_stderr("Invalid arguments given.\n"); exit(1); } char *source_path = (args.src_index == -1 ) ? DEFAULT_READ_PATH : argv[args.src_index]; char *dir_path; if (args.dir_flag){ dir_path = argv[args.dir_index]; copy_into_dir(source_path, dir_path, args.move_flag, args.force_flag); } else { print_file(source_path); } } 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); } return 0; }