From 88ab5a5273e13066ce3f496a690f10d20a278bb4 Mon Sep 17 00:00:00 2001 From: Charles Date: Mon, 22 Jun 2020 19:13:19 +0200 Subject: Added better option handling --- inc/tar.h | 37 +++++++++++++++++++++++----- src/archive.c | 77 +++++++++++++++++++++++++++++++---------------------------- src/args.c | 45 ++++++++++++++++++++++++++++++++++ src/fs.c | 2 +- src/main.c | 46 +++++++++-------------------------- 5 files changed, 128 insertions(+), 79 deletions(-) create mode 100644 src/args.c diff --git a/inc/tar.h b/inc/tar.h index 66e3c64..876c554 100644 --- a/inc/tar.h +++ b/inc/tar.h @@ -35,6 +35,8 @@ # define RECORD_SIZE 512 +# define DEFAULT_UMASK 0644 + // # define FILE_NAME_MAX 100 // https://en.wikipedia.org/wiki/Tar_(computing)?oldformat=true#Header @@ -56,14 +58,32 @@ typedef struct char device_major_number[8]; char device_minor_number[8]; char file_name_prefix[155]; -} t_header; +} t_header; + +typedef enum +{ + ACTION_CONCAT, + ACTION_CREATE, + ACTION_DIFF, + ACTION_LIST, + ACTION_APPEND, + ACTION_UPDATE, + ACTION_EXTRACT, +} t_action; typedef enum { - FLAG_CREATE = 1 << 0, FLAG_VERBOSE = 1 << 0, - FLAG_LIST = 1 << 0, -} t_flags; + FLAG_FILE = 1 << 1, +} t_flags; + +typedef struct +{ + char *archive_name; + char **files; + t_action action; + t_flags flags; +} t_args; // header.c int header_write(int fd, char *file_name, struct stat *statbuf); @@ -75,8 +95,10 @@ int file_write(int fd, char file_name[PATH_MAX]); int directory_write(int fd, char dir_name[PATH_MAX]); // archive.c -int archive_write(char *archive_file_name, char **files); -int archive_read(char *archive_file_name); +int archive_dispatch_action(int archive_fd, t_args *args); +int archive_create(int archive_fd, char **files); +int archive_extract(int archive_fd); +int archive_get_fd(t_args *args); // record.c int record_write(int fd, char *s, size_t size); @@ -84,4 +106,7 @@ int record_write_blank(int fd, size_t count); int record_read(int fd, char record[RECORD_SIZE]); bool record_is_blank(char record[RECORD_SIZE]); +// args.c +bool args_parse(int argc, char **argv, t_args *args); + #endif // TAR_H diff --git a/src/archive.c b/src/archive.c index a3addd3..48fa55d 100644 --- a/src/archive.c +++ b/src/archive.c @@ -1,59 +1,28 @@ #include "tar.h" -int archive_write(char *archive_file_name, char **files) +int archive_create(int archive_fd, char **files) { - int fd; char file_name[PATH_MAX]; struct stat root_statbuf; - if (archive_file_name == NULL) - fd = STDOUT_FILENO; - else - { - fd = open(archive_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) - { - perror("achive_write"); - return -1; - } - } for (; *files != NULL; files++) { bzero(file_name, PATH_MAX); strcpy(file_name, *files); - file_write(fd, file_name); + file_write(archive_fd, file_name); } if (stat("/", &root_statbuf) == -1) { perror("achive_write"); - close(fd); return -1; } - if (record_write_blank(fd, 2 + (2 * root_statbuf.st_blksize) / RECORD_SIZE) == -1) - { - close(fd); + if (record_write_blank(archive_fd, 2 + (2 * root_statbuf.st_blksize) / RECORD_SIZE) == -1) return -1; - } - if (fd != STDOUT_FILENO) - close(fd); return 0; } -int archive_read(char *archive_file_name) +int archive_extract(int archive_fd) { - int archive_fd; - - if (archive_file_name == NULL) - archive_fd = STDIN_FILENO; - else - { - if ((archive_fd = open(archive_file_name, O_RDONLY)) == -1) - { - perror("achive_write"); - return -1; - } - } - char record[RECORD_SIZE]; t_header header; int fd; @@ -80,7 +49,6 @@ int archive_read(char *archive_file_name) case '5': if (mkdir(header.file_name, statbuf.st_mode) == -1) { - close(archive_fd); perror(NULL); return -1; } @@ -106,6 +74,41 @@ int archive_read(char *archive_file_name) return -1; } } - close(archive_fd); + return 0; +} + +int archive_get_fd(t_args *args) +{ + int fd; + bool is_read; + + is_read = args->action == ACTION_DIFF || + args->action == ACTION_LIST || + args->action == ACTION_EXTRACT; + if (args->archive_name == NULL) + return is_read ? STDIN_FILENO : STDOUT_FILENO; + if (is_read) + fd = open(args->archive_name, O_RDONLY); + else + fd = open(args->archive_name, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_UMASK); + if (fd == -1) + { + perror("archive fd"); + return -1; + } + return fd; +} + +int archive_dispatch_action(int archive_fd, t_args *args) +{ + switch (args->action) + { + case ACTION_CREATE: + return archive_create(archive_fd, args->files); + case ACTION_EXTRACT: + return archive_extract(archive_fd); + default: + return -1; + } return 0; } diff --git a/src/args.c b/src/args.c new file mode 100644 index 0000000..1600e0e --- /dev/null +++ b/src/args.c @@ -0,0 +1,45 @@ +#include "tar.h" + +bool args_parse(int argc, char **argv, t_args *args) +{ + int opt; + int action_counter = 0; + + args->archive_name = NULL; + args->files = NULL; + while ((opt = getopt(argc, argv, "Acdtruxvf:")) != -1) + { + switch (opt) + { + case 'A': args->action = ACTION_CONCAT; break; + case 'c': args->action = ACTION_CREATE; break; + case 'd': args->action = ACTION_DIFF; break; + case 't': args->action = ACTION_LIST; break; + case 'r': args->action = ACTION_APPEND; break; + case 'u': args->action = ACTION_UPDATE; break; + case 'x': args->action = ACTION_EXTRACT; break; + + case 'v': args->flags |= FLAG_VERBOSE; break; + case 'f': + args->flags |= FLAG_FILE; + args->archive_name = optarg; + break; + default: + return false; + } + if (strchr("Acdtrux", opt) != NULL) + action_counter++; + } + if (action_counter != 1) + { + fprintf(stderr, "%s: You way not specify more than one '-Acdtrux' option\n", argv[0]); + return false; + } + if (!(args->flags & FLAG_FILE) && isatty(STDOUT_FILENO)) + { + fprintf(stderr, "%s: Refusing to write archive contents to terminal (missing -f option?)\n", argv[0]); + return false; + } + args->files = argv + optind; + return true; +} diff --git a/src/fs.c b/src/fs.c index c285259..24de763 100644 --- a/src/fs.c +++ b/src/fs.c @@ -28,7 +28,7 @@ int file_write(int fd, char file_name[PATH_MAX]) int file_fd; struct stat statbuf; - fprintf(stderr, "|%s|\n", file_name); + /* fprintf(stderr, "|%s|\n", file_name); */ if (stat(file_name, &statbuf) == -1) { perror("file_write stat"); diff --git a/src/main.c b/src/main.c index e536e93..4a7ce24 100644 --- a/src/main.c +++ b/src/main.c @@ -5,40 +5,16 @@ int main(int argc, char **argv) { - int opt; - char *archive_file_name = NULL; - bool create; + t_args args; + int archive_fd; + int ret; - while ((opt = getopt(argc, argv, "Oxcvtf:")) != -1) - { - switch (opt) - { - case 'c': - create = true; - break; - case 'x': - create = false; - break; - case 'f': - archive_file_name = optarg; - break; - case 'v': - break; - case 't': - break; - default: - return 1; - } - } - if (create) - { - if (archive_write(archive_file_name, argv + optind) == -1) - return 1; - } - else - { - if (archive_read(archive_file_name) == -1) - return 1; - } - return 0; + if (!args_parse(argc, argv, &args) || + (archive_fd = archive_get_fd(&args)) == -1) + return EXIT_FAILURE; + + ret = archive_dispatch_action(archive_fd, &args); + if (archive_fd != STDOUT_FILENO && archive_fd != STDIN_FILENO) + close(archive_fd); + return ret == -1 ? 1 : 0; } -- cgit