Example #1
0
	void UUIDLinker::diskAppeared(DADiskRef disk, DiskInformation const & di)
	{
		auto mediaUUIDs = getUUIDs(di);
		for (auto mediaID: mediaUUIDs)
		{
			try
			{
				mediaID = m_base + "/" + mediaID;
				std::string devicePath = "/dev/" + di.mediaBSDName;
				logger().log(ASL_LEVEL_NOTICE, "Creating symlink: ", mediaID, " -> ", devicePath);
				createSymlink(mediaID, devicePath);
			}
			catch (std::exception const & e)
			{
				logger().log(ASL_LEVEL_ERR, "Could not create symlink: ", e.what());
			}
		}
	}
//
// private methods
//
void ExportSymlinks::doExport()
{
    KFileItem * currentFile;
    for ( currentFile = m_sourceFiles->first(); currentFile; currentFile = m_sourceFiles->next() ) {
    
        QString symlink = QString("%1/%2").arg(*m_destinationDir).arg(currentFile->name());
        m_progressDialog->setLabel(symlink);
        kapp->processEvents();
    
        createSymlink(currentFile->url().path(), symlink);
    
        // in any case increase progress
        m_progressDialog->progressBar()->advance(1);
    
        // exit loop if cancel was called
        if (m_cancelling) {
        break;
        }
    }
    
    m_progressDialog->hide();
}
void ExportSymlinks::createSymlink(QString sourceFile, QString symlink)
{
    tracer->sinvoked(__func__) << "Creating symlink: " << symlink << "-->" << sourceFile << endl;
    
    // create the symbolic link
    int result = ::symlink(sourceFile.ascii(), symlink.ascii());
    
    // handle possible problems
    if (result != 0) {
        int errorNo = errno;
    
        tracer->serror(__func__) << "Could not create symlink: '" << strerror(errorNo) << "' (" << symlink << "-->" << sourceFile << ")" << endl;
    
        // an error occured
        switch ( errorNo ) {
            case EPERM: {
                tracer->serror(__func__) << "The filesystem containing newpath does not support the creation of symbolic links: " << *m_destinationDir << endl;
        
                QString msg = QString(i18n("The filesystem containing the destination directory does not support symbolic links:\n%1")).arg(*m_destinationDir);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            case EFAULT: {
                tracer->serror(__func__) << "Oldpath or newpath points outside your accessible address space: " << symlink << "-->" << sourceFile << endl;
        
                QString msg = QString(i18n("Sourcefile or destinationfile points outside your accessible address space:\nSource: %1\nDestination: %2")).arg(sourceFile).arg(symlink);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            case EACCES: {
                tracer->serror(__func__) << "Write access to the directory containing newpath is not allowed for the process's effective uid, or one of the directories in newpath did not allow search (execute) permission: " << *m_destinationDir << endl;
        
                QString msg = QString(i18n("Can not write to the specified destination directory:\n%1\nPlease check that you have write permission.")).arg(*m_destinationDir);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            case ENAMETOOLONG: {
                tracer->serror(__func__) << "Oldpath or newpath was too long: " << symlink << "-->" << sourceFile << endl;
        
                QString msg = QString(i18n("The Sourcefilename or destinationfilename is too long:\nSource: %1\nDestination: %2")).arg(sourceFile).arg(symlink);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            case ENOENT: {
                tracer->serror(__func__) << "A directory component in newpath does not exist or is a dangling symbolic link: " << *m_destinationDir << endl;
        
                QString msg = QString(i18n("The destination directory is invalid:\n%1")).arg(*m_destinationDir);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            case ENOTDIR: {
                tracer->serror(__func__) << "A component used as a directory in newpath is not, in fact, a directory: " << *m_destinationDir << endl;
        
                QString msg = QString(i18n("The destination directory is invalid:\n%1")).arg(*m_destinationDir);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            case ENOMEM: {
                tracer->serror(__func__) << "Insufficient kernel memory was available." << endl;
        
                QString msg = QString(i18n("Insufficient kernel memory was available."));
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            case EROFS: {
                tracer->serror(__func__) << "Newpath is on a read-only filesystem: " << *m_destinationDir << endl;
        
                QString msg = QString(i18n("The destination directory is on a read only filesystem:\n%1")).arg(*m_destinationDir);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            case EEXIST: {
                tracer->sinfo(__func__) << "Newpath already exists: " << symlink << endl;
        
                if (m_autoSkip) {
                    tracer->sinfo(__func__) << "Autoskip is enabled. proceeding with next file." << endl;
                } else if (m_overwriteAll) {
                    tracer->sinfo(__func__) << "Overwrite all is enabled. deleting existing file." << endl;
        
                    if(::remove(symlink.ascii()) == 0) {
                        // already existing file successfully removed
                        createSymlink(sourceFile, symlink);
                    } else {
                        // could not delete existing file
                        tracer->serror(__func__) << "Could not delete file: '" << strerror(errno) << "' (" << symlink << ")" << endl;
            
                        QString msgOverwriteAllDisabled = QString(i18n("\nFunction 'Overwrite all' disabled automatically!"));
                        QString msg = QString(i18n("Could not overwrite the destination file:\n%1%2")).arg(symlink).arg(msgOverwriteAllDisabled);
                        KMessageBox::sorry(m_parent, msg, i18n("Could not overwrite"));
            
                        // reset overwrite all
                        m_overwriteAll = false;
            
                        createSymlink(sourceFile, symlink);
                    }
                } else {
        
                    KIO::RenameDlg* renameDlg = new KIO::RenameDlg(
                        m_parent,                       // parent
                        i18n("File already exists"),    // caption
                        sourceFile,                     // source
                        symlink,                        // destination
                        (KIO::RenameDlg_Mode)(KIO::M_OVERWRITE | KIO::M_SKIP | KIO::M_MULTI)  // mode
                    );
                    renameDlg->setModal(true);
                    int result = renameDlg->exec();
                    renameDlg->hide();
            
                    // analyze the chosen action
                    switch (result) {
                        case KIO::R_CANCEL: {
                            m_cancelling = true;
                            break;
                        }
                        case KIO::R_RENAME: {
                            createSymlink(sourceFile, renameDlg->newDestURL().path().ascii());
                            break;
                        }
                        case KIO::R_AUTO_SKIP: {
                            m_autoSkip = true;
                            m_overwriteAll = false;
                        }
                        case KIO::R_SKIP: {
                            // nothing to do... just skip
                            break;
                        }
                        case KIO::R_OVERWRITE_ALL: {
                            m_overwriteAll = true;
                            m_autoSkip = false;
                        }
                        case KIO::R_OVERWRITE: {
                            if(::remove(symlink.ascii()) == 0) {
                                // already existing file successfully removed
                                createSymlink(sourceFile, symlink);
                            } else {
                                // could not delete existing file
                                tracer->serror(__func__) << "Could not delete file: '" << strerror(errno) << "' (" << symlink << ")" << endl;
                
                                QString msgOverwriteAllDisabled = QString::null;
                                if (m_overwriteAll) {
                                msgOverwriteAllDisabled = QString(i18n("\nFunction 'Overwrite all' disabled automatically!"));
                                }
                
                                QString msg = QString(i18n("Could not overwrite the destination file:\n%1%2")).arg(symlink).arg(msgOverwriteAllDisabled);
                                KMessageBox::sorry(m_parent, msg, i18n("Could not overwrite"));
                
                                // reset overwrite all
                                m_overwriteAll = false;
                
                                createSymlink(sourceFile, symlink);
                            }
                            break;
                        }
                    }
            
                    delete renameDlg;
                }
                break;
            }
            case ELOOP: {
                tracer->serror(__func__) << "To many symbolic links were encountered in resolving newpath: " << *m_destinationDir << endl;
        
                QString msg = QString(i18n("The destination path contains too many symbolic links:\n%1")).arg(*m_destinationDir);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            case ENOSPC: {
                tracer->serror(__func__) << "The device containing the file has no room for the new directory entry: " << *m_destinationDir << endl;
        
                QString msg = QString(i18n("The device for the destination directory is full:\n%1")).arg(*m_destinationDir);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            case EIO: {
                tracer->serror(__func__) << "An I/O error occurred: " << symlink << "-->" << sourceFile << endl;
        
                QString msg = QString(i18n("An I/O error occured:\nSource: %1\nDestination: %2")).arg(sourceFile).arg(symlink);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
            default: {
                tracer->serror(__func__) << "An unexpected error number catched (" << errorNo << "): " << symlink << "-->" << sourceFile << endl;
        
                QString msg = QString(i18n("An unexpected error occured while creating symbolic link:\nSource: %1\nDestination: %2")).arg(sourceFile).arg(symlink);
                KMessageBox::sorry(m_parent, msg, i18n("Could not export"));
                m_cancelling = true;
                break;
            }
        }
    }
}