diff options
| author | Charles <sircharlesaze@gmail.com> | 2020-06-20 17:17:36 +0200 |
|---|---|---|
| committer | Charles <sircharlesaze@gmail.com> | 2020-06-20 17:17:36 +0200 |
| commit | 0fa3308034c7776b6c078e493f3b758f0a0bf7e6 (patch) | |
| tree | e4f2ea5954009bfa3fcd3caf6196a4b4a9f4dc87 /src | |
| parent | 95e1552a898078b4dec1eae3fcf975b392cfad6d (diff) | |
| download | tar-0fa3308034c7776b6c078e493f3b758f0a0bf7e6.tar.gz tar-0fa3308034c7776b6c078e493f3b758f0a0bf7e6.tar.bz2 tar-0fa3308034c7776b6c078e493f3b758f0a0bf7e6.zip | |
Added recursion for directory, not complete ustar format
Diffstat (limited to 'src')
| -rw-r--r-- | src/fs.c | 85 | ||||
| -rw-r--r-- | src/header.c | 79 | ||||
| -rw-r--r-- | src/main.c | 64 |
3 files changed, 168 insertions, 60 deletions
diff --git a/src/fs.c b/src/fs.c new file mode 100644 index 0000000..78ef25a --- /dev/null +++ b/src/fs.c @@ -0,0 +1,85 @@ +#include "tar.h" + +int file_content_write(int fd, int file_fd, struct stat *statbuf) +{ + char *content; + + if ((content = malloc(statbuf->st_size)) == NULL) + { + perror("file_content_write"); + close(file_fd); + return -1; + } + if (read(file_fd, content, statbuf->st_size) == -1) + { + perror("file_content_write"); + close(file_fd); + free(content); + return -1; + } + int ret = record_write(fd, content, statbuf->st_size); + close(file_fd); + free(content); + return (ret); +} + +int file_write(int fd, char file_name[PATH_MAX]) +{ + int file_fd; + struct stat statbuf; + + fprintf(stderr, "|%s|\n", file_name); + if (stat(file_name, &statbuf) == -1) + { + perror("file_write stat"); + return -1; + } + if (header_write(fd, file_name, &statbuf) == -1) + return -1; + + switch (statbuf.st_mode & S_IFMT) + { + case S_IFDIR: + return directory_write(fd, file_name); + default: + if ((file_fd = open(file_name, O_RDONLY)) == -1) + { + perror("file_write open"); + return -1; + } + return file_content_write(fd, file_fd, &statbuf); + } + return (0); +} + +int directory_write(int fd, char dir_name[PATH_MAX]) +{ + DIR *dir; + struct dirent *entry; + size_t len; + + if ((dir = opendir(dir_name)) == NULL) + { + perror("directory_write"); + return -1; + } + len = strlen(dir_name); + strcat(dir_name, "/"); + len++; + while ((entry = readdir(dir)) != NULL) + { + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) + continue; + strcat(dir_name, entry->d_name); + if (file_write(fd, dir_name) == -1) + { + closedir(dir); + return -1; + } + dir_name[len] = '\0'; + } + dir_name[len - 1] = '\0'; + closedir(dir); + return 0; +} diff --git a/src/header.c b/src/header.c index a0cf2fb..133a895 100644 --- a/src/header.c +++ b/src/header.c @@ -1,3 +1,80 @@ #include "tar.h" -/* int header_write(int fd, */ +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)); +} @@ -3,63 +3,6 @@ // only first hard link // checksum positive and negative bytes -int write_file(int fd, char *file_name) -{ - struct stat statbuf; - t_header header; - - stat(file_name, &statbuf); - bzero(&header, sizeof(t_header)); - strncpy(header.file_name, file_name, sizeof(header.file_name)); - 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)); - header.file_type[0] = '0'; - - /* strncpy(header.ustar, "ustar", sizeof(header.ustar)); */ - char *header_ptr = (char*)&header; - unsigned int sum = 0; - for (size_t i = 0; i < sizeof(t_header); i++) - sum += header_ptr[i]; - sprintf(header.checksum, "%06o", sum); - - char buf[512] = {0}; - memcpy(buf, &header, sizeof(t_header)); - write(fd, buf, 512); - - - int from; - char *content; - switch (statbuf.st_mode & S_IFMT) - { - case S_IFDIR: break; - default: - from = open(file_name, O_RDONLY); - content = calloc(statbuf.st_size + 1, sizeof(char)); - read(from, content, statbuf.st_size); - write(fd, content, statbuf.st_size); - free(content); - close(from); - memset(buf, '\0', 512); - write(fd, buf, 512 - statbuf.st_size % 512); - } - - // if dir - // write_dir - // else - // write content - return (0); -} - -int write_directory(int fd, char *dirname) -{ - // for f in files - // write_file -} - int main(int argc, char **argv) { int opt; @@ -90,17 +33,20 @@ int main(int argc, char **argv) fd = open(output_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd == -1) { - perror(NULL); + perror("main"); return 1; } } /* printf("out: %s\n", output_file_name); */ + char file_name[PATH_MAX]; char **files = argv + optind; for (; *files != NULL; files++) { /* printf("%s\n", *files); */ - write_file(fd, *files); + bzero(file_name, PATH_MAX); + strcpy(file_name, *files); + file_write(fd, file_name); } char buf[512] = {'\0'}; write(fd, buf, 512); |
