diff options
Diffstat (limited to 'tdeioslave/floppy')
-rw-r--r-- | tdeioslave/floppy/AUTHORS | 2 | ||||
-rw-r--r-- | tdeioslave/floppy/CMakeLists.txt | 41 | ||||
-rw-r--r-- | tdeioslave/floppy/Makefile.am | 20 | ||||
-rw-r--r-- | tdeioslave/floppy/README | 7 | ||||
-rw-r--r-- | tdeioslave/floppy/TODO | 3 | ||||
-rw-r--r-- | tdeioslave/floppy/floppy.protocol | 14 | ||||
-rw-r--r-- | tdeioslave/floppy/kio_floppy.cpp | 1169 | ||||
-rw-r--r-- | tdeioslave/floppy/kio_floppy.h | 78 | ||||
-rw-r--r-- | tdeioslave/floppy/program.cpp | 201 | ||||
-rw-r--r-- | tdeioslave/floppy/program.h | 53 |
10 files changed, 1588 insertions, 0 deletions
diff --git a/tdeioslave/floppy/AUTHORS b/tdeioslave/floppy/AUTHORS new file mode 100644 index 000000000..062f9d6cb --- /dev/null +++ b/tdeioslave/floppy/AUTHORS @@ -0,0 +1,2 @@ +Written and maintained by: +Alexander Neundorf, neundorf@kde.org diff --git a/tdeioslave/floppy/CMakeLists.txt b/tdeioslave/floppy/CMakeLists.txt new file mode 100644 index 000000000..b328998ab --- /dev/null +++ b/tdeioslave/floppy/CMakeLists.txt @@ -0,0 +1,41 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES floppy.protocol DESTINATION ${SERVICES_INSTALL_DIR} ) + + +##### kio_floppy (module) ####################### + +set( target kio_floppy ) + +set( ${target}_SRCS + kio_floppy.cpp program.cpp +) + +tde_add_kpart( ${target} AUTOMOC + SOURCES ${${target}_SRCS} + LINK tdeio-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/tdeioslave/floppy/Makefile.am b/tdeioslave/floppy/Makefile.am new file mode 100644 index 000000000..ec422f75d --- /dev/null +++ b/tdeioslave/floppy/Makefile.am @@ -0,0 +1,20 @@ +## Makefile.am of tdebase/tdeioslave/floppy + +INCLUDES= $(all_includes) +AM_LDFLAGS = $(all_libraries) + +####### Files + +kde_module_LTLIBRARIES = kio_floppy.la + +kio_floppy_la_SOURCES = kio_floppy.cpp program.cpp +kio_floppy_la_LIBADD = $(LIB_KIO) +kio_floppy_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) + +kdelnk_DATA = floppy.protocol +kdelnkdir = $(kde_servicesdir) + +METASOURCES = AUTO + +messages: + $(XGETTEXT) *.cpp -o $(podir)/tdeio_floppy.pot diff --git a/tdeioslave/floppy/README b/tdeioslave/floppy/README new file mode 100644 index 000000000..99d87bd71 --- /dev/null +++ b/tdeioslave/floppy/README @@ -0,0 +1,7 @@ +this is an ioslave for KDE 2/3 for accessing fat/vfat floppies without +mounting. +It is a wrapper around the mtools. + + +Alex +neundorf@kde.org diff --git a/tdeioslave/floppy/TODO b/tdeioslave/floppy/TODO new file mode 100644 index 000000000..f4f1e679e --- /dev/null +++ b/tdeioslave/floppy/TODO @@ -0,0 +1,3 @@ +-error handling (will be done until new year) + +Alex diff --git a/tdeioslave/floppy/floppy.protocol b/tdeioslave/floppy/floppy.protocol new file mode 100644 index 000000000..af861d1be --- /dev/null +++ b/tdeioslave/floppy/floppy.protocol @@ -0,0 +1,14 @@ +[Protocol] +exec=kio_floppy +protocol=floppy +input=none +output=filesystem +listing=Name,Type,Size,Date +reading=true +writing=true +makedir=true +deleting=true +moving=true +Icon=3floppy_mount +DocPath=tdeioslave/floppy.html +Class=:local diff --git a/tdeioslave/floppy/kio_floppy.cpp b/tdeioslave/floppy/kio_floppy.cpp new file mode 100644 index 000000000..626a4a1f0 --- /dev/null +++ b/tdeioslave/floppy/kio_floppy.cpp @@ -0,0 +1,1169 @@ +/* This file is part of the KDE project + + Copyright (C) 2000 Alexander Neundorf <neundorf@kde.org> + + 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. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif + +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/stat.h> +#include <time.h> +#include <sys/time.h> +#include <sys/types.h> + +#include <tqtextstream.h> +#include <tqcstring.h> +#include <tqfile.h> + +#include "kio_floppy.h" + +#include <kinstance.h> +#include <kdebug.h> +#include <tdeio/global.h> +#include <klocale.h> + +using namespace TDEIO; + +extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); } + +int kdemain( int argc, char **argv ) +{ + TDEInstance instance( "kio_floppy" ); + + if (argc != 4) + { + fprintf(stderr, "Usage: kio_floppy protocol domain-socket1 domain-socket2\n"); + exit(-1); + } + kdDebug(7101) << "Floppy: kdemain: starting" << endl; + + FloppyProtocol slave(argv[2], argv[3]); + slave.dispatchLoop(); + return 0; +} + +void getDriveAndPath(const TQString& path, TQString& drive, TQString& rest) +{ + drive=TQString::null; + rest=TQString::null; + TQStringList list=TQStringList::split("/",path); + for (TQStringList::Iterator it=list.begin(); it!=list.end(); it++) + { + if (it==list.begin()) + drive=(*it)+":"; + else + rest=rest+"/"+(*it); + } +} + +FloppyProtocol::FloppyProtocol (const TQCString &pool, const TQCString &app ) +:SlaveBase( "floppy", pool, app ) +,m_mtool(0) +,m_stdoutBuffer(0) +,m_stderrBuffer(0) +,m_stdoutSize(0) +,m_stderrSize(0) +{ + kdDebug(7101)<<"Floppy::Floppy: -"<<pool<<"-"<<endl; +} + +FloppyProtocol::~FloppyProtocol() +{ + delete [] m_stdoutBuffer; + delete [] m_stderrBuffer; + delete m_mtool; + m_mtool=0; + m_stdoutBuffer=0; + m_stderrBuffer=0; +} + +int FloppyProtocol::readStdout() +{ + //kdDebug(7101)<<"Floppy::readStdout"<<endl; + if (m_mtool==0) return 0; + + char buffer[16*1024]; + int length=::read(m_mtool->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]; + kdDebug(7101)<<"Floppy::readStdout(): length: "<<length<<" m_tsdoutSize: "<<m_stdoutSize<<" +1="<<length+m_stdoutSize+1<<endl; + if (m_stdoutBuffer!=0) + { + memcpy(newBuffer, m_stdoutBuffer, m_stdoutSize); + } + memcpy(newBuffer+m_stdoutSize, buffer, length); + m_stdoutSize+=length; + newBuffer[m_stdoutSize]='\0'; + + delete [] m_stdoutBuffer; + m_stdoutBuffer=newBuffer; + //kdDebug(7101)<<"Floppy::readStdout(): -"<<m_stdoutBuffer<<"-"<<endl; + + //kdDebug(7101)<<"Floppy::readStdout ends"<<endl; + return length; +} + +int FloppyProtocol::readStderr() +{ + //kdDebug(7101)<<"Floppy::readStderr"<<endl; + if (m_mtool==0) return 0; + + /*struct timeval tv; + tv.tv_sec=0; + tv.tv_usec=1000*300; + ::select(0,0,0,0,&tv);*/ + + char buffer[16*1024]; + int length=::read(m_mtool->stderrFD(),buffer,16*1024); + kdDebug(7101)<<"Floppy::readStderr(): read "<<length<<" bytes"<<endl; + if (length<=0) return 0; + + //+1 gives us room for a terminating 0 + char *newBuffer=new char[length+m_stderrSize+1]; + memcpy(newBuffer, m_stderrBuffer, m_stderrSize); + memcpy(newBuffer+m_stderrSize, buffer, length); + m_stderrSize+=length; + newBuffer[m_stderrSize]='\0'; + delete [] m_stderrBuffer; + m_stderrBuffer=newBuffer; + kdDebug(7101)<<"Floppy::readStderr(): -"<<m_stderrBuffer<<"-"<<endl; + + return length; +} + +void FloppyProtocol::clearBuffers() +{ + kdDebug(7101)<<"Floppy::clearBuffers()"<<endl; + m_stdoutSize=0; + m_stderrSize=0; + delete [] m_stdoutBuffer; + m_stdoutBuffer=0; + delete [] m_stderrBuffer; + m_stderrBuffer=0; + //kdDebug(7101)<<"Floppy::clearBuffers() ends"<<endl; +} + +void FloppyProtocol::terminateBuffers() +{ + //kdDebug(7101)<<"Floppy::terminateBuffers()"<<endl; + //append a terminating 0 to be sure + if (m_stdoutBuffer!=0) + { + m_stdoutBuffer[m_stdoutSize]='\0'; + } + if (m_stderrBuffer!=0) + { + m_stderrBuffer[m_stderrSize]='\0'; + } + //kdDebug(7101)<<"Floppy::terminateBuffers() ends"<<endl; +} + +bool FloppyProtocol::stopAfterError(const KURL& url, const TQString& drive) +{ + if (m_stderrSize==0) + return true; + //m_stderrBuffer[m_stderrSize]='\0'; + + TQString outputString(m_stderrBuffer); + TQTextIStream output(&outputString); + TQString line=output.readLine(); + kdDebug(7101)<<"line: -"<<line<<"-"<<endl; + if (line.find("resource busy") > -1) + { + error( TDEIO::ERR_SLAVE_DEFINED, i18n("Could not access drive %1.\nThe drive is still busy.\nWait until it is inactive and then try again.").arg(drive)); + } + else if ((line.find("Disk full") > -1) || (line.find("No free cluster") > -1)) + { + error( TDEIO::ERR_SLAVE_DEFINED, i18n("Could not write to file %1.\nThe disk in drive %2 is probably full.").arg(url.prettyURL(),drive)); + } + //file not found + else if (line.find("not found") > -1) + { + error( TDEIO::ERR_DOES_NOT_EXIST, url.prettyURL()); + } + //no disk + else if (line.find("not configured") > -1) + { + error( TDEIO::ERR_SLAVE_DEFINED, i18n("Could not access %1.\nThere is probably no disk in the drive %2").arg(url.prettyURL(),drive)); + } + else if (line.find("No such device") > -1) + { + error( TDEIO::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.").arg(url.prettyURL(),drive)); + } + else if (line.find("not supported") > -1) + { + error( TDEIO::ERR_SLAVE_DEFINED, i18n("Could not access %1.\nThe drive %2 is not supported.").arg(url.prettyURL(),drive)); + } + //not supported or no such drive + else if (line.find("Permission denied") > -1) + { + error( TDEIO::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).").arg(url.prettyURL(),drive)); + } + else if (line.find("non DOS media") > -1) + { + error( TDEIO::ERR_SLAVE_DEFINED, i18n("Could not access %1.\nThe disk in drive %2 is probably not a DOS-formatted floppy disk.").arg(url.prettyURL(),drive)); + } + else if (line.find("Read-only") > -1) + { + error( TDEIO::ERR_SLAVE_DEFINED, i18n("Access denied.\nCould not write to %1.\nThe disk in drive %2 is probably write-protected.").arg(url.prettyURL(),drive)); + } + else if ((outputString.find("already exists") > -1) || (outputString.find("Skipping ") > -1)) + { + error( TDEIO::ERR_FILE_ALREADY_EXIST,url.prettyURL()); + //return false; + } + else if (outputString.find("could not read boot sector") > -1) + { + error( TDEIO::ERR_SLAVE_DEFINED, i18n("Could not read boot sector for %1.\nThere is probably not any disk in drive %2.").arg(url.prettyURL(),drive)); + //return false; + } + else + { + error( TDEIO::ERR_UNKNOWN, outputString); + } + return true; +} + +void FloppyProtocol::listDir( const KURL& _url) +{ + kdDebug(7101)<<"Floppy::listDir() "<<_url.path()<<endl; + KURL url(_url); + TQString path(url.path()); + + if ((path.isEmpty()) || (path=="/")) + { + url.setPath("/a/"); + redirection(url); + finished(); + return; + } + TQString drive; + TQString floppyPath; + getDriveAndPath(path,drive,floppyPath); + + TQStringList args; + + args<<"mdir"<<"-a"<<(drive+floppyPath); + if (m_mtool!=0) + 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; + + TQString outputString(m_stdoutBuffer); + TQTextIStream output(&outputString); + TQString line; + + int totalNumber(0); + int mode(0); + UDSEntry entry; + + while (!output.atEnd()) + { + line=output.readLine(); + kdDebug(7101)<<"Floppy::listDir(): line: -"<<line<<"- length: "<<line.length()<<endl; + + if (mode==0) + { + if (line.isEmpty()) + { + kdDebug(7101)<<"Floppy::listDir(): switching to mode 1"<<endl; + mode=1; + } + } + else if (mode==1) + { + if (line[0]==' ') + { + kdDebug(7101)<<"Floppy::listDir(): ende"<<endl; + totalSize(totalNumber); + break; + } + entry.clear(); + StatInfo info=createStatInfo(line); + if (info.isValid) + { + createUDSEntry(info,entry); + //kdDebug(7101)<<"Floppy::listDir(): creating UDSEntry"<<endl; + listEntry( entry, false); + totalNumber++; + } + } + } + listEntry( entry, true ); // ready + finished(); + //kdDebug(7101)<<"Floppy::listDir() ends"<<endl; +} + +void FloppyProtocol::errorMissingMToolsProgram(const TQString& name) +{ + error(TDEIO::ERR_SLAVE_DEFINED,i18n("Could not start program \"%1\".\nEnsure that the mtools package is installed correctly on your system.").arg(name)); + } + +void FloppyProtocol::createUDSEntry(const StatInfo& info, UDSEntry& entry) +{ + UDSAtom atom; + atom.m_uds = TDEIO::UDS_NAME; + atom.m_str = info.name; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_SIZE; + atom.m_long = info.size; + entry.append(atom); + + atom.m_uds = TDEIO::UDS_MODIFICATION_TIME; + atom.m_long = info.time; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_ACCESS; + atom.m_long=info.mode; + entry.append( atom ); + + atom.m_uds = TDEIO::UDS_FILE_TYPE; + atom.m_long =(info.isDir?S_IFDIR:S_IFREG); + entry.append( atom ); +} + +StatInfo FloppyProtocol::createStatInfo(const TQString line, bool makeStat, const TQString& dirName) +{ + //kdDebug(7101)<<"Floppy::createUDSEntry()"<<endl; + TQString name; + TQString size; + bool isDir(false); + TQString day,month, year; + TQString hour, minute; + StatInfo info; + + if (line.length()==41) + { + int nameLength=line.find(' '); + kdDebug(7101)<<"Floppy::createStatInfo: line find: "<<nameLength <<"= -"<<line<<"-"<<endl; + if (nameLength>0) + { + name=line.mid(0,nameLength); + TQString ext=line.mid(9,3); + ext=ext.stripWhiteSpace(); + if (!ext.isEmpty()) + name+="."+ext; + } + kdDebug(7101)<<"Floppy::createStatInfo() name 8.3= -"<<name<<"-"<<endl; + } + else if (line.length()>41) + { + name=line.mid(42); + kdDebug(7101)<<"Floppy::createStatInfo() name vfat: -"<<name<<"-"<<endl; + } + if ((name==".") || (name=="..")) + { + if (makeStat) + name=dirName; + else + { + info.isValid=false; + return info; + } + } + + if (line.mid(13,5)=="<DIR>") + { + //kdDebug(7101)<<"Floppy::createUDSEntry() isDir"<<endl; + size="1024"; + isDir=true; + } + else + { + size=line.mid(13,9); + //kdDebug(7101)<<"Floppy::createUDSEntry() size: -"<<size<<"-"<<endl; + } + + //TEEKANNE JPG 70796 01-02-2003 17:47 Teekanne.jpg + if (line[25]=='-') + { + month=line.mid(23,2); + day=line.mid(26,2); + year=line.mid(29,4); + } + else //SETUP PKG 1019 1997-09-25 10:31 setup.pkg + { + year=line.mid(23,4); + month=line.mid(28,2); + day=line.mid(31,2); + } + hour=line.mid(35,2); + minute=line.mid(38,2); + //kdDebug(7101)<<"Floppy::createUDSEntry() day: -"<<day<<"-"<<month<<"-"<<year<<"- -"<<hour<<"-"<<minute<<"-"<<endl; + + if (name.isEmpty()) + { + info.isValid=false; + return info; + } + + info.name=name; + info.size=size.toInt(); + + TQDateTime date(TQDate(year.toInt(),month.toInt(),day.toInt()),TQTime(hour.toInt(),minute.toInt())); + info.time=date.toTime_t(); + + if (isDir) + info.mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH| S_IWOTH|S_IWGRP|S_IWUSR ; + else + info.mode = S_IRUSR | S_IRGRP | S_IROTH| S_IWOTH|S_IWGRP|S_IWUSR; + + info.isDir=isDir; + + info.isValid=true; + //kdDebug(7101)<<"Floppy::createUDSEntry() ends"<<endl; + return info; +} + +StatInfo FloppyProtocol::_stat(const KURL& url) +{ + StatInfo info; + + TQString path(url.path()); + TQString drive; + TQString floppyPath; + getDriveAndPath(path,drive,floppyPath); + + if (floppyPath.isEmpty()) + { + kdDebug(7101)<<"Floppy::_stat(): floppyPath.isEmpty()"<<endl; + info.name=path; + info.size=1024; + info.time=0; + info.mode=S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH| S_IWOTH|S_IWGRP|S_IWUSR; + info.isDir=true; + info.isValid=true; + + return info; + } + + //kdDebug(7101)<<"Floppy::_stat(): delete m_mtool"<<endl; + if (m_mtool!=0) + delete m_mtool; + + TQStringList args; + args<<"mdir"<<"-a"<<(drive+floppyPath); + + //kdDebug(7101)<<"Floppy::_stat(): create m_mtool"<<endl; + m_mtool=new Program(args); + + if (!m_mtool->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); + + //kdDebug(7101)<<"Floppy::_stat(): delete m_mtool"<<endl; + 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( TDEIO::ERR_COULD_NOT_STAT, url.prettyURL()); + return info; + } + + kdDebug(7101)<<"Floppy::_stat(): parse stuff"<<endl; + TQString outputString(m_stdoutBuffer); + TQTextIStream output(&outputString); + TQString 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( TDEIO::ERR_COULD_NOT_STAT, url.prettyURL()); + return info; + } + if (info.isValid==false) + error( TDEIO::ERR_COULD_NOT_STAT, url.prettyURL()); + return info; +} + +int FloppyProtocol::freeSpace(const KURL& url) +{ + TQString path(url.path()); + TQString drive; + TQString floppyPath; + getDriveAndPath(path,drive,floppyPath); + + //kdDebug(7101)<<"Floppy::freeSpace(): delete m_mtool"<<endl; + if (m_mtool!=0) + delete m_mtool; + + TQStringList args; + args<<"mdir"<<"-a"<<drive; + + //kdDebug(7101)<<"Floppy::freeSpace(): create m_mtool"<<endl; + m_mtool=new Program(args); + + if (!m_mtool->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); + + //kdDebug(7101)<<"Floppy::freeSpace(): delete m_mtool"<<endl; + 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( TDEIO::ERR_COULD_NOT_STAT, url.prettyURL()); + return -1; + } + + kdDebug(7101)<<"Floppy::freeSpace(): parse stuff"<<endl; + TQString outputString(m_stdoutBuffer); + TQTextIStream output(&outputString); + TQString line; + int lineNumber(0); + while (!output.atEnd()) + { + line=output.readLine(); + if (line.find("bytes free")==36) + { + TQString tmp=line.mid(24,3); + tmp=tmp.stripWhiteSpace(); + tmp+=line.mid(28,3); + tmp=tmp.stripWhiteSpace(); + tmp+=line.mid(32,3); + tmp=tmp.stripWhiteSpace(); + + return tmp.toInt(); + } + lineNumber++; + } + return -1; +} + +void FloppyProtocol::stat( const KURL & _url) +{ + kdDebug(7101)<<"Floppy::stat() "<<_url.path()<<endl; + KURL url(_url); + TQString 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(); + //kdDebug(7101)<<"Floppy::stat(): ends"<<endl; + return; + } + //otherwise the error() was already reported in _stat() +} + +void FloppyProtocol::mkdir( const KURL& url, int) +{ + kdDebug(7101)<<"FloppyProtocol::mkdir()"<<endl; + TQString path(url.path()); + + if ((path.isEmpty()) || (path=="/")) + { + KURL newUrl(url); + newUrl.setPath("/a/"); + redirection(newUrl); + finished(); + return; + } + TQString drive; + TQString floppyPath; + getDriveAndPath(path,drive,floppyPath); + if (floppyPath.isEmpty()) + { + finished(); + return; + } + if (m_mtool!=0) + delete m_mtool; + //kdDebug(7101)<<"Floppy::stat(): create args"<<endl; + TQStringList args; + + args<<"mmd"<<(drive+floppyPath); + kdDebug(7101)<<"Floppy::mkdir(): executing: mmd -"<<(drive+floppyPath)<<"-"<<endl; + + 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) +{ + kdDebug(7101)<<"FloppyProtocol::del()"<<endl; + TQString path(url.path()); + + if ((path.isEmpty()) || (path=="/")) + { + KURL newUrl(url); + newUrl.setPath("/a/"); + redirection(newUrl); + finished(); + return; + } + TQString drive; + TQString floppyPath; + getDriveAndPath(path,drive,floppyPath); + if (floppyPath.isEmpty()) + { + finished(); + return; + } + + if (m_mtool!=0) + delete m_mtool; + //kdDebug(7101)<<"Floppy::stat(): create args"<<endl; + TQStringList args; + + bool usingmdel; + + if (isfile) + { + args<<"mdel"<<(drive+floppyPath); + usingmdel=true; + } + else + { + args<<"mrd"<<(drive+floppyPath); + usingmdel=false; + } + + kdDebug(7101)<<"Floppy::del(): executing: " << (usingmdel ? TQString("mdel") : TQString("mrd") ) << "-"<<(drive+floppyPath)<<"-"<<endl; + + m_mtool=new Program(args); + if (!m_mtool->start()) + { + delete m_mtool; + m_mtool=0; + errorMissingMToolsProgram(usingmdel ? TQString("mdel") : TQString("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, bool _overwrite ) +{ + TQString srcPath(src.path()); + TQString destPath(dest.path()); + + kdDebug(7101)<<"Floppy::rename() -"<<srcPath<<"- to -"<<destPath<<"-"<<endl; + + if ((srcPath.isEmpty()) || (srcPath=="/")) + srcPath="/a/"; + + if ((destPath.isEmpty()) || (destPath=="/")) + destPath="/a/"; + + TQString srcDrive; + TQString srcFloppyPath; + getDriveAndPath(srcPath,srcDrive,srcFloppyPath); + if (srcFloppyPath.isEmpty()) + { + finished(); + return; + } + + TQString destDrive; + TQString destFloppyPath; + getDriveAndPath(destPath,destDrive,destFloppyPath); + if (destFloppyPath.isEmpty()) + { + finished(); + return; + } + + if (m_mtool!=0) + delete m_mtool; + //kdDebug(7101)<<"Floppy::stat(): create args"<<endl; + TQStringList args; + + if (_overwrite) + args<<"mren"<<"-o"<<(srcDrive+srcFloppyPath)<<(destDrive+destFloppyPath); + else + args<<"mren"<<"-D"<<"s"<<(srcDrive+srcFloppyPath)<<(destDrive+destFloppyPath); + + kdDebug(7101)<<"Floppy::move(): executing: mren -"<<(srcDrive+srcFloppyPath)<<" "<<(destDrive+destFloppyPath)<<endl; + + m_mtool=new Program(args); + if (!m_mtool->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 ) +{ + TQString path(url.path()); + kdDebug(7101)<<"Floppy::get() -"<<path<<"-"<<endl; + + if ((path.isEmpty()) || (path=="/")) + { + KURL newUrl(url); + newUrl.setPath("/a/"); + redirection(newUrl); + finished(); + return; + } + StatInfo info=this->_stat(url); + //the error was already reported in _stat() + if (info.isValid==false) + return; + + totalSize( info.size); + + TQString drive; + TQString floppyPath; + getDriveAndPath(path,drive,floppyPath); + if (floppyPath.isEmpty()) + { + finished(); + return; + } + + if (m_mtool!=0) + delete m_mtool; + //kdDebug(7101)<<"Floppy::stat(): create args"<<endl; + TQStringList args; + args<<"mcopy"<<(drive+floppyPath)<<"-"; + + kdDebug(7101)<<"Floppy::get(): executing: mcopy -"<<(drive+floppyPath)<<"-"<<endl; + + m_mtool=new Program(args); + if (!m_mtool->start()) + { + delete m_mtool; + m_mtool=0; + errorMissingMToolsProgram("mcopy"); + return; + } + + clearBuffers(); + int result; + int bytesRead(0); + TQByteArray array; + 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) + { + kdDebug(7101)<<"Floppy::get(): m_stdoutSize:"<<m_stdoutSize<<endl; + bytesRead+=m_stdoutSize; + array.setRawData(m_stdoutBuffer, m_stdoutSize); + data( array ); + array.resetRawData(m_stdoutBuffer, m_stdoutSize); + + } + else + { + loopFinished=true; + } + } + if (stderrEvent) + { + if (readStderr()==0) + loopFinished=true; + else + if (stopAfterError(url,drive)) + { + errorOccured=true; + loopFinished=true; + } + } + } while (!loopFinished); + + //kdDebug(7101)<<"Floppy::get(): deleting m_mtool"<<endl; + delete m_mtool; + m_mtool=0; + if (errorOccured) + return; + + //kdDebug(7101)<<"Floppy::get(): finishing"<<endl; + data( TQByteArray() ); + finished(); +} + +void FloppyProtocol::put( const KURL& url, int , bool overwrite, bool ) +{ + TQString path(url.path()); + kdDebug(7101)<<"Floppy::put() -"<<path<<"-"<<endl; + + if ((path.isEmpty()) || (path=="/")) + { + KURL newUrl(url); + newUrl.setPath("/a/"); + redirection(newUrl); + finished(); + return; + } + TQString drive; + TQString floppyPath; + getDriveAndPath(path,drive,floppyPath); + if (floppyPath.isEmpty()) + { + finished(); + return; + } + int freeSpaceLeft=freeSpace(url); + if (freeSpaceLeft==-1) + return; + + if (m_mtool!=0) + delete m_mtool; + //kdDebug(7101)<<"Floppy::stat(): create args"<<endl; + TQStringList args; + if (overwrite) + args<<"mcopy"<<"-o"<<"-"<<(drive+floppyPath); + else + args<<"mcopy"<<"-s"<<"-"<<(drive+floppyPath); + + kdDebug(7101)<<"Floppy::put(): executing: mcopy -"<<(drive+floppyPath)<<"-"<<endl; + + m_mtool=new Program(args); + if (!m_mtool->start()) + { + delete m_mtool; + m_mtool=0; + errorMissingMToolsProgram("mcopy"); + return; + } + + + clearBuffers(); + int result(0); + int bytesRead(0); + TQByteArray array; + + //from file.cc + // Loop until we got 0 (end of data) + do + { + bool stdoutEvent; + bool stderrEvent; + kdDebug(7101)<<"Floppy::put(): select()..."<<endl; + 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; + kdDebug(7101)<<"Floppy::put(): error: result=="<<result<<endl; + } + else + { + TQByteArray buffer; + dataReq(); // Request for data + //kdDebug(7101)<<"Floppy::put(): after dataReq()"<<endl; + result = readData( buffer ); + //kdDebug(7101)<<"Floppy::put(): after readData(), read "<<result<<" bytes"<<endl; + if (result > 0) + { + bytesRead+=result; + kdDebug(7101)<<"Floppy::put() bytesRead: "<<bytesRead<<" space: "<<freeSpaceLeft<<endl; + if (bytesRead>freeSpaceLeft) + { + result=0; + error( TDEIO::ERR_SLAVE_DEFINED, i18n("Could not write to file %1.\nThe disk in drive %2 is probably full.").arg(url.prettyURL(),drive)); + } + else + { + //kdDebug(7101)<<"Floppy::put(): writing..."<<endl; + result=::write(m_mtool->stdinFD(),buffer.data(), buffer.size()); + kdDebug(7101)<<"Floppy::put(): after write(), wrote "<<result<<" bytes"<<endl; + } + } + } + } + while ( result > 0 ); + + if (result<0) + { + perror("writing to stdin"); + error( TDEIO::ERR_CANNOT_OPEN_FOR_WRITING, url.prettyURL()); + return; + } + + delete m_mtool; + m_mtool=0; + + finished(); +} + diff --git a/tdeioslave/floppy/kio_floppy.h b/tdeioslave/floppy/kio_floppy.h new file mode 100644 index 000000000..d38340729 --- /dev/null +++ b/tdeioslave/floppy/kio_floppy.h @@ -0,0 +1,78 @@ +/* This file is part of the KDE project + Copyright (C) 2000 Alexander Neundorf <neundorf@kde.org> + + 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. +*/ + +#ifndef KIO_FLOPPY_H +#define KIO_FLOPPY_H + +#include <tdeio/slavebase.h> +#include <tdeio/global.h> + +#include "program.h" + +#include <tqstring.h> + +struct StatInfo +{ + StatInfo():name(""),time(0),size(0),mode(0),freeSpace(0),isDir(false),isValid(false) {;} + TQString name; + time_t time; + int size; + int mode; + int freeSpace; + bool isDir:1; + bool isValid:1; +}; + + +class FloppyProtocol : public TDEIO::SlaveBase +{ + public: + FloppyProtocol (const TQCString &pool, const TQCString &app ); + virtual ~FloppyProtocol(); + + virtual void listDir( const KURL& url); + virtual void stat( const KURL & url); + virtual void mkdir( const KURL& url, int); + virtual void del( const KURL& url, bool isfile); + virtual void rename(const KURL &src, const KURL &dest, bool overwrite); + virtual void get( const KURL& url ); + virtual void put( const KURL& url, int _mode,bool overwrite, bool _resume ); + //virtual void copy( const KURL& src, const KURL &dest, int, bool overwrite ); + protected: + Program *m_mtool; + int readStdout(); + int readStderr(); + + StatInfo createStatInfo(const TQString line, bool makeStat=false, const TQString& dirName=""); + void createUDSEntry(const StatInfo& info, TDEIO::UDSEntry& entry); + StatInfo _stat(const KURL& _url); + int freeSpace(const KURL& url); + + bool stopAfterError(const KURL& url, const TQString& drive); + void errorMissingMToolsProgram(const TQString& name); + + void clearBuffers(); + void terminateBuffers(); + char *m_stdoutBuffer; + char *m_stderrBuffer; + int m_stdoutSize; + int m_stderrSize; +}; + +#endif diff --git a/tdeioslave/floppy/program.cpp b/tdeioslave/floppy/program.cpp new file mode 100644 index 000000000..83080c233 --- /dev/null +++ b/tdeioslave/floppy/program.cpp @@ -0,0 +1,201 @@ +/* This file is part of the KDE project + Copyright (C) 2000-2002 Alexander Neundorf <neundorf@kde.org> + + 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 <config.h> +#include "program.h" +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <signal.h> + +#include <kdebug.h> + +Program::Program(const TQStringList &args) +:m_pid(0) +,mArgs(args) +,mStarted(false) +{ +} + +Program::~Program() +{ + if (m_pid!=0) + { + ::close(mStdin[0]); + ::close(mStdout[0]); + ::close(mStderr[0]); + + ::close(mStdin[1]); + ::close(mStdout[1]); + ::close(mStderr[1]); + + int s(0); + //::wait(&s); + ::waitpid(m_pid,&s,0); + this->kill(); + ::waitpid(m_pid,&s,WNOHANG); + }; +} + +bool Program::start() +{ + if (mStarted) return false; + if (pipe(mStdout)==-1) return false; + if (pipe(mStdin )==-1) return false; + if (pipe(mStderr )==-1) return false; + + int notificationPipe[2]; + if (pipe(notificationPipe )==-1) return false; + + m_pid=fork(); + + if (m_pid>0) + { + //parent + ::close(mStdin[0]); + ::close(mStdout[1]); + ::close(mStderr[1]); + ::close(notificationPipe[1]); + mStarted=true; + fd_set notifSet; + FD_ZERO(¬ifSet); + FD_SET(notificationPipe[0],¬ifSet); + struct timeval tv; + //wait up to five seconds + + kdDebug(7101)<<"**** waiting for notification"<<endl; + //0.2 sec + tv.tv_sec=0; + tv.tv_usec=1000*200; + int result=::select(notificationPipe[0]+1,¬ifSet,0,0,&tv); +/* if (result<1) + { + kdDebug(7101)<<"**** waiting for notification: failed "<<result<<endl; + return false; + } + else*/ + if(result==1) + { + char buf[256]; + result=::read(notificationPipe[0],buf,256); + //if execvp() failed the child sends us "failed" + if (result>0) + return false; + }; + kdDebug(7101)<<"**** waiting for notification: succeeded"<<result<<endl; + return true; + } + else if (m_pid==-1) + { + //failed + return false; + } + else if (m_pid==0) + { + ::close(notificationPipe[0]); + + //child + ::close(0); // close the stdios + ::close(1); + ::close(2); + + dup(mStdin[0]); + dup(mStdout[1]); + dup(mStderr[1]); + + ::close(mStdin[1]); + ::close(mStdout[0]); + ::close(mStderr[0]); + + fcntl(mStdin[0], F_SETFD, FD_CLOEXEC); + fcntl(mStdout[1], F_SETFD, FD_CLOEXEC); + fcntl(mStderr[1], F_SETFD, FD_CLOEXEC); + + char **arglist=(char**)malloc((mArgs.count()+1)*sizeof(char*)); + int c=0; + + for (TQStringList::Iterator it=mArgs.begin(); it!=mArgs.end(); ++it) + { + arglist[c]=(char*)malloc((*it).length()+1); + strcpy(arglist[c], (*it).latin1()); + c++; + } + arglist[mArgs.count()]=0; + //make parsing easier + putenv(strdup("LANG=C")); + execvp(arglist[0], arglist); + //we only get here if execvp() failed + ::write(notificationPipe[1],"failed",strlen("failed")); + ::close(notificationPipe[1]); + _exit(-1); + }; + return false; +} + +bool Program::isRunning() +{ + return mStarted; +} + +int Program::select(int secs, int usecs, bool& stdoutReceived, bool& stderrReceived/*, bool& stdinWaiting*/) +{ + stdoutReceived=false; + stderrReceived=false; + + struct timeval tv; + tv.tv_sec=secs; + tv.tv_usec=usecs; + + fd_set readFDs; + FD_ZERO(&readFDs); + FD_SET(stdoutFD(),&readFDs); + FD_SET(stderrFD(),&readFDs); + + int maxFD=stdoutFD(); + if (stderrFD()>maxFD) maxFD=stderrFD(); + + /*fd_set writeFDs; + FD_ZERO(&writeFDs); + FD_SET(stdinFD(),&writeFDs); + if (stdinFD()>maxFD) maxFD=stdinFD();*/ + maxFD++; + + int result=::select(maxFD,&readFDs,/*&writeFDs*/0,0,&tv); + if (result>0) + { + stdoutReceived=FD_ISSET(stdoutFD(),&readFDs); + stderrReceived=FD_ISSET(stderrFD(),&readFDs); + //stdinWaiting=(FD_ISSET(stdinFD(),&writeFDs)); + }; + return result; +} + +int Program::kill() +{ + if (m_pid==0) + return -1; + return ::kill(m_pid, SIGTERM); + //::kill(m_pid, SIGKILL); +} + diff --git a/tdeioslave/floppy/program.h b/tdeioslave/floppy/program.h new file mode 100644 index 000000000..409603689 --- /dev/null +++ b/tdeioslave/floppy/program.h @@ -0,0 +1,53 @@ +/* This file is part of the KDE project + Copyright (C) 2000-2002 Alexander Neundorf <neundorf@kde.org> + + 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. +*/ + +#ifndef PROGRAM_H +#define PROGRAM_H + +#include <tqstringlist.h> + +/** + * start programs and write to thieir stdin, stderr, + * and read from stdout + **/ +class Program +{ +public: + Program(const TQStringList &args); + ~Program(); + bool start(); + bool isRunning(); + + int stdinFD() {return mStdin[1];} + int stdoutFD() {return mStdout[0];} + int stderrFD() {return mStderr[0];} + int pid() {return m_pid;} + int kill(); + int select(int secs, int usecs, bool& stdoutReceived, bool& stderrReceived/*, bool& stdinWaiting*/); +protected: + int mStdout[2]; + int mStdin[2]; + int mStderr[2]; + int m_pid; + TQStringList mArgs; + bool mStarted; +}; + +#endif + |