Browse Source

Sync
Author: jgg
Date: 1998-10-30 07:53:30 GMT
Sync

Arch Librarian 22 years ago
parent
commit
93bf083d69

+ 36 - 0
AUTHORS

@@ -0,0 +1,36 @@
+NOTE: The ChangeLog generator will parse for names and email addresses. The
+'CVS:<name>' tag should indicate who this pair refers to.
+
+The project hierachy stands at:
+
+CVS:bcwhite Brian White <bcwhite@verisim.com>
+- Project Leader
+- General organization, dispute resolution, final say on "capabilities"
+
+CVS:jgg Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>
+- Chief Programmer      
+- Code organization, task breakdown, final say on "code"
+
+CVS:tom Tom Lees <tom@lpsg.demon.co.uk>
+- Dpkg Consultant
+- Make system
+- Expert on compatibility with existing dpkg, dependency algorithms, etc.
+
+CVS:srivasta Manoj Srivastava <srivasta@datasync.com>
+- Dependency Expert
+
+CVS:behanw Behan Webster <behanw@verisim.com>
+- Chief Designer     
+- Screen layout, ease of use, final say on "user interface"
+
+CVS:che Ben Gertzfield <che@debian.org>
+- Documentation
+
+CVS:branden Branden Robinson <branden@purdue.edu>
+- Man Page Documentation
+
+CVS:scott Scott Ellis <storm@gate.net>
+- .deb archive creater
+
+CVS:doogie Adam Heath <doogie@debian.org>
+- FTP method author

+ 14 - 0
Makefile

@@ -2,7 +2,9 @@
 
 
 # This is the top level make file for APT, it recurses to each lower
 # This is the top level make file for APT, it recurses to each lower
 # level make file and runs it with the proper target
 # level make file and runs it with the proper target
+ifndef NOISY
 .SILENT:
 .SILENT:
+endif
 
 
 .PHONY: headers library clean veryclean all binary program doc
 .PHONY: headers library clean veryclean all binary program doc
 all headers library clean veryclean binary program doc:
 all headers library clean veryclean binary program doc:
@@ -15,3 +17,15 @@ all headers library clean veryclean binary program doc:
 
 
 .PHONY: maintainer-clean dist-clean distclean pristine sanity 
 .PHONY: maintainer-clean dist-clean distclean pristine sanity 
 maintainer-clean dist-clean distclean pristine sanity: veryclean
 maintainer-clean dist-clean distclean pristine sanity: veryclean
+
+
+# The startup target builds the necessary configure scripts. It should
+# be used after a CVS checkout.
+.PHONY: startup
+startup: configure
+
+configure: aclocal.m4 configure.in
+	autoconf	
+
+aclocal.m4:
+	aclocal -I buildlib

+ 36 - 2
README.make

@@ -58,10 +58,16 @@ the source directory but is logically divided in the following manner
 Only .o and .d files are placed in the obj/ subdirectory. The final compiled
 Only .o and .d files are placed in the obj/ subdirectory. The final compiled
 binaries are placed in bin, published headers for inter-component linking
 binaries are placed in bin, published headers for inter-component linking
 are placed in include/ and documentation is generated into doc/. This means
 are placed in include/ and documentation is generated into doc/. This means
-all runnable programs are within the bin/ directory a huge benifit for
+all runnable programs are within the bin/ directory, a huge benifit for
 debugging inter-program relationships. The .so files are also placed in
 debugging inter-program relationships. The .so files are also placed in
 bin/ for simplicity.
 bin/ for simplicity.
 
 
+By default make is put into silent mode. During operation there should be
+no shell or compiler messages only status messages from the makefiles, 
+if any pop up that indicates there may be a problem with your environment.
+For debugging you can disable this by setting NOISY=1, ala
+   make NOISY=1
+
 Using the makefiles
 Using the makefiles
 ~~~~~ ~~~ ~~~~~~~~~
 ~~~~~ ~~~ ~~~~~~~~~
 The makefiles for the components are really simple. The complexity is hidden
 The makefiles for the components are really simple. The complexity is hidden
@@ -76,4 +82,32 @@ directories and other interesting features. They are more completely
 described in the fragment code in buildlib. Some tips on writing fragments
 described in the fragment code in buildlib. Some tips on writing fragments
 are included in buildlib/defaults.mak
 are included in buildlib/defaults.mak
 
 
-Jason
+The fragments are NEVER processed by configure, so if you make changes to 
+them they will have an immediate effect.
+
+Autoconf
+~~~~~~~~
+Straight out of CVS you have to initialize autoconf. This requires 
+automake (I really don't know why) and autoconf and requires doing 
+  aclocal -I buidlib
+  autoconf
+
+Autoconf is configured to do some basic system probes for optional and 
+required functionality and generate an environment.mak and include/config.h 
+from it's findings. It will then write a 'makefile' and run make dirs to 
+create the output directory tree.
+
+It is not my belief that autoconf should be used to generate substantial 
+source code markup to escape OS problems. If an OS problem does crop up 
+it can likely be corrected by installing the correct files into the 
+build include/ dir and perhaps writing some replacement code and 
+linking it in. To the fullest extent possible the source code should conform
+to standards and not cater to broken systems.
+
+Autoconf will also wite a makefile into the top level of the build dir, 
+this simply acts as a wrapper to the main top level make in the source tree.
+There is one big warning, you can't use both this make file and the
+ones in the top level tree. Make is not able to resolve rules that 
+go to the same file through different paths and this will confuse the
+depends mechanism. I recommend always using the makefiles in the
+source directory and exporting BUILD

+ 8 - 4
apt-pkg/acquire-item.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: acquire-item.cc,v 1.5 1998/10/26 07:11:43 jgg Exp $
+// $Id: acquire-item.cc,v 1.6 1998/10/30 07:53:34 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    Acquire Item - Item to acquire
    Acquire Item - Item to acquire
@@ -46,13 +46,17 @@ pkgAcquire::Item::~Item()
 									/*}}}*/
 									/*}}}*/
 // Acquire::Item::Failed - Item failed to download			/*{{{*/
 // Acquire::Item::Failed - Item failed to download			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* */
+/* We return to an idle state if there are still other queues that could
+   fetch this object */
 void pkgAcquire::Item::Failed(string Message)
 void pkgAcquire::Item::Failed(string Message)
 {
 {
-   Status = StatError;
-   ErrorText = LookupTag(Message,"Message");
+   Status = StatIdle;
    if (QueueCounter <= 1)
    if (QueueCounter <= 1)
+   {
+      ErrorText = LookupTag(Message,"Message");
+      Status = StatError;
       Owner->Dequeue(this);
       Owner->Dequeue(this);
+   }   
 }
 }
 									/*}}}*/
 									/*}}}*/
 // Acquire::Item::Done - Item downloaded OK				/*{{{*/
 // Acquire::Item::Done - Item downloaded OK				/*{{{*/

+ 245 - 0
apt-pkg/acquire-method.cc

@@ -0,0 +1,245 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: acquire-method.cc,v 1.1 1998/10/30 07:53:35 jgg Exp $
+/* ######################################################################
+
+   Acquire Method
+
+   ##################################################################### */
+									/*}}}*/
+// Include Files							/*{{{*/
+#ifdef __GNUG__
+#pragma implementation "apt-pkg/acquire-method.h"
+#endif
+#include <apt-pkg/acquire-method.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/configuration.h>
+#include <strutl.h>
+#include <apt-pkg/fileutl.h>
+
+#include <stdio.h>
+									/*}}}*/
+
+// AcqMethod::pkgAcqMethod - Constructor				/*{{{*/
+// ---------------------------------------------------------------------
+/* This constructs the initialization text */
+pkgAcqMethod::pkgAcqMethod(const char *Ver,unsigned long Flags)
+{
+   char S[300] = "";
+   char *End = S;
+   strcat(End,"100 Capabilities\n");
+   sprintf(End+strlen(End),"Version: %s\n",Ver);
+
+   if ((Flags & SingleInstance) == SingleInstance)
+      strcat(End,"Single-Instance: true\n");
+   
+   if ((Flags & PreScan) == PreScan)
+      strcat(End,"Pre-Scan: true\n");
+   
+   if ((Flags & Pipeline) == Pipeline)
+      strcat(End,"Pipeline: true\n");
+   
+   if ((Flags & SendConfig) == SendConfig)
+      strcat(End,"Send-Config: true\n");
+   strcat(End,"\n");
+
+   if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
+      exit(100);
+}
+									/*}}}*/
+// AcqMethod::Fail - A fetch has failed					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqMethod::Fail()
+{
+   string Err = "Undetermined Error";
+   if (_error->empty() == false)
+      _error->PopMessage(Err);   
+   _error->Discard();
+   Fail(Err);
+}
+									/*}}}*/
+// AcqMethod::Fail - A fetch has failed					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqMethod::Fail(string Err)
+{   
+   char S[1024];
+   snprintf(S,sizeof(S),"400 URI Failure\nURI: %s\n"
+	    "Message %s\n\n",CurrentURI.c_str(),Err.c_str());
+
+   if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
+      exit(100);
+}
+									/*}}}*/
+// AcqMethod::URIStart - Indicate a download is starting		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqMethod::URIStart(FetchResult &Res,unsigned long Resume = 0)
+{
+   char S[1024] = "";
+   char *End = S;
+   
+   End += snprintf(S,sizeof(S),"200 URI Start\nURI: %s\n",CurrentURI.c_str());
+   if (Res.Size != 0)
+      End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
+   
+   if (Res.LastModified != 0)
+      End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
+		      TimeRFC1123(Res.LastModified).c_str());
+   
+   if (Resume != 0)
+      End += snprintf(End,sizeof(S) - (End - S),"Resume-Point: %u\n",
+		      Resume);
+      
+   strcat(End,"\n");
+   if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
+      exit(100);
+}
+									/*}}}*/
+// AcqMethod::URIDone - A URI is finished				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
+{
+   char S[1024] = "";
+   char *End = S;
+   
+   End += snprintf(S,sizeof(S),"201 URI Done\nURI: %s\n",CurrentURI.c_str());
+
+   if (Res.Filename.empty() == false)
+      End += snprintf(End,sizeof(S) - (End - S),"Filename: %s\n",Res.Filename.c_str());
+   
+   if (Res.Size != 0)
+      End += snprintf(End,sizeof(S) - (End - S),"Size: %u\n",Res.Size);
+   
+   if (Res.LastModified != 0)
+      End += snprintf(End,sizeof(S) - (End - S),"Last-Modified: %s\n",
+		      TimeRFC1123(Res.LastModified).c_str());
+
+   if (Res.MD5Sum.empty() == false)
+      End += snprintf(End,sizeof(S) - (End - S),"MD5Sum: %s\n",Res.MD5Sum.c_str());
+
+   if (Res.IMSHit == true)
+      strcat(End,"IMS-Hit: true\n");
+   End = S + strlen(S);
+   
+   if (Alt != 0)
+   {
+      if (Alt->Filename.empty() == false)
+	 End += snprintf(End,sizeof(S) - (End - S),"Alt-Filename: %s\n",Alt->Filename.c_str());
+      
+      if (Alt->Size != 0)
+	 End += snprintf(End,sizeof(S) - (End - S),"Alt-Size: %u\n",Alt->Size);
+      
+      if (Alt->LastModified != 0)
+	 End += snprintf(End,sizeof(S) - (End - S),"Alt-Last-Modified: %s\n",
+			 TimeRFC1123(Alt->LastModified).c_str());
+      
+      if (Alt->MD5Sum.empty() == false)
+	 End += snprintf(End,sizeof(S) - (End - S),"Alt-MD5Sum: %s\n",
+			 Alt->MD5Sum.c_str());
+      
+      if (Alt->IMSHit == true)
+	 strcat(End,"Alt-IMS-Hit: true\n");
+   }
+   
+   strcat(End,"\n");
+   if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
+      exit(100);
+}
+									/*}}}*/
+// AcqMethod::Configuration - Handle the configuration message		/*{{{*/
+// ---------------------------------------------------------------------
+/* This parses each configuration entry and puts it into the _config 
+   Configuration class. */
+bool pkgAcqMethod::Configuration(string Message)
+{
+   ::Configuration &Cnf = *_config;
+   
+   const char *I = Message.begin();
+   
+   unsigned int Length = strlen("Config-Item");
+   for (; I + Length < Message.end(); I++)
+   {
+      // Not a config item
+      if (I[Length] != ':' || stringcasecmp(I,I+Length,"Config-Item") != 0)
+	 continue;
+      
+      I += Length + 1;
+      
+      for (; I < Message.end() && *I == ' '; I++);
+      const char *Equals = I;
+      for (; Equals < Message.end() && *Equals != '='; Equals++);
+      const char *End = Equals;
+      for (; End < Message.end() && *End != '\n'; End++);
+      if (End == Equals)
+	 return false;
+      
+      Cnf.Set(string(I,Equals-I),string(Equals+1,End-Equals-1));
+      I = End;
+   }
+   
+   return true;
+}
+									/*}}}*/
+// AcqMethod::Run - Run the message engine				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+int pkgAcqMethod::Run()
+{
+   SetNonBlock(STDIN_FILENO,true);
+
+   while (1)
+   {
+      if (Messages.empty() == true)
+	 if (WaitFd(STDIN_FILENO) == false)
+	    return 0;
+      
+      if (ReadMessages(STDIN_FILENO,Messages) == false)
+	 return 0;
+	 
+      string Message = Messages.front();
+      Messages.erase(Messages.begin());
+      
+      // Fetch the message number
+      char *End;
+      int Number = strtol(Message.c_str(),&End,10);
+      if (End == Message.c_str())
+      {	 
+	 cerr << "Malformed message!" << endl;
+	 return 100;
+      }
+
+      switch (Number)
+      {
+	 case 601:
+	 if (Configuration(Message) == false)
+	    return 100;
+	 break;
+	 
+	 case 600:
+	 {	    
+	    CurrentURI = LookupTag(Message,"URI");
+	    DestFile = LookupTag(Message,"FileName");
+	    StrToTime(LookupTag(Message,"Last-Modified"),LastModified);
+		      
+	    if (Fetch(Message,CurrentURI) == false)
+	       Fail();
+	    break;					     
+	 }   
+      }      
+   }
+
+   return 0;
+}
+									/*}}}*/
+// AcqMethod::FetchResult::FetchResult - Constructor			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgAcqMethod::FetchResult::FetchResult() : LastModified(0), 
+                                   IMSHit(false), Size(0)
+{
+}
+									/*}}}*/
+

+ 65 - 0
apt-pkg/acquire-method.h

@@ -0,0 +1,65 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: acquire-method.h,v 1.1 1998/10/30 07:53:35 jgg Exp $
+/* ######################################################################
+
+   Acquire Method - Method helper class + functions
+   
+   These functions are designed to be used within the method task to
+   ease communication with APT.
+   
+   ##################################################################### */
+									/*}}}*/
+#ifndef PKGLIB_ACQUIRE_METHOD_H
+#define PKGLIB_ACQUIRE_METHOD_H
+
+#include <apt-pkg/configuration.h>
+#include <strutl.h>
+
+#ifdef __GNUG__
+#pragma interface "apt-pkg/acquire-method.h"
+#endif 
+
+class pkgAcqMethod
+{
+   protected:
+   
+   string CurrentURI;
+   string DestFile;
+   time_t LastModified;
+
+   vector<string> Messages;
+   
+   struct FetchResult
+   {
+      string MD5Sum;
+      time_t LastModified;
+      bool IMSHit;
+      string Filename;
+      unsigned long Size;
+      FetchResult();
+   };
+   
+   // Handlers for messages
+   virtual bool Configuration(string Message);
+   virtual bool Fetch(string Message,URI Get) {return true;};
+   
+   // Outgoing messages
+   void Fail();
+   void Fail(string Why);
+//   void Log(const char *Format,...);
+   void URIStart(FetchResult &Res,unsigned long Resume = 0);
+   void URIDone(FetchResult &Res,FetchResult *Alt = 0);
+		 
+   public:
+   
+   enum CnfFlags {SingleInstance = (1<<0), PreScan = (1<<1), 
+                  Pipeline = (1<<2), SendConfig = (1<<3)};
+
+   int Run();
+   
+   pkgAcqMethod(const char *Ver,unsigned long Flags = 0);
+   virtual ~pkgAcqMethod() {};
+};
+
+#endif

+ 4 - 36
apt-pkg/acquire-worker.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: acquire-worker.cc,v 1.7 1998/10/26 07:11:45 jgg Exp $
+// $Id: acquire-worker.cc,v 1.8 1998/10/30 07:53:35 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    Acquire Worker 
    Acquire Worker 
@@ -218,7 +218,7 @@ bool pkgAcquire::Worker::RunMessages()
 	 {
 	 {
 	    if (Itm == 0)
 	    if (Itm == 0)
 	    {
 	    {
-	       _error->Warning("Method gave invalid 200 URI Start message");
+	       _error->Error("Method gave invalid 200 URI Start message");
 	       break;
 	       break;
 	    }
 	    }
 	    CurrentItem = Itm;
 	    CurrentItem = Itm;
@@ -233,7 +233,7 @@ bool pkgAcquire::Worker::RunMessages()
 	 {
 	 {
 	    if (Itm == 0)
 	    if (Itm == 0)
 	    {
 	    {
-	       _error->Warning("Method gave invalid 400 URI Failure message");
+	       _error->Error("Method gave invalid 201 URI Done message");
 	       break;
 	       break;
 	    }
 	    }
 
 
@@ -248,7 +248,7 @@ bool pkgAcquire::Worker::RunMessages()
 	 {
 	 {
 	    if (Itm == 0)
 	    if (Itm == 0)
 	    {
 	    {
-	       _error->Warning("Method gave invalid 400 URI Failure message");
+	       _error->Error("Method gave invalid 400 URI Failure message");
 	       break;
 	       break;
 	    }
 	    }
 
 
@@ -417,35 +417,3 @@ bool pkgAcquire::Worker::MethodFailure()
    return false;
    return false;
 }
 }
 									/*}}}*/
 									/*}}}*/
-
-// InjectConfiguration - Configuration aid for methods			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool pkgInjectConfiguration(string &Message,Configuration &Cnf)
-{
-   const char *I = Message.begin();
-   
-   unsigned int Length = strlen("Config-Item");
-   for (; I + Length < Message.end(); I++)
-   {
-      // Not a config item
-      if (I[Length] != ':' || stringcasecmp(I,I+Length,"Config-Item") != 0)
-	 continue;
-      
-      I += Length + 1;
-      
-      for (; I < Message.end() && *I == ' '; I++);
-      const char *Equals = I;
-      for (; Equals < Message.end() && *Equals != '='; Equals++);
-      const char *End = Equals;
-      for (; End < Message.end() && *End != '\n'; End++);
-      if (End == Equals)
-	 return false;
-      
-      Cnf.Set(string(I,Equals-I),string(Equals+1,End-Equals-1));
-      I = End;
-   }
-   
-   return true;
-}
-									/*}}}*/

+ 1 - 4
apt-pkg/acquire-worker.h

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: acquire-worker.h,v 1.5 1998/10/26 07:11:46 jgg Exp $
+// $Id: acquire-worker.h,v 1.6 1998/10/30 07:53:36 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    Acquire Worker - Worker process manager
    Acquire Worker - Worker process manager
@@ -13,7 +13,6 @@
 #define PKGLIB_ACQUIRE_WORKER_H
 #define PKGLIB_ACQUIRE_WORKER_H
 
 
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire.h>
-#include <apt-pkg/configuration.h>
 
 
 #ifdef __GNUG__
 #ifdef __GNUG__
 #pragma interface "apt-pkg/acquire-worker.h"
 #pragma interface "apt-pkg/acquire-worker.h"
@@ -81,6 +80,4 @@ class pkgAcquire::Worker
    ~Worker();
    ~Worker();
 };
 };
 
 
-bool pkgInjectConfiguration(string &Message,Configuration &Cnf);
-
 #endif
 #endif

+ 87 - 38
apt-pkg/acquire.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: acquire.cc,v 1.5 1998/10/26 07:11:47 jgg Exp $
+// $Id: acquire.cc,v 1.6 1998/10/30 07:53:37 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    Acquire - File Acquiration
    Acquire - File Acquiration
@@ -26,7 +26,7 @@
 
 
 // Acquire::pkgAcquire - Constructor					/*{{{*/
 // Acquire::pkgAcquire - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* */
+/* We grab some runtime state from the configuration space */
 pkgAcquire::pkgAcquire()
 pkgAcquire::pkgAcquire()
 {
 {
    Queues = 0;
    Queues = 0;
@@ -46,7 +46,7 @@ pkgAcquire::pkgAcquire()
 									/*}}}*/
 									/*}}}*/
 // Acquire::~pkgAcquire	- Destructor					/*{{{*/
 // Acquire::~pkgAcquire	- Destructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* Free our memory */
+/* Free our memory, clean up the queues (destroy the workers) */
 pkgAcquire::~pkgAcquire()
 pkgAcquire::~pkgAcquire()
 {
 {
    while (Items.size() != 0)
    while (Items.size() != 0)
@@ -69,7 +69,8 @@ pkgAcquire::~pkgAcquire()
 									/*}}}*/
 									/*}}}*/
 // Acquire::Add - Add a new item					/*{{{*/
 // Acquire::Add - Add a new item					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* */
+/* This puts an item on the acquire list. This list is mainly for tracking
+   item status */
 void pkgAcquire::Add(Item *Itm)
 void pkgAcquire::Add(Item *Itm)
 {
 {
    Items.push_back(Itm);
    Items.push_back(Itm);
@@ -77,7 +78,7 @@ void pkgAcquire::Add(Item *Itm)
 									/*}}}*/
 									/*}}}*/
 // Acquire::Remove - Remove a item					/*{{{*/
 // Acquire::Remove - Remove a item					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* */
+/* Remove an item from the acquire list. This is usually not used.. */
 void pkgAcquire::Remove(Item *Itm)
 void pkgAcquire::Remove(Item *Itm)
 {
 {
    for (vector<Item *>::iterator I = Items.begin(); I < Items.end(); I++)
    for (vector<Item *>::iterator I = Items.begin(); I < Items.end(); I++)
@@ -89,7 +90,8 @@ void pkgAcquire::Remove(Item *Itm)
 									/*}}}*/
 									/*}}}*/
 // Acquire::Add - Add a worker						/*{{{*/
 // Acquire::Add - Add a worker						/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* */
+/* A list of workers is kept so that the select loop can direct their FD
+   usage. */
 void pkgAcquire::Add(Worker *Work)
 void pkgAcquire::Add(Worker *Work)
 {
 {
    Work->NextAcquire = Workers;
    Work->NextAcquire = Workers;
@@ -98,9 +100,14 @@ void pkgAcquire::Add(Worker *Work)
 									/*}}}*/
 									/*}}}*/
 // Acquire::Remove - Remove a worker					/*{{{*/
 // Acquire::Remove - Remove a worker					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* */
+/* A worker has died. This can not be done while the select loop is running
+   as it would require that RunFds could handling a changing list state and
+   it cant.. */
 void pkgAcquire::Remove(Worker *Work)
 void pkgAcquire::Remove(Worker *Work)
 {
 {
+   if (Running == true)
+      abort();
+   
    Worker **I = &Workers;
    Worker **I = &Workers;
    for (; *I != 0;)
    for (; *I != 0;)
    {
    {
@@ -113,7 +120,10 @@ void pkgAcquire::Remove(Worker *Work)
 									/*}}}*/
 									/*}}}*/
 // Acquire::Enqueue - Queue an URI for fetching				/*{{{*/
 // Acquire::Enqueue - Queue an URI for fetching				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* */
+/* This is the entry point for an item. An item calls this function when
+   it is construction which creates a queue (based on the current queue
+   mode) and puts the item in that queue. If the system is running then
+   the queue might be started. */
 void pkgAcquire::Enqueue(Item *Itm,string URI,string Description)
 void pkgAcquire::Enqueue(Item *Itm,string URI,string Description)
 {
 {
    // Determine which queue to put the item in
    // Determine which queue to put the item in
@@ -129,15 +139,15 @@ void pkgAcquire::Enqueue(Item *Itm,string URI,string Description)
       I = new Queue(Name,this);
       I = new Queue(Name,this);
       I->Next = Queues;
       I->Next = Queues;
       Queues = I;
       Queues = I;
+      
+      if (Running == true)
+	 I->Startup();
    }
    }
    
    
    // Queue it into the named queue
    // Queue it into the named queue
    I->Enqueue(Itm,URI,Description);
    I->Enqueue(Itm,URI,Description);
    ToFetch++;
    ToFetch++;
-   
-   if (Running == true)
-      I->Startup();
-      
+         
    // Some trace stuff
    // Some trace stuff
    if (Debug == true)
    if (Debug == true)
    {
    {
@@ -149,12 +159,16 @@ void pkgAcquire::Enqueue(Item *Itm,string URI,string Description)
 									/*}}}*/
 									/*}}}*/
 // Acquire::Dequeue - Remove an item from all queues			/*{{{*/
 // Acquire::Dequeue - Remove an item from all queues			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* */
+/* This is called when an item is finished being fetched. It removes it
+   from all the queues */
 void pkgAcquire::Dequeue(Item *Itm)
 void pkgAcquire::Dequeue(Item *Itm)
 {
 {
    Queue *I = Queues;
    Queue *I = Queues;
    for (; I != 0; I = I->Next)
    for (; I != 0; I = I->Next)
       I->Dequeue(Itm);
       I->Dequeue(Itm);
+   
+   if (Debug == true)
+      clog << "Dequeuing " << Itm->DestFile << endl;
    ToFetch--;
    ToFetch--;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -163,24 +177,20 @@ void pkgAcquire::Dequeue(Item *Itm)
 /* The string returned depends on the configuration settings and the
 /* The string returned depends on the configuration settings and the
    method parameters. Given something like http://foo.org/bar it can
    method parameters. Given something like http://foo.org/bar it can
    return http://foo.org or http */
    return http://foo.org or http */
-string pkgAcquire::QueueName(string URI)
+string pkgAcquire::QueueName(string Uri)
 {
 {
-   const MethodConfig *Config = GetConfig(URIAccess(URI));
+   URI U(Uri);
+   
+   const MethodConfig *Config = GetConfig(U.Access);
    if (Config == 0)
    if (Config == 0)
       return string();
       return string();
    
    
    /* Single-Instance methods get exactly one queue per URI. This is
    /* Single-Instance methods get exactly one queue per URI. This is
       also used for the Access queue method  */
       also used for the Access queue method  */
    if (Config->SingleInstance == true || QueueMode == QueueAccess)
    if (Config->SingleInstance == true || QueueMode == QueueAccess)
-      return URIAccess(URI);
-      
-   // Host based queue 
-   string::iterator I = URI.begin();
-   for (; I < URI.end() && *I != ':'; I++);
-   for (; I < URI.end() && (*I == '/' || *I == ':'); I++);
-   for (; I < URI.end() && *I != '/'; I++);
-	
-   return string(URI,0,I - URI.begin());
+      return U.Access;
+
+   return U.Access + ':' + U.Host;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // Acquire::GetConfig - Fetch the configuration information		/*{{{*/
 // Acquire::GetConfig - Fetch the configuration information		/*{{{*/
@@ -234,7 +244,9 @@ void pkgAcquire::SetFds(int &Fd,fd_set *RSet,fd_set *WSet)
 									/*}}}*/
 									/*}}}*/
 // Acquire::RunFds - Deal with active FDs				/*{{{*/
 // Acquire::RunFds - Deal with active FDs				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* Dispatch active FDs over to the proper workers */
+/* Dispatch active FDs over to the proper workers. It is very important
+   that a worker never be erased while this is running! The queue class
+   should never erase a worker except during shutdown processing. */
 void pkgAcquire::RunFds(fd_set *RSet,fd_set *WSet)
 void pkgAcquire::RunFds(fd_set *RSet,fd_set *WSet)
 {
 {
    for (Worker *I = Workers; I != 0; I = I->NextAcquire)
    for (Worker *I = Workers; I != 0; I = I->NextAcquire)
@@ -273,15 +285,26 @@ bool pkgAcquire::Run()
 	 Running = false;
 	 Running = false;
 	 return _error->Errno("select","Select has failed");
 	 return _error->Errno("select","Select has failed");
       }
       }
-      
+	     
       RunFds(&RFds,&WFds);
       RunFds(&RFds,&WFds);
+      if (_error->PendingError() == true)
+	 break;
    }   
    }   
    
    
    for (Queue *I = Queues; I != 0; I = I->Next)
    for (Queue *I = Queues; I != 0; I = I->Next)
       I->Shutdown();
       I->Shutdown();
 
 
    Running = false;
    Running = false;
-   return true;
+   return _error->PendingError();
+}
+									/*}}}*/
+// pkgAcquire::Bump - Called when an item is dequeued			/*{{{*/
+// ---------------------------------------------------------------------
+/* This routine bumps idle queues in hopes that they will be able to fetch
+   the dequeued item */
+void pkgAcquire::Bump()
+{
+   
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 
@@ -339,6 +362,9 @@ void pkgAcquire::Queue::Enqueue(Item *Owner,string URI,string Description)
    Items->URI = URI;
    Items->URI = URI;
    Items->Description = Description;
    Items->Description = Description;
    Owner->QueueCounter++;
    Owner->QueueCounter++;
+   
+   if (Items->Next == 0)
+      Cycle();
 }
 }
 									/*}}}*/
 									/*}}}*/
 // Queue::Dequeue - Remove an item from the queue			/*{{{*/
 // Queue::Dequeue - Remove an item from the queue			/*{{{*/
@@ -368,7 +394,8 @@ bool pkgAcquire::Queue::Startup()
 {
 {
    Shutdown();
    Shutdown();
    
    
-   pkgAcquire::MethodConfig *Cnf = Owner->GetConfig(URIAccess(Name));
+   URI U(Name);
+   pkgAcquire::MethodConfig *Cnf = Owner->GetConfig(U.Access);
    if (Cnf == 0)
    if (Cnf == 0)
       return false;
       return false;
    
    
@@ -376,11 +403,8 @@ bool pkgAcquire::Queue::Startup()
    Owner->Add(Workers);
    Owner->Add(Workers);
    if (Workers->Start() == false)
    if (Workers->Start() == false)
       return false;
       return false;
-      
-   Items->Worker = Workers;
-   Workers->QueueItem(Items);
    
    
-   return true;
+   return Cycle();
 }
 }
 									/*}}}*/
 									/*}}}*/
 // Queue::Shutdown - Shutdown the worker processes			/*{{{*/
 // Queue::Shutdown - Shutdown the worker processes			/*{{{*/
@@ -414,16 +438,41 @@ pkgAcquire::Queue::QItem *pkgAcquire::Queue::FindItem(string URI,pkgAcquire::Wor
 // Queue::ItemDone - Item has been completed				/*{{{*/
 // Queue::ItemDone - Item has been completed				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* The worker signals this which causes the item to be removed from the
 /* The worker signals this which causes the item to be removed from the
-   queue. */
+   queue. If this is the last queue instance then it is removed from the
+   main queue too.*/
 bool pkgAcquire::Queue::ItemDone(QItem *Itm)
 bool pkgAcquire::Queue::ItemDone(QItem *Itm)
 {
 {
-   Dequeue(Itm->Owner);
+   if (Itm->Owner->QueueCounter <= 1)
+      Owner->Dequeue(Itm->Owner);
+   else
+   {
+      Dequeue(Itm->Owner);
+      Owner->Bump();
+   }
    
    
-   if (Items == 0)
+   return Cycle();
+}
+									/*}}}*/
+// Queue::Cycle - Queue new items into the method			/*{{{*/
+// ---------------------------------------------------------------------
+/* This locates a new idle item and sends it to the worker */
+bool pkgAcquire::Queue::Cycle()
+{
+   if (Items == 0 || Workers == 0)
       return true;
       return true;
 
 
-   Items->Worker = Workers;
-   Items->Owner->Status = pkgAcquire::Item::StatFetching;
-   return Workers->QueueItem(Items);
+   // Look for a queable item
+   QItem *I = Items;
+   for (; I != 0; I = I->Next)
+      if (I->Owner->Status == pkgAcquire::Item::StatIdle)
+	 break;
+
+   // Nothing to do, queue is idle.
+   if (I == 0)
+      return true;
+   
+   I->Worker = Workers;
+   I->Owner->Status = pkgAcquire::Item::StatFetching;
+   return Workers->QueueItem(I);
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 5 - 1
apt-pkg/acquire.h

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: acquire.h,v 1.5 1998/10/26 07:11:48 jgg Exp $
+// $Id: acquire.h,v 1.6 1998/10/30 07:53:38 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    Acquire - File Acquiration
    Acquire - File Acquiration
@@ -80,6 +80,9 @@ class pkgAcquire
    // FDSET managers for derived classes
    // FDSET managers for derived classes
    void SetFds(int &Fd,fd_set *RSet,fd_set *WSet);
    void SetFds(int &Fd,fd_set *RSet,fd_set *WSet);
    void RunFds(fd_set *RSet,fd_set *WSet);   
    void RunFds(fd_set *RSet,fd_set *WSet);   
+
+   // A queue calls this when it dequeues an item
+   void Bump();
    
    
    public:
    public:
 
 
@@ -129,6 +132,7 @@ class pkgAcquire::Queue
    
    
    bool Startup();
    bool Startup();
    bool Shutdown();
    bool Shutdown();
+   bool Cycle();
    
    
    Queue(string Name,pkgAcquire *Owner);
    Queue(string Name,pkgAcquire *Owner);
    ~Queue();
    ~Queue();

+ 26 - 1
apt-pkg/contrib/configuration.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: configuration.cc,v 1.8 1998/10/22 04:56:45 jgg Exp $
+// $Id: configuration.cc,v 1.9 1998/10/30 07:53:42 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    Configuration Class
    Configuration Class
@@ -212,6 +212,31 @@ bool Configuration::Exists(const char *Name)
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
+// Configuration::Dump - Dump the config				/*{{{*/
+// ---------------------------------------------------------------------
+/* Dump the entire configuration space */
+void Configuration::Dump()
+{
+   /* Write out all of the configuration directives by walking the 
+      configuration tree */
+   const Configuration::Item *Top = _config->Tree(0);
+   for (; Top != 0;)
+   {
+      clog << Top->FullTag() << " \"" << Top->Value << "\";" << endl;
+      
+      if (Top->Child != 0)
+      {
+	 Top = Top->Child;
+	 continue;
+      }
+      
+      while (Top != 0 && Top->Next == 0)
+	 Top = Top->Parent;
+      if (Top != 0)
+	 Top = Top->Next;
+   }   
+}
+									/*}}}*/
 
 
 // Configuration::Item::FullTag - Return the fully scoped tag		/*{{{*/
 // Configuration::Item::FullTag - Return the fully scoped tag		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------

+ 3 - 1
apt-pkg/contrib/configuration.h

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: configuration.h,v 1.6 1998/10/22 04:56:46 jgg Exp $
+// $Id: configuration.h,v 1.7 1998/10/30 07:53:44 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    Configuration Class
    Configuration Class
@@ -65,6 +65,8 @@ class Configuration
    bool Exists(const char *Name);
    bool Exists(const char *Name);
       
       
    inline const Item *Tree(const char *Name) {return Lookup(Name,false);};
    inline const Item *Tree(const char *Name) {return Lookup(Name,false);};
+
+   void Dump();
    
    
    Configuration();
    Configuration();
 };
 };

+ 102 - 12
apt-pkg/contrib/strutl.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: strutl.cc,v 1.8 1998/10/24 04:58:07 jgg Exp $
+// $Id: strutl.cc,v 1.9 1998/10/30 07:53:45 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    String Util - Some usefull string functions.
    String Util - Some usefull string functions.
@@ -308,17 +308,6 @@ string URItoFileName(string URI)
    return URI;
    return URI;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// URIAccess - Return the access method for the URI			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-string URIAccess(string URI)
-{
-   string::size_type Pos = URI.find(':');
-   if (Pos == string::npos)
-      return URI;
-   return string(URI,0,Pos);
-}
-									/*}}}*/
 // Base64Encode - Base64 Encoding routine for short strings		/*{{{*/
 // Base64Encode - Base64 Encoding routine for short strings		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This routine performs a base64 transformation on a string. It was ripped
 /* This routine performs a base64 transformation on a string. It was ripped
@@ -619,3 +608,104 @@ bool StrToTime(string Val,time_t &Result)
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
+
+// URI::URI - Constructor						/*{{{*/
+// ---------------------------------------------------------------------
+/* This parses the URI into all of its components */
+URI::URI(string U)
+{
+   string::const_iterator I = U.begin();
+
+   // Locate the first colon, this seperates the scheme
+   for (; I < U.end() && *I != ':' ; I++);
+   string::const_iterator FirstColon = I;
+
+   // Determine if this is a host type URI with a leading double //
+   string::const_iterator SingleSlash = I;
+   if (I + 3 < U.end() && I[1] == '/' && I[2] == '/')
+   {
+      // Locate the single / that starts the path
+      for (; I < U.end(); I++)
+      {
+	 if (*I == '/' && I[1] == '/')
+	    I += 2;
+	 else 
+	    if (*I == '/')
+	       break;
+      }
+      if (I > U.end())
+	 I = U.end();
+      SingleSlash = I;      
+   }
+
+   // We can now write the access and path specifiers
+   Access = string(U,0,FirstColon - U.begin());
+   if (SingleSlash != U.end())
+      Path = string(U,SingleSlash - U.begin() + 1);
+   
+   // Now we attempt to locate a user:pass@host fragment
+   FirstColon += 3;
+   if (FirstColon >= U.end())
+      return;
+   
+   if (FirstColon > SingleSlash)
+      FirstColon = SingleSlash;
+   
+   // Search for the @
+   I = FirstColon;
+   for (; I < SingleSlash && *I != '@'; I++);
+   string::const_iterator At = I;
+   
+   // Colon in the @ section
+   I = FirstColon + 1;
+   for (; I < At && *I != ':'; I++);
+   string::const_iterator SecondColon = I;
+      
+   // Now write the host and user/pass
+   if (At == SingleSlash)
+   {
+      if (FirstColon < SingleSlash)
+	 Host = string(U,FirstColon - U.begin(),SingleSlash - FirstColon);
+   }
+   else
+   {
+      Host = string(U,At - U.begin() + 1,SingleSlash - At - 1);
+      User = string(U,FirstColon - U.begin(),SecondColon - FirstColon);
+      if (SecondColon < At)
+	 Password = string(U,SecondColon - U.begin() + 1,At - SecondColon - 1);
+   }   
+   
+   // Now we parse off a pot number from the hostname
+   Port = 0;
+   string::size_type Pos = Host.rfind(':');
+   if (Pos == string::npos)
+      return;
+   
+   Port = atoi(string(Host,Pos+1).c_str());
+   Host = string(Host,0,Pos);
+}
+									/*}}}*/
+// URI::operator string - Convert the URI to a string			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+URI::operator string()
+{
+   string Res = Access + ':';
+   if (Host.empty() == false)
+   {
+      if (User.empty() == false)
+      {
+	 Res += "//" + User;
+	 if (Password.empty() == false)
+	    Res += ":" + Password;
+	 Res += "@";
+      }
+      Res += Host;
+   }
+   
+   if (Path.empty() == false)
+      Res += "/" + Path;
+   
+   return Res;
+}
+									/*}}}*/

+ 17 - 2
apt-pkg/contrib/strutl.h

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: strutl.h,v 1.7 1998/10/23 00:50:00 jgg Exp $
+// $Id: strutl.h,v 1.8 1998/10/30 07:53:46 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    String Util - These are some usefull string functions
    String Util - These are some usefull string functions
@@ -32,7 +32,6 @@ string TimeToStr(unsigned long Sec);
 string SubstVar(string Str,string Subst,string Contents);
 string SubstVar(string Str,string Subst,string Contents);
 string Base64Encode(string Str);
 string Base64Encode(string Str);
 string URItoFileName(string URI);
 string URItoFileName(string URI);
-string URIAccess(string URI);
 string TimeRFC1123(time_t Date);
 string TimeRFC1123(time_t Date);
 bool StrToTime(string Val,time_t &Result);
 bool StrToTime(string Val,time_t &Result);
 string LookupTag(string Message,const char *Tag,const char *Default = 0);
 string LookupTag(string Message,const char *Tag,const char *Default = 0);
@@ -44,4 +43,20 @@ inline int stringcmp(const char *A,const char *AEnd,const char *B) {return strin
 int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd);
 int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd);
 inline int stringcasecmp(const char *A,const char *AEnd,const char *B) {return stringcasecmp(A,AEnd,B,B+strlen(B));};
 inline int stringcasecmp(const char *A,const char *AEnd,const char *B) {return stringcasecmp(A,AEnd,B,B+strlen(B));};
 
 
+class URI
+{
+   public:
+   
+   string Access;
+   string User;
+   string Password;
+   string Host;
+   string Path;
+   unsigned int Port;
+   
+   operator string();
+   
+   URI(string Path);
+};
+
 #endif
 #endif

+ 16 - 4
apt-pkg/init.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: init.cc,v 1.8 1998/10/20 02:39:19 jgg Exp $
+// $Id: init.cc,v 1.9 1998/10/30 07:53:39 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    Init - Initialize the package library
    Init - Initialize the package library
@@ -9,6 +9,7 @@
 									/*}}}*/
 									/*}}}*/
 // Include files							/*{{{*/
 // Include files							/*{{{*/
 #include <apt-pkg/init.h>
 #include <apt-pkg/init.h>
+#include <config.h>
 
 
 #include <sys/stat.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <unistd.h>
@@ -22,7 +23,7 @@
 bool pkgInitialize(Configuration &Cnf)
 bool pkgInitialize(Configuration &Cnf)
 {
 {
    // General APT things
    // General APT things
-   Cnf.Set("APT::Architecture","i386");
+   Cnf.Set("APT::Architecture",ARCHITECTURE);
 
 
    // State
    // State
    Cnf.Set("Dir::State","/var/state/apt/");
    Cnf.Set("Dir::State","/var/state/apt/");
@@ -45,12 +46,23 @@ bool pkgInitialize(Configuration &Cnf)
    Cnf.Set("Dir::Etc","/etc/apt/");
    Cnf.Set("Dir::Etc","/etc/apt/");
    Cnf.Set("Dir::Etc::sourcelist","sources.list");
    Cnf.Set("Dir::Etc::sourcelist","sources.list");
    Cnf.Set("Dir::Etc::main","apt.conf");
    Cnf.Set("Dir::Etc::main","apt.conf");
-
+   Cnf.Set("Dir::Bin::methods","/usr/lib/apt/metods");
+   
    // Read the main config file
    // Read the main config file
    string FName = Cnf.FindFile("Dir::Etc::main");
    string FName = Cnf.FindFile("Dir::Etc::main");
    struct stat Buf;   
    struct stat Buf;   
    if (stat(FName.c_str(),&Buf) != 0)
    if (stat(FName.c_str(),&Buf) != 0)
       return true;
       return true;
-   return ReadConfigFile(Cnf,FName);
+   
+   // Read an alternate config file
+   const char *Cfg = getenv("APT_CONFIG");
+   
+   if (ReadConfigFile(Cnf,FName) != true || ReadConfigFile(Cnf,Cfg) != true)
+      return false;
+   
+   if (Cnf.FindB("Debug::pkgInitialize",false) == true)
+      Cnf.Dump();
+      
+   return true;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 2 - 2
apt-pkg/makefile

@@ -23,7 +23,7 @@ SOURCE = contrib/mmap.cc contrib/error.cc contrib/strutl.cc \
 SOURCE+= pkgcache.cc version.cc fileutl.cc pkgcachegen.cc depcache.cc \
 SOURCE+= pkgcache.cc version.cc fileutl.cc pkgcachegen.cc depcache.cc \
          orderlist.cc tagfile.cc sourcelist.cc packagemanager.cc \
          orderlist.cc tagfile.cc sourcelist.cc packagemanager.cc \
 	 pkgrecords.cc algorithms.cc acquire.cc acquire-item.cc \
 	 pkgrecords.cc algorithms.cc acquire.cc acquire-item.cc \
-	 acquire-worker.cc init.cc templates.cc
+	 acquire-worker.cc acquire-method.cc init.cc templates.cc
 
 
 # Source code for the debian specific components	 
 # Source code for the debian specific components	 
 SOURCE+= deb/deblistparser.cc deb/debrecords.cc
 SOURCE+= deb/deblistparser.cc deb/debrecords.cc
@@ -33,7 +33,7 @@ HEADERS = algorithms.h depcache.h mmap.h pkgcachegen.h cacheiterators.h \
           error.h orderlist.h sourcelist.h configuration.h fileutl.h \
           error.h orderlist.h sourcelist.h configuration.h fileutl.h \
           packagemanager.h tagfile.h deblistparser.h init.h pkgcache.h \
           packagemanager.h tagfile.h deblistparser.h init.h pkgcache.h \
           version.h progress.h pkgrecords.h debrecords.h cmndline.h \
           version.h progress.h pkgrecords.h debrecords.h cmndline.h \
-	  acquire.h acquire-worker.h acquire-item.h
+	  acquire.h acquire-worker.h acquire-item.h acquire-method.h
 
 
 HEADERS := $(addprefix apt-pkg/,$(HEADERS))
 HEADERS := $(addprefix apt-pkg/,$(HEADERS))
 
 

+ 1 - 7
apt-pkg/tagfile.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: tagfile.cc,v 1.12 1998/10/24 04:58:06 jgg Exp $
+// $Id: tagfile.cc,v 1.13 1998/10/30 07:53:41 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    Fast scanner for RFC-822 type header information
    Fast scanner for RFC-822 type header information
@@ -45,10 +45,7 @@ bool pkgTagFile::Step(pkgTagSection &Tag)
 	 return false;
 	 return false;
       
       
       if (Tag.Scan(Start,End - Start) == false)
       if (Tag.Scan(Start,End - Start) == false)
-      {
-	 cout << string(Start,End-Start) << endl;
 	 return _error->Error("Unable to parse package file");
 	 return _error->Error("Unable to parse package file");
-      }      
    }   
    }   
    Start += Tag.size();
    Start += Tag.size();
    iOffset += Tag.size();
    iOffset += Tag.size();
@@ -87,10 +84,7 @@ bool pkgTagFile::Fill()
    else
    else
    {
    {
       if (Fd.Read(End,Size - (End - Buffer)) == false)
       if (Fd.Read(End,Size - (End - Buffer)) == false)
-      {
-	 cout << "boink" << endl;
 	 return false;
 	 return false;
-      }
       
       
       Left -= Size - (End - Buffer);
       Left -= Size - (End - Buffer);
       End = Buffer + Size;
       End = Buffer + Size;

+ 3 - 1
buildlib/defaults.mak

@@ -26,7 +26,9 @@
 # but by explicly setting the BUILD variable. Make is invoked from
 # but by explicly setting the BUILD variable. Make is invoked from
 # within the source itself which is much more compatible with compilation
 # within the source itself which is much more compatible with compilation
 # environments.
 # environments.
+ifndef NOISY
 .SILENT:
 .SILENT:
+endif
 
 
 # Search for the build directory
 # Search for the build directory
 ifdef BUILD
 ifdef BUILD
@@ -51,7 +53,7 @@ BIN := $(BUILD)/bin
 LIB := $(BIN)
 LIB := $(BIN)
 OBJ := $(BUILD)/obj/$(SUBDIR)
 OBJ := $(BUILD)/obj/$(SUBDIR)
 DEP := $(OBJ)
 DEP := $(OBJ)
-DOC := $(BUILD)/doc
+DOC := $(BUILD)/docs
 
 
 # Module types
 # Module types
 LIBRARY_H = $(BASE)/buildlib/library.mak
 LIBRARY_H = $(BASE)/buildlib/library.mak

+ 1 - 1
buildlib/makefile.in

@@ -6,7 +6,7 @@
 
 
 SRCDIR=@top_srcdir@
 SRCDIR=@top_srcdir@
 SUBDIRS:=./doc ./bin ./bin/methods ./obj ./include/apt-pkg ./include/deity
 SUBDIRS:=./doc ./bin ./bin/methods ./obj ./include/apt-pkg ./include/deity
-SUBDIRS+=./obj/doc ./obj/apt-pkg ./obj/deity ./obj/gui ./obj/cmdline \
+SUBDIRS+=./obj/docs ./obj/apt-pkg ./obj/deity ./obj/gui ./obj/cmdline \
          ./obj/test ./obj/methods
          ./obj/test ./obj/methods
 BUILD:=$(shell pwd)
 BUILD:=$(shell pwd)
 export BUILD
 export BUILD

+ 3 - 0
configure.in

@@ -9,6 +9,9 @@ dnl some of the more populare bsd/sysv ones (like select). You'll also
 dnl need a C++ compiler that is semi-standard conformant, exceptions are 
 dnl need a C++ compiler that is semi-standard conformant, exceptions are 
 dnl not used but STL is.
 dnl not used but STL is.
 
 
+dnl 'make -f Makefile startup' will generate the configure file from 
+dnl configure.in correctly and can be run at any time
+
 AC_INIT(configure.in)
 AC_INIT(configure.in)
 AC_CONFIG_AUX_DIR(buildlib)
 AC_CONFIG_AUX_DIR(buildlib)
 AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in)
 AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in)

+ 29 - 8
doc/examples/apt.conf

@@ -1,12 +1,25 @@
-// $Id: apt.conf,v 1.6 1998/10/26 07:11:51 jgg Exp $
+// $Id: apt.conf,v 1.7 1998/10/30 07:53:50 jgg Exp $
 /* This file is an index of all APT configuration directives. It should
 /* This file is an index of all APT configuration directives. It should
    NOT actually be used as a real config file, though it is a completely
    NOT actually be used as a real config file, though it is a completely
    valid file.
    valid file.
+   
+   In some instances involing filenames it is possible to set the default
+   directory when the path is evaluated. This means you can use relative
+   paths within the sub scope.
+   
+   The configuration directives are specified in a tree with {} designating
+   a subscope relative to the tag before the {}. You can further specify
+   a subscope using scope notation eg,
+     APT::Architecture "i386";
+   This is prefixed with the current scope. Scope notation must be used
+   if an option is specified on the command line with -o.
 */
 */
 
 
+// Options for APT in general
 APT {
 APT {
   Architecture "i386";
   Architecture "i386";
   
   
+  // Options for apt-get
   Get {
   Get {
      Download-Only "false";
      Download-Only "false";
      Simulate "false";
      Simulate "false";
@@ -15,17 +28,20 @@ APT {
      Show-Upgraded "false";
      Show-Upgraded "false";
   };
   };
   
   
+  // Some general options
   Ingore-Hold "false";
   Ingore-Hold "false";
 };
 };
 
 
+// Options for the downloading routines
 Acquire
 Acquire
 {
 {
   Queue-Mode "access";       // host|access
   Queue-Mode "access";       // host|access
 };
 };
 
 
+// Directory layout
 Dir 
 Dir 
 {
 {
-  
+  // Location of the state dir
   State "/var/state/apt/" 
   State "/var/state/apt/" 
   {
   {
      lists "lists/";
      lists "lists/";
@@ -34,20 +50,23 @@ Dir
      status "/var/lib/dpkg/status";     
      status "/var/lib/dpkg/status";     
   };
   };
   
   
+  // Location of the cache dir
   Cache "/var/cache/apt/" {
   Cache "/var/cache/apt/" {
      archives "archives/";
      archives "archives/";
      srcpkgcache "srcpkgcache.bin";
      srcpkgcache "srcpkgcache.bin";
      pkgcache "pkgcache.bin";     
      pkgcache "pkgcache.bin";     
   };
   };
   
   
+  // Config files
   Etc "/etc/apt/" {
   Etc "/etc/apt/" {
-     sourcelist "sources.list.test";
+     sourcelist "sources.list";
      main "apt.conf";
      main "apt.conf";
   };
   };
   
   
+  // Locations of binaries
   Bin {
   Bin {
      methods "/home/jgg/work/apt/build/bin/methods/";
      methods "/home/jgg/work/apt/build/bin/methods/";
-     gzip "gzip";
+     gzip "/bin/gzip";
   };
   };
 };
 };
 
 
@@ -55,10 +74,12 @@ DSelect {
 
 
 }
 }
 
 
+/* Options you can set to see some debugging text They corrispond to names
+   of classes in the source code */
 Debug {
 Debug {
-  pkgProblemResolver "true";
+  pkgProblemResolver "false";
   pkgAcquire "false";
   pkgAcquire "false";
-  pkgAcquire::Worker "true";
+  pkgAcquire::Worker "false";
+  
+  pkgInitialize "false";   // This one will dump the configuration space
 }
 }
-
-dir::state::lists "/tmp/lists/";

+ 11 - 19
doc/method.sgml

@@ -4,7 +4,7 @@
 <title>APT Method Interface </title>
 <title>APT Method Interface </title>
 
 
 <author>Jason Gunthorpe <email>jgg@debian.org</email></author>
 <author>Jason Gunthorpe <email>jgg@debian.org</email></author>
-<version>$Id: method.sgml,v 1.3 1998/10/08 04:55:06 jgg Exp $</version>
+<version>$Id: method.sgml,v 1.4 1998/10/30 07:53:49 jgg Exp $</version>
 
 
 <abstract>
 <abstract>
 This document describes the interface that APT uses to the archive
 This document describes the interface that APT uses to the archive
@@ -128,15 +128,6 @@ are opened for use by the method allowing two way communication and
 emergency error reporting. The FD's corrispond to the well known unix FD's, 
 emergency error reporting. The FD's corrispond to the well known unix FD's, 
 stdin, stdout and stderr.
 stdin, stdout and stderr.
 
 
-<p>
-The basic startup sequence depends on how the method is invoked. If any
-command line arguments are passed then the method should start in 
-automatic mode. This facility is provided soley to make the methods
-easier to test and perhaps use outside of APT. Upon startup the method
-will print out a header describing its capabilities and requirements.
-After that it either begins processing the command line arugments and
-exits when done or waits for commands to be fed to it.
-
 <p>
 <p>
 Throught operation of the method communication is done via http 
 Throught operation of the method communication is done via http 
 style plain text. Specifically RFC-822 (like the Package file) fields
 style plain text. Specifically RFC-822 (like the Package file) fields
@@ -175,7 +166,6 @@ status code is an informational string provided for visual debugging.
 <item>601 Configuration - Sends the configuration space
 <item>601 Configuration - Sends the configuration space
 <item>602 Authorization Credentials - Response to the 402 message
 <item>602 Authorization Credentials - Response to the 402 message
 <item>603 Media Changed - Response to the 403 message
 <item>603 Media Changed - Response to the 403 message
-<item>605 Shutdown - Exit
 </list>
 </list>
 
 
 Only the 6xx series of status codes is sent TO the method. Furthermore
 Only the 6xx series of status codes is sent TO the method. Furthermore
@@ -208,6 +198,7 @@ The following is a short index of the header fields that are supported
 <tag>URI<item>URI being described by the message
 <tag>URI<item>URI being described by the message
 <tag>Filename<item>Location in the filesystem
 <tag>Filename<item>Location in the filesystem
 <tag>Last-Modified<item>A time stamp in RFC1123 notation for use by IMS checks
 <tag>Last-Modified<item>A time stamp in RFC1123 notation for use by IMS checks
+<tag>IMS-Hit<item>The already existing item is valid
 <tag>Size<item>Size of the file in bytes
 <tag>Size<item>Size of the file in bytes
 <tag>Resume-Point<item>Location that transfer was started
 <tag>Resume-Point<item>Location that transfer was started
 <tag>MD5-Hash<item>Computed MD5 hash for the file
 <tag>MD5-Hash<item>Computed MD5 hash for the file
@@ -225,6 +216,8 @@ the ones it wants.
                           This is a yes/no value.
                           This is a yes/no value.
 <tag>Pre-Scan<item>Method can detect if archives are already available.
 <tag>Pre-Scan<item>Method can detect if archives are already available.
                    This is a yes/no value.
                    This is a yes/no value.
+<tag>Pipeline<item>The method is capable of pipelining.
+<tag>Send-Config<item>Send configuration to the method.
 <tag>Version<item>Version string for the method
 <tag>Version<item>Version string for the method
 </taglist>
 </taglist>
 
 
@@ -232,8 +225,10 @@ This is a list of which headers each status code can use
 
 
 <taglist>
 <taglist>
 <tag>100 Capabilities<item>
 <tag>100 Capabilities<item>
-Displays the capabilities of the method. 
-Fields: Version, Single-Instance, Pre-Scan
+Displays the capabilities of the method. Methods should set the
+pipeline bit if their underlying protocol supports pipeling. The
+only known method that does support pipelining is http.
+Fields: Version, Single-Instance, Pre-Scan, Pipeline, Send-Config
 
 
 <tag>101 Log<item>
 <tag>101 Log<item>
 A log message may be printed to the screen if debugging is enabled. This
 A log message may be printed to the screen if debugging is enabled. This
@@ -256,7 +251,9 @@ to specify a <em>201 URI Done</> without a <em>URI Start</> which would
 mean no data was transfered but the file is now available. A Filename
 mean no data was transfered but the file is now available. A Filename
 field is specified when the URI is directly available in the local 
 field is specified when the URI is directly available in the local 
 pathname space. APT will either directly use that file or copy it into 
 pathname space. APT will either directly use that file or copy it into 
-another location.
+another location. It is possible to return Alt-* feilds to indicate that
+another possibility for the URI has been found in the local pathname space.
+This is done if a decompressed version of a .gz file is found.
 Fields: URI, Size, Last-Modified, Filename, MD5-Hash
 Fields: URI, Size, Last-Modified, Filename, MD5-Hash
 
 
 <tag>400 URI Failure<item>
 <tag>400 URI Failure<item>
@@ -305,11 +302,6 @@ Fields: Site, User, Password
 This is sent in response to a <em>403 Media Failure</> message. It
 This is sent in response to a <em>403 Media Failure</> message. It
 indicates that the user has changed media and it is safe to proceed.
 indicates that the user has changed media and it is safe to proceed.
 Fields: Media
 Fields: Media
-
-<tag>605 Shutdown<item>
-APT sends this to signal the shutdown of the method. The method should
-terminate immidiately.
-Fields: None
 </taglist>
 </taglist>
 
 
 </sect>
 </sect>

+ 56 - 111
methods/copy.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: copy.cc,v 1.3 1998/10/26 07:11:52 jgg Exp $
+// $Id: copy.cc,v 1.4 1998/10/30 07:53:51 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    Copy URI - This method takes a uri like a file: uri and copies it
    Copy URI - This method takes a uri like a file: uri and copies it
@@ -10,130 +10,75 @@
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>
-#include <strutl.h>
+#include <apt-pkg/acquire-method.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 
 
 #include <sys/stat.h>
 #include <sys/stat.h>
 #include <utime.h>
 #include <utime.h>
 #include <unistd.h>
 #include <unistd.h>
-#include <stdio.h>
 									/*}}}*/
 									/*}}}*/
 
 
-// Fail - Generate a failure message					/*{{{*/
+class CopyMethod : public pkgAcqMethod
+{
+   virtual bool Fetch(string Message,URI Get);
+   
+   public:
+   
+   CopyMethod() : pkgAcqMethod("1.0",SingleInstance) {};
+};
+
+// CopyMethod::Fetch - Fetch a file					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-void Fail(string URI)
+bool CopyMethod::Fetch(string Message,URI Get)
 {
 {
-   string Err = "Undetermined Error";
-   if (_error->empty() == false)
-      _error->PopMessage(Err);
+   string File = Get.Path;
+
+   // See if the file exists
+   FileFd From(File,FileFd::ReadOnly);
+   FileFd To(DestFile,FileFd::WriteEmpty);
+   To.EraseOnFailure();
+   if (_error->PendingError() == true)
+      return false;
    
    
-   printf("400 URI Failure\n"
-	  "URI: %s\n"
-	  "Message: %s\n\n",URI.c_str(),Err.c_str());
-   _error->Discard();
-}
-									/*}}}*/
+   // Copy the file
+   if (CopyFile(From,To) == false)
+      return false;
 
 
-int main()
-{
-   setlinebuf(stdout);
-   SetNonBlock(STDIN_FILENO,true);
+   From.Close();
+   To.Close();
    
    
-   printf("100 Capabilities\n"
-	  "Version: 1.0\n"
-	  "Pipeline: true\n\n");
-      
-   vector<string> Messages;   
-   while (1)
+   // Transfer the modification times
+   struct stat Buf;
+   if (stat(File.c_str(),&Buf) != 0)
    {
    {
-      if (WaitFd(STDIN_FILENO) == false ||
-	  ReadMessages(STDIN_FILENO,Messages) == false)
-	 return 0;
-
-      while (Messages.empty() == false)
-      {
-	 string Message = Messages.front();
-	 Messages.erase(Messages.begin());
-	 
-	 // Fetch the message number
-	 char *End;
-	 int Number = strtol(Message.c_str(),&End,10);
-	 if (End == Message.c_str())
-	 {
-	    cerr << "Malformed message!" << endl;
-	    return 100;
-	 }
-	 
-	 // We only understand 600 URI Fetch messages
-	 if (Number != 600)
-	    continue;
-	 
-	 // Grab the URI bit 
-	 string URI = LookupTag(Message,"URI");
-	 string Target = LookupTag(Message,"Filename");
-	 
-	 // Grab the filename
-	 string::size_type Pos = URI.find(':');
-	 if (Pos == string::npos)
-	 {
-	    _error->Error("Invalid message");
-	    Fail(URI);
-	    continue;
-	 }
-	 string File = string(URI,Pos+1);
-	 
-	 // Start the reply message
-	 string Result = "201 URI Done";
-	 Result += "\nURI: " + URI;
-	 Result += "\nFileName: " + Target;
-	 
-	 // See if the file exists
-	 FileFd From(File,FileFd::ReadOnly);
-	 FileFd To(Target,FileFd::WriteEmpty);
-	 To.EraseOnFailure();
-	 if (_error->PendingError() == true)
-	 {
-	    Fail(URI);
-	    continue;
-	 }	 
-	 
-	 // Copy the file
-	 if (CopyFile(From,To) == false)
-	 {
-	    Fail(URI);
-	    continue;
-	 }	 
-	
-	 From.Close();
-	 To.Close();
-	 
-	 // Transfer the modification times
-	 struct stat Buf;
-	 if (stat(File.c_str(),&Buf) != 0)
-	 {
-	    _error->Errno("stat","Failed to stat");
-	    Fail(URI);
-	    continue;
-	 }
-	 struct utimbuf TimeBuf;
-	 TimeBuf.actime = Buf.st_atime;
-	 TimeBuf.modtime = Buf.st_mtime;
-	 if (utime(Target.c_str(),&TimeBuf) != 0)
-	 {
-	    To.OpFail();
-	    _error->Errno("utime","Failed to set modification time");
-	    Fail(URI);
-	    continue;
-	 }
-	       
-	 // Send the message
-	 Result += "\n\n";
-	 if (write(STDOUT_FILENO,Result.begin(),Result.length()) != 
-	     (signed)Result.length())
-	    return 100;
-      }      
+      To.OpFail();
+      return _error->Errno("stat","Failed to stat");
    }
    }
    
    
-   return 0;
+   struct utimbuf TimeBuf;
+   TimeBuf.actime = Buf.st_atime;
+   TimeBuf.modtime = Buf.st_mtime;
+   if (utime(DestFile.c_str(),&TimeBuf) != 0)
+   {
+      To.OpFail();
+      return _error->Errno("utime","Failed to set modification time");
+   }
+   
+   // Forumulate a result
+   FetchResult Res;
+   Res.Size = Buf.st_size;
+   Res.Filename = DestFile;
+   Res.LastModified = Buf.st_mtime;
+   Res.IMSHit = false;
+   
+   URIDone(Res);
+   return true;
+}
+									/*}}}*/
+
+int main()
+{
+   CopyMethod Mth;
+   return Mth.Run();
 }
 }

+ 54 - 114
methods/file.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: file.cc,v 1.3 1998/10/23 00:50:02 jgg Exp $
+// $Id: file.cc,v 1.4 1998/10/30 07:53:52 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    File URI method for APT
    File URI method for APT
@@ -13,132 +13,72 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#include <apt-pkg/fileutl.h>
-#include <strutl.h>
+#include <apt-pkg/acquire-method.h>
+#include <apt-pkg/error.h>
 
 
 #include <sys/stat.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <unistd.h>
-#include <stdio.h>
 									/*}}}*/
 									/*}}}*/
 
 
-// Fail - Generate a failure message					/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void Fail(string URI)
+class FileMethod : public pkgAcqMethod
 {
 {
-   printf("400 URI Failure\n"
-	  "URI: %s\n"
-	  "Message: File does not exist\n\n",URI.c_str());
-}
-									/*}}}*/
+   virtual bool Fetch(string Message,URI Get);
+   
+   public:
+   
+   FileMethod() : pkgAcqMethod("1.0",SingleInstance) {};
+};
 
 
-int main()
+// FileMethod::Fetch - Fetch a file					/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool FileMethod::Fetch(string Message,URI Get)
 {
 {
-   setlinebuf(stdout);
-   SetNonBlock(STDIN_FILENO,true);
+   string File = Get.Path;
+   FetchResult Res;
    
    
-   printf("100 Capabilities\n"
-	  "Version: 1.0\n"
-	  "Pipeline: true\n\n");
-      
-   vector<string> Messages;   
-   while (1)
+   // See if the file exists
+   struct stat Buf;
+   if (stat(File.c_str(),&Buf) == 0)
    {
    {
-      if (WaitFd(STDIN_FILENO) == false ||
-	  ReadMessages(STDIN_FILENO,Messages) == false)
-	 return 0;
-
-      while (Messages.empty() == false)
+      Res.Size = Buf.st_size;
+      Res.Filename = File;
+      Res.LastModified = Buf.st_mtime;
+      Res.IMSHit = false;
+      if (LastModified == Buf.st_mtime)
+	 Res.IMSHit = true;
+   }
+   
+   // See if we can compute a file without a .gz exentsion
+   string::size_type Pos = File.rfind(".gz");
+   if (Pos + 3 == File.length())
+   {
+      File = string(File,0,Pos);
+      if (stat(File.c_str(),&Buf) == 0)
       {
       {
-	 string Message = Messages.front();
-	 Messages.erase(Messages.begin());
-	 
-	 // Fetch the message number
-	 char *End;
-	 int Number = strtol(Message.c_str(),&End,10);
-	 if (End == Message.c_str())
-	 {
-	    cerr << "Malformed message!" << endl;
-	    return 100;
-	 }
+	 FetchResult AltRes;
+	 AltRes.Size = Buf.st_size;
+	 AltRes.Filename = File;
+	 AltRes.LastModified = Buf.st_mtime;
+	 AltRes.IMSHit = false;
+	 if (LastModified == Buf.st_mtime)
+	    AltRes.IMSHit = true;
 	 
 	 
-	 // We only understand 600 URI Fetch messages
-	 if (Number != 600)
-	    continue;
-	 
-	 // Grab the URI bit 
-	 string URI = LookupTag(Message,"URI");
-	 
-	 // Grab the filename
-	 string::size_type Pos = URI.find(':');
-	 if (Pos == string::npos)
-	 {
-	    Fail(URI);
-	    continue;
-	 }
-	 string File = string(URI,Pos+1);
-	 
-	 // Grab the modification time
-	 time_t LastMod;
-	 string LTime = LookupTag(Message,"Last-Modified");
-	 if (LTime.empty() == false && StrToTime(LTime,LastMod) == false)
-	    LTime = string();
-	 
-	 // Start the reply message
-	 string Result = "201 URI Done";
-	 Result += "\nURI: " + URI;
-
-	 // See if the file exists
-	 struct stat Buf;
-	 bool Ok = false;
-	 if (stat(File.c_str(),&Buf) == 0)
-	 {
-	    char S[300];
-	    sprintf(S,"\nSize: %ld",Buf.st_size);
-	    
-	    Result += "\nFilename: " + File;
-	    Result += S;
-	    Result += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
-	    if (LTime.empty() == false && LastMod == Buf.st_mtime)
-	       Result += "\nIMS-Hit: true";
-		
-	    Ok = true;
-	 }
-	 
-	 // See if we can compute a file without a .gz exentsion
-	 Pos = File.rfind(".gz");
-	 if (Pos + 3 == File.length())
-	 {
-	    File = string(File,0,Pos);
-	    if (stat(File.c_str(),&Buf) == 0)
-	    {
-	       char S[300];
-	       sprintf(S,"\nAlt-Size: %ld",Buf.st_size);
-	       
-	       Result += "\nAlt-Filename: " + File;
-	       Result += S;
-	       Result += "\nAlt-Last-Modified: " + TimeRFC1123(Buf.st_mtime);
-	       if (LTime.empty() == false && LastMod == Buf.st_mtime)
-		  Result += "\nAlt-IMS-Hit: true";
-	       
-	       Ok = true;
-	    }
-	 }
-	 
-	 // Did we find something?
-	 if (Ok == false)
-	 {
-	    Fail(URI);
-	    continue;
-	 }
-	 Result += "\n\n";
-	 
-	 // Send the message
-	 if (write(STDOUT_FILENO,Result.begin(),Result.length()) != 
-	     (signed)Result.length())
-	    return 100;
+	 URIDone(Res,&AltRes);
+	 return true;
       }      
       }      
    }
    }
    
    
-   return 0;
+   if (Res.Filename.empty() == true)
+      return _error->Error("File not found");
+   
+   URIDone(Res);
+   return true;
+}
+									/*}}}*/
+
+int main()
+{
+   FileMethod Mth;
+   return Mth.Run();
 }
 }

+ 79 - 156
methods/gzip.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
-// $Id: gzip.cc,v 1.2 1998/10/26 07:11:53 jgg Exp $
+// $Id: gzip.cc,v 1.3 1998/10/30 07:53:53 jgg Exp $
 /* ######################################################################
 /* ######################################################################
 
 
    GZip method - Take a file URI in and decompress it into the target 
    GZip method - Take a file URI in and decompress it into the target 
@@ -11,8 +11,7 @@
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
-#include <apt-pkg/configuration.h>
-#include <apt-pkg/acquire-worker.h>
+#include <apt-pkg/acquire-method.h>
 #include <strutl.h>
 #include <strutl.h>
 
 
 #include <sys/stat.h>
 #include <sys/stat.h>
@@ -22,166 +21,90 @@
 #include <stdio.h>
 #include <stdio.h>
 									/*}}}*/
 									/*}}}*/
 
 
-// Fail - Generate a failure message					/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-void Fail(string URI)
+class GzipMethod : public pkgAcqMethod
 {
 {
-   string Err = "Undetermined Error";
-   if (_error->empty() == false)
-      _error->PopMessage(Err);
+   virtual bool Fetch(string Message,URI Get);
    
    
-   printf("400 URI Failure\n"
-	  "URI: %s\n"
-	  "Message: %s\n\n",URI.c_str(),Err.c_str());
-   _error->Discard();
-}
-									/*}}}*/
+   public:
+   
+   GzipMethod() : pkgAcqMethod("1.0",SingleInstance | SendConfig) {};
+};
 
 
-int main()
+// GzipMethod::Fetch - Decompress the passed URI			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool GzipMethod::Fetch(string Message,URI Get)
 {
 {
-   setlinebuf(stdout);
-   SetNonBlock(STDIN_FILENO,true);
+   // Open the source and destintation files
+   FileFd From(Get.Path,FileFd::ReadOnly);
+   FileFd To(DestFile,FileFd::WriteEmpty);   
+   To.EraseOnFailure();
+   if (_error->PendingError() == true)
+      return false;
    
    
-   printf("100 Capabilities\n"
-	  "Version: 1.0\n"
-	  "Pipeline: true\n"
-	  "Send-Config: true\n\n");
-
-   vector<string> Messages;   
-   while (1)
+   // Fork gzip
+   int Process = fork();
+   if (Process < 0)
+      return _error->Errno("fork","Couldn't fork gzip");
+   
+   // The child
+   if (Process == 0)
    {
    {
-      if (WaitFd(STDIN_FILENO) == false ||
-	  ReadMessages(STDIN_FILENO,Messages) == false)
-	 return 0;
-
-      while (Messages.empty() == false)
-      {
-	 string Message = Messages.front();
-	 Messages.erase(Messages.begin());
-	 
-	 // Fetch the message number
-	 char *End;
-	 int Number = strtol(Message.c_str(),&End,10);
-	 if (End == Message.c_str())
-	 {
-	    cerr << "Malformed message!" << endl;
-	    return 100;
-	 }
-	 
-	 // 601 configuration message
-	 if (Number == 601)
-	 {
-	    pkgInjectConfiguration(Message,*_config);
-	    continue;
-	 }	 
+      dup2(From.Fd(),STDIN_FILENO);
+      dup2(To.Fd(),STDOUT_FILENO);
+      From.Close();
+      To.Close();
+      SetCloseExec(STDIN_FILENO,false);
+      SetCloseExec(STDOUT_FILENO,false);
+      
+      const char *Args[3];
+      Args[0] = _config->Find("Dir::bin::gzip","gzip").c_str();
+      Args[1] = "-d";
+      Args[2] = 0;
+      execvp(Args[0],(char **)Args);
+      exit(100);
+   }
+   From.Close();
+   
+   // Wait for gzip to finish
+   int Status;
+   if (waitpid(Process,&Status,0) != Process)
+   {
+      To.OpFail();
+      return _error->Errno("wait","Waiting for gzip failed");
+   }	 
+   
+   if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
+   {
+      To.OpFail();
+      return _error->Error("gzip failed, perhaps the disk is full or the directory permissions are wrong.");
+   }	 
+   
+   To.Close();
+   
+   // Transfer the modification times
+   struct stat Buf;
+   if (stat(Get.Path.c_str(),&Buf) != 0)
+      return _error->Errno("stat","Failed to stat");
 
 
-	 // 600 URI Fetch message
-	 if (Number != 600)
-	    continue;
-	 
-	 // Grab the URI bit 
-	 string URI = LookupTag(Message,"URI");
-	 string Target = LookupTag(Message,"Filename");
-	 
-	 // Grab the filename
-	 string::size_type Pos = URI.find(':');
-	 if (Pos == string::npos)
-	 {
-	    _error->Error("Invalid message");
-	    Fail(URI);
-	    continue;
-	 }
-	 string File = string(URI,Pos+1);
-	 
-	 // Start the reply message
-	 string Result = "201 URI Done";
-	 Result += "\nURI: " + URI;
-	 Result += "\nFileName: " + Target;
-	 
-	 // See if the file exists
-	 FileFd From(File,FileFd::ReadOnly);
-	 FileFd To(Target,FileFd::WriteEmpty);
-	 To.EraseOnFailure();
-	 if (_error->PendingError() == true)
-	 {
-	    Fail(URI);
-	    continue;
-	 }	 
-	 
-	 // Fork gzip
-	 int Process = fork();
-	 if (Process < 0)
-	 {
-	    _error->Errno("fork","Couldn't fork gzip");
-	    Fail(URI);
-	    continue;
-	 }
-	 
-	 // The child
-	 if (Process == 0)
-	 {
-	    dup2(From.Fd(),STDIN_FILENO);
-	    dup2(To.Fd(),STDOUT_FILENO);
-	    From.Close();
-	    To.Close();
-	    SetCloseExec(STDIN_FILENO,false);
-	    SetCloseExec(STDOUT_FILENO,false);
-	    
-	    const char *Args[3];
-	    Args[0] = _config->Find("Dir::bin::gzip","gzip").c_str();
-	    Args[1] = "-d";
-	    Args[2] = 0;
-	    execvp(Args[0],(char **)Args);
-	    exit(100);
-	 }
-	 From.Close();
-	 
-	 // Wait for gzip to finish
-	 int Status;
-	 if (waitpid(Process,&Status,0) != Process)
-	 {
-	    To.OpFail();
-	    _error->Errno("wait","Waiting for gzip failed");
-	    Fail(URI);
-	    continue;
-	 }	 
+   struct utimbuf TimeBuf;
+   TimeBuf.actime = Buf.st_atime;
+   TimeBuf.modtime = Buf.st_mtime;
+   if (utime(DestFile.c_str(),&TimeBuf) != 0)
+      return _error->Errno("utime","Failed to set modification time");
 
 
-	 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
-	 {
-	    To.OpFail();
-	    _error->Error("gzip failed, perhaps the disk is full or the directory permissions are wrong.");
-	    Fail(URI);
-	    continue;
-	 }	 
-	 
-	 To.Close();
-	 
-	 // Transfer the modification times
-	 struct stat Buf;
-	 if (stat(File.c_str(),&Buf) != 0)
-	 {
-	    _error->Errno("stat","Failed to stat");
-	    Fail(URI);
-	    continue;
-	 }
-	 struct utimbuf TimeBuf;
-	 TimeBuf.actime = Buf.st_atime;
-	 TimeBuf.modtime = Buf.st_mtime;
-	 if (utime(Target.c_str(),&TimeBuf) != 0)
-	 {
-	    _error->Errno("utime","Failed to set modification time");
-	    Fail(URI);
-	    continue;
-	 }
-	 
-	 // Send the message
-	 Result += "\n\n";
-	 if (write(STDOUT_FILENO,Result.begin(),Result.length()) != 
-	     (signed)Result.length())
-	    return 100;
-      }      
-   }
+   // Return a Done response
+   FetchResult Res;
+   Res.LastModified = Buf.st_mtime;
+   Res.Filename = DestFile;
+   URIDone(Res);
    
    
-   return 0;
+   return true;
+}
+									/*}}}*/
+
+int main()
+{
+   GzipMethod Mth;
+   return Mth.Run();
 }
 }

+ 12 - 1
test/scratch.cc

@@ -2,10 +2,21 @@
 #include <apt-pkg/init.h>
 #include <apt-pkg/init.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <signal.h>
 #include <signal.h>
+#include <strutl.h>
 
 
-int main()
+int main(int argc,char *argv[])
 {
 {
    signal(SIGPIPE,SIG_IGN);
    signal(SIGPIPE,SIG_IGN);
+
+/*   URI Foo(argv[1]);
+   cout << Foo.Access << '\'' << endl;
+   cout << Foo.Host << '\'' << endl;
+   cout << Foo.Path << '\'' << endl;
+   cout << Foo.User << '\'' << endl;
+   cout << Foo.Password << '\'' << endl;
+   cout << Foo.Port << endl;
+   
+   return 0;*/
    
    
    pkgInitialize(*_config);
    pkgInitialize(*_config);