1 // Include Files /*{{{*/
4 #include <apt-pkg/acquire.h>
5 #include <apt-pkg/acquire-item.h>
6 #include <apt-pkg/cacheset.h>
7 #include <apt-pkg/cmndline.h>
8 #include <apt-pkg/clean.h>
9 #include <apt-pkg/configuration.h>
10 #include <apt-pkg/error.h>
11 #include <apt-pkg/fileutl.h>
12 #include <apt-pkg/strutl.h>
14 #include <apt-private/private-cachefile.h>
15 #include <apt-private/private-download.h>
16 #include <apt-private/private-output.h>
17 #include <apt-private/private-utils.h>
18 #include <apt-private/acqprogress.h>
25 #include <sys/types.h>
29 #include <sys/statvfs.h>
36 // CheckAuth - check if each download comes form a trusted source /*{{{*/
37 bool CheckAuth(pkgAcquire
& Fetcher
, bool const PromptUser
)
39 std::vector
<std::string
> UntrustedList
;
40 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin(); I
< Fetcher
.ItemsEnd(); ++I
)
41 if (!(*I
)->IsTrusted())
42 UntrustedList
.push_back((*I
)->ShortDesc());
44 if (UntrustedList
.empty())
47 return AuthPrompt(UntrustedList
, PromptUser
);
50 bool AuthPrompt(std::vector
<std::string
> const &UntrustedList
, bool const PromptUser
)/*{{{*/
52 ShowList(c2out
,_("WARNING: The following packages cannot be authenticated!"), UntrustedList
,
53 [](std::string
const&) { return true; },
54 [](std::string
const&str
) { return str
; },
55 [](std::string
const&) { return ""; });
57 if (_config
->FindB("APT::Get::AllowUnauthenticated",false) == true)
59 c2out
<< _("Authentication warning overridden.\n");
63 if (PromptUser
== false)
64 return _error
->Error(_("Some packages could not be authenticated"));
66 if (_config
->FindI("quiet",0) < 2
67 && _config
->FindB("APT::Get::Assume-Yes",false) == false)
69 c2out
<< _("Install these packages without verification?") << std::flush
;
71 return _error
->Error(_("Some packages could not be authenticated"));
75 else if (_config
->FindB("APT::Get::Force-Yes",false) == true) {
76 _error
->Warning(_("--force-yes is deprecated, use one of the options starting with --allow instead."));
80 return _error
->Error(_("There were unauthenticated packages and -y was used without --allow-unauthenticated"));
83 bool AcquireRun(pkgAcquire
&Fetcher
, int const PulseInterval
, bool * const Failure
, bool * const TransientNetworkFailure
)/*{{{*/
85 pkgAcquire::RunResult res
;
87 res
= Fetcher
.Run(PulseInterval
);
91 if (res
== pkgAcquire::Failed
)
94 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin();
95 I
!= Fetcher
.ItemsEnd(); ++I
)
98 if ((*I
)->Status
== pkgAcquire::Item::StatDone
&&
99 (*I
)->Complete
== true)
102 if (TransientNetworkFailure
!= NULL
&& (*I
)->Status
== pkgAcquire::Item::StatIdle
)
104 *TransientNetworkFailure
= true;
108 ::URI
uri((*I
)->DescURI());
110 uri
.Password
.clear();
111 std::string descUri
= std::string(uri
);
112 _error
->Error(_("Failed to fetch %s %s"), descUri
.c_str(),
113 (*I
)->ErrorText
.c_str());
122 bool CheckFreeSpaceBeforeDownload(std::string
const &Dir
, unsigned long long FetchBytes
)/*{{{*/
124 uint32_t const RAMFS_MAGIC
= 0x858458f6;
125 /* Check for enough free space, but only if we are actually going to
127 if (_config
->FindB("APT::Get::Print-URIs", false) == true ||
128 _config
->FindB("APT::Get::Download", true) == false)
132 if (statvfs(Dir
.c_str(),&Buf
) != 0) {
133 if (errno
== EOVERFLOW
)
134 return _error
->WarningE("statvfs",_("Couldn't determine free space in %s"),
137 return _error
->Errno("statvfs",_("Couldn't determine free space in %s"),
142 unsigned long long const FreeBlocks
= _config
->Find("APT::Sandbox::User").empty() ? Buf
.f_bfree
: Buf
.f_bavail
;
143 if (FreeBlocks
< (FetchBytes
/ Buf
.f_bsize
))
146 if (statfs(Dir
.c_str(),&Stat
) != 0
147 #if HAVE_STRUCT_STATFS_F_TYPE
148 || Stat
.f_type
!= RAMFS_MAGIC
151 return _error
->Error(_("You don't have enough free space in %s."),
159 aptAcquireWithTextStatus::aptAcquireWithTextStatus() : pkgAcquire::pkgAcquire(),
160 Stat(std::cout
, ScreenWidth
, _config
->FindI("quiet",0))
165 // DoDownload - download a binary /*{{{*/
166 bool DoDownload(CommandLine
&CmdL
)
169 if (Cache
.ReadOnlyOpen() == false)
172 APT::CacheSetHelper helper
;
173 APT::VersionSet verset
= APT::VersionSet::FromCommandLine(Cache
,
174 CmdL
.FileList
+ 1, APT::CacheSetHelper::CANDIDATE
, helper
);
176 if (verset
.empty() == true)
179 pkgRecords
Recs(Cache
);
180 pkgSourceList
*SrcList
= Cache
.GetSourceList();
182 // reuse the usual acquire methods for deb files, but don't drop them into
183 // the usual directories - keep everything in the current directory
184 aptAcquireWithTextStatus Fetcher
;
185 std::vector
<std::string
> storefile(verset
.size());
186 std::string
const cwd
= SafeGetCWD();
187 _config
->Set("Dir::Cache::Archives", cwd
);
189 for (APT::VersionSet::const_iterator Ver
= verset
.begin();
190 Ver
!= verset
.end(); ++Ver
, ++i
)
192 pkgAcquire::Item
*I
= new pkgAcqArchive(&Fetcher
, SrcList
, &Recs
, *Ver
, storefile
[i
]);
193 if (storefile
[i
].empty())
195 std::string
const filename
= cwd
+ flNotDir(storefile
[i
]);
196 storefile
[i
].assign(filename
);
197 I
->DestFile
.assign(filename
);
200 // Just print out the uris and exit if the --print-uris flag was used
201 if (_config
->FindB("APT::Get::Print-URIs") == true)
203 pkgAcquire::UriIterator I
= Fetcher
.UriBegin();
204 for (; I
!= Fetcher
.UriEnd(); ++I
)
205 std::cout
<< '\'' << I
->URI
<< "' " << flNotDir(I
->Owner
->DestFile
) << ' ' <<
206 I
->Owner
->FileSize
<< ' ' << I
->Owner
->HashSum() << std::endl
;
210 if (_error
->PendingError() == true || CheckAuth(Fetcher
, false) == false)
214 if (AcquireRun(Fetcher
, 0, &Failed
, NULL
) == false)
217 // copy files in local sources to the current directory
218 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin(); I
!= Fetcher
.ItemsEnd(); ++I
)
220 std::string
const filename
= cwd
+ flNotDir((*I
)->DestFile
);
221 if ((*I
)->Local
== true &&
222 filename
!= (*I
)->DestFile
&&
223 (*I
)->Status
== pkgAcquire::Item::StatDone
)
225 std::ifstream
src((*I
)->DestFile
.c_str(), std::ios::binary
);
226 std::ofstream
dst(filename
.c_str(), std::ios::binary
);
228 chmod(filename
.c_str(), 0644);
231 return Failed
== false;
234 // DoChangelog - Get changelog from the command line /*{{{*/
235 bool DoChangelog(CommandLine
&CmdL
)
238 if (Cache
.ReadOnlyOpen() == false)
241 APT::CacheSetHelper helper
;
242 APT::VersionList verset
= APT::VersionList::FromCommandLine(Cache
,
243 CmdL
.FileList
+ 1, APT::CacheSetHelper::CANDIDATE
, helper
);
244 if (verset
.empty() == true)
247 bool const downOnly
= _config
->FindB("APT::Get::Download-Only", false);
248 bool const printOnly
= _config
->FindB("APT::Get::Print-URIs", false);
250 _config
->CndSet("Acquire::Changelogs::AlwaysOnline", true);
252 aptAcquireWithTextStatus Fetcher
;
253 for (APT::VersionList::const_iterator Ver
= verset
.begin();
258 new pkgAcqChangelog(&Fetcher
, Ver
, "/dev/null");
260 new pkgAcqChangelog(&Fetcher
, Ver
, ".");
262 new pkgAcqChangelog(&Fetcher
, Ver
);
265 if (printOnly
== false)
268 if (AcquireRun(Fetcher
, 0, &Failed
, NULL
) == false || Failed
== true)
272 if (downOnly
== false || printOnly
== true)
275 for (pkgAcquire::ItemIterator I
= Fetcher
.ItemsBegin(); I
!= Fetcher
.ItemsEnd(); ++I
)
279 if ((*I
)->ErrorText
.empty() == false)
282 _error
->Error("%s", (*I
)->ErrorText
.c_str());
285 std::cout
<< '\'' << (*I
)->DescURI() << "' " << flNotDir((*I
)->DestFile
) << std::endl
;
288 DisplayFileInPager((*I
)->DestFile
);
290 return Failed
== false;
297 // DoClean - Remove download archives /*{{{*/
298 bool DoClean(CommandLine
&)
300 std::string
const archivedir
= _config
->FindDir("Dir::Cache::archives");
301 std::string
const listsdir
= _config
->FindDir("Dir::state::lists");
303 if (_config
->FindB("APT::Get::Simulate") == true)
305 std::string
const pkgcache
= _config
->FindFile("Dir::cache::pkgcache");
306 std::string
const srcpkgcache
= _config
->FindFile("Dir::cache::srcpkgcache");
307 std::cout
<< "Del " << archivedir
<< "* " << archivedir
<< "partial/*"<< std::endl
308 << "Del " << listsdir
<< "partial/*" << std::endl
309 << "Del " << pkgcache
<< " " << srcpkgcache
<< std::endl
;
314 if (archivedir
.empty() == false && FileExists(archivedir
) == true &&
315 Fetcher
.GetLock(archivedir
) == true)
317 Fetcher
.Clean(archivedir
);
318 Fetcher
.Clean(archivedir
+ "partial/");
321 if (listsdir
.empty() == false && FileExists(listsdir
) == true &&
322 Fetcher
.GetLock(listsdir
) == true)
324 Fetcher
.Clean(listsdir
+ "partial/");
327 pkgCacheFile::RemoveCaches();
332 // DoAutoClean - Smartly remove downloaded archives /*{{{*/
333 // ---------------------------------------------------------------------
334 /* This is similar to clean but it only purges things that cannot be
335 downloaded, that is old versions of cached packages. */
336 class LogCleaner
: public pkgArchiveCleaner
339 virtual void Erase(const char *File
, std::string Pkg
, std::string Ver
,struct stat
&St
) APT_OVERRIDE
341 c1out
<< "Del " << Pkg
<< " " << Ver
<< " [" << SizeToStr(St
.st_size
) << "B]" << std::endl
;
343 if (_config
->FindB("APT::Get::Simulate") == false)
344 RemoveFile("Cleaner::Erase", File
);
347 bool DoAutoClean(CommandLine
&)
349 std::string
const archivedir
= _config
->FindDir("Dir::Cache::Archives");
350 if (FileExists(archivedir
) == false)
353 // Lock the archive directory
355 if (_config
->FindB("Debug::NoLocking",false) == false)
357 int lock_fd
= GetLock(flCombine(archivedir
, "lock"));
359 return _error
->Error(_("Unable to lock the download directory"));
364 if (Cache
.Open() == false)
369 return Cleaner
.Go(archivedir
, *Cache
) &&
370 Cleaner
.Go(flCombine(archivedir
, "partial/"), *Cache
);