Esempio n. 1
0
bool
IcePatch2::Patcher::removeFiles(const FileInfoSeq& files)
{
    if(_remove < 1)
    {
        return true;
    }

    for(FileInfoSeq::const_reverse_iterator p = files.rbegin(); p != files.rend(); ++p)
    {
        try
        {
            remove(_dataDir + '/' + p->path);
            if(fputc('-', _log) == EOF || ! writeFileInfo(_log, *p))
            {
                throw "error writing log file:\n" + IceUtilInternal::lastErrorToString();
            }
        }
        catch(...)
        {
            if(_remove < 2) // We ignore errors if IcePatch2Client.Remove >= 2.
            {
                throw;
            }
        }
    }
    
    FileInfoSeq newLocalFiles;
    newLocalFiles.reserve(_localFiles.size());
    
    set_difference(_localFiles.begin(),
                   _localFiles.end(),
                   files.begin(),
                   files.end(),
                   back_inserter(newLocalFiles),
                   FileInfoLess());
    
    _localFiles.swap(newLocalFiles);
    
    FileInfoSeq newRemoveFiles;
    
    set_difference(_removeFiles.begin(),
                   _removeFiles.end(),
                   files.begin(),
                   files.end(),
                   back_inserter(newRemoveFiles),
                   FileInfoLess());
    
    _removeFiles.swap(newRemoveFiles);

    return true;
}
Esempio n. 2
0
bool
IcePatch2::Patcher::updateFlags(const FileInfoSeq& files)
{
    for(FileInfoSeq::const_iterator p = files.begin(); p != files.end(); ++p)
    {
        if(p->size >= 0) // Regular file?
        {
            setFileFlags(_dataDir + '/' + p->path, *p);
        }
    }

    //
    // Remove the old files whose flags were updated from the set of
    // local files.
    // 
    FileInfoSeq localFiles;
    localFiles.reserve(_localFiles.size());
    set_difference(_localFiles.begin(),
                   _localFiles.end(),
                   files.begin(),
                   files.end(),
                   back_inserter(localFiles),
                   FileInfoWithoutFlagsLess()); // NOTE: We ignore the flags.

    //
    // Add the new files to the set of local file. 
    //
    _localFiles.clear();
    set_union(localFiles.begin(),
              localFiles.end(),
              files.begin(),
              files.end(),
              back_inserter(_localFiles),
              FileInfoLess());

    FileInfoSeq newUpdateFlags;

    set_difference(_updateFlags.begin(),
                   _updateFlags.end(),
                   files.begin(),
                   files.end(),
                   back_inserter(newUpdateFlags),
                   FileInfoLess());
        
    _updateFlags.swap(newUpdateFlags);

    return true;
}
Esempio n. 3
0
bool
IcePatch2::Patcher::updateFilesInternal(const FileInfoSeq& files, const DecompressorPtr& decompressor)
{
    Long total = 0;
    Long updated = 0;
    
    for(FileInfoSeq::const_iterator p = files.begin(); p != files.end(); ++p)
    {
        if(p->size > 0) // Regular, non-empty file?
        {
            total += p->size;
        }
    }
    
    AsyncResultPtr curCB;
    AsyncResultPtr nxtCB;

    for(FileInfoSeq::const_iterator p = files.begin(); p != files.end(); ++p)
    {
        if(p->size < 0) // Directory?
        {
            createDirectoryRecursive(_dataDir + '/' + p->path);
            if(fputc('+', _log) == EOF || !writeFileInfo(_log, *p))
            {
                throw "error writing log file:\n" + IceUtilInternal::lastErrorToString();
            }
        }
        else // Regular file.
        {
            if(!_feedback->patchStart(p->path, p->size, updated, total))
            {
                return false;
            }

            if(p->size == 0)
            {
                string path = simplify(_dataDir + '/' + p->path);
                FILE* fp = IceUtilInternal::fopen(path, "wb");
                if(fp == 0)
                {
                    throw "cannot open `" + path +"' for writing:\n" + IceUtilInternal::lastErrorToString();
                }
                fclose(fp);
            }
            else
            {
                string pathBZ2 = simplify(_dataDir + '/' + p->path + ".bz2");
            
                string dir = getDirname(pathBZ2);
                if(!dir.empty())
                {
                    createDirectoryRecursive(dir);
                }
                
                try
                {
                    removeRecursive(pathBZ2);
                }
                catch(...)
                {
                }
                
                FILE* fileBZ2 = IceUtilInternal::fopen(pathBZ2, "wb");
                if(fileBZ2 == 0)
                {
                    throw "cannot open `" + pathBZ2 + "' for writing:\n" + IceUtilInternal::lastErrorToString();
                }

                try
                {
                    Int pos = 0;

                    while(pos < p->size)
                    {
                        if(!curCB)
                        {
                            assert(!nxtCB);
                            curCB = _serverNoCompress->begin_getFileCompressed(p->path, pos, _chunkSize);
                        }
                        else
                        {
                            assert(nxtCB);
                            swap(nxtCB, curCB);
                        }

                        if(pos + _chunkSize < p->size)
                        {
                            nxtCB = _serverNoCompress->begin_getFileCompressed(p->path, pos + _chunkSize, _chunkSize);
                        }
                        else
                        {
                            FileInfoSeq::const_iterator q = p + 1;

                            while(q != files.end() && q->size <= 0)
                            {
                                ++q;
                            }

                            if(q != files.end())
                            {
                                nxtCB = _serverNoCompress->begin_getFileCompressed(q->path, 0, _chunkSize);
                            }
                        }

                        ByteSeq bytes;

                        try
                        {
                            bytes = _serverNoCompress->end_getFileCompressed(curCB);
                        }
                        catch(const FileAccessException& ex)
                        {
                            throw "error from IcePatch2 server for `" + p->path + "': " + ex.reason;
                        }

                        if(bytes.empty())
                        {
                            throw "size mismatch for `" + p->path + "'";
                        }

                        if(fwrite(reinterpret_cast<char*>(&bytes[0]), bytes.size(), 1, fileBZ2) != 1)
                        {
                            throw ": cannot write `" + pathBZ2 + "':\n" + IceUtilInternal::lastErrorToString();
                        }

                        pos += static_cast<int>(bytes.size());
                        updated += bytes.size();

                        if(!_feedback->patchProgress(pos, p->size, updated, total))
                        {
                            fclose(fileBZ2);
                            return false;
                        }
                    }
                }
                catch(...)
                {
                    fclose(fileBZ2);
                    throw;
                }
                
                fclose(fileBZ2);
                
                decompressor->log(_log);
                decompressor->add(*p);
            }
            
            if(!_feedback->patchEnd())
            {
                return false;
            }
        }
    }

    FileInfoSeq newLocalFiles;
    newLocalFiles.reserve(_localFiles.size());
        
    set_union(_localFiles.begin(),
              _localFiles.end(),
              files.begin(),
              files.end(),
              back_inserter(newLocalFiles),
              FileInfoLess());
        
    _localFiles.swap(newLocalFiles);

    FileInfoSeq newUpdateFiles;

    set_difference(_updateFiles.begin(),
                   _updateFiles.end(),
                   files.begin(),
                   files.end(),
                   back_inserter(newUpdateFiles),
                   FileInfoLess());
        
    _updateFiles.swap(newUpdateFiles);

    return true;
}
Esempio n. 4
0
bool
IcePatch2::Patcher::prepare()
{
    _localFiles.clear();

    bool thorough = _thorough;

    if(!thorough)
    {
        try
        {
            loadFileInfoSeq(_dataDir, _localFiles);
        }
        catch(const string& ex)
        {
            thorough = _feedback->noFileSummary(ex);
            if(!thorough)
            {
                return false;
            }
        }
    }
    
    if(thorough)
    {
        if(!_feedback->checksumStart())
        {
            return false;
        }

        PatcherGetFileInfoSeqCB cb(_feedback);
        if(!getFileInfoSeq(_dataDir, 0, &cb, _localFiles))
        {
            return false;
        }

        if(!_feedback->checksumEnd())
        {
            return false;          
        }

        saveFileInfoSeq(_dataDir, _localFiles);
    }

    FileTree0 tree0;
    getFileTree0(_localFiles, tree0);

    if(tree0.checksum != _serverCompress->getChecksum())
    {
        if(!_feedback->fileListStart())
        {
            return false;
        }
        
        ByteSeqSeq checksumSeq = _serverCompress->getChecksumSeq();
        if(checksumSeq.size() != 256)
        {
            throw string("server returned illegal value");
        }
        
        AsyncResultPtr curCB;
        AsyncResultPtr nxtCB;

        for(int node0 = 0; node0 < 256; ++node0)
        {
            if(tree0.nodes[node0].checksum != checksumSeq[node0])
            {
                if(!curCB)
                {
                    assert(!nxtCB);
                    curCB = _serverCompress->begin_getFileInfoSeq(node0);
                }
                else
                {
                    assert(nxtCB);
                    swap(nxtCB, curCB);
                }
                
                int node0Nxt = node0;
                
                do
                {
                    ++node0Nxt;
                }
                while(node0Nxt < 256 && tree0.nodes[node0Nxt].checksum == checksumSeq[node0Nxt]);

                if(node0Nxt < 256)
                {
                    nxtCB = _serverCompress->begin_getFileInfoSeq(node0Nxt);
                }

                FileInfoSeq files = _serverCompress->end_getFileInfoSeq(curCB);
                
                sort(files.begin(), files.end(), FileInfoLess());
                files.erase(unique(files.begin(), files.end(), FileInfoEqual()), files.end());

                //
                // Compute the set of files which were removed.
                //
                set_difference(tree0.nodes[node0].files.begin(),
                               tree0.nodes[node0].files.end(),
                               files.begin(),
                               files.end(),
                               back_inserter(_removeFiles),
                               FileInfoWithoutFlagsLess()); // NOTE: We ignore the flags here.

                //
                // Compute the set of files which were updated (either the file contents, flags or both).
                //
                FileInfoSeq updatedFiles;
                updatedFiles.reserve(files.size());
                                    
                set_difference(files.begin(),
                               files.end(),
                               tree0.nodes[node0].files.begin(),
                               tree0.nodes[node0].files.end(),
                               back_inserter(updatedFiles),
                               FileInfoLess());

                //
                // Compute the set of files whose contents was updated.
                //
                FileInfoSeq contentsUpdatedFiles;
                contentsUpdatedFiles.reserve(files.size());

                set_difference(files.begin(),
                               files.end(),
                               tree0.nodes[node0].files.begin(),
                               tree0.nodes[node0].files.end(),
                               back_inserter(contentsUpdatedFiles),
                               FileInfoWithoutFlagsLess()); // NOTE: We ignore the flags here.
                copy(contentsUpdatedFiles.begin(), contentsUpdatedFiles.end(), back_inserter(_updateFiles));

                //
                // Compute the set of files whose flags were updated.
                //
                set_difference(updatedFiles.begin(),
                               updatedFiles.end(),
                               contentsUpdatedFiles.begin(),
                               contentsUpdatedFiles.end(),
                               back_inserter(_updateFlags),
                               FileInfoLess());
            }

            if(!_feedback->fileListProgress((node0 + 1) * 100 / 256))
            {
                return false;
            }
        }

        if(!_feedback->fileListEnd())
        {
            return false;
        }
    }    

    sort(_removeFiles.begin(), _removeFiles.end(), FileInfoLess());
    sort(_updateFiles.begin(), _updateFiles.end(), FileInfoLess());
    sort(_updateFlags.begin(), _updateFlags.end(), FileInfoLess());
                
    string pathLog = simplify(_dataDir + '/' + logFile);
    _log = IceUtilInternal::fopen(pathLog, "w");
    if(!_log)
    {
        throw "cannot open `" + pathLog + "' for writing:\n" + IceUtilInternal::lastErrorToString();
    }

    return true;
}