]>
Commit | Line | Data |
---|---|---|
866893a6 DK |
1 | // Include Files /*{{{*/ |
2 | #include <config.h> | |
3 | ||
4 | #include <apt-pkg/acquire.h> | |
5 | #include <apt-pkg/acquire-item.h> | |
9055d5e6 DK |
6 | #include <apt-pkg/cacheset.h> |
7 | #include <apt-pkg/cmndline.h> | |
8 | #include <apt-pkg/clean.h> | |
866893a6 DK |
9 | #include <apt-pkg/configuration.h> |
10 | #include <apt-pkg/error.h> | |
460601d5 | 11 | #include <apt-pkg/fileutl.h> |
866893a6 DK |
12 | #include <apt-pkg/strutl.h> |
13 | ||
9055d5e6 | 14 | #include <apt-private/private-cachefile.h> |
453b82a3 | 15 | #include <apt-private/private-download.h> |
9055d5e6 DK |
16 | #include <apt-private/private-output.h> |
17 | #include <apt-private/private-utils.h> | |
2b0660b5 | 18 | #include <apt-private/acqprogress.h> |
866893a6 DK |
19 | |
20 | #include <fstream> | |
21 | #include <string> | |
22 | #include <vector> | |
23 | ||
460601d5 DK |
24 | #include <unistd.h> |
25 | #include <sys/types.h> | |
26 | #include <pwd.h> | |
27 | #include <fcntl.h> | |
2c391d85 | 28 | #ifdef HAVE_VFS_H |
9c81f8de | 29 | #include <sys/vfs.h> |
2c391d85 JAK |
30 | #else |
31 | #ifdef HAVE_PARAMS_H | |
32 | #include <sys/params.h> | |
33 | #endif | |
34 | #include <sys/mount.h> | |
35 | #endif | |
9c81f8de | 36 | #include <sys/statvfs.h> |
30c8107e | 37 | #include <sys/stat.h> |
9c81f8de | 38 | #include <errno.h> |
460601d5 | 39 | |
866893a6 DK |
40 | #include <apti18n.h> |
41 | /*}}}*/ | |
42 | ||
43 | // CheckAuth - check if each download comes form a trusted source /*{{{*/ | |
44 | bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser) | |
45 | { | |
9112f777 | 46 | std::vector<std::string> UntrustedList; |
866893a6 DK |
47 | for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I) |
48 | if (!(*I)->IsTrusted()) | |
9112f777 | 49 | UntrustedList.push_back((*I)->ShortDesc()); |
866893a6 | 50 | |
9112f777 | 51 | if (UntrustedList.empty()) |
866893a6 DK |
52 | return true; |
53 | ||
a3f1d60c MV |
54 | return AuthPrompt(UntrustedList, PromptUser); |
55 | } | |
2b0660b5 DK |
56 | /*}}}*/ |
57 | bool AuthPrompt(std::vector<std::string> const &UntrustedList, bool const PromptUser)/*{{{*/ | |
a3f1d60c | 58 | { |
9112f777 DK |
59 | ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"), UntrustedList, |
60 | [](std::string const&) { return true; }, | |
61 | [](std::string const&str) { return str; }, | |
62 | [](std::string const&) { return ""; }); | |
866893a6 DK |
63 | |
64 | if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true) | |
65 | { | |
66 | c2out << _("Authentication warning overridden.\n"); | |
67 | return true; | |
68 | } | |
69 | ||
70 | if (PromptUser == false) | |
71 | return _error->Error(_("Some packages could not be authenticated")); | |
72 | ||
73 | if (_config->FindI("quiet",0) < 2 | |
74 | && _config->FindB("APT::Get::Assume-Yes",false) == false) | |
75 | { | |
fd789740 | 76 | if (!YnPrompt(_("Install these packages without verification?"), false)) |
866893a6 DK |
77 | return _error->Error(_("Some packages could not be authenticated")); |
78 | ||
79 | return true; | |
80 | } | |
b381a482 JAK |
81 | else if (_config->FindB("APT::Get::Force-Yes",false) == true) { |
82 | _error->Warning(_("--force-yes is deprecated, use one of the options starting with --allow instead.")); | |
866893a6 | 83 | return true; |
b381a482 | 84 | } |
866893a6 | 85 | |
b381a482 | 86 | return _error->Error(_("There were unauthenticated packages and -y was used without --allow-unauthenticated")); |
866893a6 DK |
87 | } |
88 | /*}}}*/ | |
89 | bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure)/*{{{*/ | |
90 | { | |
91 | pkgAcquire::RunResult res; | |
92 | if(PulseInterval > 0) | |
93 | res = Fetcher.Run(PulseInterval); | |
94 | else | |
95 | res = Fetcher.Run(); | |
96 | ||
97 | if (res == pkgAcquire::Failed) | |
98 | return false; | |
99 | ||
100 | for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); | |
101 | I != Fetcher.ItemsEnd(); ++I) | |
102 | { | |
103 | ||
104 | if ((*I)->Status == pkgAcquire::Item::StatDone && | |
105 | (*I)->Complete == true) | |
106 | continue; | |
107 | ||
108 | if (TransientNetworkFailure != NULL && (*I)->Status == pkgAcquire::Item::StatIdle) | |
109 | { | |
110 | *TransientNetworkFailure = true; | |
111 | continue; | |
112 | } | |
113 | ||
114 | ::URI uri((*I)->DescURI()); | |
115 | uri.User.clear(); | |
116 | uri.Password.clear(); | |
117 | std::string descUri = std::string(uri); | |
3f760434 | 118 | _error->Error(_("Failed to fetch %s %s"), descUri.c_str(), |
866893a6 DK |
119 | (*I)->ErrorText.c_str()); |
120 | ||
121 | if (Failure != NULL) | |
122 | *Failure = true; | |
123 | } | |
124 | ||
125 | return true; | |
126 | } | |
127 | /*}}}*/ | |
9c81f8de DK |
128 | bool CheckFreeSpaceBeforeDownload(std::string const &Dir, unsigned long long FetchBytes)/*{{{*/ |
129 | { | |
130 | uint32_t const RAMFS_MAGIC = 0x858458f6; | |
131 | /* Check for enough free space, but only if we are actually going to | |
132 | download */ | |
133 | if (_config->FindB("APT::Get::Print-URIs", false) == true || | |
134 | _config->FindB("APT::Get::Download", true) == false) | |
135 | return true; | |
136 | ||
137 | struct statvfs Buf; | |
138 | if (statvfs(Dir.c_str(),&Buf) != 0) { | |
139 | if (errno == EOVERFLOW) | |
140 | return _error->WarningE("statvfs",_("Couldn't determine free space in %s"), | |
141 | Dir.c_str()); | |
142 | else | |
143 | return _error->Errno("statvfs",_("Couldn't determine free space in %s"), | |
144 | Dir.c_str()); | |
145 | } | |
146 | else | |
147 | { | |
148 | unsigned long long const FreeBlocks = _config->Find("APT::Sandbox::User").empty() ? Buf.f_bfree : Buf.f_bavail; | |
149 | if (FreeBlocks < (FetchBytes / Buf.f_bsize)) | |
150 | { | |
151 | struct statfs Stat; | |
152 | if (statfs(Dir.c_str(),&Stat) != 0 | |
f9de4208 | 153 | #ifdef HAVE_STRUCT_STATFS_F_TYPE |
9c81f8de DK |
154 | || Stat.f_type != RAMFS_MAGIC |
155 | #endif | |
156 | ) | |
157 | return _error->Error(_("You don't have enough free space in %s."), | |
158 | Dir.c_str()); | |
159 | } | |
160 | } | |
161 | return true; | |
162 | } | |
163 | /*}}}*/ | |
2b0660b5 DK |
164 | |
165 | aptAcquireWithTextStatus::aptAcquireWithTextStatus() : pkgAcquire::pkgAcquire(), | |
166 | Stat(std::cout, ScreenWidth, _config->FindI("quiet",0)) | |
167 | { | |
168 | SetLog(&Stat); | |
169 | } | |
9055d5e6 DK |
170 | |
171 | // DoDownload - download a binary /*{{{*/ | |
172 | bool DoDownload(CommandLine &CmdL) | |
173 | { | |
174 | CacheFile Cache; | |
175 | if (Cache.ReadOnlyOpen() == false) | |
176 | return false; | |
177 | ||
178 | APT::CacheSetHelper helper; | |
179 | APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache, | |
180 | CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper); | |
181 | ||
182 | if (verset.empty() == true) | |
183 | return false; | |
184 | ||
185 | pkgRecords Recs(Cache); | |
186 | pkgSourceList *SrcList = Cache.GetSourceList(); | |
187 | ||
188 | // reuse the usual acquire methods for deb files, but don't drop them into | |
189 | // the usual directories - keep everything in the current directory | |
190 | aptAcquireWithTextStatus Fetcher; | |
191 | std::vector<std::string> storefile(verset.size()); | |
192 | std::string const cwd = SafeGetCWD(); | |
193 | _config->Set("Dir::Cache::Archives", cwd); | |
194 | int i = 0; | |
195 | for (APT::VersionSet::const_iterator Ver = verset.begin(); | |
196 | Ver != verset.end(); ++Ver, ++i) | |
197 | { | |
198 | pkgAcquire::Item *I = new pkgAcqArchive(&Fetcher, SrcList, &Recs, *Ver, storefile[i]); | |
199 | if (storefile[i].empty()) | |
200 | continue; | |
201 | std::string const filename = cwd + flNotDir(storefile[i]); | |
202 | storefile[i].assign(filename); | |
203 | I->DestFile.assign(filename); | |
204 | } | |
205 | ||
206 | // Just print out the uris and exit if the --print-uris flag was used | |
207 | if (_config->FindB("APT::Get::Print-URIs") == true) | |
208 | { | |
209 | pkgAcquire::UriIterator I = Fetcher.UriBegin(); | |
210 | for (; I != Fetcher.UriEnd(); ++I) | |
211 | std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << | |
212 | I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl; | |
213 | return true; | |
214 | } | |
215 | ||
216 | if (_error->PendingError() == true || CheckAuth(Fetcher, false) == false) | |
217 | return false; | |
218 | ||
219 | bool Failed = false; | |
220 | if (AcquireRun(Fetcher, 0, &Failed, NULL) == false) | |
221 | return false; | |
222 | ||
223 | // copy files in local sources to the current directory | |
224 | for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) | |
225 | { | |
226 | std::string const filename = cwd + flNotDir((*I)->DestFile); | |
227 | if ((*I)->Local == true && | |
228 | filename != (*I)->DestFile && | |
229 | (*I)->Status == pkgAcquire::Item::StatDone) | |
230 | { | |
231 | std::ifstream src((*I)->DestFile.c_str(), std::ios::binary); | |
232 | std::ofstream dst(filename.c_str(), std::ios::binary); | |
233 | dst << src.rdbuf(); | |
30c8107e | 234 | chmod(filename.c_str(), 0644); |
9055d5e6 DK |
235 | } |
236 | } | |
237 | return Failed == false; | |
238 | } | |
239 | /*}}}*/ | |
240 | // DoChangelog - Get changelog from the command line /*{{{*/ | |
241 | bool DoChangelog(CommandLine &CmdL) | |
242 | { | |
243 | CacheFile Cache; | |
244 | if (Cache.ReadOnlyOpen() == false) | |
245 | return false; | |
246 | ||
247 | APT::CacheSetHelper helper; | |
248 | APT::VersionList verset = APT::VersionList::FromCommandLine(Cache, | |
249 | CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper); | |
250 | if (verset.empty() == true) | |
251 | return false; | |
252 | ||
253 | bool const downOnly = _config->FindB("APT::Get::Download-Only", false); | |
254 | bool const printOnly = _config->FindB("APT::Get::Print-URIs", false); | |
b5aba909 DK |
255 | if (printOnly) |
256 | _config->CndSet("Acquire::Changelogs::AlwaysOnline", true); | |
9055d5e6 DK |
257 | |
258 | aptAcquireWithTextStatus Fetcher; | |
259 | for (APT::VersionList::const_iterator Ver = verset.begin(); | |
260 | Ver != verset.end(); | |
261 | ++Ver) | |
262 | { | |
263 | if (printOnly) | |
264 | new pkgAcqChangelog(&Fetcher, Ver, "/dev/null"); | |
265 | else if (downOnly) | |
266 | new pkgAcqChangelog(&Fetcher, Ver, "."); | |
267 | else | |
268 | new pkgAcqChangelog(&Fetcher, Ver); | |
269 | } | |
270 | ||
271 | if (printOnly == false) | |
272 | { | |
273 | bool Failed = false; | |
274 | if (AcquireRun(Fetcher, 0, &Failed, NULL) == false || Failed == true) | |
275 | return false; | |
276 | } | |
277 | ||
278 | if (downOnly == false || printOnly == true) | |
279 | { | |
280 | bool Failed = false; | |
281 | for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) | |
282 | { | |
283 | if (printOnly) | |
284 | { | |
285 | if ((*I)->ErrorText.empty() == false) | |
286 | { | |
287 | Failed = true; | |
288 | _error->Error("%s", (*I)->ErrorText.c_str()); | |
289 | } | |
290 | else | |
291 | std::cout << '\'' << (*I)->DescURI() << "' " << flNotDir((*I)->DestFile) << std::endl; | |
292 | } | |
293 | else | |
294 | DisplayFileInPager((*I)->DestFile); | |
295 | } | |
296 | return Failed == false; | |
297 | } | |
298 | ||
299 | return true; | |
300 | } | |
301 | /*}}}*/ | |
302 | ||
303 | // DoClean - Remove download archives /*{{{*/ | |
304 | bool DoClean(CommandLine &) | |
305 | { | |
306 | std::string const archivedir = _config->FindDir("Dir::Cache::archives"); | |
307 | std::string const listsdir = _config->FindDir("Dir::state::lists"); | |
308 | ||
309 | if (_config->FindB("APT::Get::Simulate") == true) | |
310 | { | |
311 | std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache"); | |
312 | std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache"); | |
313 | std::cout << "Del " << archivedir << "* " << archivedir << "partial/*"<< std::endl | |
314 | << "Del " << listsdir << "partial/*" << std::endl | |
315 | << "Del " << pkgcache << " " << srcpkgcache << std::endl; | |
316 | return true; | |
317 | } | |
318 | ||
319 | pkgAcquire Fetcher; | |
8d968cc2 DK |
320 | if (archivedir.empty() == false && FileExists(archivedir) == true && |
321 | Fetcher.GetLock(archivedir) == true) | |
dffc17ba | 322 | { |
dffc17ba DK |
323 | Fetcher.Clean(archivedir); |
324 | Fetcher.Clean(archivedir + "partial/"); | |
325 | } | |
9055d5e6 | 326 | |
8d968cc2 DK |
327 | if (listsdir.empty() == false && FileExists(listsdir) == true && |
328 | Fetcher.GetLock(listsdir) == true) | |
dffc17ba | 329 | { |
dffc17ba DK |
330 | Fetcher.Clean(listsdir + "partial/"); |
331 | } | |
9055d5e6 DK |
332 | |
333 | pkgCacheFile::RemoveCaches(); | |
334 | ||
335 | return true; | |
336 | } | |
337 | /*}}}*/ | |
338 | // DoAutoClean - Smartly remove downloaded archives /*{{{*/ | |
339 | // --------------------------------------------------------------------- | |
340 | /* This is similar to clean but it only purges things that cannot be | |
341 | downloaded, that is old versions of cached packages. */ | |
342 | class LogCleaner : public pkgArchiveCleaner | |
343 | { | |
344 | protected: | |
345 | virtual void Erase(const char *File, std::string Pkg, std::string Ver,struct stat &St) APT_OVERRIDE | |
346 | { | |
347 | c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << std::endl; | |
348 | ||
349 | if (_config->FindB("APT::Get::Simulate") == false) | |
ce1f3a2c | 350 | RemoveFile("Cleaner::Erase", File); |
9055d5e6 DK |
351 | }; |
352 | }; | |
353 | bool DoAutoClean(CommandLine &) | |
354 | { | |
dffc17ba DK |
355 | std::string const archivedir = _config->FindDir("Dir::Cache::Archives"); |
356 | if (FileExists(archivedir) == false) | |
357 | return true; | |
358 | ||
9055d5e6 DK |
359 | // Lock the archive directory |
360 | FileFd Lock; | |
361 | if (_config->FindB("Debug::NoLocking",false) == false) | |
362 | { | |
dffc17ba | 363 | int lock_fd = GetLock(flCombine(archivedir, "lock")); |
9055d5e6 DK |
364 | if (lock_fd < 0) |
365 | return _error->Error(_("Unable to lock the download directory")); | |
366 | Lock.Fd(lock_fd); | |
367 | } | |
368 | ||
369 | CacheFile Cache; | |
370 | if (Cache.Open() == false) | |
371 | return false; | |
372 | ||
373 | LogCleaner Cleaner; | |
374 | ||
dffc17ba DK |
375 | return Cleaner.Go(archivedir, *Cache) && |
376 | Cleaner.Go(flCombine(archivedir, "partial/"), *Cache); | |
9055d5e6 DK |
377 | } |
378 | /*}}}*/ |