📄 partfile.cpp
字号:
strError += _T(" - ");
strError += szError;
}
AddLogLine(false, _T("%s"), strError);
return false;
}
// read part file creation time
struct _stat fileinfo;
if (_tstat(searchpath, &fileinfo) == 0){
m_tLastModified = fileinfo.st_mtime;
m_tCreated = fileinfo.st_ctime;
}
else
AddDebugLogLine(false, _T("Failed to get file date for \"%s\" - %hs"), searchpath, strerror(errno));
try{
SetFilePath(searchpath);
m_dwFileAttributes = GetFileAttributes(GetFilePath());
if (m_dwFileAttributes == INVALID_FILE_ATTRIBUTES)
m_dwFileAttributes = 0;
// SLUGFILLER: SafeHash - final safety, make sure any missing part of the file is gap
if (m_hpartfile.GetLength() < m_nFileSize)
AddGap(m_hpartfile.GetLength(), m_nFileSize-1);
// Goes both ways - Partfile should never be too large
if (m_hpartfile.GetLength() > m_nFileSize){
TRACE(_T("Partfile \"%s\" is too large! Truncating %I64u bytes.\n"), GetFileName(), m_hpartfile.GetLength() - m_nFileSize);
m_hpartfile.SetLength(m_nFileSize);
}
// SLUGFILLER: SafeHash
m_SrcpartFrequency.SetSize(GetPartCount());
for (uint32 i = 0; i != GetPartCount();i++)
m_SrcpartFrequency[i] = 0;
SetStatus(PS_EMPTY);
// check hashcount, filesatus etc
if (GetHashCount() != GetED2KPartHashCount()){
ASSERT( hashlist.GetSize() == 0 );
hashsetneeded = true;
return true;
}
else {
hashsetneeded = false;
for (int i = 0; i < hashlist.GetSize(); i++){
if (IsComplete(i*PARTSIZE,((i+1)*PARTSIZE)-1)){
SetStatus(PS_READY);
break;
}
}
}
if (gaplist.IsEmpty()){ // is this file complete already?
CompleteFile(false);
return true;
}
if (!isnewstyle) // not for importing
{
// check date of .part file - if its wrong, rehash file
CFileStatus filestatus;
m_hpartfile.GetStatus(filestatus); // this; "...returns m_attribute without high-order flags" indicates a known MFC bug, wonder how many unknown there are... :)
uint32 fdate = filestatus.m_mtime.GetTime();
if (fdate == -1){
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Failed to convert file date of %s (%s)"), filestatus.m_szFullName, GetFileName());
}
else
AdjustNTFSDaylightFileTime(fdate, filestatus.m_szFullName);
if (m_tUtcLastModified != fdate){
CString strFileInfo;
strFileInfo.Format(_T("%s (%s)"), GetFilePath(), GetFileName());
AddLogLine(false, GetResString(IDS_ERR_REHASH), strFileInfo);
// rehash
SetStatus(PS_WAITINGFORHASH);
CAddFileThread* addfilethread = (CAddFileThread*) AfxBeginThread(RUNTIME_CLASS(CAddFileThread), THREAD_PRIORITY_NORMAL,0, CREATE_SUSPENDED);
if (addfilethread){
SetFileOp(PFOP_HASHING);
SetFileOpProgress(0);
addfilethread->SetValues(0, GetPath(), m_hpartfile.GetFileName(), this);
addfilethread->ResumeThread();
}
else
SetStatus(PS_ERROR);
}
}
}
catch(CFileException* error){
CString strError;
strError.Format(_T("Failed to initialize part file \"%s\" (%s)"), m_hpartfile.GetFilePath(), GetFileName());
TCHAR szError[MAX_CFEXP_ERRORMSG];
if (error->GetErrorMessage(szError, ARRSIZE(szError))){
strError += _T(" - ");
strError += szError;
}
AddLogLine(false, _T("%s"), strError);
error->Delete();
return false;
}
UpdateCompletedInfos();
if ( completedsize > transfered )
m_iGainDueToCompression = completedsize - transfered;
else if ( completedsize != transfered )
m_iLostDueToCorruption = transfered - completedsize;
return true;
}
bool CPartFile::SavePartFile()
{
switch (status){
case PS_WAITINGFORHASH:
case PS_HASHING:
return false;
}
// search part file
CFileFind ff;
CString searchpath(RemoveFileExtension(m_fullname));
bool end = !ff.FindFile(searchpath,0);
if (!end)
ff.FindNextFile();
if (end || ff.IsDirectory()){
AddLogLine(false, GetResString(IDS_ERR_SAVEMET) + _T(" - %s"), m_partmetfilename, GetFileName(), GetResString(IDS_ERR_PART_FNF));
return false;
}
//get filedate
CTime lwtime;
if (!ff.GetLastWriteTime(lwtime)){
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Failed to get file date of %s (%s) - %s"), m_partmetfilename, GetFileName(), GetErrorMessage(GetLastError()));
}
m_tLastModified = lwtime.GetTime();
m_tUtcLastModified = m_tLastModified;
if (m_tUtcLastModified == -1){
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Failed to convert file date of %s (%s)"), m_partmetfilename, GetFileName());
}
else
AdjustNTFSDaylightFileTime(m_tUtcLastModified, ff.GetFilePath());
ff.Close();
CString strTmpFile(m_fullname);
strTmpFile += PARTMET_TMP_EXT;
// save file data to part.met file
CSafeBufferedFile file;
CFileException fexp;
if (!file.Open(strTmpFile, CFile::modeWrite|CFile::modeCreate|CFile::typeBinary|CFile::shareDenyWrite, &fexp)){
CString strError;
strError.Format(GetResString(IDS_ERR_SAVEMET), m_partmetfilename, GetFileName());
TCHAR szError[MAX_CFEXP_ERRORMSG];
if (fexp.GetErrorMessage(szError, ARRSIZE(szError))){
strError += _T(" - ");
strError += szError;
}
AddLogLine(false, _T("%s"), strError);
return false;
}
setvbuf(file.m_pStream, NULL, _IOFBF, 16384);
try{
//version
file.WriteUInt8(PARTFILE_VERSION);
//date
file.WriteUInt32(m_tUtcLastModified);
//hash
file.WriteHash16(m_abyFileHash);
UINT parts = hashlist.GetCount();
file.WriteUInt16(parts);
for (UINT x = 0; x < parts; x++)
file.WriteHash16(hashlist[x]);
UINT uTagCount = 0;
ULONG uTagCountFilePos = (ULONG)file.GetPosition();
file.WriteUInt32(uTagCount);
#ifdef _UNICODE
if (WriteOptED2KUTF8Tag(&file, GetFileName(), FT_FILENAME))
uTagCount++;
#endif
CTag nametag(FT_FILENAME, GetFileName());
nametag.WriteTagToFile(&file);
uTagCount++;
CTag sizetag(FT_FILESIZE, m_nFileSize);
sizetag.WriteTagToFile(&file);
uTagCount++;
if (transfered){
CTag transtag(FT_TRANSFERED, transfered);
transtag.WriteTagToFile(&file);
uTagCount++;
}
if (paused){
CTag statustag(FT_STATUS, 1);
statustag.WriteTagToFile(&file);
uTagCount++;
}
CTag prioritytag(FT_DLPRIORITY, IsAutoDownPriority() ? PR_AUTO : m_iDownPriority);
prioritytag.WriteTagToFile(&file);
uTagCount++;
CTag ulprioritytag(FT_ULPRIORITY, IsAutoUpPriority() ? PR_AUTO : GetUpPriority());
ulprioritytag.WriteTagToFile(&file);
uTagCount++;
if (lastseencomplete.GetTime()){
CTag lsctag(FT_LASTSEENCOMPLETE,lastseencomplete.GetTime());
lsctag.WriteTagToFile(&file);
uTagCount++;
}
if (m_category){
CTag categorytag(FT_CATEGORY, m_category);
categorytag.WriteTagToFile(&file);
uTagCount++;
}
if (GetLastPublishTimeKadSrc()){
CTag kadLastPubSrc(FT_KADLASTPUBLISHSRC, GetLastPublishTimeKadSrc());
kadLastPubSrc.WriteTagToFile(&file);
uTagCount++;
}
if (GetDlActiveTime()){
CTag tagDlActiveTime(FT_DL_ACTIVE_TIME, GetDlActiveTime());
tagDlActiveTime.WriteTagToFile(&file);
uTagCount++;
}
if (GetPreviewPrio()){
CTag tagDlPreview(FT_DL_PREVIEW, GetPreviewPrio() ? 1 : 0);
tagDlPreview.WriteTagToFile(&file);
uTagCount++;
}
// statistics
if (statistic.GetAllTimeTransferred()){
CTag attag1(FT_ATTRANSFERED, (uint32)statistic.GetAllTimeTransferred());
attag1.WriteTagToFile(&file);
uTagCount++;
CTag attag4(FT_ATTRANSFEREDHI, (uint32)(statistic.GetAllTimeTransferred() >> 32));
attag4.WriteTagToFile(&file);
uTagCount++;
}
if (statistic.GetAllTimeRequests()){
CTag attag2(FT_ATREQUESTED, statistic.GetAllTimeRequests());
attag2.WriteTagToFile(&file);
uTagCount++;
}
if (statistic.GetAllTimeAccepts()){
CTag attag3(FT_ATACCEPTED, statistic.GetAllTimeAccepts());
attag3.WriteTagToFile(&file);
uTagCount++;
}
// currupt part infos
POSITION posCorruptedPart = corrupted_list.GetHeadPosition();
if (posCorruptedPart)
{
CString strCorruptedParts;
while (posCorruptedPart)
{
uint16 uCorruptedPart = corrupted_list.GetNext(posCorruptedPart);
if (!strCorruptedParts.IsEmpty())
strCorruptedParts += _T(",");
strCorruptedParts.AppendFormat(_T("%u"), (UINT)uCorruptedPart);
}
ASSERT( !strCorruptedParts.IsEmpty() );
CTag tagCorruptedParts(FT_CORRUPTEDPARTS, strCorruptedParts);
tagCorruptedParts.WriteTagToFile(&file);
uTagCount++;
}
//AICH Filehash
if (m_pAICHHashSet->HasValidMasterHash() && (m_pAICHHashSet->GetStatus() == AICH_VERIFIED)){
CTag aichtag(FT_AICH_HASH, m_pAICHHashSet->GetMasterHash().GetString() );
aichtag.WriteTagToFile(&file);
uTagCount++;
}
for (int j = 0; j < taglist.GetCount(); j++){
if (taglist[j]->IsStr() || taglist[j]->IsInt()){
taglist[j]->WriteTagToFile(&file);
uTagCount++;
}
}
//gaps
char namebuffer[10];
char* number = &namebuffer[1];
uint16 i_pos = 0;
for (POSITION pos = gaplist.GetHeadPosition();pos != 0;)
{
Gap_Struct* gap = gaplist.GetNext(pos);
itoa(i_pos,number,10);
namebuffer[0] = FT_GAPSTART;
CTag gapstarttag(namebuffer,gap->start);
gapstarttag.WriteTagToFile(&file);
uTagCount++;
// gap start = first missing byte but gap ends = first non-missing byte in edonkey
// but I think its easier to user the real limits
namebuffer[0] = FT_GAPEND;
CTag gapendtag(namebuffer,gap->end+1);
gapendtag.WriteTagToFile(&file);
uTagCount++;
i_pos++;
}
file.Seek(uTagCountFilePos, CFile::begin);
file.WriteUInt32(uTagCount);
file.SeekToEnd();
if (thePrefs.GetCommitFiles() >= 2 || (thePrefs.GetCommitFiles() >= 1 && !theApp.emuledlg->IsRunning())){
file.Flush(); // flush file stream buffers to disk buffers
if (_commit(_fileno(file.m_pStream)) != 0) // commit disk buffers to disk
AfxThrowFileException(CFileException::hardIO, GetLastError(), file.GetFileName());
}
file.Close();
}
catch(CFileException* error){
CString strError;
strError.Format(GetResString(IDS_ERR_SAVEMET), m_partmetfilename, GetFileName());
TCHAR szError[MAX_CFEXP_ERRORMSG];
if (error->GetErrorMessage(szError, ARRSIZE(szError))){
strError += _T(" - ");
strError += szError;
}
AddLogLine(false, _T("%s"), strError);
error->Delete();
// remove the partially written or otherwise damaged temporary file
file.Abort(); // need to close the file before removing it. call 'Abort' instead of 'Close', just to avoid an ASSERT.
(void)_tremove(strTmpFile);
return false;
}
// after successfully writing the temporary part.met file...
if (_tremove(m_fullname) != 0 && errno != ENOENT){
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Failed to remove \"%s\" - %s"), m_fullname, strerror(errno));
}
if (_trename(strTmpFile, m_fullname) != 0){
int iErrno = errno;
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Failed to move temporary part.met file \"%s\" to \"%s\" - %s"), strTmpFile, m_fullname, strerror(iErrno));
CString strError;
strError.Format(GetResString(IDS_ERR_SAVEMET), m_partmetfilename, GetFileName());
strError += _T(" - ");
strError += strerror(iErrno);
AddLogLine(false, _T("%s"), strError);
return false;
}
// create a backup of the successfully written part.met file
CString BAKName(m_fullname);
BAKName.Append(PARTMET_BAK_EXT);
if (!::CopyFile(m_fullname, BAKName, FALSE)){
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Failed to create backup of %s (%s) - %s"), m_fullname, GetFileName(), GetErrorMessage(GetLastError()));
}
return true;
}
void CPartFile::PartFileHashFinished(CKnownFile* result){
newdate = true;
bool errorfound = false;
if (GetED2KPartHashCount()==0 || GetHashCount()==0){
if (IsComplete(0, m_nFileSize-1)){
if (md4cmp(result->GetFileHash(), GetFileHash())){
AddLogLine(false, GetResString(IDS_ERR_FOUNDCORRUPTION), 1, GetFileName());
AddGap(0, m_nFileSize-1);
errorfound = true;
}
else{
if (GetED2KPartHashCount() != GetHashCount()){
ASSERT( result->GetED2KPartHashCount() == GetED2KPartHashCount() );
if (SetHashset(result->GetHashset()))
hashsetneeded = false;
}
}
}
}
else{
for (uint32 i = 0; i < (uint32)hashlist.GetSize(); i++){
if (IsComplete(i*PARTSIZE,((i+1)*PARTSIZE)-1)){
if (!(result->GetPartHash(i) && !md4cmp(result->GetPartHash(i),this->GetPartHash(i)))){
AddLogLine(false, GetResString(IDS_ERR_FOUNDCORRUPTION), i+1, GetFileName());
AddGap(i*PARTSIZE,((((i+1)*PARTSIZE)-1) >= m_nFileSize) ? m_nFileSize-1 : ((i+1)*PARTSIZE)-1);
errorfound = true;
}
}
}
}
if (!errorfound && result->GetAICHHashset()->GetStatus() == AICH_HASHSETCOMPLETE && status == PS_COMPLETING){
delete m_pAICHHashSet;
m_pAICHHashSet = result->GetAICHHashset();
result->SetAICHHashset(NULL);
}
else if (status == PS_COMPLETING){
AddDebugLogLine(false, _T("Failed to store new AICH Hashset for completed file %s"), GetFileName());
}
delete result;
if (!errorfound){
if (status == PS_COMPLETING){
if (thePrefs.GetVerbose())
AddDebugLogLine(true, _T("Completed file-hashing for \"%s\""), GetFileName());
if (theApp.sharedfiles->GetFileByID(GetFileHash()) == NULL)
theApp.sharedfiles->SafeAddKFile(this);
CompleteFile(true);
return;
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -