/* This file is part of the KDE project Copyright (C) 2000 Alexander Neundorf This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kio_floppy.h" #include "config-unix.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KIO; extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); } int kdemain( int argc, char **argv ) { KComponentData componentData( "kio_floppy" ); if (argc != 4) { fprintf(stderr, "Usage: kio_floppy protocol domain-socket1 domain-socket2\n"); exit(-1); } kDebug(7104) << "Floppy: kdemain: starting"; FloppyProtocol slave(argv[2], argv[3]); slave.dispatchLoop(); return 0; } void getDriveAndPath(const QString& path, QString& drive, QString& rest) { drive.clear(); rest.clear(); const QStringList list=path.split('/'); for (QStringList::const_iterator it=list.constBegin(); it!=list.constEnd(); ++it) { if (it==list.begin()) drive=(*it)+':'; else rest=rest+'/'+(*it); } } FloppyProtocol::FloppyProtocol (const QByteArray &pool, const QByteArray &app ) :SlaveBase( "floppy", pool, app ) ,m_mtool(0) ,m_stdoutBuffer(0) ,m_stderrBuffer(0) ,m_stdoutSize(0) ,m_stderrSize(0) { kDebug(7104)<<"Floppy::Floppy: -"<stdoutFD(),buffer,16*1024); if (length<=0) return 0; //+1 gives us room for a terminating 0 char *newBuffer=new char[length+m_stdoutSize+1]; kDebug(7104)<<"Floppy::readStdout(): length: "<stderrFD(),buffer,16*1024); kDebug(7104)<<"Floppy::readStderr(): read "< -1) { error( KIO::ERR_SLAVE_DEFINED, i18n("Could not access drive %1.\nThe drive is still busy.\nWait until it is inactive and then try again.", drive)); } else if ((line.indexOf("Disk full") > -1) || (line.indexOf("No free cluster") > -1)) { error( KIO::ERR_SLAVE_DEFINED, i18n("Could not write to file %1.\nThe disk in drive %2 is probably full.", url.prettyUrl(), drive)); } //file not found else if (line.indexOf("not found") > -1) { error( KIO::ERR_DOES_NOT_EXIST, url.prettyUrl()); } //no disk else if (line.indexOf("not configured") > -1) { error( KIO::ERR_SLAVE_DEFINED, i18n("Could not access %1.\nThere is probably no disk in the drive %2", url.prettyUrl(), drive)); } else if (line.indexOf("No such device") > -1) { error( KIO::ERR_SLAVE_DEFINED, i18n("Could not access %1.\nThere is probably no disk in the drive %2 or you do not have enough permissions to access the drive.", url.prettyUrl(), drive)); } else if (line.indexOf("not supported") > -1) { error( KIO::ERR_SLAVE_DEFINED, i18n("Could not access %1.\nThe drive %2 is not supported.", url.prettyUrl(), drive)); } //not supported or no such drive else if (line.indexOf("Permission denied") > -1) { error( KIO::ERR_SLAVE_DEFINED, i18n("Could not access %1.\nMake sure the floppy in drive %2 is a DOS-formatted floppy disk \nand that the permissions of the device file (e.g. /dev/fd0) are set correctly (e.g. rwxrwxrwx).", url.prettyUrl(), drive)); } else if (line.indexOf("non DOS media") > -1) { error( KIO::ERR_SLAVE_DEFINED, i18n("Could not access %1.\nThe disk in drive %2 is probably not a DOS-formatted floppy disk.", url.prettyUrl(), drive)); } else if (line.indexOf("Read-only") > -1) { error( KIO::ERR_SLAVE_DEFINED, i18n("Access denied.\nCould not write to %1.\nThe disk in drive %2 is probably write-protected.", url.prettyUrl(), drive)); } else if ((outputString.indexOf("already exists") > -1) || (outputString.indexOf("Skipping ") > -1)) { error( KIO::ERR_FILE_ALREADY_EXIST,url.prettyUrl()); //return false; } else if (outputString.indexOf("could not read boot sector") > -1) { error( KIO::ERR_SLAVE_DEFINED, i18n("Could not read boot sector for %1.\nThere is probably not any disk in drive %2.", url.prettyUrl(), drive)); //return false; } else { error( KIO::ERR_UNKNOWN, outputString); } return true; } void FloppyProtocol::listDir( const KUrl& _url) { kDebug(7104)<<"Floppy::listDir() "<<_url.path(); KUrl url(_url); QString path(url.path()); if ((path.isEmpty()) || (path=="/")) { url.setPath("/a/"); redirection(url); finished(); return; } QString drive; QString floppyPath; getDriveAndPath(path,drive,floppyPath); QStringList args; args<<"mdir"<<"-a"<<(drive+floppyPath); delete m_mtool; m_mtool=new Program(args); clearBuffers(); if (!m_mtool->start()) { delete m_mtool; m_mtool=0; errorMissingMToolsProgram("mdir"); return; } int result; bool loopFinished(false); bool errorOccured(false); do { bool stdoutEvent; bool stderrEvent; result=m_mtool->select(1,0,stdoutEvent, stderrEvent); if (stdoutEvent) if (readStdout()==0) loopFinished=true; if (stderrEvent) { if (readStderr()==0) loopFinished=true; else if (stopAfterError(url,drive)) { loopFinished=true; errorOccured=true; } } } while (!loopFinished); delete m_mtool; m_mtool=0; //now mdir has finished //let's parse the output terminateBuffers(); if (errorOccured) return; QString outputString(m_stdoutBuffer); QTextStream output(&outputString, QIODevice::ReadOnly); QString line; int totalNumber(0); int mode(0); UDSEntry entry; while (!output.atEnd()) { line=output.readLine(); kDebug(7104)<<"Floppy::listDir(): line: -"<") { //kDebug(7104)<<"Floppy::createUDSEntry() isDir"; size="1024"; isDir=true; } else { p = line.indexOf(' ',p-1); size=line.mid(13,p-13); //kDebug(7104)<<"Floppy::createUDSEntry() size: -"<0) { name=line.mid(0,nameLength); QString ext=line.mid(9,3); ext=ext.trimmed(); if (!ext.isEmpty()) name+='.'+ext; } kDebug(7104)<<"Floppy::createStatInfo() name 8.3= -"<p+19) { name=line.mid(p+20); kDebug(7104)<<"Floppy::createStatInfo() name vfat: -"<start()) { delete m_mtool; m_mtool=0; errorMissingMToolsProgram("mdir"); return info; } clearBuffers(); int result; bool loopFinished(false); bool errorOccured(false); do { bool stdoutEvent; bool stderrEvent; result=m_mtool->select(1,0,stdoutEvent, stderrEvent); if (stdoutEvent) if (readStdout()==0) loopFinished=true; if (stderrEvent) { if (readStderr()==0) loopFinished=true; else if (stopAfterError(url,drive)) { loopFinished=true; errorOccured=true; } } } while (!loopFinished); //kDebug(7104)<<"Floppy::_stat(): delete m_mtool"; delete m_mtool; m_mtool=0; //now mdir has finished //let's parse the output terminateBuffers(); if (errorOccured) { info.isValid=false; return info; } if (m_stdoutSize==0) { info.isValid=false; error( KIO::ERR_COULD_NOT_STAT, url.prettyUrl()); return info; } kDebug(7104)<<"Floppy::_stat(): parse stuff"; QString outputString(m_stdoutBuffer); QTextStream output(&outputString, QIODevice::ReadOnly); QString line; for (int lineNumber=0; !output.atEnd(); lineNumber++) { line=output.readLine(); if ( (lineNumber<3) || (line.isEmpty()) ) continue; StatInfo info=createStatInfo(line,true,url.fileName()); if (info.isValid==false) error( KIO::ERR_COULD_NOT_STAT, url.prettyUrl()); return info; } if (info.isValid==false) error( KIO::ERR_COULD_NOT_STAT, url.prettyUrl()); return info; } int FloppyProtocol::freeSpace(const KUrl& url) { QString path(url.path()); QString drive; QString floppyPath; getDriveAndPath(path,drive,floppyPath); //kDebug(7104)<<"Floppy::freeSpace(): delete m_mtool"; delete m_mtool; QStringList args; args<<"mdir"<<"-a"<start()) { delete m_mtool; m_mtool=0; errorMissingMToolsProgram("mdir"); return -1; } clearBuffers(); int result; bool loopFinished(false); bool errorOccured(false); do { bool stdoutEvent; bool stderrEvent; result=m_mtool->select(1,0,stdoutEvent, stderrEvent); if (stdoutEvent) if (readStdout()==0) loopFinished=true; if (stderrEvent) { if (readStderr()==0) loopFinished=true; else if (stopAfterError(url,drive)) { loopFinished=true; errorOccured=true; } } } while (!loopFinished); //kDebug(7104)<<"Floppy::freeSpace(): delete m_mtool"; delete m_mtool; m_mtool=0; //now mdir has finished //let's parse the output terminateBuffers(); if (errorOccured) { return -1; } if (m_stdoutSize==0) { error( KIO::ERR_COULD_NOT_STAT, url.prettyUrl()); return -1; } kDebug(7104)<<"Floppy::freeSpace(): parse stuff"; QString outputString(m_stdoutBuffer); QTextStream output(&outputString, QIODevice::ReadOnly); QString line; int lineNumber(0); while (!output.atEnd()) { line=output.readLine(); if (line.indexOf("bytes free")==36) { QString tmp=line.mid(24,3); tmp=tmp.trimmed(); tmp+=line.mid(28,3); tmp=tmp.trimmed(); tmp+=line.mid(32,3); tmp=tmp.trimmed(); return tmp.toInt(); } lineNumber++; } return -1; } void FloppyProtocol::stat( const KUrl & _url) { kDebug(7104)<<"Floppy::stat() "<<_url.path(); KUrl url(_url); QString path(url.path()); if ((path.isEmpty()) || (path=="/")) { url.setPath("/a/"); redirection(url); finished(); return; } StatInfo info=this->_stat(url); if (info.isValid) { UDSEntry entry; createUDSEntry(info,entry); statEntry( entry ); finished(); //kDebug(7104)<<"Floppy::stat(): ends"; return; } //otherwise the error() was already reported in _stat() } void FloppyProtocol::mkdir( const KUrl& url, int) { kDebug(7104)<<"FloppyProtocol::mkdir()"; QString path(url.path()); if ((path.isEmpty()) || (path=="/")) { KUrl newUrl(url); newUrl.setPath("/a/"); redirection(newUrl); finished(); return; } QString drive; QString floppyPath; getDriveAndPath(path,drive,floppyPath); if (floppyPath.isEmpty()) { finished(); return; } delete m_mtool; //kDebug(7104)<<"Floppy::stat(): create args"; QStringList args; args<<"mmd"<<(drive+floppyPath); kDebug(7104)<<"Floppy::mkdir(): executing: mmd -"<<(drive+floppyPath)<<"-"; m_mtool=new Program(args); if (!m_mtool->start()) { delete m_mtool; m_mtool=0; errorMissingMToolsProgram("mmd"); return; } clearBuffers(); int result; bool loopFinished(false); bool errorOccured(false); do { bool stdoutEvent; bool stderrEvent; result=m_mtool->select(1,0,stdoutEvent, stderrEvent); if (stdoutEvent) if (readStdout()==0) loopFinished=true; if (stderrEvent) { if (readStderr()==0) loopFinished=true; else if (stopAfterError(url,drive)) { loopFinished=true; errorOccured=true; } } } while (!loopFinished); delete m_mtool; m_mtool=0; terminateBuffers(); if (errorOccured) return; finished(); } void FloppyProtocol::del( const KUrl& url, bool isfile) { kDebug(7104)<<"FloppyProtocol::del()"; const QString path(url.path()); if ((path.isEmpty()) || (path=="/")) { KUrl newUrl(url); newUrl.setPath("/a/"); redirection(newUrl); finished(); return; } QString drive; QString floppyPath; getDriveAndPath(path,drive,floppyPath); if (floppyPath.isEmpty()) { finished(); return; } delete m_mtool; //kDebug(7104)<<"Floppy::stat(): create args"; QStringList args; bool usingmdel; if (isfile) { args<<"mdel"<<(drive+floppyPath); usingmdel=true; } else { args<<"mrd"<<(drive+floppyPath); usingmdel=false; } kDebug(7104)<<"Floppy::del(): executing: " << (usingmdel ? QString("mdel") : QString("mrd") ) << "-"<<(drive+floppyPath)<<"-"; m_mtool=new Program(args); if (!m_mtool->start()) { delete m_mtool; m_mtool=0; errorMissingMToolsProgram(usingmdel ? QString("mdel") : QString("mrd")); return; } clearBuffers(); int result; bool loopFinished(false); bool errorOccured(false); do { bool stdoutEvent; bool stderrEvent; result=m_mtool->select(1,0,stdoutEvent, stderrEvent); if (stdoutEvent) if (readStdout()==0) loopFinished=true; if (stderrEvent) { if (readStderr()==0) loopFinished=true; else if (stopAfterError(url,drive)) { loopFinished=true; errorOccured=true; } } } while (!loopFinished); delete m_mtool; m_mtool=0; terminateBuffers(); if (errorOccured) return; finished(); } void FloppyProtocol::rename( const KUrl &src, const KUrl &dest, KIO::JobFlags flags ) { QString srcPath(src.path()); QString destPath(dest.path()); kDebug(7104)<<"Floppy::rename() -"<start()) { delete m_mtool; m_mtool=0; errorMissingMToolsProgram("mren"); return; } clearBuffers(); int result; bool loopFinished(false); bool errorOccured(false); do { bool stdoutEvent; bool stderrEvent; result=m_mtool->select(1,0,stdoutEvent, stderrEvent); if (stdoutEvent) if (readStdout()==0) loopFinished=true; if (stderrEvent) { if (readStderr()==0) loopFinished=true; else if (stopAfterError(src,srcDrive)) { loopFinished=true; errorOccured=true; } } } while (!loopFinished); delete m_mtool; m_mtool=0; terminateBuffers(); if (errorOccured) return; finished(); } void FloppyProtocol::get( const KUrl& url ) { QString path(url.path()); kDebug(7104)<<"Floppy::get() -"<_stat(url); //the error was already reported in _stat() if (info.isValid==false) return; totalSize( info.size); QString drive; QString floppyPath; getDriveAndPath(path,drive,floppyPath); if (floppyPath.isEmpty()) { finished(); return; } delete m_mtool; //kDebug(7104)<<"Floppy::stat(): create args"; QStringList args; args<<"mcopy"<<(drive+floppyPath)<<"-"; kDebug(7104)<<"Floppy::get(): executing: mcopy -"<<(drive+floppyPath)<<"-"; m_mtool=new Program(args); if (!m_mtool->start()) { delete m_mtool; m_mtool=0; errorMissingMToolsProgram("mcopy"); return; } clearBuffers(); int result; bool loopFinished(false); bool errorOccured(false); do { bool stdoutEvent; bool stderrEvent; result=m_mtool->select(1,0,stdoutEvent, stderrEvent); if (stdoutEvent) { delete [] m_stdoutBuffer; m_stdoutBuffer=0; m_stdoutSize=0; if (readStdout()>0) { kDebug(7104)<<"Floppy::get(): m_stdoutSize:"<start()) { delete m_mtool; m_mtool=0; errorMissingMToolsProgram("mcopy"); return; } clearBuffers(); int result(0); int bytesRead(0); //from file.cc // Loop until we got 0 (end of data) do { bool stdoutEvent; bool stderrEvent; kDebug(7104)<<"Floppy::put(): select()..."; m_mtool->select(0,100,stdoutEvent, stderrEvent); if (stdoutEvent) { if (readStdout()==0) result=0; } if (stderrEvent) { if (readStderr()==0) result=0; else if (stopAfterError(url,drive)) result=-1; kDebug(7104)<<"Floppy::put(): error: result=="< 0) { bytesRead+=result; kDebug(7104)<<"Floppy::put() bytesRead: "<freeSpaceLeft) { result=0; error( KIO::ERR_SLAVE_DEFINED, i18n("Could not write to file %1.\nThe disk in drive %2 is probably full.", url.prettyUrl(), drive)); } else { //kDebug(7104)<<"Floppy::put(): writing..."; result=::write(m_mtool->stdinFD(),buffer.data(), buffer.size()); kDebug(7104)<<"Floppy::put(): after write(), wrote "< 0 ); if (result<0) { perror("writing to stdin"); error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, url.prettyUrl()); return; } delete m_mtool; m_mtool=0; finished(); }