]>
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>
21 #include <apt-private/private-cacheset.h>
22 #include <apt-private/private-output.h>
23 #include <apt-private/private-show.h>
32 static bool OpenPackagesFile ( pkgCacheFile
& CacheFile
, pkgCache :: VerIterator
const & V
, /*{{{*/
33 FileFd
& PkgF
, pkgCache :: VerFileIterator
& Vf
)
35 pkgCache
const * const Cache
= CacheFile
. GetPkgCache ();
36 if ( unlikely ( Cache
== NULL
))
39 // Find an appropriate file
41 for (; Vf
. end () == false ; ++ Vf
)
42 if (( Vf
. File ()-> Flags
& pkgCache :: Flag :: NotSource
) == 0 )
47 // Check and load the package list file
48 pkgCache :: PkgFileIterator I
= Vf
. File ();
49 if ( I
. IsOk () == false )
50 return _error
-> Error ( _ ( "Package file %s is out of sync." ), I
. FileName ());
53 return PkgF
. Open ( I
. FileName (), FileFd :: ReadOnly
, FileFd :: Extension
);
56 static APT_PURE
unsigned char const * skipDescriptionFields ( unsigned char const * DescP
) /*{{{*/
58 char const * const TagName
= " \n Description" ;
59 size_t const TagLen
= strlen ( TagName
);
60 while (( DescP
= ( unsigned char *) strchr (( char *) DescP
, ' \n ' )) != NULL
)
64 else if ( strncmp (( char *) DescP
, TagName
, TagLen
) == 0 )
74 bool DisplayRecordV1 ( pkgCacheFile
& CacheFile
, pkgCache :: VerIterator
const & V
, /*{{{*/
78 pkgCache :: VerFileIterator Vf
;
79 if ( OpenPackagesFile ( CacheFile
, V
, PkgF
, Vf
) == false )
82 pkgCache
* const Cache
= CacheFile
. GetPkgCache ();
83 if ( unlikely ( Cache
== NULL
))
86 // Read the record (and ensure that it ends with a newline and NUL)
87 unsigned char * Buffer
= new unsigned char [ Cache
-> HeaderP
-> MaxVerFileSize
+ 2 ];
88 Buffer
[ Vf
-> Size
] = ' \n ' ;
89 Buffer
[ Vf
-> Size
+ 1 ] = '\0' ;
90 if ( PkgF
. Seek ( Vf
-> Offset
) == false ||
91 PkgF
. Read ( Buffer
, Vf
-> Size
) == false )
97 // Get a pointer to start of Description field
98 const unsigned char * DescP
= ( unsigned char *) strstr (( char *) Buffer
, " \n Description" );
102 DescP
= Buffer
+ Vf
-> Size
;
104 // Write all but Description
105 size_t const length
= DescP
- Buffer
;
106 if ( length
!= 0 && FileFd :: Write ( STDOUT_FILENO
, Buffer
, length
) == false )
112 // Show the right description
113 pkgRecords
Recs (* Cache
);
114 pkgCache :: DescIterator Desc
= V
. TranslatedDescription ();
115 if ( Desc
. end () == false )
117 pkgRecords :: Parser
& P
= Recs
. Lookup ( Desc
. FileList ());
118 out
<< "Description" << ( ( strcmp ( Desc
. LanguageCode (), "" ) != 0 ) ? "-" : "" ) << Desc
. LanguageCode () << ": " << P
. LongDesc ();
119 out
<< std :: endl
<< "Description-md5: " << Desc
. md5 () << std :: endl
;
121 // Find the first field after the description (if there is any)
122 DescP
= skipDescriptionFields ( DescP
);
124 // else we have no translation, so we found a lonely Description-md5 -> don't skip it
126 // write the rest of the buffer, but skip mixed in Descriptions* fields
127 while ( DescP
!= NULL
)
129 const unsigned char * const Start
= DescP
;
130 const unsigned char * End
= ( unsigned char *) strstr (( char *) DescP
, " \n Description" );
133 End
= & Buffer
[ Vf
-> Size
];
138 ++ End
; // get the newline into the output
139 DescP
= skipDescriptionFields ( End
+ strlen ( "Description" ));
141 size_t const length
= End
- Start
;
142 if ( length
!= 0 && FileFd :: Write ( STDOUT_FILENO
, Start
, length
) == false )
148 // write a final newline after the last field
155 static bool DisplayRecordV2 ( pkgCacheFile
& CacheFile
, pkgCache :: VerIterator
const & V
, /*{{{*/
159 pkgCache :: VerFileIterator Vf
;
160 if ( OpenPackagesFile ( CacheFile
, V
, PkgF
, Vf
) == false )
163 // Check and load the package list file
164 pkgCache :: PkgFileIterator I
= Vf
. File ();
165 if ( I
. IsOk () == false )
166 return _error
-> Error ( _ ( "Package file %s is out of sync." ), I
. FileName ());
168 // find matching sources.list metaindex
169 pkgSourceList
* SrcList
= CacheFile
. GetSourceList ();
171 if ( SrcList
-> FindIndex ( I
, Index
) == false &&
172 _system
-> FindIndex ( I
, Index
) == false )
173 return _error
-> Error ( "Can not find indexfile for Package %s ( %s )" ,
174 V
. ParentPkg (). Name (), V
. VerStr ());
175 std :: string source_index_file
= Index
-> Describe ( true );
179 pkgTagFile
TagF (& PkgF
);
181 if ( TagF
. Jump ( Tags
, V
. FileList ()-> Offset
) == false )
182 return _error
-> Error ( "Internal Error, Unable to parse a package record" );
185 std :: string installed_size
;
186 if ( Tags
. FindI ( "Installed-Size" ) > 0 )
187 strprintf ( installed_size
, " %s B" , SizeToStr ( Tags
. FindI ( "Installed-Size" )* 1024 ). c_str ());
189 installed_size
= _ ( "unknown" );
190 std :: string package_size
;
191 if ( Tags
. FindI ( "Size" ) > 0 )
192 strprintf ( package_size
, " %s B" , SizeToStr ( Tags
. FindI ( "Size" )). c_str ());
194 package_size
= _ ( "unknown" );
196 const char * manual_installed
= nullptr ;
197 if ( V
. ParentPkg (). CurrentVer () == V
)
199 pkgDepCache
* depCache
= CacheFile
. GetDepCache ();
200 if ( unlikely ( depCache
== nullptr ))
202 pkgDepCache :: StateCache
& state
= (* depCache
)[ V
. ParentPkg ()];
203 manual_installed
= !( state
. Flags
& pkgCache :: Flag :: Auto
) ? "yes" : "no" ;
206 // FIXME: add verbose that does not do the removal of the tags?
207 std :: vector
< pkgTagSection :: Tag
> RW
;
208 // delete, apt-cache show has this info and most users do not care
209 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "MD5sum" ));
210 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "SHA1" ));
211 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "SHA256" ));
212 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "SHA512" ));
213 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Filename" ));
214 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Multi-Arch" ));
215 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Architecture" ));
216 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Conffiles" ));
217 // we use the translated description
218 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Description" ));
219 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Description-md5" ));
221 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "Installed-Size" , installed_size
));
222 RW
. push_back ( pkgTagSection :: Tag :: Remove ( "Size" ));
223 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "Download-Size" , package_size
));
225 if ( manual_installed
!= nullptr )
226 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "APT-Manual-Installed" , manual_installed
));
227 RW
. push_back ( pkgTagSection :: Tag :: Rewrite ( "APT-Sources" , source_index_file
));
230 if ( stdoutfd
. OpenDescriptor ( STDOUT_FILENO
, FileFd :: WriteOnly
, false ) == false ||
231 Tags
. Write ( stdoutfd
, TFRewritePackageOrder
, RW
) == false || stdoutfd
. Close () == false )
232 return _error
-> Error ( "Internal Error, Unable to parse a package record" );
234 // write the description
235 pkgCache
* const Cache
= CacheFile
. GetPkgCache ();
236 if ( unlikely ( Cache
== NULL
))
238 pkgRecords
Recs (* Cache
);
239 // FIXME: show (optionally) all available translations(?)
240 pkgCache :: DescIterator Desc
= V
. TranslatedDescription ();
241 if ( Desc
. end () == false )
243 pkgRecords :: Parser
& P
= Recs
. Lookup ( Desc
. FileList ());
244 out
<< "Description: " << P
. LongDesc ();
247 // write a final newline (after the description)
248 out
<< std :: endl
<< std :: endl
;
253 bool ShowPackage ( CommandLine
& CmdL
) /*{{{*/
255 pkgCacheFile CacheFile
;
256 CacheSetHelperVirtuals
helper ( true , GlobalError :: NOTICE
);
257 APT :: CacheSetHelper :: VerSelector
const select
= _config
-> FindB ( "APT::Cache::AllVersions" , true ) ?
258 APT :: CacheSetHelper :: ALL
: APT :: CacheSetHelper :: CANDIDATE
;
259 APT :: VersionList
const verset
= APT :: VersionList :: FromCommandLine ( CacheFile
, CmdL
. FileList
+ 1 , select
, helper
);
260 int const ShowVersion
= _config
-> FindI ( "APT::Cache::Show::Version" , 1 );
261 for ( APT :: VersionList :: const_iterator Ver
= verset
. begin (); Ver
!= verset
. end (); ++ Ver
)
262 if ( ShowVersion
<= 1 )
264 if ( DisplayRecordV1 ( CacheFile
, Ver
, std :: cout
) == false )
268 if ( DisplayRecordV2 ( CacheFile
, Ver
, c1out
) == false )
271 if ( select
== APT :: CacheSetHelper :: CANDIDATE
)
273 APT :: VersionList
const verset_all
= APT :: VersionList :: FromCommandLine ( CacheFile
, CmdL
. FileList
+ 1 , APT :: CacheSetHelper :: ALL
, helper
);
274 int const records
= verset_all
. size () - verset
. size ();
276 _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
);
279 if ( _config
-> FindB ( "APT::Cache::ShowVirtuals" , false ) == true )
280 for ( APT :: PackageSet :: const_iterator Pkg
= helper
. virtualPkgs
. begin ();
281 Pkg
!= helper
. virtualPkgs
. end (); ++ Pkg
)
283 c1out
<< "Package: " << Pkg
. FullName ( true ) << std :: endl
;
284 c1out
<< "State: " << _ ( "not a real package (virtual)" ) << std :: endl
;
285 // FIXME: show providers, see private-cacheset.h
286 // CacheSetHelperAPTGet::showVirtualPackageErrors()
289 if ( verset
. empty () == true )
291 if ( helper
. virtualPkgs
. empty () == true )
292 return _error
-> Error ( _ ( "No packages found" ));
294 _error
-> Notice ( _ ( "No packages found" ));