aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--inc/tar.h37
-rw-r--r--src/archive.c77
-rw-r--r--src/args.c45
-rw-r--r--src/fs.c2
-rw-r--r--src/main.c46
5 files changed, 128 insertions, 79 deletions
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;
}