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 locked_pid = 0;
178 fscanf(_zypp_lockfile, "%ld", &readpid);
179 MIL << "read: Lockfile " << ZYPP_LOCK_FILE << " has pid " << readpid << std::endl;
180 locked_pid = (pid_t) readpid;
188 pid_t curr_pid = getpid();
189 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
191 if ( lockFileExists() )
196 pid_t locker_pid = lockerPid();
197 if ( locker_pid == curr_pid )
199 // alles ok, we are requesting the instance again
200 //MIL << "Lockfile found, but it is myself. Assuming same process getting zypp instance again." << std::endl;
205 if ( isProcessRunning(locker_pid) )
207 if ( geteuid() == 0 )
210 MIL << locker_pid << " is running and has a ZYpp lock. Sorry" << std::endl;
215 MIL << locker_pid << " is running and has a ZYpp lock. Access as normal user allowed." << std::endl;
221 if ( geteuid() == 0 )
223 MIL << locker_pid << " has a ZYpp lock, but process is not running. Cleaning lock file." << std::endl;
224 if ( filesystem::unlink(lock_file) == 0 )
227 // now open it for reading
234 ERR << "Can't clean lockfile. Sorry, can't create a new lock. Zypp still locked." << std::endl;
243 if ( geteuid() == 0 )
246 // now open it for reading
257 static ZYppGlobalLock globalLock;
259 ///////////////////////////////////////////////////////////////////
261 // CLASS NAME : ZYppFactoryException
263 ///////////////////////////////////////////////////////////////////
265 ZYppFactoryException::ZYppFactoryException( const std::string & msg_r )
266 : Exception(N_("Cannot aquire zypp lock."))
269 ///////////////////////////////////////////////////////////////////
271 // CLASS NAME : ZYppFactory
273 ///////////////////////////////////////////////////////////////////
275 ///////////////////////////////////////////////////////////////////
277 // METHOD NAME : ZYppFactory::instance
278 // METHOD TYPE : ZYppFactory
280 ZYppFactory ZYppFactory::instance()
282 return ZYppFactory();
285 ///////////////////////////////////////////////////////////////////
287 // METHOD NAME : ZYppFactory::ZYppFactory
288 // METHOD TYPE : Ctor
290 ZYppFactory::ZYppFactory()
295 ///////////////////////////////////////////////////////////////////
297 // METHOD NAME : ZYppFactory::~ZYppFactory
298 // METHOD TYPE : Dtor
300 ZYppFactory::~ZYppFactory()
303 ///////////////////////////////////////////////////////////////////
305 ZYpp::Ptr ZYppFactory::getZYpp() const
307 static ZYpp::Ptr _instance;
311 /*--------------------------------------------------*/
312 if ( zypp_readonly_hack::active )
314 _instance = new ZYpp( ZYpp::Impl_Ptr(new ZYpp::Impl) );
315 MIL << "ZYPP_READONLY active." << endl;
318 /*--------------------------------------------------*/
319 if ( globalLock.zyppLocked() )
321 ZYPP_THROW( ZYppFactoryException(N_("Cannot aquire zypp lock.")) );
325 _instance = new ZYpp( ZYpp::Impl_Ptr(new ZYpp::Impl) );
326 globalLock._clean_lock = true;
333 /******************************************************************
335 ** FUNCTION NAME : operator<<
336 ** FUNCTION TYPE : std::ostream &
338 std::ostream & operator<<( std::ostream & str, const ZYppFactory & obj )
340 return str << "ZYppFactory";
343 /////////////////////////////////////////////////////////////////
345 ///////////////////////////////////////////////////////////////////