libzypp: zypp/zypp_detail/ZYppImpl.cc Source File

libzypp 17.38.9

ZYppImpl.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12
13#include <iostream>
14#include <zypp/TmpPath.h>
15#include <zypp-core/base/Logger.h>
16#include <zypp-core/base/String.h>
17#include <zypp-core/base/Env.h>
18
19#include <zypp/zypp_detail/ZYppImpl.h>
20#include <zypp/target/TargetImpl.h>
21#include <zypp/ZYpp.h>
22#include <zypp/DiskUsageCounter.h>
23#include <zypp/ZConfig.h>
24#include <zypp/sat/Pool.h>
25#include <zypp/PoolItem.h>
26
27#include <zypp/ZYppCallbacks.h> // JobReport::instance
28
29using std::endl;
30
31#include <glib.h>
32#include <zypp-core/ng/base/private/linuxhelpers_p.h>
33#include <zypp-core/base/userrequestexception.h>
34
35namespace {
36
37 // Helper pipe to safely signal libzypp's poll code
38 // to stop polling and throw a user abort exception.
39 // Due to the pain that is unix signal handling we need
40 // to use atomics and be very careful about what we are calling.
41 //
42 // Not cleaned up, this happens when the application that is using libzypp
43 // exits.
44 volatile sig_atomic_t shutdownPipeRead{-1};
45 volatile sig_atomic_t shutdownPipeWrite{-1};
46
47 bool makeShutdownPipe() {
48 int pipeFds[]{ -1, -1 };
49 #ifdef HAVE_PIPE2
50 if ( ::pipe2( pipeFds, O_CLOEXEC ) != 0 )
51 return false;
52 #else
53 if ( ::pipe( pipeFds ) != 0 )
54 return false;
55 ::fcntl( pipeFds[0], F_SETFD, O_CLOEXEC );
56 ::fcntl( pipeFds[1], F_SETFD, O_CLOEXEC );
57 #endif
58 shutdownPipeRead = pipeFds[0];
59 shutdownPipeWrite = pipeFds[1];
60 return true;
61 }
62
63 const bool ensureShutdownPipe() {
64 static auto pipesInitialized = makeShutdownPipe();
65 return pipesInitialized;
66 }
67
68 const int shutdownPipeReadFd() {
69 if ( !ensureShutdownPipe() )
70 return -1;
71 return static_cast<int>(shutdownPipeRead);
72 }
73
74 const int shutdownPipeWriteFd() {
75 return static_cast<int>(shutdownPipeWrite);
76 }
77
78}
79
81namespace zypp
82{
83
85 namespace media
86 {
87 ScopedDisableMediaChangeReport::ScopedDisableMediaChangeReport( bool condition_r )
88 {
89 static weak_ptr<callback::TempConnect<media::MediaChangeReport> > globalguard;
90 if ( condition_r && ! (_guard = globalguard.lock()) )
91 {
92 // aquire a new one....
93 _guard.reset( new callback::TempConnect<media::MediaChangeReport>() );
94 globalguard = _guard;
95 }
96 }
97 } // namespace media
99
100 callback::SendReport<JobReport> & JobReport::instance()
101 {
102 static callback::SendReport<JobReport> _report;
103 return _report;
104 }
105
106
108 namespace zypp_detail
109 {
110
112 //
113 // METHOD NAME : ZYppImpl::ZYppImpl
114 // METHOD TYPE : Constructor
115 //
116 ZYppImpl::ZYppImpl()
117 : _target( nullptr )
118 , _resolver( new Resolver( ResPool::instance()) )
119 {
120 // trigger creation of the shutdown pipe
121 if ( !ensureShutdownPipe() )
122 WAR << "Failed to create shutdown pipe" << std::endl;
123
124 ZConfig::instance().about( MIL );
125 MIL << "Initializing keyring..." << std::endl;
126 _keyring = new KeyRing(tmpPath());
127 _keyring->allowPreload( true );
128 }
129
131 //
132 // METHOD NAME : ZYppImpl::~ZYppImpl
133 // METHOD TYPE : Destructor
134 //
135 ZYppImpl::~ZYppImpl()
136 {}
137
138 //------------------------------------------------------------------------
139 // add/remove resolvables
140
141 DiskUsageCounter::MountPointSet ZYppImpl::diskUsage()
142 {
143 if ( ! _disk_usage )
144 {
145 setPartitions( DiskUsageCounter::detectMountPoints() );
146 }
147 return _disk_usage->disk_usage(pool());
148 }
149
150 void ZYppImpl::setPartitions(const DiskUsageCounter::MountPointSet &mp)
151 {
152 _disk_usage.reset(new DiskUsageCounter());
153 _disk_usage->setMountPoints(mp);
154 }
155
156 DiskUsageCounter::MountPointSet ZYppImpl::getPartitions() const
157 {
158 if (_disk_usage)
159 return _disk_usage->getMountPoints();
160 else
161 return DiskUsageCounter::detectMountPoints();
162 }
163
164 //------------------------------------------------------------------------
165 // target
166
167 Target_Ptr ZYppImpl::target() const
168 {
169 if (! _target)
170 ZYPP_THROW(Exception("Target not initialized."));
171 return _target;
172 }
173
174 void ZYppImpl::changeTargetTo( const Target_Ptr& newtarget_r )
175 {
176 if ( _target && newtarget_r ) // bsc#1203760: Make sure the old target is deleted before a new one is created!
177 INT << "2 active targets at the same time must not happen!" << endl;
178 _target = newtarget_r;
179 ZConfig::instance().notifyTargetChanged();
180 resolver()->setDefaultSolverFlags( /*all_r*/false ); // just changed defaults
181 }
182
183 void ZYppImpl::initializeTarget( const Pathname & root, bool doRebuild_r )
184 {
185 MIL << "initTarget( " << root << (doRebuild_r?", rebuilddb":"") << ")" << endl;
186 if (_target) {
187 if (_target->root() == root) {
188 MIL << "Repeated call to initializeTarget()" << endl;
189 return;
190 }
191 _target->unload();
192 _target = nullptr; // bsc#1203760: Make sure the old target is deleted before a new one is created!
193 }
194 changeTargetTo( new Target( root, doRebuild_r ) );
195 _target->buildCache();
196 }
197
198 void ZYppImpl::finishTarget()
199 {
200 if (_target)
201 _target->unload();
202
203 changeTargetTo( nullptr );
204 }
205
206 //------------------------------------------------------------------------
207 // commit
208
211 ZYppCommitResult ZYppImpl::commit( const ZYppCommitPolicy & policy_r )
212 {
213 if ( getenv("ZYPP_TESTSUITE_FAKE_ARCH") )
214 {
215 ZYPP_THROW( Exception("ZYPP_TESTSUITE_FAKE_ARCH set. Commit not allowed and disabled.") );
216 }
217
218 MIL << "Attempt to commit (" << policy_r << ")" << endl;
219 if (! _target)
220 ZYPP_THROW( Exception("Target not initialized.") );
221
222
223 env::ScopedSet ea { "ZYPP_IS_RUNNING", str::numstring(getpid()).c_str() };
224 env::ScopedSet eb;
225 if ( _target->chrooted() )
226 eb = env::ScopedSet( "SYSTEMD_OFFLINE", "1" ); // bsc#1118758 - indicate no systemd if chrooted install
227 env::ScopedSet ec;
228 {
229 std::string val;
230 if ( const char * env = getenv("GLIBC_TUNABLES"); env ) { // colon-separated list of k=v pairs
231 val = env;
232 val += ":";
233 }
234 val += "glibc.cpu.hwcaps=-SSE4_1,-arch_3_00,-z13"; // bsc#1246912 - make ld.so ignore the subarch packages
235 ec = env::ScopedSet( "GLIBC_TUNABLES", val.c_str() );
236 }
237
238 ZYppCommitResult res = _target->_pimpl->commit( pool(), policy_r );
239
240 if (! policy_r.dryRun() )
241 {
242 if ( policy_r.syncPoolAfterCommit() )
243 {
244 // reload new status from target
245 DBG << "reloading " << sat::Pool::instance().systemRepoAlias() << " repo to pool" << endl;
246 _target->load();
247 }
248 else
249 {
250 DBG << "unloading " << sat::Pool::instance().systemRepoAlias() << " repo from pool" << endl;
251 _target->unload();
252 }
253 }
254
255 MIL << "Commit (" << policy_r << ") returned: "
256 << res << endl;
257 return res;
258 }
259
260 void ZYppImpl::installSrcPackage( const SrcPackage_constPtr & srcPackage_r )
261 {
262 if (! _target)
263 ZYPP_THROW( Exception("Target not initialized.") );
264 _target->_pimpl->installSrcPackage( srcPackage_r );
265 }
266
267 ManagedFile ZYppImpl::provideSrcPackage( const SrcPackage_constPtr & srcPackage_r )
268 {
269 if (! _target)
270 ZYPP_THROW( Exception("Target not initialized.") );
271 return _target->_pimpl->provideSrcPackage( srcPackage_r );
272 }
273
274 //------------------------------------------------------------------------
275 // target store path
276
277 Pathname ZYppImpl::homePath() const
278 { return _home_path.empty() ? Pathname("/var/lib/zypp") : _home_path; }
279
280 void ZYppImpl::setHomePath( const Pathname & path )
281 { _home_path = path; }
282
283 Pathname ZYppImpl::tmpPath() const
284 { return zypp::myTmpDir(); }
285
286 void ZYppImpl::setShutdownSignal()
287 {
288 // ONLY signal safe code here, that means no logging or anything else that is more than using atomics
289 // or writing a fd
290 int sigFd = shutdownPipeWriteFd();
291 if ( sigFd == -1 ) {
292 // we have no fd to set this
293 return;
294 }
295 zyppng::eintrSafeCall( write, sigFd, "1", 1 );
296 }
297
298 void ZYppImpl::clearShutdownSignal()
299 {
300 // ONLY signal safe code here, that means no logging or anything else that is more than using atomics
301 // or writing a fd
302 int sigFd = shutdownPipeWriteFd();
303 if ( sigFd == -1 ) {
304 // we have no fd so nothing to clear
305 return;
306 }
307
308 char buf = 0;
309 while( zyppng::eintrSafeCall( read, sigFd, &buf, 1 ) > 0 )
310 continue;
311 }
312
313 /******************************************************************
314 **
315 ** FUNCTION NAME : operator<<
316 ** FUNCTION TYPE : std::ostream &
317 */
318 std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj )
319 {
320 return str << "ZYppImpl";
321 }
322
323 int zypp_poll( std::vector<GPollFD> &fds, int timeout)
324 {
325 // request a shutdown fd we can use
326 const auto shutdownFd = shutdownPipeReadFd();
327 if (shutdownFd == -1) {
328 ZYPP_THROW( zypp::Exception("Failed to get shutdown pipe") );
329 }
330
331 fds.push_back( GPollFD {
332 .fd = shutdownFd,
333 .events = G_IO_IN,
334 .revents = 0
335 });
336
337 // make sure to remove our fd again
338 OnScopeExit removeShutdownFd( [&](){ fds.pop_back(); } );
339
340 int r = zyppng::eintrSafeCall( g_poll, fds.data(), fds.size(), timeout );
341 if ( r > 0 ) {
342 // at least one fd triggered, if its our's we throw
343 if ( fds.back().revents )
344 ZYPP_THROW( UserRequestException( UserRequestException::ABORT, "Shutdown signal received during poll." ) );
345 }
346 return r;
347 }
348
350 } // namespace zypp_detail
352
354} // namespace zypp
DiskUsageCounter.h
Env.h
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
Logger.h
DBG
#define DBG
Definition Logger.h:102
MIL
#define MIL
Definition Logger.h:103
WAR
#define WAR
Definition Logger.h:104
INT
#define INT
Definition Logger.h:107
PoolItem.h
Pool.h
String.h
TargetImpl.h
ZConfig.h
ZYppCallbacks.h
ZYppImpl.h
GPollFD
struct _GPollFD GPollFD
Definition ZYppImpl.h:26
ZYpp.h
Target_Ptr
weak_ptr
zypp::DiskUsageCounter
Compute disk space occupied by packages across partitions/directories.
Definition DiskUsageCounter.h:33
zypp::DiskUsageCounter::detectMountPoints
static MountPointSet detectMountPoints(const std::string &rootdir="/")
Get mountpoints of system below rootdir If we happen to detect snapshotting btrfs partitions,...
Definition DiskUsageCounter.cc:129
zypp::DiskUsageCounter::MountPointSet
std::set< MountPoint > MountPointSet
Definition DiskUsageCounter.h:154
zypp::Exception
Base class for Exception.
Definition Exception.h:153
zypp::KeyRing
Gpg key handling.
Definition KeyRing.h:170
zypp::ResPool
Global ResObject pool.
Definition ResPool.h:62
zypp::Resolver
Dependency resolver interface.
Definition Resolver.h:45
zypp::Target
Definition Target.h:51
zypp::UserRequestException
Base for exceptions caused by explicit user request.
Definition userrequestexception.h:65
zypp::UserRequestException::ABORT
@ ABORT
Definition userrequestexception.h:67
zypp::ZConfig::notifyTargetChanged
void notifyTargetChanged()
internal
Definition ZConfig.cc:790
zypp::ZConfig::instance
static ZConfig & instance()
Singleton ctor.
Definition ZConfig.cc:756
zypp::ZConfig::about
std::ostream & about(std::ostream &str) const
Print some detail about the current libzypp version.
Definition ZConfig.cc:1183
zypp::ZYppCommitPolicy
Options and policies for ZYpp::commit.
Definition ZYppCommitPolicy.h:34
zypp::ZYppCommitPolicy::syncPoolAfterCommit
ZYppCommitPolicy & syncPoolAfterCommit(bool yesNo_r)
Kepp pool in sync with the Target databases after commit (default: true).
Definition ZYppCommitPolicy.cc:196
zypp::ZYppCommitPolicy::dryRun
ZYppCommitPolicy & dryRun(bool yesNo_r)
Set dry run (default: false).
Definition ZYppCommitPolicy.cc:154
zypp::ZYppCommitResult
Result returned from ZYpp::commit.
Definition ZYppCommitResult.h:64
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:48
zypp::sat::Pool::instance
static Pool instance()
Singleton ctor.
Definition Pool.h:55
zypp::sat::Pool::systemRepoAlias
static const std::string & systemRepoAlias()
Reserved system repository alias @System .
Definition Pool.cc:46
zypp::zypp_detail::ZYppImpl::getPartitions
DiskUsageCounter::MountPointSet getPartitions() const
Definition ZYppImpl.cc:156
zypp::zypp_detail::ZYppImpl::pool
ResPool pool() const
Definition ZYppImpl.h:52
zypp::zypp_detail::ZYppImpl::ZYppImpl
ZYppImpl()
Default ctor.
Definition ZYppImpl.cc:116
zypp::zypp_detail::ZYppImpl::setPartitions
void setPartitions(const DiskUsageCounter::MountPointSet &mp)
Definition ZYppImpl.cc:150
zypp::zypp_detail::ZYppImpl::target
Target_Ptr target() const
Definition ZYppImpl.cc:167
zypp::zypp_detail::ZYppImpl::_keyring
KeyRing_Ptr _keyring
Definition ZYppImpl.h:134
zypp::zypp_detail::ZYppImpl::setHomePath
void setHomePath(const Pathname &path)
set the home, if you need to change it
Definition ZYppImpl.cc:280
zypp::zypp_detail::ZYppImpl::~ZYppImpl
~ZYppImpl()
Dtor.
Definition ZYppImpl.cc:135
zypp::zypp_detail::ZYppImpl::resolver
Resolver_Ptr resolver() const
Definition ZYppImpl.h:63
zypp::zypp_detail::ZYppImpl::tmpPath
Pathname tmpPath() const
Get the path where zypp related plugins store tmp data.
Definition ZYppImpl.cc:283
zypp::zypp_detail::ZYppImpl::commit
ZYppCommitResult commit(const ZYppCommitPolicy &policy_r)
Commit changes and transactions.
Definition ZYppImpl.cc:211
zypp::zypp_detail::ZYppImpl::finishTarget
void finishTarget()
Definition ZYppImpl.cc:198
zypp::zypp_detail::ZYppImpl::setShutdownSignal
static void setShutdownSignal()
Enable the shutdown signal for zypp_poll calls.
Definition ZYppImpl.cc:286
zypp::zypp_detail::ZYppImpl::installSrcPackage
void installSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Install a source package on the Target.
Definition ZYppImpl.cc:260
zypp::zypp_detail::ZYppImpl::_home_path
Pathname _home_path
Definition ZYppImpl.h:136
zypp::zypp_detail::ZYppImpl::_disk_usage
shared_ptr< DiskUsageCounter > _disk_usage
defined mount points, used for disk usage counting
Definition ZYppImpl.h:138
zypp::zypp_detail::ZYppImpl::provideSrcPackage
ManagedFile provideSrcPackage(const SrcPackage_constPtr &srcPackage_r)
Install a source package on the Target.
Definition ZYppImpl.cc:267
zypp::zypp_detail::ZYppImpl::changeTargetTo
void changeTargetTo(const Target_Ptr &newtarget_r)
Hook for actions to trigger if the Target changes (initialize/finish).
Definition ZYppImpl.cc:174
zypp::zypp_detail::ZYppImpl::homePath
Pathname homePath() const
Get the path where zypp related plugins store persistent data and caches.
Definition ZYppImpl.cc:277
zypp::zypp_detail::ZYppImpl::_resolver
Resolver_Ptr _resolver
Definition ZYppImpl.h:132
zypp::zypp_detail::ZYppImpl::diskUsage
DiskUsageCounter::MountPointSet diskUsage()
Definition ZYppImpl.cc:141
zypp::zypp_detail::ZYppImpl::clearShutdownSignal
static void clearShutdownSignal()
Disable the shutdown signal for zypp_poll calls.
Definition ZYppImpl.cc:298
zypp::zypp_detail::ZYppImpl::_target
Target_Ptr _target
Definition ZYppImpl.h:130
zypp::zypp_detail::ZYppImpl::initializeTarget
void initializeTarget(const Pathname &root, bool doRebuild_r)
Definition ZYppImpl.cc:183
linuxhelpers_p.h
str
String related utilities and Regular expression matching.
zypp::env
Namespace intended to collect all environment variables we use.
Definition RepoVariables.cc:34
zypp::media
Definition MediaNetworkRequestExecutor.h:22
zypp::str::numstring
std::string numstring(char n, int w=0)
Definition String.h:290
zypp::zypp_detail
Definition Target.h:38
zypp::zypp_detail::operator<<
std::ostream & operator<<(std::ostream &str, const ZYppImpl &obj)
relates: ZYppImpl Stream output
Definition ZYppImpl.cc:318
zypp::zypp_detail::zypp_poll
int zypp_poll(std::vector< GPollFD > &fds, int timeout)
Small wrapper around g_poll that additionally listens to the shutdown FD returned by ZYpp::shutdownSi...
Definition ZYppImpl.cc:323
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2
zypp::myTmpDir
Pathname myTmpDir()
Global access to the zypp.TMPDIR (created on demand, deleted when libzypp is unloaded).
Definition TmpPath.cc:276
zypp::ManagedFile
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
zypp::OnScopeExit
AutoDispose< void > OnScopeExit
Definition AutoDispose.h:276
zyppng::eintrSafeCall
auto eintrSafeCall(Fun &&function, Args &&... args)
Definition linuxhelpers_p.h:50
zypp::JobReport::instance
static callback::SendReport< JobReport > & instance()
Singleton sender instance.
Definition ZYppImpl.cc:100
zypp::callback::SendReport
Definition Callback.h:237
zypp::callback::TempConnect
Temporarily connect a ReceiveReport then restore the previous one.
Definition Callback.h:285
zypp::env::ScopedSet
Temporarily set/unset an environment variable.
Definition Env.h:45
zypp::media::ScopedDisableMediaChangeReport::ScopedDisableMediaChangeReport
ScopedDisableMediaChangeReport(bool condition_r=true)
Disbale MediaChangeReport if condition_r is true.
Definition ZYppImpl.cc:87
zypp::media::ScopedDisableMediaChangeReport::_guard
shared_ptr< callback::TempConnect< media::MediaChangeReport > > _guard
Definition ZYppCallbacks.h:358
userrequestexception.h
TmpPath.h