diff options
Diffstat (limited to 'konq-plugins/rsync/rsyncplugin.cpp')
-rw-r--r-- | konq-plugins/rsync/rsyncplugin.cpp | 238 |
1 files changed, 215 insertions, 23 deletions
diff --git a/konq-plugins/rsync/rsyncplugin.cpp b/konq-plugins/rsync/rsyncplugin.cpp index 11785ac..ebf7dd7 100644 --- a/konq-plugins/rsync/rsyncplugin.cpp +++ b/konq-plugins/rsync/rsyncplugin.cpp @@ -173,9 +173,9 @@ close_master: #endif } /** -creates the subprocess +creates the unidirectional sync subprocess */ -bool RsyncPlugin::connectionStart(QString localfolder, QString remotepath) { +bool RsyncPlugin::syncUnidirectional(QString synccommand, QString syncflags, int parameter_order, QString localfolder, QString remotepath) { int fd[2]; int rc, flags; thisFn = QString::null; @@ -186,8 +186,6 @@ bool RsyncPlugin::connectionStart(QString localfolder, QString remotepath) { return true; } - //myDebug( << "Exec: " << (local ? suPath : rsyncPath) << " Port: " << connectionPort << " User: " << connectionUser << endl); - //infoMessage(rsyncPath); childPid = fork(); if (childPid == -1) { myDebug( << "fork failed, error: " << strerror(errno) << endl); @@ -199,7 +197,146 @@ bool RsyncPlugin::connectionStart(QString localfolder, QString remotepath) { if (childPid == 0) { // Create the rsync command to run QString execstring; - execstring = QString(rsyncPath) + QString(" -avtzAXE --delete --progress ") + localfolder + QString("/ ") + remotepath; + if (parameter_order == 0) { + execstring = synccommand + syncflags + localfolder + QString("/ ") + remotepath; + } + else { + execstring = synccommand + syncflags + remotepath + QString("/ ") + localfolder; + } + + // taken from konsole, see TEPty.C for details + // note: if we're running on socket pairs, + // this will fail, but thats what we expect + + for (int sig = 1; sig < NSIG; sig++) signal(sig,SIG_DFL); + + struct rlimit rlp; + getrlimit(RLIMIT_NOFILE, &rlp); + for (int i = 0; i < (int)rlp.rlim_cur; i++) + if (i != fd[1]) close(i); + + dup2(fd[1],0); + dup2(fd[1],1); + dup2(fd[1],2); + if (fd[1] > 2) close(fd[1]); + + setsid(); + +#if defined(TIOCSCTTY) + ioctl(0, TIOCSCTTY, 0); +#endif + + int pgrp = getpid(); +#if defined( _AIX) || defined( __hpux) + tcsetpgrp(0, pgrp); +#else + ioctl(0, TIOCSPGRP, (char *)&pgrp); +#endif + + const char *dev = ttyname(0); + setpgid(0,0); + if (dev) close(open(dev, O_WRONLY, 0)); + setpgid(0,0); + + system(execstring.ascii()); + #undef common_args + myDebug( << "could not exec! " << strerror(errno) << endl); + ::exit(-1); + } + close(fd[1]); + rc = fcntl(fd[0],F_GETFL,&flags); + rc = fcntl(fd[0],F_SETFL,flags|O_NONBLOCK); + childFd = fd[0]; + + fd_set rfds, wfds; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + char buf[32768]; + int offset = 0; + while (!isLoggedIn) { + FD_SET(childFd,&rfds); + FD_ZERO(&wfds); + if (outBufPos >= 0) FD_SET(childFd,&wfds); + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 1000; + rc = select(childFd+1, &rfds, &wfds, NULL, &timeout); + if (rc < 0) { + if (errno == EINTR) + continue; + myDebug( << "select failed, rc: " << rc << ", error: " << strerror(errno) << endl); + return true; + } + if (FD_ISSET(childFd,&wfds) && outBufPos >= 0) { + if (outBuf) { + rc = write(childFd,outBuf+outBufPos,outBufLen-outBufPos); + fflush(stdout); + } + else { + rc = 0; + } + if (rc >= 0) outBufPos += rc; + else { + if (errno == EINTR) + continue; + myDebug( << "write failed, rc: " << rc << ", error: " << strerror(errno) << endl); + outBufPos = -1; + //return true; + } + if (outBufPos >= outBufLen) { + outBufPos = -1; + outBuf = NULL; + outBufLen = 0; + } + } + if (FD_ISSET(childFd,&rfds)) { + rc = read(childFd,buf+offset,32768-offset); + if (rc > 0) { + int noff = establishConnection(buf,rc+offset); + if (noff < 0) return false; + if (noff > 0) memmove(buf,buf+offset+rc-noff,noff); + offset = noff; + } else { + if (errno == EINTR) + continue; + //if (errno == EAGAIN) + // continue; + myDebug( << "read failed, rc: " << rc << ", error: " << strerror(errno) << endl); + return true; + } + } + } + return false; +} + +/** +creates the bidirectional sync subprocess +*/ +bool RsyncPlugin::syncBidirectional(QString localfolder, QString remotepath) { + int fd[2]; + int rc, flags; + thisFn = QString::null; + + rc = open_pty_pair(fd); + if (rc == -1) { + myDebug( << "socketpair failed, error: " << strerror(errno) << endl); + return true; + } + + childPid = fork(); + if (childPid == -1) { + myDebug( << "fork failed, error: " << strerror(errno) << endl); + close(fd[0]); + close(fd[1]); + childPid = 0; + return true; + } + if (childPid == 0) { + // Create the rsync command to run + QString execstring; + // FIXME + //execstring = synccommand + syncflags + localfolder + QString("/ ") + remotepath; + exit -1; // taken from konsole, see TEPty.C for details // note: if we're running on socket pairs, @@ -471,15 +608,11 @@ void RsyncPlugin::saveSettings() KConfig cfg ("rsyncrc", false, false); cfg.setGroup ("General"); - bool min_entry = false; QString longstring = QString(""); - for (QStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) { - if (min_entry) - longstring = longstring + QString(";"); + for (QStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end();) { longstring = longstring + (*i); i++; - longstring = longstring + QString(";") + (*i); - min_entry = true; + longstring = longstring + QString(";"); } cfg.writeEntry("LocalFolders", longstring); @@ -508,6 +641,24 @@ QString RsyncPlugin::findLocalFolderByName(QString folderurl) if (QString::compare((*i), folderurl_stripped) == 0) { i++; return (*i); + i++; + i++; + } + } + return NULL; +} + +QString RsyncPlugin::findSyncMethodByName(QString folderurl) +{ + QString folderurl_stripped; + folderurl_stripped = folderurl; + folderurl_stripped.replace(QString("file://"), QString("")); + for (QStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) { + if (QString::compare((*i), folderurl_stripped) == 0) { + i++; + i++; + return (*i); + i++; } } return NULL; @@ -521,6 +672,8 @@ int RsyncPlugin::deleteLocalFolderByName(QString folderurl) for (QStringList::Iterator i(cfgfolderlist.begin()); i != cfgfolderlist.end(); ++i) { if (QString::compare((*i), folderurl_stripped) == 0) { i=cfgfolderlist.remove(i); + i=cfgfolderlist.remove(i); + i=cfgfolderlist.remove(i); cfgfolderlist.remove(i); return 0; } @@ -528,13 +681,15 @@ int RsyncPlugin::deleteLocalFolderByName(QString folderurl) return 1; } -int RsyncPlugin::addLocalFolderByName(QString folderurl, QString remoteurl) +int RsyncPlugin::addLocalFolderByName(QString folderurl, QString remoteurl, QString syncmethod, QString excludelist) { QString folderurl_stripped; folderurl_stripped = folderurl; folderurl_stripped.replace(QString("file://"), QString("")); cfgfolderlist.append(folderurl); cfgfolderlist.append(remoteurl); + cfgfolderlist.append(syncmethod); + cfgfolderlist.append(excludelist); return 1; } @@ -647,8 +802,22 @@ void RsyncPlugin::slotSetup() // Look up settings QString localfolder = url.directory(true, true) + QString("/") + url.fileName(true); QString remotefolder = findLocalFolderByName(url.directory(true, true) + QString("/") + url.fileName(true)); + QString syncmethod = findSyncMethodByName(url.directory(true, true) + QString("/") + url.fileName(true)); + int syncint; + if (syncmethod == NULL) { + syncint = 1; + } + else if (syncmethod == "rsync_upload") { + syncint = 1; + } + else if (syncmethod == "rsync_download") { + syncint = 2; + } + else if (syncmethod == "rsync_bidirectional") { + syncint = 3; + } - m_configDialog = new RsyncConfigDialog(0, "rsyncConfig", i18n("Remote Folder Synchronization"), i18n("Configuring Remote Folder Synchronization"), localfolder, remotefolder, true); + m_configDialog = new RsyncConfigDialog(0, "rsyncConfig", i18n("Remote Folder Synchronization"), i18n("Configuring Remote Folder Synchronization"), localfolder, remotefolder, syncint, true); m_configDialog->show(); connect (m_configDialog, SIGNAL(okClicked()), SLOT(slotSetupOK())); @@ -666,13 +835,24 @@ void RsyncPlugin::slotSetupOK() QString localfolder = url.directory(true, true) + QString("/") + url.fileName(true); QString remotefolder = findLocalFolderByName(localfolder); QString remotefolder_new = m_configDialog->lineEdit()->text().ascii(); + int syncmethod = m_configDialog->getSyncMode(); + QString syncmethod_new = ""; + if (syncmethod == 1) { + syncmethod_new = "rsync_upload"; + } + else if (syncmethod == 2) { + syncmethod_new = "rsync_download"; + } + else if (syncmethod == 3) { + syncmethod_new = "rsync_bidirectional"; + } // See if an old entry has to be deleted if (remotefolder.isEmpty() == false) { deleteLocalFolderByName(localfolder); } if (remotefolder_new.isEmpty() == false) { - addLocalFolderByName(localfolder, remotefolder_new); + addLocalFolderByName(localfolder, remotefolder_new, syncmethod_new, ""); } saveSettings(); @@ -701,18 +881,30 @@ void RsyncPlugin::slotRsyncCancelled() void RsyncPlugin::slotSync() { - if (!m_part) - return; - - KURL url = m_part->url(); + if (!m_part) + return; - m_pSyncNow->setEnabled (false); + KURL url = m_part->url(); - // Initiate rsync - connectionStart(url.directory(true, true) + QString("/") + url.fileName(true), findLocalFolderByName(url.directory(true, true) + QString("/") + url.fileName(true))); + m_pSyncNow->setEnabled (false); - m_progressDialogExists = false; - m_pSyncNow->setEnabled (true); + QString syncmethod = findSyncMethodByName(url.directory(true, true) + QString("/") + url.fileName(true)); + if (syncmethod == NULL) { + // Do nothing + } + else if (syncmethod == "rsync_upload") { + // Initiate rsync + syncUnidirectional(QString("rsync"), QString(" -avtzAXE --delete --progress "), 0, url.directory(true, true) + QString("/") + url.fileName(true), findLocalFolderByName(url.directory(true, true) + QString("/") + url.fileName(true))); + } + else if (syncmethod == "rsync_download") { + syncUnidirectional(QString("rsync"), QString(" -avtzAXE --delete --progress "), 1, url.directory(true, true) + QString("/") + url.fileName(true), findLocalFolderByName(url.directory(true, true) + QString("/") + url.fileName(true))); + } +// else if (syncmethod == "rsync_bidirectional") { +// syncint = 3; +// } + + m_progressDialogExists = false; + m_pSyncNow->setEnabled (true); } typedef KGenericFactory<RsyncPlugin> RsyncFactory; |