Error saveBinaryFile(const ByteArray & _data, const String & _uri) { FILE * fp = fopen(_uri.cString(), "wb"); if (!fp) { return Error(ec::SystemErrorCode(errno), "fopen failed", STICK_FILE, STICK_LINE); } fwrite(&_data[0], sizeof(char), _data.count(), fp); if (ferror(fp) != 0) { fclose(fp); return Error(ec::SystemErrorCode(errno), "fwrite failed", STICK_FILE, STICK_LINE); } fclose(fp); return Error(); }
bool TarReader::readHeader(Ref<ArchiveEntry> *nextEntry) { if (!data_) data_ = ByteArray::create(512); *nextEntry = ArchiveEntry::create(); ByteArray *data = data_; ArchiveEntry *entry = *nextEntry; if (source_->readAll(data) < data->count()) return false; i_ += data->count(); bool eoi = true; for (int i = 0; i < data->count(); ++i) { if (data->byteAt(i) != 0) { eoi = false; break; } } if (eoi) return false; bool ustarMagic = false; bool gnuMagic = false; bool readAgain = true; while (readAgain) { readAgain = false; String magic; data->scanString(&magic, "", 257, 263); ustarMagic = (magic == "ustar"); gnuMagic = (magic == "ustar "); unsigned checksum, probesum; data->scanNumber(&checksum, 8, 148, 156); entry->type_ = data->at(156); if (entry->path_ == "") data->scanString(&entry->path_, "", 0, 100); if (entry->linkPath_ == "") data->scanString(&entry->linkPath_, "", 157, 257); probesum = tarHeaderSum(data); if (checksum != probesum) throw BrokenArchive(i_ - data->count(), Format("Checksum mismatch (%% != %%), path = \"%%\"") << oct(checksum, 6) << oct(probesum, 6) << entry->path()); if (gnuMagic) { while ((entry->type_ == 'K' || entry->type_ == 'L') /*&& entry->path_ == "././@LongLink"*/) { data->scanNumber(&entry->size_, 8, 124, 136); String longPath = source_->readAll(entry->size_); if (longPath->count() < entry->size_) throw BrokenArchive(i_, "Expected GNU @LongLink data"); i_ += entry->size_; if (entry->size() % 512 != 0) { i_ += source_->skip(512 - entry->size() % 512); } if (longPath->byteAt(longPath->count() - 1) == 0) longPath->truncate(longPath->count() - 1); if (entry->type_ == 'K') entry->linkPath_ = longPath; else if (entry->type_ == 'L') entry->path_ = longPath; if (source_->readAll(data) < data->count()) throw BrokenArchive(i_, "Expected GNU @LongLink header"); i_ += data->count(); entry->type_ = data->at(156); readAgain = true; } } } if (ustarMagic || gnuMagic) { String prefix; data->scanString(&entry->userName_, "", 265, 297); data->scanString(&entry->groupName_, "", 297, 329); if (!gnuMagic) { data->scanString(&prefix, "", 345, 500); if (prefix != "") entry->path_ = prefix + "/" + entry->path_; } } data->scanNumber(&entry->mode_, 8, 100, 108); data->scanNumber(&entry->userId_, 8, 108, 116); data->scanNumber(&entry->groupId_, 8, 116, 124); data->scanNumber(&entry->size_, 8, 124, 136); data->scanNumber(&entry->lastModified_, 8, 136, 148); if (entry->type() == 0 && entry->path()->count() > 0) { if (entry->path()->at(entry->path()->count() - 1) == '/') entry->type_ = ArchiveEntry::Directory; } entry->offset_ = i_; return true; }