Example #1
0
void File::list(FileVector& files, bool bRecursive) const
{
    files.clear();
    DirectoryIterator it(*this, bRecursive);
    while (it.hasNext())
    {
        files.push_back(it.next());
    }
}
bool Ini_UpdaterLists::saveRollbackInfo(const FileVector &rollbackList)
{
    STRING section_name = SS_KEY_RollbackTree;
    long k = 0;
    
    STRING rollbackFileAndPath;
    if(!getProductFolder(m_useCurrentFolder, rollbackFileAndPath, pLog))
    {
        TRACE_MESSAGE("Unable to save rollback information, because failed to get product folder");
        return false;
    }
    rollbackFileAndPath += UPDATER_LISTS_FILENEME;
    
    TRACE_MESSAGE2("Saving rollback list to '%s'", rollbackFileAndPath.to_string().c_str());

    removeRollbackSection();

    // for output saved entries in rows and save space in trace file
    std::string savedEntries;
    unsigned long logLineSplitIndex = 0;

    for(FileVector::const_iterator iter = rollbackList.begin(); iter != rollbackList.end(); ++iter)
    {
        if(iter->m_rollbackChange == STRING(SS_KEY_RecentStatusAdded)
            || iter->m_rollbackChange == STRING(SS_KEY_RecentStatusModified)
            || iter->m_rollbackChange == STRING(SS_KEY_RecentStatusDeleted))
        {
            STRING newSectionName;
            const long order_number = k++;
            makeNewSectionName(order_number, iter->m_filename, newSectionName);
            
            if(!saveRollbackListEntry(rollbackFileAndPath.c_str(), section_name.c_str(), order_number, newSectionName, *iter))
            {
                TRACE_MESSAGE2("Unable to save rollback information for file entry '%s'", (iter->m_localPath + iter->m_filename).to_string().c_str());
                return false;
            }


            // append comma before all items, but the very first one
            if(logLineSplitIndex++)
                savedEntries += ", ";
            // split line each 3 elements, but not before last element
            if(iter + 1 != rollbackList.end())
            {
                if(!(logLineSplitIndex % 3))
                    savedEntries += "\n\t";
            }
            savedEntries += (iter->m_localPath + iter->m_filename).to_string();
        }
    }

    TRACE_MESSAGE3("Rollback information saved successfully to %s, entries: %s", rollbackFileAndPath.to_string().c_str(), savedEntries.c_str());
    return true;
}
Example #3
0
void File::remove(bool bRecursive)
{
    if (bRecursive && !isLink() && isDirectory())
    {
        FileVector files;
        list(files, false);
        for (FileVector::iterator it = files.begin(); it != files.end(); ++it)
        {
            it->remove(true);
        }
    }
    FileImpl::remove(m_sPath);
}
bool Ini_UpdaterLists::readRollbackFileListFromSS(FileVector &changedFiles)
{
    const STRING section_name = SS_KEY_RollbackTree;
    
    STRING rollbackFileAndPath;
    if(!getProductFolder(m_useCurrentFolder, rollbackFileAndPath, pLog))
        return false;
    rollbackFileAndPath += UPDATER_LISTS_FILENEME;
    
    TCHAR childSectionName[MAX_PATH + 1];
    
    for(int _i = 0;; ++_i)
    {
        TCHAR szKeyName[MAX_PATH + 1];
        TCHAR fullSectionName[MAX_PATH + MAX_PATH + 1];
        
        memset(childSectionName, 0, (MAX_PATH + 1) * sizeof(TCHAR));
        memset(szKeyName, 0, (MAX_PATH + 1) * sizeof(TCHAR));
        memset(fullSectionName, 0, (MAX_PATH + MAX_PATH + 1) * sizeof(TCHAR));
        
        _stprintf(szKeyName, _T("entry%d"), _i);
        
        GetPrivateProfileString(section_name.c_str(), szKeyName, _T(""), childSectionName, MAX_PATH, rollbackFileAndPath.c_str());
        
        if(!childSectionName[0])
            break;
        
        _tcscpy(fullSectionName, section_name.c_str());
        _tcscat(fullSectionName, _T(":"));
        _tcscat(fullSectionName, childSectionName);
        
        FileInfo rec;
        if(!readSingleFileInfoRollback(rollbackFileAndPath.c_str(), fullSectionName, rec))
        {
            TRACE_MESSAGE2("Invalid content of '%s' section, skipping", fullSectionName);
            // ignore error, try next entry if any
            continue;
        }
        
        changedFiles.push_back(rec);
    }
    
    return true;
}
Example #5
0
//------------------------------------------------------------------------------
void DirectoryComparer::copy () {
   // variables
   FileCopier copier(safe_mode);
   FileVector& f0 = _uc[0].f;    // for convenience
   vector<path>& d0 = _uc[0].d;  // for convenience
   path fullpath0;               // convenience (updated in loops)
   path fullpath1;               // convenience (updated in loops)
   FileVector errors;            // holds files that we fail to copy
   
   // precompute total number of files and bytes to be transferred
   annotate0();

   // prepare batch, print totals
   unsigned totalFiles = _uc[0].files();
   FileSize totalBytes = _uc[0].bytes();
   copier.startBatch(totalFiles, totalBytes);
   cout << "========== Copying Files from A to B ==========\n";
   cout << "Copying " << totalFiles  << " files totaling " << totalBytes
        << " from " << workingPath(0) << " to " << workingPath(1) << ".\n";
   cout << "  Bytes Processed   |   Current File\n";

   // copy files from _uc[0].f
   for (unsigned i=0; i<f0.size(); ++i) {
      fullpath0 = groundPath(f0[i], 0);
      fullpath1 = groundPath(f0[i], 1);
      if (exists(fullpath1)) {
         // error!
         errors.push_back(f0[i], fullpath0);
         cout << "Warning: Cannot copy " << fullpath0 << " to " << fullpath1 << " because the latter already exists.\n";
      } else {
         copier.copy(fullpath0, fullpath1, f0[i]);
      }
   }

   // copy files from _uc[0].d
   recursive_directory_iterator end;
   unsigned depth = 0;
   path connector;
   path new_extension;
   for (unsigned i=0; i<d0.size(); ++i) {
      // initialize for recursive crawl of this directory
      recursive_directory_iterator itr(groundPath(d0[i], 0));
      depth = 0;
      connector = d0[i];
      cout << copier.status << "Creating directory " << connector << '.' << '\n';
      if (!safe_mode) create_directory(_p[1] / connector);

      while (itr != end) {
         // update connector
         if (depth < itr.level()) {
            connector /= new_extension;
            cout << copier.status << "Creating directory " << connector << '.' << '\n';
            if (!safe_mode) create_directory(_p[1] / connector);
            ++depth;  // this makes depth equal to itr.level()
         } else while (depth > itr.level()) {
            connector.remove_filename();
            --depth;
         }

         // copy file or save name of directory we may iterate into
         if (is_regular_file(itr->path())) {
            fullpath0 = itr->path();
            fullpath1 = _p[1] / connector / fullpath0.filename();
            if (exists(fullpath1)) {
               // error!
               errors.push_back(connector / fullpath0.filename(), fullpath0);
               cout << copier.status << "Warning: Cannot copy " << fullpath0 << " to " << fullpath1 << " because the latter already exists.\n";
            } else {
               copier.copy(fullpath0, fullpath1, connector / fullpath0.filename());
            }
         } else if (is_directory(itr->path())) {
            new_extension = itr->path().filename();
         }
         ++itr;
      }
   }

   // cleanup
   _uc[0].f.clear();
   _uc[0].d.clear();
   _annotations &= ~A0;

   // print outline
   cout << setw(9) << totalBytes << '/' << setw(9) << totalBytes << " | ";
   cout << totalFiles - errors.size() << " of " << totalFiles << " files were copied.\n";
   if (errors.size()) {
      cout << "The following files were not copied:\n";
      for (unsigned i=0; i<errors.size(); ++i) {
         cout << errors[i] << '\n';
      }
   }
   cout << '\n';
}
bool Ini_UpdaterLists::processChangedFiles(const STRING &rollbackFolder, const bool validLocalFilesForRollback)
{
    // Ini updater can not perform rollback in retranslation mode
    if(m_retranslation)
        return false;

    if(!validLocalFilesForRollback)
    {
        TRACE_MESSAGE("Rollback is not created, because inconsistent bases set was locally before update operation started");
        removeRollbackSection();
        return false;
    }
    
    TRACE_MESSAGE("Saving rollback file list");
    
    FileVector updateList;
    
    // set correct status for all entries that have changed
    std::string rollbackTrace;
    for(size_t index = 0; index < m_changedFiles.size(); ++index)
    {
        // entry copy, because size, signature, and hash tags are not valid here.
        //  There are values not for rollback, but values for new files
		FileInfo entryCopy;
        entryCopy.m_filename = m_changedFiles[index].m_filename;
        entryCopy.m_localPath = m_changedFiles[index].m_localPath;

		entryCopy.m_rollbackChange;
        switch(m_changedFiles[index].m_transactionInformation.m_changeStatus)
		{
		case FileInfo::added:
			entryCopy.m_rollbackChange = SS_KEY_RecentStatusAdded;
			break;

		case FileInfo::deleted:
			entryCopy.m_rollbackChange = SS_KEY_RecentStatusDeleted;
			break;
		
		case FileInfo::modified:
			entryCopy.m_rollbackChange = SS_KEY_RecentStatusModified;
			break;

		default:
            // do not write to rollback settings storage unchanged files
            continue;
		}

        // calculate MD5 for consistency check to restore changed and deleted files
        if((entryCopy.m_rollbackChange != SS_KEY_RecentStatusAdded)
            && !calcMD5Hash(STRING(rollbackFolder + entryCopy.m_filename).to_string().c_str(), entryCopy.m_md5))
        {
            TRACE_MESSAGE2("Rollback is not created, failed to calculate md5 for '%s'", (rollbackFolder + entryCopy.m_filename).to_string().c_str());
            return false;
        }
		updateList.push_back(entryCopy);

        if(index != 0)
            rollbackTrace += ", ";
        if(!(index % 15))
            rollbackTrace += "\n\t";
        rollbackTrace += entryCopy.m_filename.to_string() + " " + entryCopy.m_rollbackChange.to_string().c_str();
    }

    TRACE_MESSAGE2("Saving rollback files: %s", rollbackTrace.c_str());
    
    // saving rollback information
    if(!saveRollbackInfo(updateList))
    {
        TRACE_MESSAGE("Failed to save rollback file list");
        return false;
    }
    
    TRACE_MESSAGE("Rollback file list saved successfully");
    return true;
}
Example #7
0
KLUPD::CoreError KLUPD::UpdateInfo::parse(const Path &path,
                                          FileInfo &fileInfo,
                                          const ChangeStateCheck &changeStateCheck,
                                          const FileVector &localFilesToCheckAgainst,
                                          const bool suppressSuccessLogMessages)
{
    // index is already parsed, files already attached
    if(fileAlreadyParsed(fileInfo))
        return CORE_NO_ERROR;

    const Path fullFileName = path + fileInfo.m_filename;

    if(!suppressSuccessLogMessages)
        TRACE_MESSAGE2("Parsing XML index file '%S'", fullFileName.toWideChar());

    std::vector<unsigned char> buffer;
    const CoreError readFileResult = LocalFile(fullFileName, pLog).read(buffer);
    if(!KLUPD::isSuccess(readFileResult))
    {
        TRACE_MESSAGE3("Failed to read XML index file '%S', result '%S'",
            fullFileName.toWideChar(), KLUPD::toString(readFileResult).toWideChar());
        return readFileResult;
    }
    if(buffer.empty())
    {
        TRACE_MESSAGE3("Index XML file '%S' is corrupted, file size is %d", fullFileName.toWideChar(), buffer.size());
        return CORE_UPDATE_DESCRIPTION_DAMAGED;
    }

    // a file list obtained from XML
    FileVector fileList;
    IndexFileXMLParser xmler(fileInfo.m_filename.m_value, fileList, m_signature6Checker, fileInfo.m_relativeURLPath, m_retranslationMode, m_callbacks, pLog);

    XmlReader xmlReader(reinterpret_cast<const char *>(&buffer[0]), buffer.size());
    if(!xmler.parseXMLRecursively(xmlReader, 0)
        || fileList.empty())
    {
        TRACE_MESSAGE3("\tXML file parse error '%S', file number found %d",
            fullFileName.toWideChar(), fileList.size());
        return CORE_UPDATE_DESCRIPTION_DAMAGED;
    }
    m_parsedIndexCache.push_back(fileInfo);

    xmler.GetUpdateDate(fileInfo.m_strUpdateDate);
    xmler.GetBlackDate(fileInfo.m_strBlackDate);

    // save variables to write into settings storage
    std::vector<UpdatedSettings> updatedSettings = xmler.updatedSettings();
    m_updatedSettings.insert(m_updatedSettings.end(), updatedSettings.begin(), updatedSettings.end());

    // copy to match list only those items which suits download criteria
    for(FileVector::iterator fileIter = fileList.begin(); fileIter != fileList.end(); ++fileIter)
    {
        // check download filters criteria should be performed
        NoCaseString reasonNotMatch;
        if(!matchesSettings(reasonNotMatch, *fileIter))
        {
            if(!suppressSuccessLogMessages)
            {
                TRACE_MESSAGE3("\tFile filtered, download criteria does not matches: '%S', %S",
                    reasonNotMatch.toWideChar(), fileIter->toString().toWideChar());
            }
            continue;
        }

        // check download mandatory criteria
        reasonNotMatch.erase();
        if(!isEntryRequired(reasonNotMatch, *fileIter, m_filterFlags))
        {
            if(!suppressSuccessLogMessages)
            {
                TRACE_MESSAGE3("\tFile filtered, mandatory criteria does not matches: '%S', %S",
                    reasonNotMatch.toWideChar(), fileIter->toString().toWideChar());
            }
            continue;
        }

        // setup transaction folders
        fileIter->m_transactionInformation.m_currentLocation = m_callbacks.productFolder(*fileIter, m_retranslationMode);
        fileIter->m_transactionInformation.m_newLocation = m_callbacks.temporaryFolder(*fileIter);
        NoCaseString statusExplanations;
        fileIter->m_transactionInformation.m_changeStatus = getFileStatusAgainstLocal(*fileIter,
            changeStateCheck, localFilesToCheckAgainst, statusExplanations);

        // insert file with filtering duplicates
        bool fileDuplicate = false;

        // insert black list into the beginning of list, because it should be checked before downloading other bases
        if(fileIter->m_type == FileInfo::blackList)
            m_matchFileList.insertNewInTheBeginOfListOrUpdateTheSame(*fileIter, *fileIter, fileDuplicate, m_retranslationMode);
        else
            m_matchFileList.insertNewOrUpdateTheSame(*fileIter, *fileIter, fileDuplicate, m_retranslationMode);


        if(!suppressSuccessLogMessages)
        {
            // to avoid empty brackets output to trace
            if(!statusExplanations.empty())
                statusExplanations = NoCaseString(L"(") + statusExplanations + L")";

            if(fileDuplicate)
            {
                TRACE_MESSAGE3("\tDuplicate file information updated: %S %S",
                    fileIter->toString().toWideChar(), statusExplanations.toWideChar());
            }
            else
            {
                TRACE_MESSAGE3("\tFile matches download criteria: %S %S",
                    fileIter->toString().toWideChar(), statusExplanations.toWideChar());
            }
        }
    }

    return CORE_NO_ERROR;
}
Example #8
0
KLUPD::FileInfo::ChangeStatus KLUPD::UpdateInfo::getFileStatusAgainstLocal(const FileInfo &etalon,
    const ChangeStateCheck &changeStateCheck, const FileVector &localFilesToCheckAgainst, NoCaseString &statusExplanations)const
{
    if(changeStateCheck == noStateChangeCheck)
        return FileInfo::unchanged;

    statusExplanations.erase();

    LocalFile fileInProductFolder(m_callbacks.productFolder(etalon, m_retranslationMode) + etalon.m_filename);

    //////////////////////////////////////////////////////////////////////////
    // check if file in product folder exists
    if(!fileInProductFolder.exists())
    {
        statusExplanations = L"original files does not exist";
        return FileInfo::added;
    }

    // inlined file is already downloaded together with index file, can be only compared if it changed
    if(etalon.isInlined())
    {
        std::vector<unsigned char> buffer;
        const CoreError readInlinedFileResult = fileInProductFolder.read(buffer);
        if(!isSuccess(readInlinedFileResult))
        {
            TRACE_MESSAGE3("Failed to detect change state for inlined file '%S', file operation error '%S'",
                fileInProductFolder.m_name.toWideChar(), toString(readInlinedFileResult).toWideChar());
            statusExplanations = L"inlined file can not be read";
            return FileInfo::added;
        }

        if(buffer == etalon.m_inlinedContent)
        {
            statusExplanations = L"inlined file is not changed";
            return FileInfo::unchanged;
        }
        else
        {
            statusExplanations = L"inlined file is not modified";
            return FileInfo::modified;
        }
    }


    //////////////////////////////////////////////////////////////////////////
    // check against signature 5
    if(!etalon.m_signature5.empty())
    {
        if(checkInsideSignature5AgainstEtalon(fileInProductFolder.m_name, etalon.m_signature5, pLog))
        {
            statusExplanations = L"signature 5 is not changed";
            return FileInfo::unchanged;
        }
        else
        {
            statusExplanations = L"signature 5 is changed";
            return FileInfo::modified;
        }
    }

    //////////////////////////////////////////////////////////////////////////
    // check file against md5
    if(!etalon.m_md5.empty())
    {
        std::vector<unsigned char> md5;
        if(!calcMD5Hash(fileInProductFolder.m_name, md5))
        {
            statusExplanations = L"failed to calculate md5 hash";
            return FileInfo::added;
        }

        if(md5 == etalon.m_md5)
        {
            statusExplanations = L"md5 unchanged";
            return FileInfo::unchanged;
        }
        else
        {
            statusExplanations = L"md5 changed";
            return FileInfo::modified;
        }
    }

    //////////////////////////////////////////////////////////////////////////
    // check date

    statusExplanations += NoCaseString(L"date from index '") + etalon.m_dateFromIndex + L"', "
        + (localFilesToCheckAgainst.empty() ? L"local bases are not consistent" : L"local bases are consistent");

    if(!etalon.m_dateFromIndex.empty()
        // date check is only performed if file presents in consistent local file set,
        // otherwise file may belong to other Update set and must be updated
        && !localFilesToCheckAgainst.empty())
    {
        FileInfo::ChangeStatus modifiedIfDatesAreIgnored = FileInfo::unchanged;

        // check if index date is newer is only performed for Kaspersky sources
        if(changeStateCheck == checkStateButIgnoreDate)
        {
            modifiedIfDatesAreIgnored = FileInfo::modified;
            statusExplanations = L", dates are ignored for user-specified sources";
        }

        FileInfo localConsistentFile;
        if(localFilesToCheckAgainst.findTheSameFile(etalon, localConsistentFile, m_retranslationMode))
        {
            bool bIndex = etalon.isIndex();
            const NoCaseString& strLocalFileDate = bIndex ? localConsistentFile.m_strUpdateDate : localConsistentFile.m_dateFromIndex;
            NoCaseString strFileType(bIndex ? L"index" : L"non-index"); // for trace

            if(!strLocalFileDate.empty())
            {
                // if expected date on source is less, then file is skipped
                unsigned long nEtalonDate = updateDateStringToSequenceNumber(etalon.m_dateFromIndex);
                unsigned long nLocalFileDate = updateDateStringToSequenceNumber(strLocalFileDate);
                if(nEtalonDate < nLocalFileDate)
                {
                    statusExplanations += NoCaseString(L", ") + FileInfo::toString(modifiedIfDatesAreIgnored).toWideChar() +
                        L" " + strFileType + L" file is found in local consistent set with date '" + localConsistentFile.m_dateFromIndex + L"'";
                    return modifiedIfDatesAreIgnored;
                }
                else if( bIndex || nEtalonDate > nLocalFileDate)
                {
                    statusExplanations += NoCaseString(L", modified ") + strFileType + L" file is found in local consistent set, date from file '" + strLocalFileDate + L"'";
                    return FileInfo::modified;
                }
                else
                    statusExplanations +=  NoCaseString(L", ") + strFileType + L" file is found in local consistent set with same date";
            }
            else
                statusExplanations += NoCaseString(L", ") + strFileType + L" file is found in local consistent set, but there is no date in index specified";
        }
        else
            statusExplanations += L", file is not found in local consistent set";
    }

    //////////////////////////////////////////////////////////////////////////
    // check against signature 6

    bool insideSignature = false;
    NoCaseString errorMessage;
    if(!m_signature6Checker.checkSignature(fileInProductFolder.m_name, insideSignature, errorMessage))
    {
        statusExplanations += NoCaseString(L", signature 6 check changed (") + errorMessage + L")";
        return FileInfo::modified;
    }

    // file may contain inside signature6, then there is no way to determine whether
     //  file is different on source, and that is why must always be downloaded
    if(insideSignature)
    {
        statusExplanations += L", inside signature 6 check unchanged (file needs being downloaded)";
        return FileInfo::modified;
    }
    else
    {
        statusExplanations += L", signature 6 check unchanged";
        return FileInfo::unchanged;
    }
}