]>
git.saurik.com Git - apt.git/blob - apt-private/private-show.cc
4 #include <apt-pkg/cachefile.h>
5 #include <apt-pkg/cacheset.h>
6 #include <apt-pkg/cmndline.h>
7 #include <apt-pkg/error.h>
8 #include <apt-pkg/fileutl.h>
9 #include <apt-pkg/indexfile.h>
10 #include <apt-pkg/pkgrecords.h>
11 #include <apt-pkg/pkgsystem.h>
12 #include <apt-pkg/sourcelist.h>
13 #include <apt-pkg/strutl.h>
14 #include <apt-pkg/tagfile.h>
15 #include <apt-pkg/cacheiterators.h>
16 #include <apt-pkg/configuration.h>
17 #include <apt-pkg/depcache.h>
18 #include <apt-pkg/macros.h>
19 #include <apt-pkg/pkgcache.h>
20 #include <apt-pkg/policy.h>
22 #include <apt-private/private-cacheset.h>
23 #include <apt-private/private-output.h>
24 #include <apt-private/private-show.h>
34 static bool OpenPackagesFile ( pkgCacheFile
& CacheFile
, pkgCache :: VerIterator
const & V
, /*{{{*/
35 FileFd
& PkgF
, pkgCache :: VerFileIterator
& Vf
)
37 pkgCache
const * const Cache
= CacheFile
. GetPkgCache ();
38 if ( unlikely ( Cache
== NULL
))
41 // Find an appropriate file
43 for (; Vf
. end () == false ; ++ Vf
)
44 if (( Vf
. File ()-> Flags
& pkgCache :: Flag :: NotSource
) == 0 )
49 // Check and load the package list file
50 pkgCache :: PkgFileIterator I
= Vf
. File ();
51 if ( I
. IsOk () == false )
52 return _error
-> Error ( _ ( "Package file %s is out of sync." ), I
. FileName ());
55 return PkgF
. Open ( I
. FileName (), FileFd :: ReadOnly
, FileFd :: Extension
);
58 static APT_PURE
unsigned char const * skipDescriptionFields ( unsigned char const * DescP
) /*{{{*/
60 char const * const TagName
= " \n Description" ;
61 size_t const TagLen
= strlen ( TagName
);
62 while (( DescP
= ( unsigned char *) strchr (( char *) DescP
, ' \n ' )) != NULL
)
66 else if ( strncmp (( char *) DescP
, TagName
, TagLen
) == 0 )
76 bool DisplayRecordV1 ( pkgCacheFile
& CacheFile
, pkgCache :: VerIterator
const & V
, /*{{{*/
80 pkgCache :: VerFileIterator Vf
;
81 if ( OpenPackagesFile ( CacheFile
, V
, PkgF
, Vf
) == false )
84 pkgCache
* const Cache
= CacheFile
. GetPkgCache ();
85 if ( unlikely ( Cache
== NULL
))
88 // Read the record (and ensure that it ends with a newline and NUL)
89 unsigned char * Buffer
= new unsigned char [ Cache
-> HeaderP
-> MaxVerFileSize
+ 2 ];
90 Buffer
[ Vf
-> Size
] = ' \n ' ;
91 Buffer
[ Vf
-> Size
+ 1 ] = '\0' ;
92 if ( PkgF
. Seek ( Vf
-> Offset
) == false ||
93 PkgF
. Read ( Buffer
, Vf
-> Size
) == false )
99 // Get a pointer to start of Description field
100 const unsigned char * DescP
= ( unsigned char *) strstr (( char *) Buffer
, " \n Description" );
104 DescP
= Buffer
+ Vf
-> Size
;
106 // Write all but Description
107 size_t const length
= DescP
- Buffer
;
108 if ( length
!= 0 && FileFd :: Write ( STDOUT_FILENO
, Buffer
, length
) == false )
114 // Show the right description
115 pkgRecords
Recs (* Cache
);
116 pkgCache :: DescIterator Desc
= V
. TranslatedDescription ();
117 if ( Desc
. end () == false )
119 pkgRecords :: Parser
& P
= Recs
. Lookup ( Desc
. FileList ());
120 out
<< "Description" << ( ( strcmp ( Desc
. LanguageCode (), "" ) != 0 ) ? "-" : "" ) << Desc
. LanguageCode () << ": " << P
. LongDesc ();
121 out
<< std :: endl
<< "Description-md5: " << Desc
. md5 () << std :: endl
;
123 // Find the first field after the description (if there is any)
124 DescP
= skipDescriptionFields ( DescP
);
126 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
128 // write the rest of the buffer, but skip mixed in Descriptions* fields
129 while ( DescP
!= NULL
)
131 const unsigned char * const Start
= DescP
;
132 const unsigned char * End
= ( unsigned char *) strstr (( char *) DescP
, " \n Description" );
135 End
= & Buffer
[ Vf
-> Size
];
140 ++ End
; // get the newline into the output
141 DescP
= skipDescriptionFields ( End
+ strlen ( "Description" ));
143 size_t const length
= End
- Start
;
144 if ( length
!= 0 && FileFd :: Write ( STDOUT_FILENO
, Start
, length
) == false )
150 // write a final newline after the last field
157 static bool DisplayRecordV2 ( pkgCacheFile
& CacheFile
, pkgCache :: VerIterator
const & V
, /*{{{*/
161 pkgCache :: VerFileIterator Vf
;
162 if ( OpenPackagesFile ( CacheFile
, V
, PkgF
, Vf
) == false )
165 // Check and load the package list file
166 pkgCache :: PkgFileIterator I
= Vf
. File ();
167 if ( I
. IsOk () == false )
168 return _error
-> Error ( _ ( "Package file %s is out of sync." ), I
. FileName ());
170 // find matching sources.list metaindex
171 pkgSourceList
* SrcList
= CacheFile
. GetSourceList ();
173 if ( SrcList
-> FindIndex ( I
, Index
) == false &&
174 _system
-> FindIndex ( I
, Index
) == false )
175 return _error
-> Error ( "Can not find indexfile for Package %s ( %s )" ,
176 V
. ParentPkg (). Name (), V
. VerStr ());
177 std :: string source_index_file
= Index
-> Describe ( true );
181 pkgTagFile
TagF (& PkgF
);
183 if ( TagF
. Jump ( Tags
, V
. FileList ()-> Offset
) == false )
184 return _error
-> Error ( "Internal Error, Unable to parse a package record" );
187 std :: string installed_size
;
188 if ( Tags
. FindI ( "Installed-Size" ) > 0 )
189 strprintf ( installed_size
, " %s B" , SizeToStr ( Tags
. FindI ( "Installed-Size" )* 1024 ). c_str ());
191 installed_size
= _ ( "unknown" );
192 std :: string package_size
;
193 if ( Tags
. FindI ( "Size" ) > 0 )
194 strprintf ( package_size
, " %s B" , SizeToStr ( Tags
. FindI ( "Size" )). c_str ());
196 package_size
= _ ( "unknown" );
198 const char * manual_installed
= nullptr ;
199 if ( V
. ParentPkg (). CurrentVer () == V
)
201 pkgDepCache
* depCache
= CacheFile
. GetDepCache ();
202 if ( unlikely ( depCache
== nullptr ))
204 pkgDepCache :: StateCache
& state
= (* depCache
)[ V
. ParentPkg ()];
205 manual_installed
= !( state
. Flags
& pkgCache :: Flag :: Auto
) ? "yes" : "no" ;
208 // FIXME: add verbose that does not do the removal of the tags?
209 std :: vector
< pkgTagSection :: Tag
> RW
;
210 // delete, apt-cache show has this info and most users do not care
211 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "MD5sum" ));
212 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "SHA1" ));
213 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "SHA256" ));
214 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "SHA512" ));
215 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Filename" ));
216 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Multi-Arch" ));
217 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Architecture" ));
218 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Conffiles" ));
219 // we use the translated description
220 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Description" ));
221 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Description-md5" ));
223 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "Package" , V
. ParentPkg (). FullName ( true )));
224 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "Installed-Size" , installed_size
));
225 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Size" ));
226 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "Download-Size" , package_size
));
228 if ( manual_installed
!= nullptr )
229 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "APT-Manual-Installed" , manual_installed
));
230 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "APT-Sources" , source_index_file
));
233 if ( stdoutfd
. OpenDescriptor ( STDOUT_FILENO
, FileFd :: WriteOnly
, false ) == false ||
234 Tags
. Write ( stdoutfd
, TFRewritePackageOrder
, RW
) == false || stdoutfd
. Close () == false )
235 return _error
-> Error ( "Internal Error, Unable to parse a package record" );
237 // write the description
238 pkgCache
* const Cache
= CacheFile
. GetPkgCache ();
239 if ( unlikely ( Cache
== NULL
))
241 pkgRecords
Recs (* Cache
);
242 // FIXME: show (optionally) all available translations(?)
243 pkgCache :: DescIterator Desc
= V
. TranslatedDescription ();
244 if ( Desc
. end () == false )
246 pkgRecords :: Parser
& P
= Recs
. Lookup ( Desc
. FileList ());
247 out
<< "Description: " << P
. LongDesc ();
250 // write a final newline (after the description)
251 out
<< std :: endl
<< std :: endl
;
256 bool ShowPackage ( CommandLine
& CmdL
) /*{{{*/
258 pkgCacheFile CacheFile
;
259 CacheSetHelperVirtuals
helper ( true , GlobalError :: NOTICE
);
260 APT :: CacheSetHelper :: VerSelector
const select
= _config
-> FindB ( "APT::Cache::AllVersions" , true ) ?
261 APT :: CacheSetHelper :: ALL
: APT :: CacheSetHelper :: CANDIDATE
;
262 if ( select
== APT :: CacheSetHelper :: CANDIDATE
&& CacheFile
. GetDepCache () == nullptr )
264 APT :: VersionList
const verset
= APT :: VersionList :: FromCommandLine ( CacheFile
, CmdL
. FileList
+ 1 , select
, helper
);
265 int const ShowVersion
= _config
-> FindI ( "APT::Cache::Show::Version" , 1 );
266 for ( APT :: VersionList :: const_iterator Ver
= verset
. begin (); Ver
!= verset
. end (); ++ Ver
)
267 if ( ShowVersion
<= 1 )
269 if ( DisplayRecordV1 ( CacheFile
, Ver
, std :: cout
) == false )
273 if ( DisplayRecordV2 ( CacheFile
, Ver
, c1out
) == false )
276 if ( select
== APT :: CacheSetHelper :: CANDIDATE
)
278 APT :: VersionList
const verset_all
= APT :: VersionList :: FromCommandLine ( CacheFile
, CmdL
. FileList
+ 1 , APT :: CacheSetHelper :: ALL
, helper
);
279 int const records
= verset_all
. size () - verset
. size ();
281 _error
-> Notice ( P_ ( "There is %i additional record. Please use the '-a' switch to see it" , "There are %i additional records. Please use the '-a' switch to see them." , records
), records
);
284 if ( _config
-> FindB ( "APT::Cache::ShowVirtuals" , false ) == true )
285 for ( APT :: PackageSet :: const_iterator Pkg
= helper
. virtualPkgs
. begin ();
286 Pkg
!= helper
. virtualPkgs
. end (); ++ Pkg
)
288 c1out
<< "Package: " << Pkg
. FullName ( true ) << std :: endl
;
289 c1out
<< "State: " << _ ( "not a real package (virtual)" ) << std :: endl
;
290 // FIXME: show providers, see private-cacheset.h
291 // CacheSetHelperAPTGet::showVirtualPackageErrors()
294 if ( verset
. empty () == true )
296 if ( helper
. virtualPkgs
. empty () == true )
297 return _error
-> Error ( _ ( "No packages found" ));
299 _error
-> Notice ( _ ( "No packages found" ));
305 static std :: string
Sha1FromString ( std :: string
const & input
) /*{{{*/
307 // XXX: move to hashes.h: HashString::FromString() ?
309 sha1
. Add ( input
. c_str (), input
. length ());
310 return sha1
. Result (). Value ();
313 bool ShowSrcPackage ( CommandLine
& CmdL
) /*{{{*/
315 pkgCacheFile CacheFile
;
316 pkgSourceList
* List
= CacheFile
. GetSourceList ();
317 if ( unlikely ( List
== NULL
))
320 // Create the text record parsers
321 pkgSrcRecords
SrcRecs (* List
);
322 if ( _error
-> PendingError () == true )
326 // avoid showing identical records
327 std :: set
< std :: string
> seen
;
328 for ( const char ** I
= CmdL
. FileList
+ 1 ; * I
!= 0 ; I
++)
332 pkgSrcRecords :: Parser
* Parse
;
333 bool found_this
= false ;
334 while (( Parse
= SrcRecs
. Find (* I
, false )) != 0 ) {
335 // SrcRecs.Find() will find both binary and source names
336 if ( _config
-> FindB ( "APT::Cache::Only-Source" , false ) == true )
337 if ( Parse
-> Package () != * I
)
339 std :: string sha1str
= Sha1FromString ( Parse
-> AsStr ());
340 if ( std :: find ( seen
. begin (), seen
. end (), sha1str
) == seen
. end ())
342 std :: cout
<< Parse
-> AsStr () << std :: endl
;;
345 seen
. insert ( sha1str
);
348 if ( found_this
== false ) {
349 _error
-> Warning ( _ ( "Unable to locate package %s " ),* I
);
354 _error
-> Notice ( _ ( "No packages found" ));
358 // Policy - Show the results of the preferences file /*{{{*/
359 bool Policy ( CommandLine
& CmdL
)
361 pkgCacheFile CacheFile
;
362 pkgSourceList
const * const SrcList
= CacheFile
. GetSourceList ();
363 if ( unlikely ( SrcList
== nullptr ))
365 pkgCache
* const Cache
= CacheFile
. GetPkgCache ();
366 if ( unlikely ( Cache
== nullptr ))
368 pkgPolicy
* const Plcy
= CacheFile
. GetPolicy ();
369 if ( unlikely ( Plcy
== nullptr ))
372 // Print out all of the package files
373 if ( CmdL
. FileList
[ 1 ] == 0 )
375 std :: cout
<< _ ( "Package files:" ) << std :: endl
;
376 for ( pkgCache :: PkgFileIterator F
= Cache
-> FileBegin (); F
. end () == false ; ++ F
)
378 if ( F
. Flagged ( pkgCache :: Flag :: NoPackages
))
380 // Locate the associated index files so we can derive a description
382 if ( SrcList
-> FindIndex ( F
, Indx
) == false &&
383 _system
-> FindIndex ( F
, Indx
) == false )
384 return _error
-> Error ( _ ( "Cache is out of sync, can't x-ref a package file" ));
387 Plcy
-> GetPriority ( F
), Indx
-> Describe ( true ). c_str ());
389 // Print the reference information for the package
390 std :: string Str
= F
. RelStr ();
391 if ( Str
. empty () == false )
392 printf ( " release %s \n " , F
. RelStr (). c_str ());
393 if ( F
. Site () != 0 && F
. Site ()[ 0 ] != 0 )
394 printf ( " origin %s \n " , F
. Site ());
397 // Show any packages have explicit pins
398 std :: cout
<< _ ( "Pinned packages:" ) << std :: endl
;
399 pkgCache :: PkgIterator I
= Cache
-> PkgBegin ();
400 for (; I
. end () != true ; ++ I
)
402 for ( pkgCache :: VerIterator V
= I
. VersionList (); ! V
. end (); ++ V
) {
403 auto Prio
= Plcy
-> GetPriority ( V
, false );
408 // Print the package name and the version we are forcing to
409 ioprintf ( std :: cout
, _ ( " %s -> %s with priority %d \n " ), I
. FullName ( true ). c_str (), V
. VerStr (), Prio
);
415 char const * const msgInstalled
= _ ( " Installed: " );
416 char const * const msgCandidate
= _ ( " Candidate: " );
417 short const InstalledLessCandidate
=
418 mbstowcs ( NULL
, msgInstalled
, 0 ) - mbstowcs ( NULL
, msgCandidate
, 0 );
419 short const deepInstalled
=
420 ( InstalledLessCandidate
< 0 ? ( InstalledLessCandidate
*- 1 ) : 0 ) - 1 ;
421 short const deepCandidate
=
422 ( InstalledLessCandidate
> 0 ? ( InstalledLessCandidate
) : 0 ) - 1 ;
424 // Print out detailed information for each package
425 APT :: CacheSetHelper
helper ( true , GlobalError :: NOTICE
);
426 APT :: PackageList pkgset
= APT :: PackageList :: FromCommandLine ( CacheFile
, CmdL
. FileList
+ 1 , helper
);
427 for ( APT :: PackageList :: const_iterator Pkg
= pkgset
. begin (); Pkg
!= pkgset
. end (); ++ Pkg
)
429 std :: cout
<< Pkg
. FullName ( true ) << ":" << std :: endl
;
432 std :: cout
<< msgInstalled
<< OutputInDepth ( deepInstalled
, " " );
433 if ( Pkg
-> CurrentVer
== 0 )
434 std :: cout
<< _ ( "(none)" ) << std :: endl
;
436 std :: cout
<< Pkg
. CurrentVer (). VerStr () << std :: endl
;
439 std :: cout
<< msgCandidate
<< OutputInDepth ( deepCandidate
, " " );
440 pkgCache :: VerIterator V
= Plcy
-> GetCandidateVer ( Pkg
);
442 std :: cout
<< _ ( "(none)" ) << std :: endl
;
444 std :: cout
<< V
. VerStr () << std :: endl
;
446 // Show the priority tables
447 std :: cout
<< _ ( " Version table:" ) << std :: endl
;
448 for ( V
= Pkg
. VersionList (); V
. end () == false ; ++ V
)
450 if ( Pkg
. CurrentVer () == V
)
451 std :: cout
<< " *** " << V
. VerStr ();
453 std :: cout
<< " " << V
. VerStr ();
455 std :: cout
<< " " << Plcy
-> GetPriority ( V
) << std :: endl
;
456 for ( pkgCache :: VerFileIterator VF
= V
. FileList (); VF
. end () == false ; ++ VF
)
458 // Locate the associated index files so we can derive a description
460 if ( SrcList
-> FindIndex ( VF
. File (), Indx
) == false &&
461 _system
-> FindIndex ( VF
. File (), Indx
) == false )
462 return _error
-> Error ( _ ( "Cache is out of sync, can't x-ref a package file" ));
463 printf ( " %4 i %s \n " , Plcy
-> GetPriority ( VF
. File ()),
464 Indx
-> Describe ( true ). c_str ());