aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md10
-rw-r--r--inc/tar.h26
-rw-r--r--src/archive.c73
-rw-r--r--src/main.c39
-rw-r--r--src/utils.c (renamed from src/header.c)44
5 files changed, 156 insertions, 36 deletions
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/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/header.c b/src/utils.c
index 133a895..ce56307 100644
--- a/src/header.c
+++ b/src/utils.c
@@ -25,6 +25,20 @@ int record_write(int fd, char *s, size_t size)
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;
@@ -39,7 +53,12 @@ int header_write(int fd, char *file_name, struct stat *statbuf)
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);
+
+ 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));
@@ -70,11 +89,30 @@ int header_write(int fd, char *file_name, struct stat *statbuf)
}
strncpy(header.group_name, group->gr_name, sizeof(header.group_name));
- /* getpwuid(); */
-
+ 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;
+}