diff options
| author | Charles <sircharlesaze@gmail.com> | 2020-06-22 15:09:59 +0200 |
|---|---|---|
| committer | Charles <sircharlesaze@gmail.com> | 2020-06-22 15:09:59 +0200 |
| commit | 86e8aeb5bb66ae5625002533b529752a7814e6c0 (patch) | |
| tree | bb30c103a5059c8dda817310dc57256d5b812ede /src | |
| parent | 3f37f1c9bf64866de90ec418adcfe31b634231c2 (diff) | |
| download | tar-86e8aeb5bb66ae5625002533b529752a7814e6c0.tar.gz tar-86e8aeb5bb66ae5625002533b529752a7814e6c0.tar.bz2 tar-86e8aeb5bb66ae5625002533b529752a7814e6c0.zip | |
Added archive extracting
Diffstat (limited to 'src')
| -rw-r--r-- | src/archive.c | 78 | ||||
| -rw-r--r-- | src/fs.c | 2 | ||||
| -rw-r--r-- | src/header.c (renamed from src/utils.c) | 71 | ||||
| -rw-r--r-- | src/record.c | 60 |
4 files changed, 138 insertions, 73 deletions
diff --git a/src/archive.c b/src/archive.c index 11457d6..a3addd3 100644 --- a/src/archive.c +++ b/src/archive.c @@ -41,33 +41,71 @@ int archive_write(char *archive_file_name, char **files) int archive_read(char *archive_file_name) { - int fd; + int archive_fd; - if ((fd = open(archive_file_name, O_RDONLY)) == -1) + if (archive_file_name == NULL) + archive_fd = STDIN_FILENO; + else { - perror("achive_write"); - return -1; + if ((archive_fd = open(archive_file_name, O_RDONLY)) == -1) + { + perror("achive_write"); + return -1; + } } - int ret; - char buf[RECORD_SIZE]; + char record[RECORD_SIZE]; t_header header; - int current_fd; + int fd; + struct stat statbuf; - 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) + while (true) { - perror(NULL); - return -1; + if (record_read(archive_fd, record) == -1) + return -1; + if (record_is_blank(record)) + { + if (record_read(archive_fd, record) == -1) + return -1; + if (record_is_blank(record)) + break; + else + return -1; + } + if (header_parse(record, &statbuf, &header) == -1) + return -1; + + switch (header.file_type[0]) + { + case '5': + if (mkdir(header.file_name, statbuf.st_mode) == -1) + { + close(archive_fd); + perror(NULL); + return -1; + } + break; + case '0': + fd = open(header.file_name, O_WRONLY | O_CREAT | O_TRUNC, statbuf.st_mode); + if (fd == -1) + { + perror(NULL); + return -1; + } + char *content = malloc(statbuf.st_size); + if (content == NULL || + read(archive_fd, content, statbuf.st_size) == -1 || + lseek(archive_fd, RECORD_SIZE - statbuf.st_size % RECORD_SIZE, SEEK_CUR) == -1 || + write(fd, content, statbuf.st_size) == -1) + { + perror(NULL); + return -1; + } + break; + default: + return -1; + } } - if (ret < RECORD_SIZE) - return -1; - close(fd); + close(archive_fd); return 0; } @@ -83,3 +83,5 @@ int directory_write(int fd, char dir_name[PATH_MAX]) closedir(dir); return 0; } + +/* int file_content_read(int archive_fd, */ diff --git a/src/utils.c b/src/header.c index ce56307..d881275 100644 --- a/src/utils.c +++ b/src/header.c @@ -1,44 +1,5 @@ #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; @@ -97,22 +58,26 @@ int header_write(int fd, char *file_name, struct stat *statbuf) return record_write(fd, (char*)&header, sizeof(t_header)); } -int header_parse(char record[RECORD_SIZE]) +int header_parse(char record[RECORD_SIZE], struct stat *statbuf, t_header *header) { - t_header header; - mode_t mode; - gid_t gid; - uid_t uid; + unsigned int actual_checksum; + unsigned int expected_checksum; + + memcpy(header, record, sizeof(t_header)); - memcpy(&header, record, sizeof(t_header)); - /* sscanf(header.file_mode, "% */ + actual_checksum = -1; + sscanf(header->checksum, "%06o", &actual_checksum); + memset(header->checksum, ' ', 8); + expected_checksum = 0; + for (size_t i = 0; i < sizeof(t_header); i++) + expected_checksum += ((uint8_t*)header)[i]; + if (actual_checksum != expected_checksum) + return -1; - /* 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); */ + 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", (long unsigned int*)&statbuf->st_size); + sscanf(header->last_time, "%011lo", (long unsigned int*)&statbuf->st_mtime); return 0; } diff --git a/src/record.c b/src/record.c new file mode 100644 index 0000000..be78978 --- /dev/null +++ b/src/record.c @@ -0,0 +1,60 @@ +#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 record_read(int fd, char record[RECORD_SIZE]) +{ + int ret = read(fd, record, RECORD_SIZE); + if (ret == -1) + { + perror(NULL); + return -1; + } + if (ret != RECORD_SIZE) + return -1; + return 0; +} + +static char g_record_blank[RECORD_SIZE] = {0}; + +bool record_is_blank(char record[RECORD_SIZE]) +{ + return memcmp(record, g_record_blank, RECORD_SIZE) == 0; +} |
