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 ///////////////////////////////////////////////////////////////////
73 pid_t curr_pid = getpid();
76 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
82 MIL << "Cleaning lock file. (" << curr_pid << ")" << std::endl;
83 if ( filesystem::unlink(lock_file) == 0 )
84 MIL << "Lockfile cleaned. (" << curr_pid << ")" << std::endl;
86 ERR << "Cant clean lockfile. (" << curr_pid << ")" << std::endl;
90 catch(...) {} // let no exception escape.
93 pid_t locker_pid() const { return _locker_pid; }
101 void openLockFile(const char *mode)
103 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
104 _zypp_lockfile = fopen(lock_file.asString().c_str(), mode);
105 if (_zypp_lockfile == 0)
106 ZYPP_THROW (Exception( "Cant open " + lock_file.asString() + " in mode " + std::string(mode) ) );
111 fclose(_zypp_lockfile);
116 int fd = fileno(_zypp_lockfile);
117 int lock_error = flock(fd, LOCK_SH);
119 ZYPP_THROW (Exception( "Cant get shared lock"));
121 MIL << "locked (shared)" << std::endl;
126 int fd = fileno(_zypp_lockfile);
127 // lock access to the file
128 int lock_error = flock(fd, LOCK_EX);
130 ZYPP_THROW (Exception( "Cant get exclusive lock" ));
132 MIL << "locked (exclusive)" << std::endl;
137 int fd = fileno(_zypp_lockfile);
138 // lock access to the file
139 int lock_error = flock(fd, LOCK_UN);
141 ZYPP_THROW (Exception( "Cant release lock" ));
143 MIL << "unlocked" << std::endl;
146 bool lockFileExists()
148 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
149 // check if the file already existed.
150 bool exists = PathInfo(lock_file).isExist();
154 void createLockFile()
156 pid_t curr_pid = getpid();
159 fprintf(_zypp_lockfile, "%ld\n", (long) curr_pid);
160 fflush(_zypp_lockfile);
162 MIL << "written lockfile with pid " << curr_pid << std::endl;
166 bool isProcessRunning(pid_t pid)
168 // it is another program, not me, see if it is still running
170 ss << "/proc/" << pid << "/status";
171 Pathname procfile = Pathname(ss.str());
172 MIL << "Checking " << procfile << " to determine if pid is running: " << pid << std::endl;
173 bool still_running = PathInfo(procfile).isExist();
174 return still_running;
179 pid_t curr_pid = getpid();
180 pid_t locker_pid = 0;
183 fscanf(_zypp_lockfile, "%ld", &readpid);
184 MIL << "read: Lockfile " << ZYPP_LOCK_FILE << " has pid " << readpid << " (our pid: " << curr_pid << ") "<< std::endl;
185 locker_pid = (pid_t) readpid;
193 pid_t curr_pid = getpid();
194 Pathname lock_file = Pathname(ZYPP_LOCK_FILE);
196 if ( lockFileExists() )
198 MIL << "found lockfile " << lock_file << std::endl;
202 pid_t locker_pid = lockerPid();
203 _locker_pid = locker_pid;
204 if ( locker_pid == curr_pid )
206 // alles ok, we are requesting the instance again
207 //MIL << "Lockfile found, but it is myself. Assuming same process getting zypp instance again." << std::endl;
212 if ( isProcessRunning(locker_pid) )
214 if ( geteuid() == 0 )
217 MIL << locker_pid << " is running and has a ZYpp lock. Sorry" << std::endl;
222 MIL << locker_pid << " is running and has a ZYpp lock. Access as normal user allowed." << std::endl;
228 if ( geteuid() == 0 )
230 MIL << locker_pid << " has a ZYpp lock, but process is not running. Cleaning lock file." << std::endl;
231 if ( filesystem::unlink(lock_file) == 0 )
234 // now open it for reading
241 ERR << "Can't clean lockfile. Sorry, can't create a new lock. Zypp still locked." << std::endl;
247 MIL << locker_pid << " is running and has a ZYpp lock. Access as normal user allowed." << std::endl;
255 MIL << "no lockfile " << lock_file << " found" << std::endl;
256 if ( geteuid() == 0 )
258 MIL << "running as root. Will attempt to create " << lock_file << std::endl;
260 // now open it for reading
266 MIL << "running as user. Skipping creating " << lock_file << std::endl;
275 static ZYppGlobalLock globalLock;
277 ///////////////////////////////////////////////////////////////////
279 // CLASS NAME : ZYppFactoryException
281 ///////////////////////////////////////////////////////////////////
283 ZYppFactoryException::ZYppFactoryException( const std::string & msg_r, pid_t locker_pid )
285 _locker_pid (locker_pid)
288 ///////////////////////////////////////////////////////////////////
290 // CLASS NAME : ZYppFactory
292 ///////////////////////////////////////////////////////////////////
294 ///////////////////////////////////////////////////////////////////
296 // METHOD NAME : ZYppFactory::instance
297 // METHOD TYPE : ZYppFactory
299 ZYppFactory ZYppFactory::instance()
301 return ZYppFactory();
304 ///////////////////////////////////////////////////////////////////
306 // METHOD NAME : ZYppFactory::ZYppFactory
307 // METHOD TYPE : Ctor
309 ZYppFactory::ZYppFactory()
314 ///////////////////////////////////////////////////////////////////
316 // METHOD NAME : ZYppFactory::~ZYppFactory
317 // METHOD TYPE : Dtor
319 ZYppFactory::~ZYppFactory()
322 ///////////////////////////////////////////////////////////////////
324 ZYpp::Ptr ZYppFactory::getZYpp() const
326 static ZYpp::Ptr _instance;
330 /*--------------------------------------------------*/
331 if ( zypp_readonly_hack::active )
333 _instance = new ZYpp( ZYpp::Impl_Ptr(new ZYpp::Impl) );
334 MIL << "ZYPP_READONLY active." << endl;
337 /*--------------------------------------------------*/
338 if ( globalLock.zyppLocked() )
340 ZYPP_THROW( ZYppFactoryException(N_("Software management is already running."),
341 globalLock.locker_pid()) );
345 _instance = new ZYpp( ZYpp::Impl_Ptr(new ZYpp::Impl) );
346 globalLock._clean_lock = true;
353 /******************************************************************
355 ** FUNCTION NAME : operator<<
356 ** FUNCTION TYPE : std::ostream &
358 std::ostream & operator<<( std::ostream & str, const ZYppFactory & obj )
360 return str << "ZYppFactory";
363 /////////////////////////////////////////////////////////////////
365 ///////////////////////////////////////////////////////////////////