]>
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>
33 static bool OpenPackagesFile ( pkgCacheFile
& CacheFile
, pkgCache :: VerIterator
const & V
, /*{{{*/
34 FileFd
& PkgF
, pkgCache :: VerFileIterator
& Vf
)
36 pkgCache
const * const Cache
= CacheFile
. GetPkgCache ();
37 if ( unlikely ( Cache
== NULL
))
40 // Find an appropriate file
42 for (; Vf
. end () == false ; ++ Vf
)
43 if (( Vf
. File ()-> Flags
& pkgCache :: Flag :: NotSource
) == 0 )
48 // Check and load the package list file
49 pkgCache :: PkgFileIterator I
= Vf
. File ();
50 if ( I
. IsOk () == false )
51 return _error
-> Error ( _ ( "Package file %s is out of sync." ), I
. FileName ());
54 return PkgF
. Open ( I
. FileName (), FileFd :: ReadOnly
, FileFd :: Extension
);
57 static APT_PURE
unsigned char const * skipDescriptionFields ( unsigned char const * DescP
) /*{{{*/
59 char const * const TagName
= " \n Description" ;
60 size_t const TagLen
= strlen ( TagName
);
61 while (( DescP
= ( unsigned char *) strchr (( char *) DescP
, ' \n ' )) != NULL
)
65 else if ( strncmp (( char *) DescP
, TagName
, TagLen
) == 0 )
75 bool DisplayRecordV1 ( pkgCacheFile
& CacheFile
, pkgCache :: VerIterator
const & V
, /*{{{*/
79 pkgCache :: VerFileIterator Vf
;
80 if ( OpenPackagesFile ( CacheFile
, V
, PkgF
, Vf
) == false )
83 pkgCache
* const Cache
= CacheFile
. GetPkgCache ();
84 if ( unlikely ( Cache
== NULL
))
87 // Read the record (and ensure that it ends with a newline and NUL)
88 unsigned char * Buffer
= new unsigned char [ Cache
-> HeaderP
-> MaxVerFileSize
+ 2 ];
89 Buffer
[ Vf
-> Size
] = ' \n ' ;
90 Buffer
[ Vf
-> Size
+ 1 ] = '\0' ;
91 if ( PkgF
. Seek ( Vf
-> Offset
) == false ||
92 PkgF
. Read ( Buffer
, Vf
-> Size
) == false )
98 // Get a pointer to start of Description field
99 const unsigned char * DescP
= ( unsigned char *) strstr (( char *) Buffer
, " \n Description" );
103 DescP
= Buffer
+ Vf
-> Size
;
105 // Write all but Description
106 size_t const length
= DescP
- Buffer
;
107 if ( length
!= 0 && FileFd :: Write ( STDOUT_FILENO
, Buffer
, length
) == false )
113 // Show the right description
114 pkgRecords
Recs (* Cache
);
115 pkgCache :: DescIterator Desc
= V
. TranslatedDescription ();
116 if ( Desc
. end () == false )
118 pkgRecords :: Parser
& P
= Recs
. Lookup ( Desc
. FileList ());
119 out
<< "Description" << ( ( strcmp ( Desc
. LanguageCode (), "" ) != 0 ) ? "-" : "" ) << Desc
. LanguageCode () << ": " << P
. LongDesc ();
120 out
<< std :: endl
<< "Description-md5: " << Desc
. md5 () << std :: endl
;
122 // Find the first field after the description (if there is any)
123 DescP
= skipDescriptionFields ( DescP
);
125 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
127 // write the rest of the buffer, but skip mixed in Descriptions* fields
128 while ( DescP
!= NULL
)
130 const unsigned char * const Start
= DescP
;
131 const unsigned char * End
= ( unsigned char *) strstr (( char *) DescP
, " \n Description" );
134 End
= & Buffer
[ Vf
-> Size
];
139 ++ End
; // get the newline into the output
140 DescP
= skipDescriptionFields ( End
+ strlen ( "Description" ));
142 size_t const length
= End
- Start
;
143 if ( length
!= 0 && FileFd :: Write ( STDOUT_FILENO
, Start
, length
) == false )
149 // write a final newline after the last field
156 static bool DisplayRecordV2 ( pkgCacheFile
& CacheFile
, pkgCache :: VerIterator
const & V
, /*{{{*/
160 pkgCache :: VerFileIterator Vf
;
161 if ( OpenPackagesFile ( CacheFile
, V
, PkgF
, Vf
) == false )
164 // Check and load the package list file
165 pkgCache :: PkgFileIterator I
= Vf
. File ();
166 if ( I
. IsOk () == false )
167 return _error
-> Error ( _ ( "Package file %s is out of sync." ), I
. FileName ());
169 // find matching sources.list metaindex
170 pkgSourceList
* SrcList
= CacheFile
. GetSourceList ();
172 if ( SrcList
-> FindIndex ( I
, Index
) == false &&
173 _system
-> FindIndex ( I
, Index
) == false )
174 return _error
-> Error ( "Can not find indexfile for Package %s ( %s )" ,
175 V
. ParentPkg (). Name (), V
. VerStr ());
176 std :: string source_index_file
= Index
-> Describe ( true );
180 pkgTagFile
TagF (& PkgF
);
182 if ( TagF
. Jump ( Tags
, V
. FileList ()-> Offset
) == false )
183 return _error
-> Error ( "Internal Error, Unable to parse a package record" );
186 std :: string installed_size
;
187 if ( Tags
. FindI ( "Installed-Size" ) > 0 )
188 strprintf ( installed_size
, " %s B" , SizeToStr ( Tags
. FindI ( "Installed-Size" )* 1024 ). c_str ());
190 installed_size
= _ ( "unknown" );
191 std :: string package_size
;
192 if ( Tags
. FindI ( "Size" ) > 0 )
193 strprintf ( package_size
, " %s B" , SizeToStr ( Tags
. FindI ( "Size" )). c_str ());
195 package_size
= _ ( "unknown" );
197 const char * manual_installed
= nullptr ;
198 if ( V
. ParentPkg (). CurrentVer () == V
)
200 pkgDepCache
* depCache
= CacheFile
. GetDepCache ();
201 if ( unlikely ( depCache
== nullptr ))
203 pkgDepCache :: StateCache
& state
= (* depCache
)[ V
. ParentPkg ()];
204 manual_installed
= !( state
. Flags
& pkgCache :: Flag :: Auto
) ? "yes" : "no" ;
207 // FIXME: add verbose that does not do the removal of the tags?
208 std :: vector
< pkgTagSection :: Tag
> RW
;
209 // delete, apt-cache show has this info and most users do not care
210 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "MD5sum" ));
211 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "SHA1" ));
212 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "SHA256" ));
213 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "SHA512" ));
214 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Filename" ));
215 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Multi-Arch" ));
216 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Architecture" ));
217 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Conffiles" ));
218 // we use the translated description
219 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Description" ));
220 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Description-md5" ));
222 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "Package" , V
. ParentPkg (). FullName ( true )));
223 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "Installed-Size" , installed_size
));
224 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Size" ));
225 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "Download-Size" , package_size
));
227 if ( manual_installed
!= nullptr )
228 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "APT-Manual-Installed" , manual_installed
));
229 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "APT-Sources" , source_index_file
));
232 if ( stdoutfd
. OpenDescriptor ( STDOUT_FILENO
, FileFd :: WriteOnly
, false ) == false ||
233 Tags
. Write ( stdoutfd
, TFRewritePackageOrder
, RW
) == false || stdoutfd
. Close () == false )
234 return _error
-> Error ( "Internal Error, Unable to parse a package record" );
236 // write the description
237 pkgCache
* const Cache
= CacheFile
. GetPkgCache ();
238 if ( unlikely ( Cache
== NULL
))
240 pkgRecords
Recs (* Cache
);
241 // FIXME: show (optionally) all available translations(?)
242 pkgCache :: DescIterator Desc
= V
. TranslatedDescription ();
243 if ( Desc
. end () == false )
245 pkgRecords :: Parser
& P
= Recs
. Lookup ( Desc
. FileList ());
246 out
<< "Description: " << P
. LongDesc ();
249 // write a final newline (after the description)
250 out
<< std :: endl
<< std :: endl
;
255 bool ShowPackage ( CommandLine
& CmdL
) /*{{{*/
257 pkgCacheFile CacheFile
;
258 CacheSetHelperVirtuals
helper ( true , GlobalError :: NOTICE
);
259 APT :: CacheSetHelper :: VerSelector
const select
= _config
-> FindB ( "APT::Cache::AllVersions" , true ) ?
260 APT :: CacheSetHelper :: ALL
: APT :: CacheSetHelper :: CANDIDATE
;
261 APT :: VersionList
const verset
= APT :: VersionList :: FromCommandLine ( CacheFile
, CmdL
. FileList
+ 1 , select
, helper
);
262 int const ShowVersion
= _config
-> FindI ( "APT::Cache::Show::Version" , 1 );
263 for ( APT :: VersionList :: const_iterator Ver
= verset
. begin (); Ver
!= verset
. end (); ++ Ver
)
264 if ( ShowVersion
<= 1 )
266 if ( DisplayRecordV1 ( CacheFile
, Ver
, std :: cout
) == false )
270 if ( DisplayRecordV2 ( CacheFile
, Ver
, c1out
) == false )
273 if ( select
== APT :: CacheSetHelper :: CANDIDATE
)
275 APT :: VersionList
const verset_all
= APT :: VersionList :: FromCommandLine ( CacheFile
, CmdL
. FileList
+ 1 , APT :: CacheSetHelper :: ALL
, helper
);
276 int const records
= verset_all
. size () - verset
. size ();
278 _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
);
281 if ( _config
-> FindB ( "APT::Cache::ShowVirtuals" , false ) == true )
282 for ( APT :: PackageSet :: const_iterator Pkg
= helper
. virtualPkgs
. begin ();
283 Pkg
!= helper
. virtualPkgs
. end (); ++ Pkg
)
285 c1out
<< "Package: " << Pkg
. FullName ( true ) << std :: endl
;
286 c1out
<< "State: " << _ ( "not a real package (virtual)" ) << std :: endl
;
287 // FIXME: show providers, see private-cacheset.h
288 // CacheSetHelperAPTGet::showVirtualPackageErrors()
291 if ( verset
. empty () == true )
293 if ( helper
. virtualPkgs
. empty () == true )
294 return _error
-> Error ( _ ( "No packages found" ));
296 _error
-> Notice ( _ ( "No packages found" ));
302 static std :: string
Sha1FromString ( std :: string
const & input
) /*{{{*/
304 // XXX: move to hashes.h: HashString::FromString() ?
306 sha1
. Add ( input
. c_str (), input
. length ());
307 return sha1
. Result (). Value ();
310 bool ShowSrcPackage ( CommandLine
& CmdL
) /*{{{*/
312 pkgCacheFile CacheFile
;
313 pkgSourceList
* List
= CacheFile
. GetSourceList ();
314 if ( unlikely ( List
== NULL
))
317 // Create the text record parsers
318 pkgSrcRecords
SrcRecs (* List
);
319 if ( _error
-> PendingError () == true )
323 // avoid showing identical records
324 std :: set
< std :: string
> seen
;
325 for ( const char ** I
= CmdL
. FileList
+ 1 ; * I
!= 0 ; I
++)
329 pkgSrcRecords :: Parser
* Parse
;
330 bool found_this
= false ;
331 while (( Parse
= SrcRecs
. Find (* I
, false )) != 0 ) {
332 // SrcRecs.Find() will find both binary and source names
333 if ( _config
-> FindB ( "APT::Cache::Only-Source" , false ) == true )
334 if ( Parse
-> Package () != * I
)
336 std :: string sha1str
= Sha1FromString ( Parse
-> AsStr ());
337 if ( std :: find ( seen
. begin (), seen
. end (), sha1str
) == seen
. end ())
339 std :: cout
<< Parse
-> AsStr () << std :: endl
;;
342 seen
. insert ( sha1str
);
345 if ( found_this
== false ) {
346 _error
-> Warning ( _ ( "Unable to locate package %s " ),* I
);
351 _error
-> Notice ( _ ( "No packages found" ));
355 // Policy - Show the results of the preferences file /*{{{*/
356 bool Policy ( CommandLine
& CmdL
)
358 pkgCacheFile CacheFile
;
359 pkgCache
* Cache
= CacheFile
. GetPkgCache ();
360 pkgPolicy
* Plcy
= CacheFile
. GetPolicy ();
361 pkgSourceList
* SrcList
= CacheFile
. GetSourceList ();
362 if ( unlikely ( Cache
== NULL
|| Plcy
== NULL
|| SrcList
== NULL
))
365 // Print out all of the package files
366 if ( CmdL
. FileList
[ 1 ] == 0 )
368 std :: cout
<< _ ( "Package files:" ) << std :: endl
;
369 for ( pkgCache :: PkgFileIterator F
= Cache
-> FileBegin (); F
. end () == false ; ++ F
)
371 if ( F
. Flagged ( pkgCache :: Flag :: NoPackages
))
373 // Locate the associated index files so we can derive a description
375 if ( SrcList
-> FindIndex ( F
, Indx
) == false &&
376 _system
-> FindIndex ( F
, Indx
) == false )
377 return _error
-> Error ( _ ( "Cache is out of sync, can't x-ref a package file" ));
380 Plcy
-> GetPriority ( F
), Indx
-> Describe ( true ). c_str ());
382 // Print the reference information for the package
383 std :: string Str
= F
. RelStr ();
384 if ( Str
. empty () == false )
385 printf ( " release %s \n " , F
. RelStr (). c_str ());
386 if ( F
. Site () != 0 && F
. Site ()[ 0 ] != 0 )
387 printf ( " origin %s \n " , F
. Site ());
390 // Show any packages have explicit pins
391 std :: cout
<< _ ( "Pinned packages:" ) << std :: endl
;
392 pkgCache :: PkgIterator I
= Cache
-> PkgBegin ();
393 for (; I
. end () != true ; ++ I
)
395 for ( pkgCache :: VerIterator V
= I
. VersionList (); ! V
. end (); ++ V
) {
396 auto Prio
= Plcy
-> GetPriority ( V
, false );
401 // Print the package name and the version we are forcing to
402 ioprintf ( std :: cout
, _ ( " %s -> %s with priority %d \n " ), I
. FullName ( true ). c_str (), V
. VerStr (), Prio
);
408 char const * const msgInstalled
= _ ( " Installed: " );
409 char const * const msgCandidate
= _ ( " Candidate: " );
410 short const InstalledLessCandidate
=
411 mbstowcs ( NULL
, msgInstalled
, 0 ) - mbstowcs ( NULL
, msgCandidate
, 0 );
412 short const deepInstalled
=
413 ( InstalledLessCandidate
< 0 ? ( InstalledLessCandidate
*- 1 ) : 0 ) - 1 ;
414 short const deepCandidate
=
415 ( InstalledLessCandidate
> 0 ? ( InstalledLessCandidate
) : 0 ) - 1 ;
417 // Print out detailed information for each package
418 APT :: CacheSetHelper
helper ( true , GlobalError :: NOTICE
);
419 APT :: PackageList pkgset
= APT :: PackageList :: FromCommandLine ( CacheFile
, CmdL
. FileList
+ 1 , helper
);
420 for ( APT :: PackageList :: const_iterator Pkg
= pkgset
. begin (); Pkg
!= pkgset
. end (); ++ Pkg
)
422 std :: cout
<< Pkg
. FullName ( true ) << ":" << std :: endl
;
425 std :: cout
<< msgInstalled
<< OutputInDepth ( deepInstalled
, " " );
426 if ( Pkg
-> CurrentVer
== 0 )
427 std :: cout
<< _ ( "(none)" ) << std :: endl
;
429 std :: cout
<< Pkg
. CurrentVer (). VerStr () << std :: endl
;
432 std :: cout
<< msgCandidate
<< OutputInDepth ( deepCandidate
, " " );
433 pkgCache :: VerIterator V
= Plcy
-> GetCandidateVer ( Pkg
);
435 std :: cout
<< _ ( "(none)" ) << std :: endl
;
437 std :: cout
<< V
. VerStr () << std :: endl
;
439 // Show the priority tables
440 std :: cout
<< _ ( " Version table:" ) << std :: endl
;
441 for ( V
= Pkg
. VersionList (); V
. end () == false ; ++ V
)
443 if ( Pkg
. CurrentVer () == V
)
444 std :: cout
<< " *** " << V
. VerStr ();
446 std :: cout
<< " " << V
. VerStr ();
448 std :: cout
<< " " << Plcy
-> GetPriority ( V
) << std :: endl
;
449 for ( pkgCache :: VerFileIterator VF
= V
. FileList (); VF
. end () == false ; ++ VF
)
451 // Locate the associated index files so we can derive a description
453 if ( SrcList
-> FindIndex ( VF
. File (), Indx
) == false &&
454 _system
-> FindIndex ( VF
. File (), Indx
) == false )
455 return _error
-> Error ( _ ( "Cache is out of sync, can't x-ref a package file" ));
456 printf ( " %4 i %s \n " , Plcy
-> GetPriority ( VF
. File ()),
457 Indx
-> Describe ( true ). c_str ());