summaryrefslogtreecommitdiffstats
path: root/konq-plugins/rsync/rsyncplugin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'konq-plugins/rsync/rsyncplugin.cpp')
-rw-r--r--konq-plugins/rsync/rsyncplugin.cpp238
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;