#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; ShowPrompt(false, "%s\n%s", tar->fname, fname); 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; }