TAR COMPATIBILITYYYYYYYYYYYY
This commit is contained in:
parent
589117ae1a
commit
d71848194f
4 changed files with 76 additions and 23 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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] = ' ';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue