From 93bf083d699c60f1ac40297bfa6783fb0cb800d8 Mon Sep 17 00:00:00 2001 From: Arch Librarian Date: Mon, 20 Sep 2004 16:51:15 +0000 Subject: Sync Author: jgg Date: 1998-10-30 07:53:30 GMT Sync --- AUTHORS | 36 ++++++ Makefile | 14 +++ README.make | 38 +++++- apt-pkg/acquire-item.cc | 12 +- apt-pkg/acquire-method.cc | 245 +++++++++++++++++++++++++++++++++++++++ apt-pkg/acquire-method.h | 65 +++++++++++ apt-pkg/acquire-worker.cc | 40 +------ apt-pkg/acquire-worker.h | 5 +- apt-pkg/acquire.cc | 125 ++++++++++++++------ apt-pkg/acquire.h | 6 +- apt-pkg/contrib/configuration.cc | 27 ++++- apt-pkg/contrib/configuration.h | 4 +- apt-pkg/contrib/strutl.cc | 114 ++++++++++++++++-- apt-pkg/contrib/strutl.h | 19 ++- apt-pkg/init.cc | 20 +++- apt-pkg/makefile | 4 +- apt-pkg/tagfile.cc | 8 +- buildlib/defaults.mak | 4 +- buildlib/makefile.in | 2 +- configure.in | 3 + doc/examples/apt.conf | 37 ++++-- doc/method.sgml | 30 ++--- methods/copy.cc | 167 +++++++++----------------- methods/file.cc | 168 +++++++++------------------ methods/gzip.cc | 235 +++++++++++++------------------------ test/scratch.cc | 13 ++- 26 files changed, 916 insertions(+), 525 deletions(-) create mode 100644 AUTHORS create mode 100644 apt-pkg/acquire-method.cc create mode 100644 apt-pkg/acquire-method.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..a5bf6fcaa --- /dev/null +++ b/AUTHORS @@ -0,0 +1,36 @@ +NOTE: The ChangeLog generator will parse for names and email addresses. The +'CVS:' tag should indicate who this pair refers to. + +The project hierachy stands at: + +CVS:bcwhite Brian White +- Project Leader +- General organization, dispute resolution, final say on "capabilities" + +CVS:jgg Jason Gunthorpe +- Chief Programmer +- Code organization, task breakdown, final say on "code" + +CVS:tom Tom Lees +- Dpkg Consultant +- Make system +- Expert on compatibility with existing dpkg, dependency algorithms, etc. + +CVS:srivasta Manoj Srivastava +- Dependency Expert + +CVS:behanw Behan Webster +- Chief Designer +- Screen layout, ease of use, final say on "user interface" + +CVS:che Ben Gertzfield +- Documentation + +CVS:branden Branden Robinson +- Man Page Documentation + +CVS:scott Scott Ellis +- .deb archive creater + +CVS:doogie Adam Heath +- FTP method author \ No newline at end of file diff --git a/Makefile b/Makefile index bc623e246..9fa624ea8 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,9 @@ # This is the top level make file for APT, it recurses to each lower # level make file and runs it with the proper target +ifndef NOISY .SILENT: +endif .PHONY: headers library clean veryclean all 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 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 diff --git a/README.make b/README.make index bee2d04c3..1d87c02cb 100644 --- a/README.make +++ b/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 binaries are placed in bin, published headers for inter-component linking 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 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 ~~~~~ ~~~ ~~~~~~~~~ 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 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 diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 4435e2553..f8cc7a0de 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -46,13 +46,17 @@ pkgAcquire::Item::~Item() /*}}}*/ // 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) { - Status = StatError; - ErrorText = LookupTag(Message,"Message"); + Status = StatIdle; if (QueueCounter <= 1) + { + ErrorText = LookupTag(Message,"Message"); + Status = StatError; Owner->Dequeue(this); + } } /*}}}*/ // Acquire::Item::Done - Item downloaded OK /*{{{*/ diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc new file mode 100644 index 000000000..bd7dd6779 --- /dev/null +++ b/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 +#include +#include +#include +#include + +#include + /*}}}*/ + +// 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) +{ +} + /*}}}*/ + diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h new file mode 100644 index 000000000..74489913f --- /dev/null +++ b/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 +#include + +#ifdef __GNUG__ +#pragma interface "apt-pkg/acquire-method.h" +#endif + +class pkgAcqMethod +{ + protected: + + string CurrentURI; + string DestFile; + time_t LastModified; + + vector 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 diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 392c8ca47..5195b5b8d 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -218,7 +218,7 @@ bool pkgAcquire::Worker::RunMessages() { if (Itm == 0) { - _error->Warning("Method gave invalid 200 URI Start message"); + _error->Error("Method gave invalid 200 URI Start message"); break; } CurrentItem = Itm; @@ -233,7 +233,7 @@ bool pkgAcquire::Worker::RunMessages() { if (Itm == 0) { - _error->Warning("Method gave invalid 400 URI Failure message"); + _error->Error("Method gave invalid 201 URI Done message"); break; } @@ -248,7 +248,7 @@ bool pkgAcquire::Worker::RunMessages() { if (Itm == 0) { - _error->Warning("Method gave invalid 400 URI Failure message"); + _error->Error("Method gave invalid 400 URI Failure message"); break; } @@ -417,35 +417,3 @@ bool pkgAcquire::Worker::MethodFailure() 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; -} - /*}}}*/ diff --git a/apt-pkg/acquire-worker.h b/apt-pkg/acquire-worker.h index b0acde3e3..ad1ea9165 100644 --- a/apt-pkg/acquire-worker.h +++ b/apt-pkg/acquire-worker.h @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -13,7 +13,6 @@ #define PKGLIB_ACQUIRE_WORKER_H #include -#include #ifdef __GNUG__ #pragma interface "apt-pkg/acquire-worker.h" @@ -81,6 +80,4 @@ class pkgAcquire::Worker ~Worker(); }; -bool pkgInjectConfiguration(string &Message,Configuration &Cnf); - #endif diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 4ed21831d..3ed0e5d28 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -26,7 +26,7 @@ // Acquire::pkgAcquire - Constructor /*{{{*/ // --------------------------------------------------------------------- -/* */ +/* We grab some runtime state from the configuration space */ pkgAcquire::pkgAcquire() { Queues = 0; @@ -46,7 +46,7 @@ pkgAcquire::pkgAcquire() /*}}}*/ // Acquire::~pkgAcquire - Destructor /*{{{*/ // --------------------------------------------------------------------- -/* Free our memory */ +/* Free our memory, clean up the queues (destroy the workers) */ pkgAcquire::~pkgAcquire() { while (Items.size() != 0) @@ -69,7 +69,8 @@ pkgAcquire::~pkgAcquire() /*}}}*/ // 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) { Items.push_back(Itm); @@ -77,7 +78,7 @@ void pkgAcquire::Add(Item *Itm) /*}}}*/ // Acquire::Remove - Remove a item /*{{{*/ // --------------------------------------------------------------------- -/* */ +/* Remove an item from the acquire list. This is usually not used.. */ void pkgAcquire::Remove(Item *Itm) { for (vector::iterator I = Items.begin(); I < Items.end(); I++) @@ -89,7 +90,8 @@ void pkgAcquire::Remove(Item *Itm) /*}}}*/ // 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) { Work->NextAcquire = Workers; @@ -98,9 +100,14 @@ void pkgAcquire::Add(Worker *Work) /*}}}*/ // 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) { + if (Running == true) + abort(); + Worker **I = &Workers; for (; *I != 0;) { @@ -113,7 +120,10 @@ void pkgAcquire::Remove(Worker *Work) /*}}}*/ // 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) { // 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->Next = Queues; Queues = I; + + if (Running == true) + I->Startup(); } // Queue it into the named queue I->Enqueue(Itm,URI,Description); ToFetch++; - - if (Running == true) - I->Startup(); - + // Some trace stuff if (Debug == true) { @@ -149,12 +159,16 @@ void pkgAcquire::Enqueue(Item *Itm,string URI,string Description) /*}}}*/ // 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) { Queue *I = Queues; for (; I != 0; I = I->Next) I->Dequeue(Itm); + + if (Debug == true) + clog << "Dequeuing " << Itm->DestFile << endl; ToFetch--; } /*}}}*/ @@ -163,24 +177,20 @@ void pkgAcquire::Dequeue(Item *Itm) /* The string returned depends on the configuration settings and the method parameters. Given something like http://foo.org/bar it can 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) return string(); /* Single-Instance methods get exactly one queue per URI. This is also used for the Access queue method */ 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 /*{{{*/ @@ -234,7 +244,9 @@ void pkgAcquire::SetFds(int &Fd,fd_set *RSet,fd_set *WSet) /*}}}*/ // 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) { for (Worker *I = Workers; I != 0; I = I->NextAcquire) @@ -273,15 +285,26 @@ bool pkgAcquire::Run() Running = false; return _error->Errno("select","Select has failed"); } - + RunFds(&RFds,&WFds); + if (_error->PendingError() == true) + break; } for (Queue *I = Queues; I != 0; I = I->Next) I->Shutdown(); 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->Description = Description; Owner->QueueCounter++; + + if (Items->Next == 0) + Cycle(); } /*}}}*/ // Queue::Dequeue - Remove an item from the queue /*{{{*/ @@ -368,7 +394,8 @@ bool pkgAcquire::Queue::Startup() { Shutdown(); - pkgAcquire::MethodConfig *Cnf = Owner->GetConfig(URIAccess(Name)); + URI U(Name); + pkgAcquire::MethodConfig *Cnf = Owner->GetConfig(U.Access); if (Cnf == 0) return false; @@ -376,11 +403,8 @@ bool pkgAcquire::Queue::Startup() Owner->Add(Workers); if (Workers->Start() == false) return false; - - Items->Worker = Workers; - Workers->QueueItem(Items); - return true; + return Cycle(); } /*}}}*/ // 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 /*{{{*/ // --------------------------------------------------------------------- /* 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) { - 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; - 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); } /*}}}*/ diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h index 2e111cccd..20ce2873f 100644 --- a/apt-pkg/acquire.h +++ b/apt-pkg/acquire.h @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -80,6 +80,9 @@ class pkgAcquire // FDSET managers for derived classes void SetFds(int &Fd,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: @@ -129,6 +132,7 @@ class pkgAcquire::Queue bool Startup(); bool Shutdown(); + bool Cycle(); Queue(string Name,pkgAcquire *Owner); ~Queue(); diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index fa07ed35a..27299ec6a 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -212,6 +212,31 @@ bool Configuration::Exists(const char *Name) 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 /*{{{*/ // --------------------------------------------------------------------- diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index 14c80e4ad..cf5a90f57 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -65,6 +65,8 @@ class Configuration bool Exists(const char *Name); inline const Item *Tree(const char *Name) {return Lookup(Name,false);}; + + void Dump(); Configuration(); }; diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 68421a241..d6a7143e4 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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. @@ -308,17 +308,6 @@ string URItoFileName(string 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 /*{{{*/ // --------------------------------------------------------------------- /* 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; } /*}}}*/ + +// 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; +} + /*}}}*/ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index 1de2437b9..7e3e47344 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -32,7 +32,6 @@ string TimeToStr(unsigned long Sec); string SubstVar(string Str,string Subst,string Contents); string Base64Encode(string Str); string URItoFileName(string URI); -string URIAccess(string URI); string TimeRFC1123(time_t Date); bool StrToTime(string Val,time_t &Result); 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); 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 diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index 645d64d30..da11e3b40 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -9,6 +9,7 @@ /*}}}*/ // Include files /*{{{*/ #include +#include #include #include @@ -22,7 +23,7 @@ bool pkgInitialize(Configuration &Cnf) { // General APT things - Cnf.Set("APT::Architecture","i386"); + Cnf.Set("APT::Architecture",ARCHITECTURE); // State 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::sourcelist","sources.list"); Cnf.Set("Dir::Etc::main","apt.conf"); - + Cnf.Set("Dir::Bin::methods","/usr/lib/apt/metods"); + // Read the main config file string FName = Cnf.FindFile("Dir::Etc::main"); struct stat Buf; if (stat(FName.c_str(),&Buf) != 0) 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; } /*}}}*/ diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 5bf6f9a8b..733196bbe 100644 --- a/apt-pkg/makefile +++ b/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 \ orderlist.cc tagfile.cc sourcelist.cc packagemanager.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+= 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 \ packagemanager.h tagfile.h deblistparser.h init.h pkgcache.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)) diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 23fc344f3..91653f602 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -45,10 +45,7 @@ bool pkgTagFile::Step(pkgTagSection &Tag) return false; if (Tag.Scan(Start,End - Start) == false) - { - cout << string(Start,End-Start) << endl; return _error->Error("Unable to parse package file"); - } } Start += Tag.size(); iOffset += Tag.size(); @@ -87,10 +84,7 @@ bool pkgTagFile::Fill() else { if (Fd.Read(End,Size - (End - Buffer)) == false) - { - cout << "boink" << endl; return false; - } Left -= Size - (End - Buffer); End = Buffer + Size; diff --git a/buildlib/defaults.mak b/buildlib/defaults.mak index c6a2c15d7..9b011301e 100644 --- a/buildlib/defaults.mak +++ b/buildlib/defaults.mak @@ -26,7 +26,9 @@ # but by explicly setting the BUILD variable. Make is invoked from # within the source itself which is much more compatible with compilation # environments. +ifndef NOISY .SILENT: +endif # Search for the build directory ifdef BUILD @@ -51,7 +53,7 @@ BIN := $(BUILD)/bin LIB := $(BIN) OBJ := $(BUILD)/obj/$(SUBDIR) DEP := $(OBJ) -DOC := $(BUILD)/doc +DOC := $(BUILD)/docs # Module types LIBRARY_H = $(BASE)/buildlib/library.mak diff --git a/buildlib/makefile.in b/buildlib/makefile.in index 424ed1e46..de44f47b6 100644 --- a/buildlib/makefile.in +++ b/buildlib/makefile.in @@ -6,7 +6,7 @@ SRCDIR=@top_srcdir@ 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 BUILD:=$(shell pwd) export BUILD diff --git a/configure.in b/configure.in index 4d9a6ce15..100784474 100644 --- a/configure.in +++ b/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 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_CONFIG_AUX_DIR(buildlib) AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in) diff --git a/doc/examples/apt.conf b/doc/examples/apt.conf index dc2f9cc3a..bbc3c7ea4 100644 --- a/doc/examples/apt.conf +++ b/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 NOT actually be used as a real config file, though it is a completely 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 { Architecture "i386"; + // Options for apt-get Get { Download-Only "false"; Simulate "false"; @@ -15,17 +28,20 @@ APT { Show-Upgraded "false"; }; + // Some general options Ingore-Hold "false"; }; +// Options for the downloading routines Acquire { Queue-Mode "access"; // host|access }; +// Directory layout Dir { - + // Location of the state dir State "/var/state/apt/" { lists "lists/"; @@ -34,20 +50,23 @@ Dir status "/var/lib/dpkg/status"; }; + // Location of the cache dir Cache "/var/cache/apt/" { archives "archives/"; srcpkgcache "srcpkgcache.bin"; pkgcache "pkgcache.bin"; }; + // Config files Etc "/etc/apt/" { - sourcelist "sources.list.test"; + sourcelist "sources.list"; main "apt.conf"; }; + // Locations of binaries Bin { 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 { - pkgProblemResolver "true"; + pkgProblemResolver "false"; pkgAcquire "false"; - pkgAcquire::Worker "true"; + pkgAcquire::Worker "false"; + + pkgInitialize "false"; // This one will dump the configuration space } - -dir::state::lists "/tmp/lists/"; diff --git a/doc/method.sgml b/doc/method.sgml index 023bac40e..35070d919 100644 --- a/doc/method.sgml +++ b/doc/method.sgml @@ -4,7 +4,7 @@ APT Method Interface Jason Gunthorpe jgg@debian.org -$Id: method.sgml,v 1.3 1998/10/08 04:55:06 jgg Exp $ +$Id: method.sgml,v 1.4 1998/10/30 07:53:49 jgg Exp $ 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, stdin, stdout and stderr. -

-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. -

Throught operation of the method communication is done via http 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. 601 Configuration - Sends the configuration space 602 Authorization Credentials - Response to the 402 message 603 Media Changed - Response to the 403 message -605 Shutdown - Exit 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 URIURI being described by the message FilenameLocation in the filesystem Last-ModifiedA time stamp in RFC1123 notation for use by IMS checks +IMS-HitThe already existing item is valid SizeSize of the file in bytes Resume-PointLocation that transfer was started MD5-HashComputed MD5 hash for the file @@ -225,6 +216,8 @@ the ones it wants. This is a yes/no value. Pre-ScanMethod can detect if archives are already available. This is a yes/no value. +PipelineThe method is capable of pipelining. +Send-ConfigSend configuration to the method. VersionVersion string for the method @@ -232,8 +225,10 @@ This is a list of which headers each status code can use 100 Capabilities -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 101 Log A log message may be printed to the screen if debugging is enabled. This @@ -256,7 +251,9 @@ to specify a 201 URI Done without a URI Start which would 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 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 400 URI Failure @@ -305,11 +302,6 @@ Fields: Site, User, Password This is sent in response to a 403 Media Failure message. It indicates that the user has changed media and it is safe to proceed. Fields: Media - -605 Shutdown -APT sends this to signal the shutdown of the method. The method should -terminate immidiately. -Fields: None diff --git a/methods/copy.cc b/methods/copy.cc index b1c0fe360..e63801f38 100644 --- a/methods/copy.cc +++ b/methods/copy.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -10,130 +10,75 @@ /*}}}*/ // Include Files /*{{{*/ #include -#include +#include #include #include #include #include -#include /*}}}*/ -// 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 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(); } diff --git a/methods/file.cc b/methods/file.cc index fc42c2968..64490749b 100644 --- a/methods/file.cc +++ b/methods/file.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -13,132 +13,72 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#include -#include +#include +#include #include #include -#include /*}}}*/ -// 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 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(); } diff --git a/methods/gzip.cc b/methods/gzip.cc index 84ad472e9..acba7fc52 100644 --- a/methods/gzip.cc +++ b/methods/gzip.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // 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 @@ -11,8 +11,7 @@ // Include Files /*{{{*/ #include #include -#include -#include +#include #include #include @@ -22,166 +21,90 @@ #include /*}}}*/ -// 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 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(); } diff --git a/test/scratch.cc b/test/scratch.cc index a8817bc41..7cd43c554 100644 --- a/test/scratch.cc +++ b/test/scratch.cc @@ -2,10 +2,21 @@ #include #include #include +#include -int main() +int main(int argc,char *argv[]) { 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); -- cgit v1.2.3