]> git.saurik.com Git - apt.git/blob - apt-pkg/acquire-item.cc
4435e255356f1edb7845b08930507446cad5ddf2
[apt.git] / apt-pkg / acquire-item.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: acquire-item.cc,v 1.5 1998/10/26 07:11:43 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 /* */
33 pkgAcquire::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 /* */
42 pkgAcquire::Item::~Item()
43 {
44 Owner->Remove(this);
45 }
46 /*}}}*/
47 // Acquire::Item::Failed - Item failed to download /*{{{*/
48 // ---------------------------------------------------------------------
49 /* */
50 void pkgAcquire::Item::Failed(string Message)
51 {
52 Status = StatError;
53 ErrorText = LookupTag(Message,"Message");
54 if (QueueCounter <= 1)
55 Owner->Dequeue(this);
56 }
57 /*}}}*/
58 // Acquire::Item::Done - Item downloaded OK /*{{{*/
59 // ---------------------------------------------------------------------
60 /* */
61 void pkgAcquire::Item::Done(string,unsigned long,string)
62 {
63 Status = StatDone;
64 ErrorText = string();
65 Owner->Dequeue(this);
66 }
67 /*}}}*/
68 // Acquire::Item::Rename - Rename a file /*{{{*/
69 // ---------------------------------------------------------------------
70 /* This helper function is used by alot of item methods as thier final
71 step */
72 void pkgAcquire::Item::Rename(string From,string To)
73 {
74 if (rename(From.c_str(),To.c_str()) != 0)
75 {
76 char S[300];
77 sprintf(S,"rename failed, %s (%s -> %s).",strerror(errno),
78 From.c_str(),To.c_str());
79 Status = StatError;
80 ErrorText = S;
81 }
82 }
83 /*}}}*/
84
85 // AcqIndex::AcqIndex - Constructor /*{{{*/
86 // ---------------------------------------------------------------------
87 /* The package file is added to the queue and a second class is
88 instantiated to fetch the revision file */
89 pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,const pkgSourceList::Item *Location) :
90 Item(Owner), Location(Location)
91 {
92 Decompression = false;
93
94 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
95 DestFile += URItoFileName(Location->PackagesURI());
96
97 QueueURI(Location->PackagesURI() + ".gz",Location->PackagesInfo());
98
99 // Create the Release fetch class
100 new pkgAcqIndexRel(Owner,Location);
101 }
102 /*}}}*/
103 // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/
104 // ---------------------------------------------------------------------
105 /* The only header we use is the last-modified header. */
106 string pkgAcqIndex::Custom600Headers()
107 {
108 string Final = _config->FindDir("Dir::State::lists");
109 Final += URItoFileName(Location->PackagesURI());
110
111 struct stat Buf;
112 if (stat(Final.c_str(),&Buf) != 0)
113 return string();
114
115 return "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
116 }
117 /*}}}*/
118 // AcqIndex::Done - Finished a fetch /*{{{*/
119 // ---------------------------------------------------------------------
120 /* This goes through a number of states.. On the initial fetch the
121 method could possibly return an alternate filename which points
122 to the uncompressed version of the file. If this is so the file
123 is copied into the partial directory. In all other cases the file
124 is decompressed with a gzip uri. */
125 void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5)
126 {
127 Item::Done(Message,Size,MD5);
128
129 if (Decompression == true)
130 {
131 // Done, move it into position
132 string FinalFile = _config->FindDir("Dir::State::lists");
133 FinalFile += URItoFileName(Location->PackagesURI());
134 Rename(DestFile,FinalFile);
135 return;
136 }
137
138 // Handle the unzipd case
139 string FileName = LookupTag(Message,"Alt-Filename");
140 if (FileName.empty() == false)
141 {
142 // The files timestamp matches
143 if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
144 return;
145
146 Decompression = true;
147 DestFile += ".decomp";
148 QueueURI("copy:" + FileName,string());
149 return;
150 }
151
152 FileName = LookupTag(Message,"Filename");
153 if (FileName.empty() == true)
154 {
155 Status = StatError;
156 ErrorText = "Method gave a blank filename";
157 }
158
159 // The files timestamp matches
160 if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
161 return;
162
163 Decompression = true;
164 DestFile += ".decomp";
165 QueueURI("gzip:" + FileName,string());
166 }
167 /*}}}*/
168
169 // AcqIndexRel::pkgAcqIndexRel - Constructor /*{{{*/
170 // ---------------------------------------------------------------------
171 /* The Release file is added to the queue */
172 pkgAcqIndexRel::pkgAcqIndexRel(pkgAcquire *Owner,
173 const pkgSourceList::Item *Location) :
174 Item(Owner), Location(Location)
175 {
176 DestFile = _config->FindDir("Dir::State::lists") + "partial/";
177 DestFile += URItoFileName(Location->ReleaseURI());
178
179 QueueURI(Location->ReleaseURI(),Location->ReleaseInfo());
180 }
181 /*}}}*/
182 // AcqIndexRel::Custom600Headers - Insert custom request headers /*{{{*/
183 // ---------------------------------------------------------------------
184 /* The only header we use is the last-modified header. */
185 string pkgAcqIndexRel::Custom600Headers()
186 {
187 string Final = _config->FindDir("Dir::State::lists");
188 Final += URItoFileName(Location->ReleaseURI());
189
190 struct stat Buf;
191 if (stat(Final.c_str(),&Buf) != 0)
192 return string();
193
194 return "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
195 }
196 /*}}}*/
197 // AcqIndexRel::Done - Item downloaded OK /*{{{*/
198 // ---------------------------------------------------------------------
199 /* The release file was not placed into the download directory then
200 a copy URI is generated and it is copied there otherwise the file
201 in the partial directory is moved into .. and the URI is finished. */
202 void pkgAcqIndexRel::Done(string Message,unsigned long Size,string MD5)
203 {
204 Item::Done(Message,Size,MD5);
205
206 string FileName = LookupTag(Message,"Filename");
207 if (FileName.empty() == true)
208 {
209 Status = StatError;
210 ErrorText = "Method gave a blank filename";
211 return;
212 }
213
214 // The files timestamp matches
215 if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
216 return;
217
218 // We have to copy it into place
219 if (FileName != DestFile)
220 {
221 QueueURI("copy:" + FileName,string());
222 return;
223 }
224
225 // Done, move it into position
226 string FinalFile = _config->FindDir("Dir::State::lists");
227 FinalFile += URItoFileName(Location->ReleaseURI());
228 Rename(DestFile,FinalFile);
229 }
230 /*}}}*/