Apply apt-0.5.5cnc5-alt-rsync.patch
Added in commit 3212342
:
0.5.5cnc1-alt3
- Introduced APT::Ignore-dpkg support and set this flag by default,
to address #0002119.
This commit is contained in:
parent
2ee8510e8c
commit
6a7d6b92b3
@ -1,780 +0,0 @@
|
||||
Index: apt-rpm.rsync/apt-pkg/acquire-item.h
|
||||
===================================================================
|
||||
--- apt-rpm.rsync/apt-pkg/acquire-item.h (revision 137)
|
||||
+++ apt-rpm.rsync/apt-pkg/acquire-item.h (working copy)
|
||||
@@ -61,6 +61,9 @@
|
||||
|
||||
// File to write the fetch into
|
||||
string DestFile;
|
||||
+ // Alternative temporary destination
|
||||
+ // Used if method (e.g. rsync) can't use directly DestFile
|
||||
+ string TmpFile;
|
||||
|
||||
// Action members invoked by the worker
|
||||
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
|
||||
Index: apt-rpm.rsync/apt-pkg/acquire-worker.cc
|
||||
===================================================================
|
||||
--- apt-rpm.rsync/apt-pkg/acquire-worker.cc (revision 137)
|
||||
+++ apt-rpm.rsync/apt-pkg/acquire-worker.cc (working copy)
|
||||
@@ -235,6 +235,7 @@
|
||||
CurrentSize = 0;
|
||||
TotalSize = atoi(LookupTag(Message,"Size","0").c_str());
|
||||
ResumePoint = atoi(LookupTag(Message,"Resume-Point","0").c_str());
|
||||
+ Itm->Owner->TmpFile = LookupTag(Message,"Tmp-Filename");
|
||||
Itm->Owner->Start(Message,atoi(LookupTag(Message,"Size","0").c_str()));
|
||||
|
||||
// Display update before completion
|
||||
@@ -526,7 +527,11 @@
|
||||
return;
|
||||
|
||||
struct stat Buf;
|
||||
- if (stat(CurrentItem->Owner->DestFile.c_str(),&Buf) != 0)
|
||||
+ int res = 1;
|
||||
+ if (CurrentItem->Owner->TmpFile.empty()==false)
|
||||
+ res = stat(CurrentItem->Owner->TmpFile.c_str(),&Buf);
|
||||
+
|
||||
+ if (res!=0 && stat(CurrentItem->Owner->DestFile.c_str(),&Buf) != 0)
|
||||
return;
|
||||
CurrentSize = Buf.st_size;
|
||||
|
||||
Index: apt-rpm.rsync/apt-pkg/acquire-method.cc
|
||||
===================================================================
|
||||
--- apt-rpm.rsync/apt-pkg/acquire-method.cc (revision 137)
|
||||
+++ apt-rpm.rsync/apt-pkg/acquire-method.cc (working copy)
|
||||
@@ -152,6 +152,9 @@
|
||||
if (Res.ResumePoint != 0)
|
||||
s << "Resume-Point: " << Res.ResumePoint << "\n";
|
||||
|
||||
+ if (Res.TmpFilename.size() != 0)
|
||||
+ s << "Tmp-Filename: " << Res.TmpFilename << "\n";
|
||||
+
|
||||
s << "\n";
|
||||
string S = s.str();
|
||||
if (write(STDOUT_FILENO,S.c_str(),S.size()) != (ssize_t)S.size())
|
||||
===================================================================
|
||||
--- apt-rpm.rsync/apt-pkg/acquire-method.h (revision 137)
|
||||
+++ apt-rpm.rsync/apt-pkg/acquire-method.h (working copy)
|
||||
@@ -47,6 +47,7 @@
|
||||
time_t LastModified;
|
||||
bool IMSHit;
|
||||
string Filename;
|
||||
+ string TmpFilename;
|
||||
unsigned long Size;
|
||||
unsigned long ResumePoint;
|
||||
|
||||
Index: apt-rpm.rsync/methods/rsync.cc
|
||||
===================================================================
|
||||
--- apt-rpm.rsync/methods/rsync.cc (working copy)
|
||||
+++ apt-rpm.rsync/methods/rsync.cc (working copy)
|
||||
@@ -0,0 +1,570 @@
|
||||
+// -*- mode: cpp; mode: fold -*-
|
||||
+// Description /*{{{*/
|
||||
+// $Id$
|
||||
+/* ######################################################################
|
||||
+
|
||||
+RSYNC Aquire Method - This is the RSYNC aquire method for APT.
|
||||
+
|
||||
+##################################################################### */
|
||||
+/*}}}*/
|
||||
+// Include Files /*{{{*/
|
||||
+#include <apt-pkg/fileutl.h>
|
||||
+#include <apt-pkg/acquire-method.h>
|
||||
+#include <apt-pkg/error.h>
|
||||
+#include <apt-pkg/md5.h>
|
||||
+
|
||||
+#include <fcntl.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <sys/time.h>
|
||||
+#include <utime.h>
|
||||
+#include <unistd.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <signal.h>
|
||||
+#include <stdio.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdarg.h>
|
||||
+#include <sys/wait.h>
|
||||
+#include <iostream>
|
||||
+
|
||||
+// Internet stuff
|
||||
+#include <netinet/in.h>
|
||||
+#include <sys/socket.h>
|
||||
+#include <arpa/inet.h>
|
||||
+#include <netdb.h>
|
||||
+
|
||||
+#include "apti18n.h"
|
||||
+#include "rfc2553emu.h"
|
||||
+#include "connect.h"
|
||||
+#include "rsync-method.h"
|
||||
+/*}}}*/
|
||||
+
|
||||
+RsyncMethod::RsyncConn *RsyncMethod::server = 0;
|
||||
+RsyncMethod::ConnType RsyncMethod::connType = RsyncMethod::ConnTypeExec;
|
||||
+bool RsyncMethod::Debug = false;
|
||||
+unsigned int RsyncMethod::Timeout = 0;
|
||||
+
|
||||
+/* Argv implementation */
|
||||
+Argv::Argv(int msize): max_size(msize), size(0)
|
||||
+{
|
||||
+ args = new char*[max_size];
|
||||
+ memset(args,0, max_size * sizeof(char*));
|
||||
+}
|
||||
+
|
||||
+Argv::~Argv()
|
||||
+{
|
||||
+ for (int i=0; i<size; i++)
|
||||
+ delete args[i];
|
||||
+ delete [] args;
|
||||
+}
|
||||
+
|
||||
+bool Argv::add(const char *arg)
|
||||
+{
|
||||
+ if (arg==0)
|
||||
+ return false;
|
||||
+ if ( size+1 >= max_size && !resize() ) {
|
||||
+ cerr << "Failed to resize" << endl;
|
||||
+ return false;
|
||||
+ }
|
||||
+ int len = strlen(arg);
|
||||
+ args[size] = new char[len+1];
|
||||
+ strncpy(args[size], arg, len+1);
|
||||
+ ++size;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool Argv::resize()
|
||||
+{
|
||||
+ static const int increment = 5;
|
||||
+ char **new_args = new char *[max_size+increment];
|
||||
+ memcpy(new_args,args,size*sizeof(char*));
|
||||
+ memset(new_args+size,0, (max_size+increment-size) * sizeof(char*));
|
||||
+ args = new_args;
|
||||
+ max_size += increment;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+Argv::operator string()
|
||||
+{
|
||||
+ string res;
|
||||
+ for (char **p=args; *p; p++)
|
||||
+ res += *p, res += " ";
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+/* RsyncConn implementation */
|
||||
+
|
||||
+/** Static buffer for RSYNC_PROXY variable */
|
||||
+char RsyncMethod::RsyncConn::proxy_value[1024];
|
||||
+
|
||||
+bool RsyncMethod::RsyncConn::initProxy()
|
||||
+{
|
||||
+ if ( proxy.empty() )
|
||||
+ return true;
|
||||
+ if ( proxy == "none" ) {
|
||||
+ unsetenv("RSYNC_PROXY");
|
||||
+ return true;
|
||||
+ }
|
||||
+ bool res = true;
|
||||
+ string var("RSYNC_PROXY=");
|
||||
+ var += proxy;
|
||||
+ strncpy(proxy_value, var.c_str(), sizeof(proxy_value) );
|
||||
+ if ( proxy_value[sizeof(proxy_value)-1]==0 ) {
|
||||
+ if ( putenv(proxy_value)!=0 ) {
|
||||
+ res = false;
|
||||
+ _error->Error("Failed to set RSYNC_PROXY: %s", proxy_value);
|
||||
+ }
|
||||
+ } else {
|
||||
+ res = false;
|
||||
+ _error->Error("Failed to set RSYNC_PROXY: not enough space in buffer");
|
||||
+ }
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+/* RsyncConnExec implementation */
|
||||
+
|
||||
+RsyncMethod::RsyncConnExec::RsyncConnExec(URI u, const string &_proxy, const string &prog)
|
||||
+ : RsyncConn(u,_proxy), ChildPid(-1), ChildFd(-1)
|
||||
+{
|
||||
+ program = prog.empty() ? RSYNC_PROGRAM : prog;
|
||||
+}
|
||||
+
|
||||
+RsyncMethod::RsyncConnExec::~RsyncConnExec()
|
||||
+{
|
||||
+ if ( ChildPid>0 ) {
|
||||
+ kill(ChildPid, SIGTERM);
|
||||
+ waitpid(ChildPid, 0, 0);
|
||||
+ ChildPid = -1;
|
||||
+ }
|
||||
+ if ( ChildFd>=0 )
|
||||
+ close(ChildFd);
|
||||
+}
|
||||
+
|
||||
+bool RsyncMethod::RsyncConnExec::WaitChild(pkgAcqMethod *Owner, FetchResult &FRes, const char *To)
|
||||
+{
|
||||
+ static const int buflen = 1024;
|
||||
+ static char buf[buflen+1];
|
||||
+ int saved = 0;
|
||||
+ int status = 0, res = 0;
|
||||
+ fd_set readfd;
|
||||
+ struct timeval tv;
|
||||
+ if ( RsyncMethod::Debug )
|
||||
+ cerr << "RSYNC: WaitChild: fd=" << ChildFd << endl;
|
||||
+
|
||||
+ while (1) {
|
||||
+ FD_ZERO(&readfd);
|
||||
+ FD_SET(ChildFd,&readfd);
|
||||
+ FD_SET(0,&readfd);
|
||||
+
|
||||
+ tv.tv_sec = 1;
|
||||
+ tv.tv_usec = 0;
|
||||
+ res = select(ChildFd+1, &readfd, 0, 0, &tv);
|
||||
+
|
||||
+ if (res>0) {
|
||||
+ if ( FD_ISSET(ChildFd,&readfd) ) {
|
||||
+ int len = read(ChildFd,buf+saved, buflen-saved);
|
||||
+ if (len>0) {
|
||||
+ // Split buffer into single-line strings
|
||||
+ // and pass each string to ParseOutput.
|
||||
+ // Strings, that are not terminated with '\n' will
|
||||
+ // be stored in buffer for later completion.
|
||||
+ buf[saved+len] = 0;
|
||||
+ int start = 0;
|
||||
+ for (int off=saved; off<len; off++) {
|
||||
+ if ( buf[off]=='\n' ) {
|
||||
+ buf[off] = 0;
|
||||
+ ParseOutput(Owner,FRes,buf+start);
|
||||
+ start = off+1;
|
||||
+ }
|
||||
+ }
|
||||
+ saved = saved+len-start;
|
||||
+ if ( saved==buflen ) {
|
||||
+ // Parse process output even it was not terminated with '\n'
|
||||
+ // in case of full buffer (we can't read anything if there is
|
||||
+ // no free space in buffer).
|
||||
+ ParseOutput(Owner,FRes,buf);
|
||||
+ saved = 0;
|
||||
+ } else if ( saved>0 ) {
|
||||
+ if ( RsyncMethod::Debug )
|
||||
+ cerr << "RSYNC: Saved " << saved << " byted in buffer:"
|
||||
+ << endl << start << endl;
|
||||
+ // Move saved data to the beginning of the buffer
|
||||
+ // including trailing zero
|
||||
+ memmove(buf,buf+start,saved+1);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ res = waitpid(ChildPid, &status, WNOHANG);
|
||||
+ if ((res>0 && WIFEXITED(status)) || res<0) {
|
||||
+ ChildPid = -1;
|
||||
+ if ( RsyncMethod::Debug )
|
||||
+ cerr << endl << "RSYNC: Closing ChildFd: " << ChildFd << endl;
|
||||
+ close(ChildFd);
|
||||
+ ChildFd = -1;
|
||||
+ // Parse end of process output if it was not terminated with '\n'
|
||||
+ if (saved>0)
|
||||
+ ParseOutput(Owner,FRes,buf);
|
||||
+ if (res < 0) {
|
||||
+ if ( RsyncMethod::Debug )
|
||||
+ cerr << endl << "RSYNC: Unknown status of child process " << ChildFd << endl;
|
||||
+ if (State == Done)
|
||||
+ return true;
|
||||
+ return false;
|
||||
+ }
|
||||
+ switch (WEXITSTATUS(status)) {
|
||||
+ case 0:
|
||||
+ return true;
|
||||
+ break;
|
||||
+ default:
|
||||
+ if ( State != Failed ) {
|
||||
+ State = Failed;
|
||||
+ _error->Error("rsync process terminated with exit code %d", WEXITSTATUS(status));
|
||||
+ }
|
||||
+ return false;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+/* Parse rysnc output
|
||||
+ * Need to parse lines like:
|
||||
+ *
|
||||
+ * ^opening tcp connection to rsync.altlinux.ru port 873
|
||||
+ * ^[11948] i=0 <NULL> FILENAME mode=0100664 len=171935
|
||||
+ * ^FILENAME
|
||||
+ * ^renaming .FILENAME.bWM2bW to FILENAME
|
||||
+ * ^set modtime of FILENAME to (1048860997) Fri Mar 28 17:16:37 2003
|
||||
+ * ^recv_files finished
|
||||
+ *
|
||||
+ */
|
||||
+void RsyncMethod::RsyncConnExec::ParseOutput(pkgAcqMethod *Owner, FetchResult &FRes, const char *buf)
|
||||
+{
|
||||
+ static const char * TMPFN = "Tmp-Filename: ";
|
||||
+ static const char * SIZE = "Size: ";
|
||||
+ static const char * START = "Start: ";
|
||||
+ static const char * DONE = "recv_files finished";
|
||||
+ static const char * FAILED= "Failed: ";
|
||||
+ const char * ptr;
|
||||
+
|
||||
+ if ( RsyncMethod::Debug )
|
||||
+ cerr << "ParseOutput: " << buf << endl;
|
||||
+
|
||||
+ ptr = strstr(buf,"opening tcp connection");
|
||||
+ if (ptr) {
|
||||
+ if ( RsyncMethod::Debug )
|
||||
+ cerr << endl << "Status: Connecting" << endl;
|
||||
+ State = Connecting;
|
||||
+ Owner->Status(_("Connecting"));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // [PID] i=0 DIRNAME FILENAME mode=XXXXXXX len=YYYYYY
|
||||
+ if (buf[0]=='[') {
|
||||
+ ptr = strstr(buf,"i=0 ");
|
||||
+ if (ptr == 0) return;
|
||||
+ ptr += 4; // skip "i=0 "
|
||||
+ ptr = strchr(ptr,' '); // skip DIRNAME
|
||||
+ }
|
||||
+
|
||||
+ ptr = strstr(buf,TMPFN);
|
||||
+ if (ptr) {
|
||||
+ ptr += strlen(TMPFN);
|
||||
+ const char *ptr2 = ptr;
|
||||
+ while (*ptr2!=0 && !isspace(*ptr2))
|
||||
+ ++ptr2;
|
||||
+ if (ptr!=ptr2) {
|
||||
+ char *tmpfn = new char[ptr2-ptr+1];
|
||||
+ bzero(tmpfn, ptr2-ptr+1);
|
||||
+ strncpy(tmpfn, ptr, ptr2-ptr);
|
||||
+ if (RsyncMethod::Debug)
|
||||
+ cerr << endl << "RSYNC: " << TMPFN << tmpfn << endl;
|
||||
+ FRes.TmpFilename = string(tmpfn);
|
||||
+ delete tmpfn;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ptr = strstr(buf,SIZE);
|
||||
+ if (ptr) {
|
||||
+ ptr += strlen(SIZE);
|
||||
+ unsigned long size = atol(ptr);
|
||||
+ if (RsyncMethod::Debug)
|
||||
+ cerr << "RSYNC: " << SIZE << size << endl;
|
||||
+ FRes.Size = size;
|
||||
+ }
|
||||
+
|
||||
+ ptr = strstr(buf,START);
|
||||
+ if (ptr) {
|
||||
+ State = Fetching;
|
||||
+ dynamic_cast<RsyncMethod*>(Owner)->Start(FRes);
|
||||
+ }
|
||||
+
|
||||
+ ptr = strstr(buf,DONE);
|
||||
+ if (ptr)
|
||||
+ State = Done;
|
||||
+
|
||||
+ ptr = strstr(buf,FAILED);
|
||||
+ if (ptr) {
|
||||
+ State = Failed;
|
||||
+ ptr += strlen(FAILED);
|
||||
+ const char *ptr2 = ptr;
|
||||
+ while (*ptr2!=0 && *ptr2!='\n')
|
||||
+ ++ptr2;
|
||||
+ if (ptr!=ptr2) {
|
||||
+ char *tmp = new char[ptr2-ptr+1];
|
||||
+ bzero(tmp, ptr2-ptr+1);
|
||||
+ strncpy(tmp, ptr, ptr2-ptr);
|
||||
+ _error->Error("%s",tmp);
|
||||
+ if (RsyncMethod::Debug)
|
||||
+ cerr << endl << FAILED << tmp << endl;
|
||||
+ delete tmp;
|
||||
+ } else {
|
||||
+ _error->Error("Child process failed (no description)");
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+bool RsyncMethod::RsyncConnExec::Get(pkgAcqMethod *Owner, FetchResult &FRes, const char *From, const char *To)
|
||||
+{
|
||||
+ int p[2];
|
||||
+ int res = 0;
|
||||
+ Argv argv(10);
|
||||
+
|
||||
+ State = Starting;
|
||||
+ if ( RsyncMethod::Debug )
|
||||
+ cerr << "RSYNC: Get: " << From << endl;
|
||||
+
|
||||
+ argv.add(program.c_str());
|
||||
+ argv.add("-Lpt");
|
||||
+ argv.add("--partial");
|
||||
+ AddOptions(argv);
|
||||
+ if (RsyncMethod::Timeout>0) {
|
||||
+ argv.add("--timeout");
|
||||
+ char S[10];
|
||||
+ sprintf(S,"%u",RsyncMethod::Timeout);
|
||||
+ argv.add(S);
|
||||
+ }
|
||||
+ // Add optional user-defined options to command line
|
||||
+ Configuration::Item const *Itm = _config->Tree("Acquire::rsync::options");
|
||||
+ if (Itm != 0 && Itm->Child != 0) {
|
||||
+ Itm = Itm->Child;
|
||||
+ while (Itm != 0) {
|
||||
+ if (Itm->Value.empty() == false)
|
||||
+ argv.add(Itm->Value.c_str());
|
||||
+ Itm = Itm->Next;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ char port[12];
|
||||
+ if (srv.Port!=0)
|
||||
+ snprintf(port, sizeof(port), ":%u", srv.Port);
|
||||
+ else port[0] = 0;
|
||||
+ argv.add( "rsync://" + srv.Host + port + From);
|
||||
+ argv.add(To);
|
||||
+
|
||||
+ if ( pipe(p) ) {
|
||||
+ _error->Error("RSYNC: RsyncConnExec: Can't create pipe");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if ( RsyncMethod::Debug )
|
||||
+ cerr << "RSYNC: Created pipe [" << p[0] << ',' << p[1] << ']' << endl;
|
||||
+ if ( RsyncMethod::Debug )
|
||||
+ cerr << "RSYNC: Starting: " << string(argv) << endl;
|
||||
+
|
||||
+ switch ( ChildPid = fork() ) {
|
||||
+ case -1:
|
||||
+ _error->Error("RsyncConnExec: Can't fork");
|
||||
+ return false;
|
||||
+ break;
|
||||
+ case 0:
|
||||
+ // Child process
|
||||
+ initProxy();
|
||||
+ //if ( RsyncMethod::Debug )
|
||||
+ // cerr << endl << "RSYNC_PROXY(" << srv.Host << "): " << getenv("RSYNC_PROXY") << endl;
|
||||
+ close(p[0]);
|
||||
+ res = dup2(p[1], STDOUT_FILENO);
|
||||
+ if (res==-1) {
|
||||
+ cout << "Failed: " << "Can't dup2(p[1], STDOUT_FILENO)" << endl;
|
||||
+ exit(100);
|
||||
+ }
|
||||
+ res = dup2(p[1], STDERR_FILENO);
|
||||
+ if (res==-1) {
|
||||
+ cout << "Failed: " << "Can't dup2(p[1], STDERR_FILENO)" << endl;
|
||||
+ exit(100);
|
||||
+ }
|
||||
+
|
||||
+ close(p[1]);
|
||||
+ execve(program.c_str(), argv, environ);
|
||||
+ cout << "Failed: " << "Can not execute " << program << endl;
|
||||
+ exit(100);
|
||||
+ break;
|
||||
+ default:
|
||||
+ // Parent process
|
||||
+ close(p[1]);
|
||||
+ ChildFd = p[0];
|
||||
+ return WaitChild(Owner,FRes,To);
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+// Parse output of rsync process with --apt-support option
|
||||
+void RsyncMethod::RsyncConnExecExt::ParseOutput(pkgAcqMethod *Owner, FetchResult &FRes, const char *buf)
|
||||
+{
|
||||
+ static const char * TMPFN = "Tmp-Filename: ";
|
||||
+ static const char * SIZE = "Size: ";
|
||||
+ static const char * START = "Start: ";
|
||||
+ static const char * DONE = "Done: ";
|
||||
+ static const char * FAILED= "Failed: ";
|
||||
+ const char * ptr;
|
||||
+
|
||||
+ //if ( RsyncMethod::Debug )
|
||||
+ // cerr << "ParseOutput: " << buf << endl;
|
||||
+
|
||||
+ ptr = strstr(buf,TMPFN);
|
||||
+ if (ptr) {
|
||||
+ ptr += strlen(TMPFN);
|
||||
+ const char *ptr2 = ptr;
|
||||
+ while (*ptr2!=0 && !isspace(*ptr2))
|
||||
+ ++ptr2;
|
||||
+ if (ptr!=ptr2) {
|
||||
+ char *tmpfn = new char[ptr2-ptr+1];
|
||||
+ bzero(tmpfn, ptr2-ptr+1);
|
||||
+ strncpy(tmpfn, ptr, ptr2-ptr);
|
||||
+ if (RsyncMethod::Debug)
|
||||
+ cerr << endl << "RSYNC: " << TMPFN << tmpfn << endl;
|
||||
+ FRes.TmpFilename = string(tmpfn);
|
||||
+ delete tmpfn;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ptr = strstr(buf,SIZE);
|
||||
+ if (ptr) {
|
||||
+ ptr += strlen(SIZE);
|
||||
+ unsigned long size = atol(ptr);
|
||||
+ if (RsyncMethod::Debug)
|
||||
+ cerr << "RSYNC: " << SIZE << size << endl;
|
||||
+ FRes.Size = size;
|
||||
+ }
|
||||
+
|
||||
+ ptr = strstr(buf,START);
|
||||
+ if (ptr) {
|
||||
+ State = Fetching;
|
||||
+ dynamic_cast<RsyncMethod*>(Owner)->Start(FRes);
|
||||
+ }
|
||||
+
|
||||
+ ptr = strstr(buf,DONE);
|
||||
+ if (ptr)
|
||||
+ State = Done;
|
||||
+
|
||||
+ ptr = strstr(buf,FAILED);
|
||||
+ if (ptr) {
|
||||
+ State = Failed;
|
||||
+ ptr += strlen(FAILED);
|
||||
+ const char *ptr2 = ptr;
|
||||
+ while (*ptr2!=0 && *ptr2!='\n')
|
||||
+ ++ptr2;
|
||||
+ if (ptr!=ptr2) {
|
||||
+ char *tmp = new char[ptr2-ptr+1];
|
||||
+ bzero(tmp, ptr2-ptr+1);
|
||||
+ strncpy(tmp, ptr, ptr2-ptr);
|
||||
+ _error->Error("%s",tmp);
|
||||
+ if (RsyncMethod::Debug)
|
||||
+ cerr << endl << FAILED << tmp << endl;
|
||||
+ delete tmp;
|
||||
+ } else {
|
||||
+ _error->Error("Child process failed (no description)");
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+// RsyncMethod::RsyncMethod - Constructor /*{{{*/
|
||||
+// ---------------------------------------------------------------------
|
||||
+/* */
|
||||
+RsyncMethod::RsyncMethod() : pkgAcqMethod("1.0",SendConfig),
|
||||
+ RsyncProg(RSYNC_PROGRAM)
|
||||
+{
|
||||
+ signal(SIGTERM,SigTerm);
|
||||
+ signal(SIGINT,SigTerm);
|
||||
+}
|
||||
+/*}}}*/
|
||||
+// RsyncMethod::SigTerm - Handle a fatal signal /*{{{*/
|
||||
+// ---------------------------------------------------------------------
|
||||
+/* Delete existing server connection */
|
||||
+void RsyncMethod::SigTerm(int)
|
||||
+{
|
||||
+ delete server;
|
||||
+ _exit(100);
|
||||
+}
|
||||
+/*}}}*/
|
||||
+// RsyncMethod::Configuration - Handle a configuration message /*{{{*/
|
||||
+// ---------------------------------------------------------------------
|
||||
+/* We stash the desired pipeline depth */
|
||||
+bool RsyncMethod::Configuration(string Message)
|
||||
+{
|
||||
+ if (pkgAcqMethod::Configuration(Message) == false)
|
||||
+ return false;
|
||||
+
|
||||
+ Debug = _config->FindB("Debug::rsync",false);
|
||||
+ Timeout = _config->FindI("Acquire::rsync::Timeout",0);
|
||||
+ RsyncProg = _config->Find("Acquire::rsync::program",RSYNC_PROGRAM);
|
||||
+ return true;
|
||||
+}
|
||||
+/*}}}*/
|
||||
+// RsyncMethod::Fetch - Fetch a file /*{{{*/
|
||||
+// ---------------------------------------------------------------------
|
||||
+/* Fetch a single file, called by the base class.. */
|
||||
+bool RsyncMethod::Fetch(FetchItem *Itm)
|
||||
+{
|
||||
+ URI Get = Itm->Uri;
|
||||
+ const char *File = Get.Path.c_str();
|
||||
+ FetchResult Res;
|
||||
+ Res.Filename = Itm->DestFile;
|
||||
+ Res.IMSHit = false;
|
||||
+
|
||||
+ struct stat st;
|
||||
+ if ( stat(Itm->DestFile.c_str(), &st)==0 ) {
|
||||
+ Res.ResumePoint = st.st_size;
|
||||
+ }
|
||||
+
|
||||
+ string proxy = _config->Find(string("Acquire::rsync::proxy::")+Get.Host);
|
||||
+ if ( proxy.empty() )
|
||||
+ proxy = _config->Find("Acquire::rsync::proxy");
|
||||
+
|
||||
+ if (Debug)
|
||||
+ cerr << endl << "RSYNC: Proxy(" << Get.Host << "): " << proxy << endl;
|
||||
+
|
||||
+ // Don't compare now for the same server uri
|
||||
+ delete server;
|
||||
+ if ( _config->FindB("Acquire::rsync::apt-support",true) )
|
||||
+ server = new RsyncConnExecExt(Get,proxy,RsyncProg);
|
||||
+ else
|
||||
+ server = new RsyncConnExec(Get,proxy,RsyncProg);
|
||||
+
|
||||
+ if ( server->Get(this,Res,File,Itm->DestFile.c_str()) ) {
|
||||
+ if ( stat(Itm->DestFile.c_str(), &st)==0 ) {
|
||||
+ Res.Size = st.st_size;
|
||||
+ // Calculating MD5
|
||||
+ //
|
||||
+ int fd = open(Itm->DestFile.c_str(), O_RDONLY);
|
||||
+ if (fd>=0) {
|
||||
+ MD5Summation md5;
|
||||
+ md5.AddFD(fd,st.st_size);
|
||||
+ Res.MD5Sum = md5.Result();
|
||||
+ close(fd);
|
||||
+ }
|
||||
+ }
|
||||
+ URIDone(Res);
|
||||
+ return true;
|
||||
+ }
|
||||
+ Fail(true);
|
||||
+ return false;
|
||||
+}
|
||||
+/*}}}*/
|
||||
+
|
||||
+int main(int argc,const char *argv[])
|
||||
+{
|
||||
+ RsyncMethod Mth;
|
||||
+
|
||||
+ return Mth.Run();
|
||||
+}
|
||||
Index: apt-rpm.rsync/methods/rsync-method.h
|
||||
===================================================================
|
||||
--- apt-rpm.rsync/methods/rsync-method.h (working copy)
|
||||
+++ apt-rpm.rsync/methods/rsync-method.h (working copy)
|
||||
@@ -0,0 +1,116 @@
|
||||
+// -*- mode: cpp; mode: fold -*-
|
||||
+// Description /*{{{*/
|
||||
+// $Id$
|
||||
+/* ######################################################################
|
||||
+
|
||||
+RSYNC Aquire Method - This is the RSYNC aquire method for APT.
|
||||
+
|
||||
+##################################################################### */
|
||||
+/*}}}*/
|
||||
+#ifndef APT_RSYNC_H
|
||||
+#define APT_RSYNC_H
|
||||
+
|
||||
+using namespace std;
|
||||
+
|
||||
+static const char * RSYNC_PROGRAM = "/usr/bin/rsync";
|
||||
+
|
||||
+class Argv
|
||||
+{
|
||||
+ int max_size;
|
||||
+ int size;
|
||||
+ char **args;
|
||||
+
|
||||
+ public:
|
||||
+ Argv(int msize);
|
||||
+ ~Argv();
|
||||
+
|
||||
+ bool add(const char *arg);
|
||||
+ bool add(const string &arg) { return add( arg.c_str()); }
|
||||
+ bool resize();
|
||||
+ int getSize() { return size; }
|
||||
+ operator char**() { return args; }
|
||||
+ operator string();
|
||||
+};
|
||||
+
|
||||
+
|
||||
+class RsyncMethod : public pkgAcqMethod
|
||||
+{
|
||||
+ protected:
|
||||
+ enum ConnType {ConnTypeExec, ConnTypeExecExt, ConnTypeProto};
|
||||
+
|
||||
+ class RsyncConn
|
||||
+ {
|
||||
+ public:
|
||||
+ enum ConnState {Idle,Starting,Connecting,Fetching,Failed,Done};
|
||||
+
|
||||
+ protected:
|
||||
+ URI srv;
|
||||
+ const string proxy;
|
||||
+ ConnState State;
|
||||
+
|
||||
+ static char proxy_value[1024];
|
||||
+ bool initProxy();
|
||||
+
|
||||
+ public:
|
||||
+ RsyncConn(URI u, const string &_proxy = ""): srv(u), proxy(_proxy) {}
|
||||
+ virtual ~RsyncConn() {}
|
||||
+
|
||||
+ virtual bool Get(pkgAcqMethod *Owner, FetchResult &FRes, const char *From, const char *To) = 0;
|
||||
+ };
|
||||
+
|
||||
+ class RsyncConnExec: public RsyncConn
|
||||
+ {
|
||||
+ // pid of child process
|
||||
+ pid_t ChildPid;
|
||||
+ // output of child process (stdout&stderr)
|
||||
+ int ChildFd;
|
||||
+ // Program to execute
|
||||
+ string program;
|
||||
+
|
||||
+ protected:
|
||||
+ bool WaitChild(pkgAcqMethod *Owner, FetchResult &FRes, const char *To);
|
||||
+ virtual void ParseOutput(pkgAcqMethod *Owner, FetchResult &FRes, const char *buf);
|
||||
+ virtual void AddOptions(Argv &argv)
|
||||
+ { argv.add("-vvvv"); };
|
||||
+
|
||||
+ public:
|
||||
+ RsyncConnExec(URI u, const string &_proxy, const string &prog);
|
||||
+ virtual ~RsyncConnExec();
|
||||
+
|
||||
+ virtual bool Get(pkgAcqMethod *Owner, FetchResult &FRes, const char *From, const char *To);
|
||||
+ };
|
||||
+
|
||||
+ class RsyncConnExecExt: public RsyncConnExec
|
||||
+ {
|
||||
+ protected:
|
||||
+ virtual void ParseOutput(pkgAcqMethod *Owner, FetchResult &FRes, const char *buf);
|
||||
+ virtual void AddOptions(Argv &argv)
|
||||
+ { argv.add("--apt-support"); };
|
||||
+
|
||||
+ public:
|
||||
+ RsyncConnExecExt(URI u, const string &_proxy, const string &prog):
|
||||
+ RsyncConnExec(u, _proxy, prog) {};
|
||||
+ };
|
||||
+
|
||||
+ static RsyncConn *server;
|
||||
+ static ConnType connType;
|
||||
+ static bool Debug;
|
||||
+ static unsigned int Timeout;
|
||||
+
|
||||
+ string RsyncProg;
|
||||
+
|
||||
+ static void SigTerm(int);
|
||||
+
|
||||
+ protected:
|
||||
+ virtual bool Fetch(FetchItem *Itm);
|
||||
+ virtual bool Configuration(string Message);
|
||||
+
|
||||
+ void Start(FetchResult &FRes)
|
||||
+ { URIStart(FRes); }
|
||||
+
|
||||
+ public:
|
||||
+
|
||||
+ RsyncMethod();
|
||||
+};
|
||||
+
|
||||
+#endif
|
||||
Index: apt-rpm.rsync/methods/Makefile.am
|
||||
===================================================================
|
||||
--- apt-rpm.rsync/methods/Makefile.am (revision 137)
|
||||
+++ apt-rpm.rsync/methods/Makefile.am (working copy)
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
methodsdir=${libdir}/apt/methods
|
||||
-methods_PROGRAMS = cdrom copy file ftp gpg gzip bzip2 http rsh ssh
|
||||
+methods_PROGRAMS = cdrom copy file ftp gpg gzip bzip2 http rsh ssh rsync
|
||||
|
||||
LDADD = ../apt-pkg/libapt-pkg.la
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
bzip2_SOURCES = $(gzip_SOURCES)
|
||||
rsh_SOURCES = rsh.cc rsh.h
|
||||
ssh_SOURCES = $(rsh_SOURCES)
|
||||
+rsync_SOURCES = rsync.cc rsync-method.h
|
||||
|
||||
http_SOURCES = \
|
||||
http.cc \
|
@ -61,6 +61,9 @@ class pkgAcquire::Item
|
||||
|
||||
// File to write the fetch into
|
||||
string DestFile;
|
||||
// Alternative temporary destination
|
||||
// Used if method (e.g. rsync) can't use directly DestFile
|
||||
string TmpFile;
|
||||
|
||||
// Action members invoked by the worker
|
||||
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
|
||||
|
@ -152,6 +152,9 @@ void pkgAcqMethod::URIStart(FetchResult &Res)
|
||||
if (Res.ResumePoint != 0)
|
||||
s << "Resume-Point: " << Res.ResumePoint << "\n";
|
||||
|
||||
if (Res.TmpFilename.size() != 0)
|
||||
s << "Tmp-Filename: " << Res.TmpFilename << "\n";
|
||||
|
||||
s << "\n";
|
||||
string S = s.str();
|
||||
if (write(STDOUT_FILENO,S.c_str(),S.size()) != (ssize_t)S.size())
|
||||
|
@ -47,6 +47,7 @@ class pkgAcqMethod
|
||||
time_t LastModified;
|
||||
bool IMSHit;
|
||||
string Filename;
|
||||
string TmpFilename;
|
||||
unsigned long Size;
|
||||
unsigned long ResumePoint;
|
||||
|
||||
|
@ -269,6 +269,7 @@ bool pkgAcquire::Worker::RunMessages()
|
||||
CurrentSize = 0;
|
||||
TotalSize = atoi(LookupTag(Message,"Size","0").c_str());
|
||||
ResumePoint = atoi(LookupTag(Message,"Resume-Point","0").c_str());
|
||||
Itm->Owner->TmpFile = LookupTag(Message,"Tmp-Filename");
|
||||
Itm->Owner->Start(Message,atoi(LookupTag(Message,"Size","0").c_str()));
|
||||
|
||||
// Display update before completion
|
||||
@ -597,7 +598,11 @@ void pkgAcquire::Worker::Pulse()
|
||||
return;
|
||||
|
||||
struct stat Buf;
|
||||
if (stat(CurrentItem->Owner->DestFile.c_str(),&Buf) != 0)
|
||||
int res = 1;
|
||||
if (CurrentItem->Owner->TmpFile.empty()==false)
|
||||
res = stat(CurrentItem->Owner->TmpFile.c_str(),&Buf);
|
||||
|
||||
if (res!=0 && stat(CurrentItem->Owner->DestFile.c_str(),&Buf) != 0)
|
||||
return;
|
||||
CurrentSize = Buf.st_size;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
methodsdir=${libdir}/apt/methods
|
||||
methods_PROGRAMS = cdrom copy file ftp gpg gzip bzip2 http rsh ssh
|
||||
methods_PROGRAMS = cdrom copy file ftp gpg gzip bzip2 http rsh ssh rsync
|
||||
|
||||
LDADD = ../apt-pkg/libapt-pkg.la
|
||||
|
||||
@ -12,6 +12,7 @@ gzip_SOURCES = gzip.cc
|
||||
bzip2_SOURCES = $(gzip_SOURCES)
|
||||
rsh_SOURCES = rsh.cc rsh.h
|
||||
ssh_SOURCES = $(rsh_SOURCES)
|
||||
rsync_SOURCES = rsync.cc rsync-method.h
|
||||
|
||||
http_SOURCES = \
|
||||
http.cc \
|
||||
|
Loading…
Reference in New Issue
Block a user