mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
89 lines
2.5 KiB
C
89 lines
2.5 KiB
C
|
#include "tar.h"
|
||
|
|
||
|
|
||
|
u64 ReadAsciiOctal(char* num, u32 len) {
|
||
|
u64 res = 0;
|
||
|
|
||
|
if ((num[len-1] != '\0') && (num[len-1] != ' '))
|
||
|
return (u64) -1;
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
u32 ValidateTarHeader(void* tardata, void* tardata_end) {
|
||
|
TarHeader* tar = tardata;
|
||
|
|
||
|
// available space
|
||
|
if ((u8*) tardata_end < (u8*) tardata + sizeof(TarHeader))
|
||
|
return 1;
|
||
|
|
||
|
// filename prefix is not supported here
|
||
|
if (*(tar->fname_prefix)) return 1;
|
||
|
|
||
|
// ustar magic
|
||
|
if (strncmp(tar->magic, USTAR_MAGIC, 5) != 0)
|
||
|
return 1;
|
||
|
|
||
|
// check filesize
|
||
|
u64 fsize_max = ((u8*) tardata_end - (u8*) tardata) - sizeof(TarHeader);
|
||
|
if (ReadAsciiOctal(tar->fsize, 12) > fsize_max)
|
||
|
return 1;
|
||
|
|
||
|
// type can only be standard file or dir
|
||
|
if ((tar->ftype != '0') && (tar->ftype != '5'))
|
||
|
return 1;
|
||
|
|
||
|
// 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;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void* GetTarFileInfo(void* tardata, char* fname, u64* fsize, bool* is_dir) {
|
||
|
// this assumes a valid TAR header
|
||
|
TarHeader* tar = tardata;
|
||
|
|
||
|
if (fname) snprintf(fname, 101, "%.100s", tar->fname);
|
||
|
if (fsize) *fsize = ReadAsciiOctal(tar->fsize, 12);
|
||
|
if (is_dir) *is_dir = (tar->ftype == '5');
|
||
|
|
||
|
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);
|
||
|
|
||
|
data += sizeof(TarHeader) + align(fsize, 512);
|
||
|
if (ValidateTarHeader(data, tardata_end) != 0)
|
||
|
return NULL;
|
||
|
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
void* FindTarFileInfo(void* tardata, void* tardata_end, const char* fname, u64* fsize, bool* is_dir) {
|
||
|
while (tardata && (tardata < tardata_end)) {
|
||
|
TarHeader* tar = tardata;
|
||
|
|
||
|
if (ValidateTarHeader(tardata, tardata_end) != 0) break;
|
||
|
if ((strncasecmp(tar->fname, fname, 100) == 0) && (tar->ftype == '0'))
|
||
|
return GetTarFileInfo(tardata, NULL, fsize, is_dir);
|
||
|
tardata = ((u8*) tardata) + sizeof(TarHeader) + align(ReadAsciiOctal(tar->fsize, 12), 512);
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|