TAR COMPATIBILITYYYYYYYYYYYY

This commit is contained in:
Gu://em_ 2026-04-08 19:57:58 +02:00
parent 589117ae1a
commit d71848194f
4 changed files with 76 additions and 23 deletions

View file

@ -1,8 +1,11 @@
#include "archive.h" #include "archive.h"
#include <grp.h>
#include <pwd.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include "../utils/filesystem.h" #include "../utils/filesystem.h"
#include "tar.h" #include "tar.h"
@ -32,31 +35,55 @@ static struct ustar_header create_header(FILE *file_stream, char *file_path)
// Versions // Versions
memcpy(header.version, TVERSION, TVERSLEN); 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 // File or directory
if (file_stream == NULL) if (file_stream == NULL)
{ {
// === Directory // === Directory
header.name[strlen(header.name)] = '/';
// Type // Type
header.typeflag = DIRTYPE; header.typeflag = DIRTYPE;
// Size
snprintf(header.size, 12, "%011o", 0);
} }
else else
{ {
// === File // === File
// Length // Size
size_t file_size = getfilesize(file_stream); snprintf(header.size, 12, "%011lo", st.st_size);
snprintf(header.size, TSIZELEN, "%lu", file_size);
// Type // Type
header.typeflag = REGTYPE; header.typeflag = REGTYPE;
} }
// Checksum // Checksum
union tar_header header_union = { .ustar = header }; union tar_header header_union = { .ustar = header };
size_t chksum = compute_checksum(&header_union); compute_checksum(&header_union);
snprintf(header.chksum, TCHKSUMLEN, "%lu", chksum); return header_union.ustar;
return header;
} }
/** /**
@ -118,7 +145,7 @@ static enum error_code archivedir(FILE *archive, char *dir_path, bool verbose)
{ {
// Add the directory itself // Add the directory itself
if (verbose) if (verbose)
puts(dir_path); printf("%s/\n", dir_path);
// Header // Header
struct ustar_header header = create_header(NULL, dir_path); struct ustar_header header = create_header(NULL, dir_path);

View file

@ -1,6 +1,6 @@
#include "tar.h" #include "tar.h"
#include <stdlib.h> #include <stdio.h>
#include <string.h> #include <string.h>
struct unixtar_header *get_unixtar_header(union tar_header *header) 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 ustar_header *ustar_header;
struct unixtar_header *unixtar_header; struct unixtar_header *unixtar_header;
int actual_checksum; char actual_checksum[TCHKSUMLEN];
// USTAR // USTAR
if ((ustar_header = get_ustar_header(header)) != NULL) 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 // UNIXTAR
else if ((unixtar_header = get_unixtar_header(header)) != NULL) 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 // Unsupported format
else else
{ {
return false; 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; // Set to spaces
int sum = 0; 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++) for (int i = 0; i < BLOCK_SIZE; i++)
sum += block[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] = ' ';
}
} }

View file

@ -86,7 +86,7 @@ union tar_header
{ {
struct unixtar_header unixtar; struct unixtar_header unixtar;
struct ustar_header ustar; struct ustar_header ustar;
char raw_block[BLOCK_SIZE]; unsigned char raw_block[BLOCK_SIZE];
}; };
// === Functions // === 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); struct ustar_header *get_ustar_header(union tar_header *header);
/* @brief checks if file has not been corrupted via checksum /* @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 * @return true if member file is valid, false otherwise
*/ */
bool check_checksum(union tar_header *header); 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 * @return the checksum
*/ */
int compute_checksum(union tar_header *header); void compute_checksum(union tar_header *header);
#endif // TAR_H #endif // TAR_H

View file

@ -14,6 +14,7 @@ enum error_code
TARGET_ALREADY_EXISTS, TARGET_ALREADY_EXISTS,
NO_TARGET_PROVIDED, NO_TARGET_PROVIDED,
EMPTY_ARCHIVE, EMPTY_ARCHIVE,
CANNOT_STAT,
NOT_IMPLEMENTED NOT_IMPLEMENTED
}; };