apt/apt-0.5.4cnc9-alt-rsync.patch
Dmitry V. Levin 3212342525 0.5.5cnc1-alt3
- Introduced APT::Ignore-dpkg support and set this flag by default,
  to address #0002119.
2003-02-13 13:28:59 +00:00

667 lines
18 KiB
Diff

diff -urN -X apt.excludes apt-0.5.4cnc9.orig/apt-pkg/acquire-item.h apt-0.5.4cnc9.rsync/apt-pkg/acquire-item.h
--- apt-0.5.4cnc9.orig/apt-pkg/acquire-item.h 2002-07-23 21:54:50 +0400
+++ apt-0.5.4cnc9.rsync/apt-pkg/acquire-item.h 2002-12-17 11:34:33 +0300
@@ -59,6 +59,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);
diff -urN -X apt.excludes apt-0.5.4cnc9.orig/apt-pkg/acquire-method.cc apt-0.5.4cnc9.rsync/apt-pkg/acquire-method.cc
--- apt-0.5.4cnc9.orig/apt-pkg/acquire-method.cc 2002-07-23 21:54:50 +0400
+++ apt-0.5.4cnc9.rsync/apt-pkg/acquire-method.cc 2002-12-17 11:34:33 +0300
@@ -135,7 +135,7 @@
if (Queue == 0)
abort();
- char S[1024] = "";
+ char S[2048] = "";
char *End = S;
End += snprintf(S,sizeof(S),"200 URI Start\nURI: %s\n",Queue->Uri.c_str());
@@ -150,6 +150,10 @@
End += snprintf(End,sizeof(S)-4 - (End - S),"Resume-Point: %lu\n",
Res.ResumePoint);
+ if (!Res.TmpFilename.empty())
+ End += snprintf(End,sizeof(S)-4 - (End - S),"Tmp-Filename: %s\n",
+ Res.TmpFilename.c_str());
+
strcat(End,"\n");
if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
exit(100);
diff -urN -X apt.excludes apt-0.5.4cnc9.orig/apt-pkg/acquire-method.h apt-0.5.4cnc9.rsync/apt-pkg/acquire-method.h
--- apt-0.5.4cnc9.orig/apt-pkg/acquire-method.h 2002-07-23 21:54:50 +0400
+++ apt-0.5.4cnc9.rsync/apt-pkg/acquire-method.h 2002-12-17 11:34:33 +0300
@@ -47,6 +47,7 @@
time_t LastModified;
bool IMSHit;
string Filename;
+ string TmpFilename;
unsigned long Size;
unsigned long ResumePoint;
diff -urN -X apt.excludes apt-0.5.4cnc9.orig/apt-pkg/acquire-worker.cc apt-0.5.4cnc9.rsync/apt-pkg/acquire-worker.cc
--- apt-0.5.4cnc9.orig/apt-pkg/acquire-worker.cc 2002-07-23 21:54:50 +0400
+++ apt-0.5.4cnc9.rsync/apt-pkg/acquire-worker.cc 2002-12-17 11:34:33 +0300
@@ -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;
diff -urN -X apt.excludes apt-0.5.4cnc9.orig/methods/makefile apt-0.5.4cnc9.rsync/methods/makefile
--- apt-0.5.4cnc9.orig/methods/makefile 2002-07-25 22:07:19 +0400
+++ apt-0.5.4cnc9.rsync/methods/makefile 2002-12-17 11:34:33 +0300
@@ -63,6 +63,13 @@
SOURCE = gpg.cc
include $(PROGRAM_H)
+# The rsync method
+PROGRAM=rsync
+SLIBS = -lapt-pkg $(SOCKETLIBS) $(RPMLIBS)
+LIB_MAKES = apt-pkg/makefile
+SOURCE = rsync.cc
+include $(PROGRAM_H)
+
# SSH and vzip2 method symlink
all: $(BIN)/ssh $(BIN)/bzip2
veryclean: clean-$(BIN)/ssh clean-$(BIN)/bzip2
diff -urN -X apt.excludes apt-0.5.4cnc9.orig/methods/rsync.cc apt-0.5.4cnc9.rsync/methods/rsync.cc
--- apt-0.5.4cnc9.orig/methods/rsync.cc 1970-01-01 03:00:00 +0300
+++ apt-0.5.4cnc9.rsync/methods/rsync.cc 2002-12-17 13:25:56 +0300
@@ -0,0 +1,468 @@
+// -*- 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 "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;
+}
+
+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 = "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)");
+ }
+ }
+}
+
+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");
+ argv.add("--apt-support");
+ 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;
+}
+
+// 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;
+ 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();
+}
diff -urN -X apt.excludes apt-0.5.4cnc9.orig/methods/rsync-method.h apt-0.5.4cnc9.rsync/methods/rsync-method.h
--- apt-0.5.4cnc9.orig/methods/rsync-method.h 1970-01-01 03:00:00 +0300
+++ apt-0.5.4cnc9.rsync/methods/rsync-method.h 2002-12-17 11:34:33 +0300
@@ -0,0 +1,102 @@
+// -*- 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, 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);
+ void ParseOutput(pkgAcqMethod *Owner, FetchResult &FRes, const char *buf);
+
+ 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);
+ };
+
+ 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