From 3f37f1c9bf64866de90ec418adcfe31b634231c2 Mon Sep 17 00:00:00 2001 From: Charles Date: Sun, 21 Jun 2020 18:16:47 +0200 Subject: Added archive_write, archive_read draft --- README.md | 10 +++++ inc/tar.h | 26 +++++++++---- src/archive.c | 73 ++++++++++++++++++++++++++++++++++++ src/header.c | 80 --------------------------------------- src/main.c | 39 +++++++------------ src/utils.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 233 insertions(+), 113 deletions(-) create mode 100644 src/archive.c delete mode 100644 src/header.c create mode 100644 src/utils.c diff --git a/README.md b/README.md index 7153804..95120ca 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ # tar Shitty clone of the `tar` program made for educational purposes. + +## TODO + +- [ ] `x` Extracting archive +- [ ] `d` Difference between file system and archive +- [ ] `t` List archive +- [ ] `v` Verbose mode +- [ ] `A` Concatenate 2 archives together +- [ ] `r` Add files to archive +- [ ] `u` Update file in archive diff --git a/inc/tar.h b/inc/tar.h index 1dc382f..dbeca6d 100644 --- a/inc/tar.h +++ b/inc/tar.h @@ -45,7 +45,7 @@ typedef struct char user_id[8]; char group_id[8]; char file_size[12]; - char last_time[12]; + char last_time[12]; // utime char checksum[8]; char file_type[1]; char link_file_name[100]; @@ -58,13 +58,25 @@ typedef struct char file_name_prefix[155]; } t_header; -// header.c -int record_write(int fd, char *s, size_t size); -int header_write(int fd, char *file_name, struct stat *statbuf); +typedef enum +{ + FLAG_CREATE = 1 << 0, + FLAG_VERBOSE = 1 << 0, + FLAG_LIST = 1 << 0, +} t_flags; + +// utils.c +int record_write(int fd, char *s, size_t size); +int record_write_blank(int fd, size_t count); +int header_write(int fd, char *file_name, struct stat *statbuf); // fs.c -int file_content_write(int fd, int file_fd, struct stat *statbuf); -int file_write(int fd, char file_name[PATH_MAX]); -int directory_write(int fd, char dir_name[PATH_MAX]); +int file_content_write(int fd, int file_fd, struct stat *statbuf); +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); #endif // TAR_H diff --git a/src/archive.c b/src/archive.c new file mode 100644 index 0000000..11457d6 --- /dev/null +++ b/src/archive.c @@ -0,0 +1,73 @@ +#include "tar.h" + +int archive_write(char *archive_file_name, 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); + } + 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); + return -1; + } + if (fd != STDOUT_FILENO) + close(fd); + return 0; +} + +int archive_read(char *archive_file_name) +{ + int fd; + + if ((fd = open(archive_file_name, O_RDONLY)) == -1) + { + perror("achive_write"); + return -1; + } + + int ret; + char buf[RECORD_SIZE]; + t_header header; + int current_fd; + + while ((ret = read(fd, buf, RECORD_SIZE)) == RECORD_SIZE) + { + /* header_parse(&header, buf); */ + /* current_fd = open(header.file_name, O_WRONLY | O_CREAT | O_TRUNC, header. */ + // read content + // TODO + } + if (ret == -1) + { + perror(NULL); + return -1; + } + if (ret < RECORD_SIZE) + return -1; + close(fd); + return 0; +} diff --git a/src/header.c b/src/header.c deleted file mode 100644 index 133a895..0000000 --- a/src/header.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "tar.h" - -int record_write(int fd, char *s, size_t size) -{ - char buf[RECORD_SIZE]; - - while (size > RECORD_SIZE) - { - memcpy(buf, s, RECORD_SIZE); - s += RECORD_SIZE; - size -= RECORD_SIZE; - if (write(fd, buf, RECORD_SIZE) == -1) - { - perror(NULL); - return -1; - } - } - bzero(buf, RECORD_SIZE); - memcpy(buf, s, size); - if (write(fd, buf, RECORD_SIZE) == -1) - { - perror(NULL); - return -1; - } - return (0); -} - -int header_write(int fd, char *file_name, struct stat *statbuf) -{ - t_header header; - struct group *group; - struct passwd *passwd; - unsigned int sum; - - bzero(&header, sizeof(t_header)); - strncpy(header.file_name, file_name, sizeof(header.file_name)); - if (S_ISDIR(statbuf->st_mode)) - strncat(header.file_name, "/", sizeof(header.file_name) - 1); - sprintf(header.file_mode, "%07o", statbuf->st_mode & 0777); - sprintf(header.user_id, "%07o", statbuf->st_uid); - sprintf(header.group_id, "%07o", statbuf->st_gid); - sprintf(header.file_size, "%011lo", statbuf->st_size); - sprintf(header.last_time, "%011lo", statbuf->st_mtime); - memset(header.checksum, ' ', sizeof(header.checksum)); - - switch (statbuf->st_mode & S_IFMT) - { - case S_IFREG: header.file_type[0] = '0'; break; - /* case S_IFLNK: header.file_type[0] = '0' break; */ - /* case S_IFBLK: header.file_type[0] = '0' break; */ - /* case S_IFCHR: header.file_type[0] = '0' break; */ - case S_IFDIR: header.file_type[0] = '5'; break; - /* case S_IFIFO: header.file_type[0] = '0' break; */ - /* case S_IFSOCK: header.file_type[0] = '0' break; */ - } - - memcpy(header.ustar, "ustar ", sizeof(header.ustar)); - memcpy(header.ustar_version, " ", sizeof(header.ustar_version)); - - if ((passwd = getpwuid(statbuf->st_gid)) == NULL) - { - perror("header_write getpwduid"); - return -1; - } - strncpy(header.user_name, passwd->pw_name, sizeof(header.user_name)); - if ((group = getgrgid(statbuf->st_gid)) == NULL) - { - perror("header_write getgrgid"); - return -1; - } - strncpy(header.group_name, group->gr_name, sizeof(header.group_name)); - - /* getpwuid(); */ - - for (size_t i = 0; i < sizeof(t_header); i++) - sum += ((uint8_t*)&header)[i]; - sprintf(header.checksum, "%06o", sum); - - return record_write(fd, (char*)&header, sizeof(t_header)); -} diff --git a/src/main.c b/src/main.c index 1c0f12f..e536e93 100644 --- a/src/main.c +++ b/src/main.c @@ -6,16 +6,21 @@ int main(int argc, char **argv) { int opt; - char *output_file_name = NULL; + char *archive_file_name = NULL; + bool create; - while ((opt = getopt(argc, argv, "cvtf:")) != -1) + while ((opt = getopt(argc, argv, "Oxcvtf:")) != -1) { switch (opt) { case 'c': + create = true; + break; + case 'x': + create = false; break; case 'f': - output_file_name = optarg; + archive_file_name = optarg; break; case 'v': break; @@ -25,33 +30,15 @@ int main(int argc, char **argv) return 1; } } - int fd = -1; - if (output_file_name == NULL) - fd = STDOUT_FILENO; - else + if (create) { - fd = open(output_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) - { - perror("main"); + if (archive_write(archive_file_name, argv + optind) == -1) return 1; - } } - - /* printf("out: %s\n", output_file_name); */ - char file_name[PATH_MAX]; - char **files = argv + optind; - for (; *files != NULL; files++) + else { - /* printf("%s\n", *files); */ - bzero(file_name, PATH_MAX); - strcpy(file_name, *files); - file_write(fd, file_name); + if (archive_read(archive_file_name) == -1) + return 1; } - char buf[512] = {'\0'}; - write(fd, buf, 512); - write(fd, buf, 512); - if (fd != STDOUT_FILENO) - close(fd); return 0; } diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..ce56307 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,118 @@ +#include "tar.h" + +int record_write(int fd, char *s, size_t size) +{ + char buf[RECORD_SIZE]; + + while (size > RECORD_SIZE) + { + memcpy(buf, s, RECORD_SIZE); + s += RECORD_SIZE; + size -= RECORD_SIZE; + if (write(fd, buf, RECORD_SIZE) == -1) + { + perror(NULL); + return -1; + } + } + bzero(buf, RECORD_SIZE); + memcpy(buf, s, size); + if (write(fd, buf, RECORD_SIZE) == -1) + { + perror(NULL); + return -1; + } + return (0); +} + +int record_write_blank(int fd, size_t count) +{ + char buf[RECORD_SIZE] = {0}; + while (count-- > 0) + { + if (write(fd, buf, RECORD_SIZE) == -1) + { + perror(NULL); + return -1; + } + } + return 0; +} + +int header_write(int fd, char *file_name, struct stat *statbuf) +{ + t_header header; + struct group *group; + struct passwd *passwd; + unsigned int sum; + + bzero(&header, sizeof(t_header)); + strncpy(header.file_name, file_name, sizeof(header.file_name)); + if (S_ISDIR(statbuf->st_mode)) + strncat(header.file_name, "/", sizeof(header.file_name) - 1); + sprintf(header.file_mode, "%07o", statbuf->st_mode & 0777); + sprintf(header.user_id, "%07o", statbuf->st_uid); + sprintf(header.group_id, "%07o", statbuf->st_gid); + + if (S_ISDIR(statbuf->st_mode)) + sprintf(header.file_size, "%011lo", 0lu); + else + sprintf(header.file_size, "%011lo", statbuf->st_size); + + sprintf(header.last_time, "%011lo", statbuf->st_mtime); + memset(header.checksum, ' ', sizeof(header.checksum)); + + switch (statbuf->st_mode & S_IFMT) + { + case S_IFREG: header.file_type[0] = '0'; break; + /* case S_IFLNK: header.file_type[0] = '0' break; */ + /* case S_IFBLK: header.file_type[0] = '0' break; */ + /* case S_IFCHR: header.file_type[0] = '0' break; */ + case S_IFDIR: header.file_type[0] = '5'; break; + /* case S_IFIFO: header.file_type[0] = '0' break; */ + /* case S_IFSOCK: header.file_type[0] = '0' break; */ + } + + memcpy(header.ustar, "ustar ", sizeof(header.ustar)); + memcpy(header.ustar_version, " ", sizeof(header.ustar_version)); + + if ((passwd = getpwuid(statbuf->st_gid)) == NULL) + { + perror("header_write getpwduid"); + return -1; + } + strncpy(header.user_name, passwd->pw_name, sizeof(header.user_name)); + if ((group = getgrgid(statbuf->st_gid)) == NULL) + { + perror("header_write getgrgid"); + return -1; + } + strncpy(header.group_name, group->gr_name, sizeof(header.group_name)); + + sum = 0; + for (size_t i = 0; i < sizeof(t_header); i++) + sum += ((uint8_t*)&header)[i]; + sprintf(header.checksum, "%06o", sum); + + return record_write(fd, (char*)&header, sizeof(t_header)); +} + +int header_parse(char record[RECORD_SIZE]) +{ + t_header header; + mode_t mode; + gid_t gid; + uid_t uid; + + memcpy(&header, record, sizeof(t_header)); + /* sscanf(header.file_mode, "% */ + + /* sscanf(header.file_mode, "%07o", statbuf->st_mode); */ + /* sscanf(header.user_id, "%07o", statbuf->st_uid); */ + /* sscanf(header.group_id, "%07o", statbuf->st_gid); */ + /* */ + /* sscanf(header.file_size, "%011lo", statbuf->st_size); */ + /* */ + /* sscanf(header.last_time, "%011lo", statbuf->st_mtime); */ + return 0; +} -- cgit