]> git.saurik.com Git - apt.git/blame_incremental - apt-pkg/acquire-item.cc
Working acquire code
[apt.git] / apt-pkg / acquire-item.cc
... / ...
CommitLineData
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3// $Id: acquire-item.cc,v 1.7 1998/11/05 07:21:35 jgg Exp $
4/* ######################################################################
5
6 Acquire Item - Item to acquire
7
8 Each item can download to exactly one file at a time. This means you
9 cannot create an item that fetches two uri's to two files at the same
10 time. The pkgAcqIndex class creates a second class upon instantiation
11 to fetch the other index files because of this.
12
13 ##################################################################### */
14 /*}}}*/
15// Include Files /*{{{*/
16#ifdef __GNUG__
17#pragma implementation "apt-pkg/acquire-item.h"
18#endif
19#include <apt-pkg/acquire-item.h>
20#include <apt-pkg/configuration.h>
21#include <strutl.h>
22
23#include <sys/stat.h>
24#include <unistd.h>
25#include <errno.h>
26#include <string.h>
27#include <stdio.h>
28 /*}}}*/
29
30// Acquire::Item::Item - Constructor /*{{{*/
31// ---------------------------------------------------------------------
32/* */
33pkgAcquire::Item::Item(pkgAcquire *Owner) : Owner(Owner), QueueCounter(0)
34{
35 Owner->Add(this);
36 Status = StatIdle;
37}
38 /*}}}*/
39// Acquire::Item::~Item - Destructor /*{{{*/
40// ---------------------------------------------------------------------
41/* */
42pkgAcquire::Item::~Item()
43{
44 Owner->Remove(this);
45}
46 /*}}}*/
47// Acquire::Item::Failed - Item failed to download /*{{{*/
48// ---------------------------------------------------------------------
49/* We return to an idle state if there are still other queues that could
50 fetch this object */
51void pkgAcquire::Item::Failed(string Message)
52{
53 Status = StatIdle;
54 if (QueueCounter <= 1)
55 {
56 ErrorText = LookupTag(Message,"Message");
57 Status = StatError;
58 Owner->Dequeue(this);
59 }
60}
61 /*}}}*/
62// Acquire::Item::Done - Item downloaded OK /*{{{*/
63// ---------------------------------------------------------------------
64/* */
65void pkgAcquire::Item::Done(string,unsigned long,string)
66{
67 Status = StatDone;
68 ErrorText = string();
69 Owner->Dequeue(this);
70}
71 /*}}}*/
72// Acquire::Item::Rename - Rename a file /*{{{*/
73// ---------------------------------------------------------------------
74/* This helper function is used by alot of item methods as thier final
75 step */
76void pkgAcquire::Item::Rename(string From,string To)
77{
78 if (rename(From.c_str(),To.c_str()) != 0)
79 {
80 char S[300];
81 sprintf(S,"rename failed, %s (%s -> %s).",strerror(errno),
82 From.c_str(),To.c_str());
83 Status = StatError;
84 ErrorText = S;
85 }
86}
87 /*}}}*/
88
89// AcqIndex::AcqIndex - Constructor /*{{{*/
90// ---------------------------------------------------------------------
91/* The package file is added to the queue and a second class is
92 instantiated to fetch the revision file */
93pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,const pkgSourceList::Item *Location) :
94 Item(Owner), Location(Location)
95{
96 Decompression = false;
97 Erase = false;
98
99 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
100 DestFile += URItoFileName(Location->PackagesURI());
101
102 QueueURI(Location->PackagesURI() + ".gz",Location->PackagesInfo());
103
104 // Create the Release fetch class
105 new pkgAcqIndexRel(Owner,Location);
106}
107 /*}}}*/
108// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
109// ---------------------------------------------------------------------
110/* The only header we use is the last-modified header. */
111string pkgAcqIndex::Custom600Headers()
112{
113 string Final = _config->FindDir("Dir::State::lists");
114 Final += URItoFileName(Location->PackagesURI());
115
116 struct stat Buf;
117 if (stat(Final.c_str(),&Buf) != 0)
118 return string();
119
120 return "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
121}
122 /*}}}*/
123// AcqIndex::Done - Finished a fetch /*{{{*/
124// ---------------------------------------------------------------------
125/* This goes through a number of states.. On the initial fetch the
126 method could possibly return an alternate filename which points
127 to the uncompressed version of the file. If this is so the file
128 is copied into the partial directory. In all other cases the file
129 is decompressed with a gzip uri. */
130void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5)
131{
132 Item::Done(Message,Size,MD5);
133
134 if (Decompression == true)
135 {
136 // Done, move it into position
137 string FinalFile = _config->FindDir("Dir::State::lists");
138 FinalFile += URItoFileName(Location->PackagesURI());
139 Rename(DestFile,FinalFile);
140
141 // Remove the compressed version.
142 if (Erase == true)
143 {
144 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
145 DestFile += URItoFileName(Location->PackagesURI());
146 unlink(DestFile.c_str());
147 }
148 return;
149 }
150
151 Erase = false;
152
153 // Handle the unzipd case
154 string FileName = LookupTag(Message,"Alt-Filename");
155 if (FileName.empty() == false)
156 {
157 // The files timestamp matches
158 if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
159 return;
160
161 Decompression = true;
162 DestFile += ".decomp";
163 QueueURI("copy:" + FileName,string());
164 return;
165 }
166
167 FileName = LookupTag(Message,"Filename");
168 if (FileName.empty() == true)
169 {
170 Status = StatError;
171 ErrorText = "Method gave a blank filename";
172 }
173
174 // The files timestamp matches
175 if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
176 return;
177
178 if (FileName == DestFile)
179 Erase = true;
180
181 Decompression = true;
182 DestFile += ".decomp";
183 QueueURI("gzip:" + FileName,string());
184}
185 /*}}}*/
186
187// AcqIndexRel::pkgAcqIndexRel - Constructor /*{{{*/
188// ---------------------------------------------------------------------
189/* The Release file is added to the queue */
190pkgAcqIndexRel::pkgAcqIndexRel(pkgAcquire *Owner,
191 const pkgSourceList::Item *Location) :
192 Item(Owner), Location(Location)
193{
194 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
195 DestFile += URItoFileName(Location->ReleaseURI());
196
197 QueueURI(Location->ReleaseURI(),Location->ReleaseInfo());
198}
199 /*}}}*/
200// AcqIndexRel::Custom600Headers - Insert custom request headers /*{{{*/
201// ---------------------------------------------------------------------
202/* The only header we use is the last-modified header. */
203string pkgAcqIndexRel::Custom600Headers()
204{
205 string Final = _config->FindDir("Dir::State::lists");
206 Final += URItoFileName(Location->ReleaseURI());
207
208 struct stat Buf;
209 if (stat(Final.c_str(),&Buf) != 0)
210 return string();
211
212 return "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
213}
214 /*}}}*/
215// AcqIndexRel::Done - Item downloaded OK /*{{{*/
216// ---------------------------------------------------------------------
217/* The release file was not placed into the download directory then
218 a copy URI is generated and it is copied there otherwise the file
219 in the partial directory is moved into .. and the URI is finished. */
220void pkgAcqIndexRel::Done(string Message,unsigned long Size,string MD5)
221{
222 Item::Done(Message,Size,MD5);
223
224 string FileName = LookupTag(Message,"Filename");
225 if (FileName.empty() == true)
226 {
227 Status = StatError;
228 ErrorText = "Method gave a blank filename";
229 return;
230 }
231
232 // The files timestamp matches
233 if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
234 return;
235
236 // We have to copy it into place
237 if (FileName != DestFile)
238 {
239 QueueURI("copy:" + FileName,string());
240 return;
241 }
242
243 // Done, move it into position
244 string FinalFile = _config->FindDir("Dir::State::lists");
245 FinalFile += URItoFileName(Location->ReleaseURI());
246 Rename(DestFile,FinalFile);
247}
248 /*}}}*/