85 lines
2.4 KiB
C
Raw Normal View History

2017-10-30 14:46:37 +01:00
#include "tar.h"
u64 ReadAsciiOctal(char* num, u32 len) {
u64 res = 0;
2017-10-30 14:46:37 +01:00
if ((num[len-1] != '\0') && (num[len-1] != ' '))
return (u64) -1;
2017-10-30 14:46:37 +01:00
for (u32 i = 0; i < (len-1); i++) {
res <<= 3;
if ((num[i] >= '0') && (num[i] < '8')) res |= (num[i] - '0');
else return (u64) -1;
}
2017-10-30 14:46:37 +01:00
return res;
}
u32 ValidateTarHeader(void* tardata, void* tardata_end) {
TarHeader* tar = tardata;
2017-10-30 14:46:37 +01:00
// available space
if ((u8*) tardata_end < (u8*) tardata + sizeof(TarHeader))
return 1;
2017-10-30 14:46:37 +01:00
// filename prefix is not supported here
if (*(tar->fname_prefix)) return 1;
2017-10-30 14:46:37 +01:00
// check filesize
u64 fsize_max = ((u8*) tardata_end - (u8*) tardata) - sizeof(TarHeader);
if (ReadAsciiOctal(tar->fsize, 12) > fsize_max)
return 1;
2017-10-30 14:46:37 +01:00
// type can only be standard file or dir
2017-11-17 16:25:30 +01:00
if (tar->ftype && (tar->ftype != '0') && (tar->ftype != '5'))
2017-10-30 14:46:37 +01:00
return 1;
2017-10-30 14:46:37 +01:00
// checksum
u8* data = (u8*) tardata;
u64 checksum = 0;
for (u32 i = 0; i < sizeof(TarHeader); i++)
checksum += ((i < 148) || (i >= 156)) ? data[i] : (u64) ' ';
if (checksum != ReadAsciiOctal(tar->checksum, 7))
return 1;
2017-10-30 14:46:37 +01:00
return 0;
}
void* GetTarFileInfo(void* tardata, char* fname, u64* fsize, bool* is_dir) {
// this assumes a valid TAR header
TarHeader* tar = tardata;
2017-10-30 14:46:37 +01:00
if (fname) snprintf(fname, 101, "%.100s", tar->fname);
if (fsize) *fsize = ReadAsciiOctal(tar->fsize, 12);
if (is_dir) *is_dir = (tar->ftype == '5');
2017-10-30 14:46:37 +01:00
return (void*) (tar + 1);
}
void* NextTarEntry(void* tardata, void* tardata_end) {
// this assumes a valid TAR header
TarHeader* tar = tardata;
u8* data = (u8*) tardata;
u64 fsize = ReadAsciiOctal(tar->fsize, 12);
2017-10-30 14:46:37 +01:00
data += sizeof(TarHeader) + align(fsize, 512);
if (ValidateTarHeader(data, tardata_end) != 0)
return NULL;
2017-10-30 14:46:37 +01:00
return data;
}
2017-11-17 16:25:30 +01:00
void* FindTarFileInfo(void* tardata, void* tardata_end, const char* fname, u64* fsize) {
2017-10-30 14:46:37 +01:00
while (tardata && (tardata < tardata_end)) {
TarHeader* tar = tardata;
2017-10-30 14:46:37 +01:00
if (ValidateTarHeader(tardata, tardata_end) != 0) break;
2017-11-17 16:25:30 +01:00
if ((strncasecmp(tar->fname, fname, 100) == 0) && (!tar->ftype || (tar->ftype == '0')))
return GetTarFileInfo(tardata, NULL, fsize, NULL);
2017-10-30 14:46:37 +01:00
tardata = ((u8*) tardata) + sizeof(TarHeader) + align(ReadAsciiOctal(tar->fsize, 12), 512);
}
2017-10-30 14:46:37 +01:00
return NULL;
}