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"
26 #include "zypp/zypp_detail/ZYppReadOnlyHack.h"
28 #define ZYPP_LOCK_FILE "/var/run/zypp.pid"
33 ///////////////////////////////////////////////////////////////////
35 { /////////////////////////////////////////////////////////////////
37 ///////////////////////////////////////////////////////////////////
38 namespace zypp_readonly_hack
39 { /////////////////////////////////////////////////////////////////
41 static bool active = false;
46 MIL << "ZYPP_READONLY promised." << endl;
49 /////////////////////////////////////////////////////////////////
50 } // namespace zypp_readonly_hack
51 ///////////////////////////////////////////////////////////////////
53 ///////////////////////////////////////////////////////////////////
55 // CLASS NAME : ZYppGlobalLock
57 ///////////////////////////////////////////////////////////////////
72 pid_t curr_pid = getpid();
75 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
81 MIL << "Cleaning lock file. (" << curr_pid << ")" << std::endl;
82 if ( filesystem::unlink(lock_file) == 0 )
83 MIL << "Lockfile cleaned. (" << curr_pid << ")" << std::endl;
85 ERR << "Cant clean lockfile. (" << curr_pid << ")" << std::endl;
89 catch(...) {} // let no exception escape.
97 void openLockFile(const char *mode)
99 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
100 _zypp_lockfile = fopen(lock_file.asString().c_str(), mode);
101 if (_zypp_lockfile == 0)
102 ZYPP_THROW (Exception( "Cant open " + lock_file.asString() + " in mode " + std::string(mode) ) );
107 fclose(_zypp_lockfile);
112 int fd = fileno(_zypp_lockfile);
113 int lock_error = flock(fd, LOCK_SH);
115 ZYPP_THROW (Exception( "Cant get shared lock"));
117 MIL << "locked (shared)" << std::endl;
122 int fd = fileno(_zypp_lockfile);
123 // lock access to the file
124 int lock_error = flock(fd, LOCK_EX);
126 ZYPP_THROW (Exception( "Cant get exclusive lock" ));
128 MIL << "locked (exclusive)" << std::endl;
133 int fd = fileno(_zypp_lockfile);
134 // lock access to the file
135 int lock_error = flock(fd, LOCK_UN);
137 ZYPP_THROW (Exception( "Cant release lock" ));
139 MIL << "unlocked" << std::endl;
142 bool lockFileExists()
144 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
145 // check if the file already existed.
146 bool exists = PathInfo(lock_file).isExist();
150 void createLockFile()
152 pid_t curr_pid = getpid();
155 fprintf(_zypp_lockfile, "%ld\n", (long) curr_pid);
156 fflush(_zypp_lockfile);
158 MIL << "written lockfile with pid " << curr_pid << std::endl;
162 bool isProcessRunning(pid_t pid)
164 // it is another program, not me, see if it is still running
166 ss << "/proc/" << pid << "/status";
167 Pathname procfile = Pathname(ss.str());
168 MIL << "Checking " << procfile << " to determine if pid is running: " << pid << std::endl;
169 bool still_running = PathInfo(procfile).isExist();
170 return still_running;
175 pid_t curr_pid = getpid();
176 pid_t locked_pid = 0;
179 fscanf(_zypp_lockfile, "%ld", &readpid);
180 MIL << "read: Lockfile " << ZYPP_LOCK_FILE << " has pid " << readpid << " (our pid: " << curr_pid << ") "<< std::endl;
181 locked_pid = (pid_t) readpid;
189 pid_t curr_pid = getpid();
190 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
192 if ( lockFileExists() )
194 MIL << "found lockfile " << lock_file << std::endl;
198 pid_t locker_pid = lockerPid();
199 if ( locker_pid == curr_pid )
201 // alles ok, we are requesting the instance again
202 //MIL << "Lockfile found, but it is myself. Assuming same process getting zypp instance again." << std::endl;
207 if ( isProcessRunning(locker_pid) )
209 if ( geteuid() == 0 )
212 MIL << locker_pid << " is running and has a ZYpp lock. Sorry" << std::endl;
217 MIL << locker_pid << " is running and has a ZYpp lock. Access as normal user allowed." << std::endl;
223 if ( geteuid() == 0 )
225 MIL << locker_pid << " has a ZYpp lock, but process is not running. Cleaning lock file." << std::endl;
226 if ( filesystem::unlink(lock_file) == 0 )
229 // now open it for reading
236 ERR << "Can't clean lockfile. Sorry, can't create a new lock. Zypp still locked." << std::endl;
242 MIL << locker_pid << " is running and has a ZYpp lock. Access as normal user allowed." << std::endl;
250 MIL << "no lockfile " << lock_file << " found" << std::endl;
251 if ( geteuid() == 0 )
253 MIL << "running as root. Will attempt to create " << lock_file << std::endl;
255 // now open it for reading
261 MIL << "running as user. Skipping creating " << lock_file << std::endl;
270 static ZYppGlobalLock globalLock;
272 ///////////////////////////////////////////////////////////////////
274 // CLASS NAME : ZYppFactoryException
276 ///////////////////////////////////////////////////////////////////
278 ZYppFactoryException::ZYppFactoryException( const std::string & msg_r )
279 : Exception(N_("Cannot aquire zypp lock."))
282 ///////////////////////////////////////////////////////////////////
284 // CLASS NAME : ZYppFactory
286 ///////////////////////////////////////////////////////////////////
288 ///////////////////////////////////////////////////////////////////
290 // METHOD NAME : ZYppFactory::instance
291 // METHOD TYPE : ZYppFactory
293 ZYppFactory ZYppFactory::instance()
295 return ZYppFactory();
298 ///////////////////////////////////////////////////////////////////
300 // METHOD NAME : ZYppFactory::ZYppFactory
301 // METHOD TYPE : Ctor
303 ZYppFactory::ZYppFactory()
308 ///////////////////////////////////////////////////////////////////
310 // METHOD NAME : ZYppFactory::~ZYppFactory
311 // METHOD TYPE : Dtor
313 ZYppFactory::~ZYppFactory()
316 ///////////////////////////////////////////////////////////////////
318 ZYpp::Ptr ZYppFactory::getZYpp() const
320 static ZYpp::Ptr _instance;
324 /*--------------------------------------------------*/
325 if ( zypp_readonly_hack::active )
327 _instance = new ZYpp( ZYpp::Impl_Ptr(new ZYpp::Impl) );
328 MIL << "ZYPP_READONLY active." << endl;
331 /*--------------------------------------------------*/
332 if ( globalLock.zyppLocked() )
334 ZYPP_THROW( ZYppFactoryException(N_("Cannot aquire zypp lock.")) );
338 _instance = new ZYpp( ZYpp::Impl_Ptr(new ZYpp::Impl) );
339 globalLock._clean_lock = true;
346 /******************************************************************
348 ** FUNCTION NAME : operator<<
349 ** FUNCTION TYPE : std::ostream &
351 std::ostream & operator<<( std::ostream & str, const ZYppFactory & obj )
353 return str << "ZYppFactory";
356 /////////////////////////////////////////////////////////////////
358 ///////////////////////////////////////////////////////////////////