1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/ZYppFactory.cc
20 #include "zypp/base/Logger.h"
21 #include "zypp/base/Gettext.h"
22 #include "zypp/PathInfo.h"
24 #include "zypp/ZYppFactory.h"
25 #include "zypp/zypp_detail/ZYppImpl.h"
27 #define ZYPP_LOCK_FILE "/var/run/zypp.pid"
32 ///////////////////////////////////////////////////////////////////
34 { /////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////
38 // CLASS NAME : ZYppGlobalLock
40 ///////////////////////////////////////////////////////////////////
46 ZYppGlobalLock() : _zypp_lockfile(0)
55 pid_t curr_pid = getpid();
58 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
62 MIL << "Cleaning lock file. (" << curr_pid << ")" << std::endl;
63 if ( filesystem::unlink(lock_file) == 0 )
64 MIL << "Lockfile cleaned. (" << curr_pid << ")" << std::endl;
66 ERR << "Cant clean lockfile. (" << curr_pid << ")" << std::endl;
69 catch(...) {} // let no exception escape.
75 void openLockFile(const char *mode)
77 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
78 _zypp_lockfile = fopen(lock_file.asString().c_str(), mode);
79 if (_zypp_lockfile == 0)
80 ZYPP_THROW (Exception( "Cant open " + lock_file.asString() + " in mode " + std::string(mode) ) );
85 fclose(_zypp_lockfile);
90 int fd = fileno(_zypp_lockfile);
91 int lock_error = flock(fd, LOCK_SH);
93 ZYPP_THROW (Exception( "Cant get shared lock"));
95 MIL << "locked (shared)" << std::endl;
100 int fd = fileno(_zypp_lockfile);
101 // lock access to the file
102 int lock_error = flock(fd, LOCK_EX);
104 ZYPP_THROW (Exception( "Cant get exclusive lock" ));
106 MIL << "locked (exclusive)" << std::endl;
111 int fd = fileno(_zypp_lockfile);
112 // lock access to the file
113 int lock_error = flock(fd, LOCK_UN);
115 ZYPP_THROW (Exception( "Cant release lock" ));
117 MIL << "unlocked" << std::endl;
120 bool lockFileExists()
122 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
123 // check if the file already existed.
124 bool exists = PathInfo(lock_file).isExist();
128 void createLockFile()
130 pid_t curr_pid = getpid();
133 fprintf(_zypp_lockfile, "%ld\n", (long) curr_pid);
134 fflush(_zypp_lockfile);
136 MIL << "written lockfile with pid " << curr_pid << std::endl;
140 bool isProcessRunning(pid_t pid)
142 // it is another program, not me, see if it is still running
144 ss << "/proc/" << pid << "/status";
145 Pathname procfile = Pathname(ss.str());
146 MIL << "Checking " << procfile << " to determine if pid is running: " << pid << std::endl;
147 bool still_running = PathInfo(procfile).isExist();
148 return still_running;
153 pid_t locked_pid = 0;
156 fscanf(_zypp_lockfile, "%ld", &readpid);
157 MIL << "read: Lockfile " << ZYPP_LOCK_FILE << " has pid " << readpid << std::endl;
158 locked_pid = (pid_t) readpid;
166 pid_t curr_pid = getpid();
167 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
169 if ( lockFileExists() )
174 pid_t locker_pid = lockerPid();
175 if ( locker_pid == curr_pid )
177 // alles ok, we are requesting the instance again
178 //MIL << "Lockfile found, but it is myself. Assuming same process getting zypp instance again." << std::endl;
183 if ( isProcessRunning(locker_pid) )
185 if ( geteuid() == 0 )
188 MIL << locker_pid << " is running and has a ZYpp lock. Sorry" << std::endl;
193 MIL << locker_pid << " is running and has a ZYpp lock. Access as normal user allowed." << std::endl;
199 if ( geteuid() == 0 )
201 MIL << locker_pid << " has a ZYpp lock, but process is not running. Cleaning lock file." << std::endl;
202 if ( filesystem::unlink(lock_file) == 0 )
205 // now open it for reading
212 ERR << "Can't clean lockfile. Sorry, can't create a new lock. Zypp still locked." << std::endl;
221 if ( geteuid() == 0 )
224 // now open it for reading
235 static ZYppGlobalLock globalLock;
237 ///////////////////////////////////////////////////////////////////
239 // CLASS NAME : ZYppFactoryException
241 ///////////////////////////////////////////////////////////////////
243 ZYppFactoryException::ZYppFactoryException( const std::string & msg_r )
244 : Exception(N_("Cannot aquire zypp lock."))
247 ///////////////////////////////////////////////////////////////////
249 // CLASS NAME : ZYppFactory
251 ///////////////////////////////////////////////////////////////////
253 ///////////////////////////////////////////////////////////////////
255 // METHOD NAME : ZYppFactory::instance
256 // METHOD TYPE : ZYppFactory
258 ZYppFactory ZYppFactory::instance()
260 return ZYppFactory();
263 ///////////////////////////////////////////////////////////////////
265 // METHOD NAME : ZYppFactory::ZYppFactory
266 // METHOD TYPE : Ctor
268 ZYppFactory::ZYppFactory()
273 ///////////////////////////////////////////////////////////////////
275 // METHOD NAME : ZYppFactory::~ZYppFactory
276 // METHOD TYPE : Dtor
278 ZYppFactory::~ZYppFactory()
281 ///////////////////////////////////////////////////////////////////
283 ZYpp::Ptr ZYppFactory::getZYpp() const
285 static ZYpp::Ptr _instance;
289 if ( globalLock.zyppLocked() )
291 ZYPP_THROW( ZYppFactoryException(N_("Cannot aquire zypp lock.")) );
295 _instance = new ZYpp( ZYpp::Impl_Ptr(new ZYpp::Impl) );
302 /******************************************************************
304 ** FUNCTION NAME : operator<<
305 ** FUNCTION TYPE : std::ostream &
307 std::ostream & operator<<( std::ostream & str, const ZYppFactory & obj )
309 return str << "ZYppFactory";
312 /////////////////////////////////////////////////////////////////
314 ///////////////////////////////////////////////////////////////////