From d71848194fa9f1b5ad7c7ee9a9f397ae4622d59c Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Wed, 8 Apr 2026 19:57:58 +0200 Subject: [PATCH] TAR COMPATIBILITYYYYYYYYYYYY --- epitar/src/tar/archive.c | 45 ++++++++++++++++++++++++++++++-------- epitar/src/tar/tar.c | 46 +++++++++++++++++++++++++++++---------- epitar/src/tar/tar.h | 7 +++--- epitar/src/utils/errors.h | 1 + 4 files changed, 76 insertions(+), 23 deletions(-) diff --git a/epitar/src/tar/archive.c b/epitar/src/tar/archive.c index 749f239..00ae94d 100644 --- a/epitar/src/tar/archive.c +++ b/epitar/src/tar/archive.c @@ -1,8 +1,11 @@ #include "archive.h" +#include +#include #include #include #include +#include #include "../utils/filesystem.h" #include "tar.h" @@ -32,31 +35,55 @@ static struct ustar_header create_header(FILE *file_stream, char *file_path) // Versions memcpy(header.version, TVERSION, TVERSLEN); - // TODO handle uid, gid, mtime, and links + // uid, gid, mtime and mode + struct stat st; + if (stat(file_path, &st) == -1) + { + printf("Could not stat file %s\n", file_path); + return header; + } + // TODO links + // UID + snprintf(header.uid, sizeof(header.uid), "%07o", st.st_uid); + // GID + snprintf(header.gid, sizeof(header.gid), "%07o", st.st_gid); + // Mtime + snprintf(header.mtime, sizeof(header.mtime), "%011lo", st.st_mtime); + // Mode + snprintf(header.mode, sizeof(header.mode), "%07o", st.st_mode & 0777); + + // User name + struct passwd *pw = getpwuid(st.st_uid); + if (pw != NULL) + strncpy(header.uname, pw->pw_name, 32); + // Group name + struct group *gr = getgrgid(st.st_gid); + if (gr != NULL) + strncpy(header.gname, gr->gr_name, 32); // File or directory if (file_stream == NULL) { // === Directory + header.name[strlen(header.name)] = '/'; // Type header.typeflag = DIRTYPE; + // Size + snprintf(header.size, 12, "%011o", 0); } else { // === File - // Length - size_t file_size = getfilesize(file_stream); - snprintf(header.size, TSIZELEN, "%lu", file_size); + // Size + snprintf(header.size, 12, "%011lo", st.st_size); // Type header.typeflag = REGTYPE; } // Checksum union tar_header header_union = { .ustar = header }; - size_t chksum = compute_checksum(&header_union); - snprintf(header.chksum, TCHKSUMLEN, "%lu", chksum); - - return header; + compute_checksum(&header_union); + return header_union.ustar; } /** @@ -118,7 +145,7 @@ static enum error_code archivedir(FILE *archive, char *dir_path, bool verbose) { // Add the directory itself if (verbose) - puts(dir_path); + printf("%s/\n", dir_path); // Header struct ustar_header header = create_header(NULL, dir_path); diff --git a/epitar/src/tar/tar.c b/epitar/src/tar/tar.c index 5defa56..ee9fd7a 100644 --- a/epitar/src/tar/tar.c +++ b/epitar/src/tar/tar.c @@ -1,6 +1,6 @@ #include "tar.h" -#include +#include #include struct unixtar_header *get_unixtar_header(union tar_header *header) @@ -26,34 +26,58 @@ bool check_checksum(union tar_header *header) { struct ustar_header *ustar_header; struct unixtar_header *unixtar_header; - int actual_checksum; + char actual_checksum[TCHKSUMLEN]; // USTAR if ((ustar_header = get_ustar_header(header)) != NULL) { - actual_checksum = atoi(ustar_header->chksum); + strcpy(actual_checksum, ustar_header->chksum); + return strcmp(actual_checksum, header->ustar.chksum) == 0; } // UNIXTAR else if ((unixtar_header = get_unixtar_header(header)) != NULL) { - actual_checksum = atoi(unixtar_header->chksum); + strcpy(actual_checksum, unixtar_header->chksum); + return strcmp(actual_checksum, header->unixtar.chksum) == 0; } // Unsupported format else { return false; } - - int computed_checksum = compute_checksum(header); - return computed_checksum == actual_checksum; } -int compute_checksum(union tar_header *header) +void compute_checksum(union tar_header *header) { - char *block = header->raw_block; - int sum = 0; + // Set to spaces + struct unixtar_header *unixtar_header = get_unixtar_header(header); + struct ustar_header *ustar_header = get_ustar_header(header); + if (ustar_header) + { + memset(ustar_header->chksum, ' ', TCHKSUMLEN); + } + else if (unixtar_header) + { + memset(unixtar_header->chksum, ' ', TCHKSUMLEN); + } + + // Compute + unsigned char *block = header->raw_block; + unsigned int sum = 0; for (int i = 0; i < BLOCK_SIZE; i++) sum += block[i]; - return sum; + // Update checksum + if (ustar_header) + { + snprintf(ustar_header->chksum, TCHKSUMLEN - 1, "%06o", sum); + ustar_header->chksum[TCHKSUMLEN - 2] = '\0'; + ustar_header->chksum[TCHKSUMLEN - 1] = ' '; + } + else if (unixtar_header) + { + snprintf(unixtar_header->chksum, TCHKSUMLEN - 1, "%06o", sum); + unixtar_header->chksum[TCHKSUMLEN - 2] = '\0'; + unixtar_header->chksum[TCHKSUMLEN - 1] = ' '; + } } diff --git a/epitar/src/tar/tar.h b/epitar/src/tar/tar.h index db62b12..82dab5f 100644 --- a/epitar/src/tar/tar.h +++ b/epitar/src/tar/tar.h @@ -86,7 +86,7 @@ union tar_header { struct unixtar_header unixtar; struct ustar_header ustar; - char raw_block[BLOCK_SIZE]; + unsigned char raw_block[BLOCK_SIZE]; }; // === Functions @@ -103,13 +103,14 @@ struct unixtar_header *get_unixtar_header(union tar_header *header); struct ustar_header *get_ustar_header(union tar_header *header); /* @brief checks if file has not been corrupted via checksum + * @warn Alters header checksum with the new one * @return true if member file is valid, false otherwise */ bool check_checksum(union tar_header *header); -/* @brief computes the checksum of the given file +/* @brief computes the checksum of the given header and updates it * @return the checksum */ -int compute_checksum(union tar_header *header); +void compute_checksum(union tar_header *header); #endif // TAR_H diff --git a/epitar/src/utils/errors.h b/epitar/src/utils/errors.h index 78caf7c..aeb20c3 100644 --- a/epitar/src/utils/errors.h +++ b/epitar/src/utils/errors.h @@ -14,6 +14,7 @@ enum error_code TARGET_ALREADY_EXISTS, NO_TARGET_PROVIDED, EMPTY_ARCHIVE, + CANNOT_STAT, NOT_IMPLEMENTED };