Exemplo n.º 1
0
computed_base &
computed_base::operator=( const computed_base &o )
{
	if ( &o != this )
		internal_copy( o );
	return *this;
}
void RecursiveDirJobHelper::recursiveCpDir(const QString & sourcePath, const QString & destPath,
                                            RecursiveDirJob::CopyOptions options)
{
    QDir source(sourcePath);
    if ( !source.exists() ) {
        emit errorOccured(Error(Error::NoSuchFileOrDirectory, sourcePath));
        return;
    }

    QDir dest(destPath);
    if ( dest.exists() ) {
        if ( options & RecursiveDirJob::RemoveDestination ) {
            //in case the destination is a symlink to another directory, we remove first
            //the symlink target (returned by dest.canonicalPath()) and then the symlink itself.
            recursiveRmDir(dest.canonicalPath());
            if ( QFileInfo(destPath).isSymLink() ) {
                QFile::remove(destPath);
            }
        } else if ( !(options & RecursiveDirJob::OverWrite) ) {
            emit errorOccured(Error(Error::FileOrDirectoryExists, destPath));
            return;
        }
    }

    if ( dest.mkdir(dest.absolutePath()) ) {
        QFile::setPermissions(destPath, QFile::permissions(sourcePath));
    }

    QFileInfoList currentList = source.entryInfoList(dirFilters);
    QFileInfo currentItem;
    QStack<QFileInfoList> stack;
    QString currentName;
    quint64 bytesCopied = 0;

    if ( m_reportProgress ) {
        quint64 dirSize = calculateDirSize(sourcePath);
        emit setLabelText(tr("Copying files from \"%1\" to \"%2\"...").arg(sourcePath).arg(destPath));
        if (dirSize > 0) {
            emit setMaximum(dirSize);
            //the directory special file is already (almost) copied in dest.mkdir() above
            bytesCopied += stat_size(sourcePath);
            emit setValue(bytesCopied);
        } else {
            //no files to be copied, so set the progressbar to 100%
            emit setMaximum(1);
            emit setValue(1);
        }
    }

    while(1)
    {
        if ( !currentList.isEmpty() )
        {
            currentItem = currentList.takeFirst();
            currentName = currentItem.fileName();

            if ( currentItem.isSymLink() )
            {
                if ( options & RecursiveDirJob::OverWrite ) {
                    if ( !QFile::remove(dest.absoluteFilePath(currentName)) )
                        emit errorOccured(Error(Error::RmFail, dest.absoluteFilePath(currentName)));
                }
                if ( !QFile::link( DirOperations::relativeSymLinkTarget(source.absoluteFilePath(currentName)),
                                    dest.absoluteFilePath(currentName) ) )
                    emit errorOccured(Error(Error::CopyFail, source.absoluteFilePath(currentName)));
            }
            else if ( currentItem.isDir() )
            {
                bool ok = false;
                QFile::Permissions sourcePermissions = QFile::permissions(source.absoluteFilePath(currentName));

                if ( !(ok = source.cd(currentName)) ) {
                    emit errorOccured(Error(Error::AccessDenied, source.absoluteFilePath(currentName)));
                }
                if ( ok && !dest.cd(currentName) ) {
                    //if the target dir doesn't exist, create it and try again.
                    if ( !dest.mkdir(currentName) ) {
                        emit errorOccured(Error(Error::MkdirFail, dest.absoluteFilePath(currentName)));
                    }

                    //preserve permissions of the directory
                    QFile::setPermissions(dest.absoluteFilePath(currentName), sourcePermissions);

                    if ( !dest.cd(currentName) ) {
                         //quite impossible to happen
                        emit errorOccured(Error(Error::AccessDenied, dest.absoluteFilePath(currentName)));
                        ok = false;
                        source.cdUp(); //revert the state of source, as we are not going to copy this dir.
                    }
                }

                if (ok) {
                    stack.push(currentList);
                    currentList = source.entryInfoList(dirFilters);
                }
            }
            else if ( currentItem.isFile() )
            {
                if ( options & RecursiveDirJob::OverWrite ) {
                    if ( !QFile::remove(dest.absoluteFilePath(currentName)) )
                        emit errorOccured(Error(Error::RmFail, dest.absoluteFilePath(currentName)));
                }
                if ( !internal_copy( source.absoluteFilePath(currentName), dest.absoluteFilePath(currentName),
                                        options & RecursiveDirJob::ReplaceKde4InFiles ) )
                    emit errorOccured(Error(Error::CopyFail, source.absoluteFilePath(currentName)));
            }
            else
            {
                if ( currentItem.exists() ) {
                    qDebug() << "Ignoring special file" << source.absoluteFilePath(currentName);
                } else {
                    //this can happen with filename encoding bugs
                    emit errorOccured(Error(Error::NoSuchFileOrDirectory, source.absoluteFilePath(currentName)));
                }
            }

            if ( m_reportProgress ) {
                bytesCopied += stat_size(currentItem.absoluteFilePath());
                emit setValue(bytesCopied);
            }
        }
        else // list is empty
        {
            if ( !stack.isEmpty() )
            {
                currentList = stack.pop();
                source.cdUp();
                dest.cdUp();
            }
            else
                break;
        }
    }
}