bool ExtractLink(ComprDataIO &DataIO,Archive &Arc,const char *LinkName,uint &LinkCRC,bool Create) { #if defined(SAVE_LINKS) && defined(_UNIX) char LinkTarget[NM]; if (IsLink(Arc.NewLhd.FileAttr)) { int DataSize=Min(Arc.NewLhd.PackSize,sizeof(LinkTarget)-1); DataIO.UnpRead((byte *)LinkTarget,DataSize); LinkTarget[DataSize]=0; if (Create) { CreatePath(LinkName,NULL,true); if (symlink(LinkTarget,LinkName)==-1) // Error. if (errno==EEXIST) Log(Arc.FileName,St(MSymLinkExists),LinkName); else { Log(Arc.FileName,St(MErrCreateLnk),LinkName); ErrHandler.SetErrorCode(RARX_WARNING); } // We do not set time of created symlink, because utime changes // time of link target and lutimes is not available on all Linux // systems at the moment of writing this code. } int NameSize=Min(DataSize,strlen(LinkTarget)); LinkCRC=CRC(0xffffffff,LinkTarget,NameSize); return(true); } #endif return(false); }
int ExtractLink(ComprDataIO &DataIO,Archive &Arc,char *DestName,unsigned int &LinkCRC,bool Create) { #if defined(SAVE_LINKS) && defined(_UNIX) char FileName[NM]; if (IsLink(Arc.NewLhd.FileAttr)) { int DataSize=Min(Arc.NewLhd.PackSize,sizeof(FileName)-1); DataIO.UnpRead((unsigned char *)FileName,DataSize); FileName[DataSize]=0; if (Create) { CreatePath(DestName,NULL,true); if (symlink(FileName,DestName)==-1) if (errno==EEXIST) Log(Arc.FileName,St(MSymLinkExists),DestName); else { Log(Arc.FileName,St(MErrCreateLnk),DestName); ErrHandler.SetErrorCode(WARNING); } } LinkCRC=CRC(0xffffffff,FileName,DataSize); return(1); } #endif return(0); }
int ExtractLink(ComprDataIO &DataIO,Archive &Arc,char *DestName,uint &LinkCRC,bool Create) { #if defined(SAVE_LINKS) && defined(_UNIX) char FileName[NM]; if (IsLink(Arc.NewLhd.FileAttr)) { uint DataSize=Min(Arc.NewLhd.PackSize,sizeof(FileName)-1); DataIO.UnpRead((byte *)FileName,DataSize); FileName[DataSize]=0; if (Create) { CStdString strPath = URIUtils::GetDirectory(DestName); CUtil::CreateDirectoryEx(strPath); if (symlink(FileName,DestName)==-1) { if (errno==EEXIST) Log(Arc.FileName,St(MSymLinkExists),DestName); else { Log(Arc.FileName,St(MErrCreateLnk),DestName); ErrHandler.SetErrorCode(WARNING); } } } int NameSize=Min(DataSize,strlen(FileName)); LinkCRC=CRC(0xffffffff,FileName,NameSize); return(1); } #endif return(0); }
void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize) { Array<byte> Buffer(0x40000); while (1) { uint Code=DataIO.UnpRead(&Buffer[0],Buffer.Size()); if (Code==0 || (int)Code==-1) break; Code=Code<DestUnpSize ? Code:(uint)DestUnpSize; DataIO.UnpWrite(&Buffer[0],Code); if (DestUnpSize>=0) DestUnpSize-=Code; } }
void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize) { // 512 KB and larger buffer reported to reduce performance on old XP // computers with WDC WD2000JD HDD. According to test made by user // 256 KB buffer is optimal. Array<byte> Buffer(0x40000); while (1) { uint Code=DataIO.UnpRead(&Buffer[0],Buffer.Size()); if (Code==0 || (int)Code==-1) break; Code=Code<DestUnpSize ? Code:(uint)DestUnpSize; DataIO.UnpWrite(&Buffer[0],Code); if (DestUnpSize>=0) DestUnpSize-=Code; } }
bool ExtractUnixLink30(ComprDataIO &DataIO,Archive &Arc,const wchar *LinkName) { char Target[NM]; if (IsLink(Arc.FileHead.FileAttr)) { size_t DataSize=Min(Arc.FileHead.PackSize,ASIZE(Target)-1); DataIO.UnpRead((byte *)Target,DataSize); Target[DataSize]=0; DataIO.UnpHash.Init(Arc.FileHead.FileHash.Type,1); DataIO.UnpHash.Update(Target,strlen(Target)); DataIO.UnpHash.Result(&Arc.FileHead.FileHash); // Return true in case of bad checksum, so link will be processed further // and extraction routine will report the checksum error. if (!DataIO.UnpHash.Cmp(&Arc.FileHead.FileHash,Arc.FileHead.UseHashKey ? Arc.FileHead.HashKey:NULL)) return true; return UnixSymlink(Target,LinkName); } return false; }
void CPsfRarArchive::ReadFileContents(const char* fileName, void* buffer, unsigned int bufferLength) { Archive* arc(ConvertArchive(m_archive)); if(!arc->IsOpened()) { throw std::runtime_error("Archive isn't opened."); } std::string fixedFileName(fileName); boost::replace_all(fixedFileName, "/", "\\"); arc->Seek(0, SEEK_SET); ComprDataIO dataIo; dataIo.Init(); Unpack unpack(&dataIo); while(arc->ReadHeader() > 0) { if(arc->ShortBlock.HeaderType == HEAD_FILE) { if(!arc->IsArcDir()) { bool isGoodFile = !stricmp(fixedFileName.c_str(), string_cast<std::string>(arc->FileHead.FileName).c_str()); dataIo.SetFiles(arc, NULL); dataIo.SetPackedSizeToRead(arc->FileHead.PackSize); dataIo.CurUnpRead = 0; dataIo.CurUnpWrite = 0; dataIo.UnpHash.Init(arc->FileHead.FileHash.Type, 1); dataIo.PackedDataHash.Init(arc->FileHead.FileHash.Type, 1); dataIo.SetTestMode(!isGoodFile); if(isGoodFile) { dataIo.SetUnpackToMemory(reinterpret_cast<byte*>(buffer), bufferLength); } unpack.Init(arc->FileHead.WinSize, arc->FileHead.Solid); unpack.SetDestSize(arc->FileHead.UnpSize); if(arc->FileHead.Method == 0x30) { std::vector<byte> unstoreBuffer; unstoreBuffer.resize(0x10000); uint toReadSize = arc->FileHead.UnpSize; while(1) { uint code = dataIo.UnpRead(&unstoreBuffer[0], unstoreBuffer.size()); if(code == 0 || code == -1) break; code = code < toReadSize ? code : toReadSize; dataIo.UnpWrite(&unstoreBuffer[0], code); if(toReadSize >= 0) { toReadSize -= code; } } } else { unpack.DoUnpack(arc->FileHead.UnpVer, arc->FileHead.Solid); } if(!dataIo.UnpHash.Cmp(&arc->FileHead.FileHash, arc->FileHead.UseHashKey ? arc->FileHead.HashKey : nullptr)) { throw std::runtime_error("CRC check error."); } if(isGoodFile) { return; } } } arc->SeekToNext(); } throw std::runtime_error("Couldn't read file from archive."); }