lock.cpp
00001 /* 00002 This file is part of libkabc. 00003 Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "lock.h" 00022 00023 #include <kapplication.h> 00024 #include <kdebug.h> 00025 #include <klocale.h> 00026 #include <kstandarddirs.h> 00027 #include <ktempfile.h> 00028 00029 #include <qfile.h> 00030 00031 #include <signal.h> 00032 #include <sys/types.h> 00033 #include <sys/stat.h> 00034 #include <unistd.h> 00035 00036 using namespace KABC; 00037 00038 Lock::Lock( const QString &identifier ) 00039 : mIdentifier( identifier ) 00040 { 00041 mIdentifier.replace( "/", "_" ); 00042 } 00043 00044 Lock::~Lock() 00045 { 00046 unlock(); 00047 } 00048 00049 QString Lock::locksDir() 00050 { 00051 return locateLocal( "data", "kabc/lock/" ); 00052 } 00053 00054 bool Lock::readLockFile( const QString &filename, int &pid, QString &app ) 00055 { 00056 QFile file( filename ); 00057 if ( !file.open( IO_ReadOnly ) ) return false; 00058 00059 QTextStream t( &file ); 00060 pid = t.readLine().toInt(); 00061 app = t.readLine(); 00062 00063 return true; 00064 } 00065 00066 bool Lock::writeLockFile( const QString &filename ) 00067 { 00068 QFile file( filename ); 00069 if ( !file.open( IO_WriteOnly ) ) return false; 00070 QTextStream t( &file ); 00071 t << ::getpid() << endl << QString( KGlobal::instance()->instanceName() ); 00072 00073 return true; 00074 } 00075 00076 QString Lock::lockFileName() const 00077 { 00078 return locksDir() + mIdentifier + ".lock"; 00079 } 00080 00081 bool Lock::lock() 00082 { 00083 kdDebug(5700) << "Lock::lock()" << endl; 00084 00085 QString lockName = lockFileName(); 00086 kdDebug(5700) << "-- lock name: " << lockName << endl; 00087 00088 if ( QFile::exists( lockName ) ) { // check if it is a stale lock file 00089 int pid; 00090 QString app; 00091 00092 if ( !readLockFile( lockFileName(), pid, app ) ) { 00093 mError = i18n("Unable to open lock file."); 00094 return false; 00095 } 00096 00097 int retval = ::kill( pid, 0 ); 00098 if ( retval == -1 && errno == ESRCH ) { // process doesn't exists anymore 00099 QFile::remove( lockName ); 00100 kdWarning(5700) << "Removed stale lock file from process '" << app << "'" 00101 << endl; 00102 } else { 00103 QString identifier( mIdentifier ); 00104 identifier.replace( '_', '/' ); 00105 00106 mError = i18n("The address book '%1' is locked by application '%2'.\nIf you believe this is incorrect, just remove the lock file from '%3'") 00107 .arg( identifier ).arg( app ).arg( locateLocal( "data", "kabc/lock/*.lock" ) ); 00108 return false; 00109 } 00110 } 00111 00112 QString lockUniqueName; 00113 lockUniqueName = mIdentifier + kapp->randomString( 8 ); 00114 mLockUniqueName = locateLocal( "data", "kabc/lock/" + lockUniqueName ); 00115 kdDebug(5700) << "-- lock unique name: " << mLockUniqueName << endl; 00116 00117 // Create unique file 00118 writeLockFile( mLockUniqueName ); 00119 00120 // Create lock file 00121 int result = ::link( QFile::encodeName( mLockUniqueName ), 00122 QFile::encodeName( lockName ) ); 00123 00124 if ( result == 0 ) { 00125 mError = ""; 00126 emit locked(); 00127 return true; 00128 } 00129 00130 // TODO: check stat 00131 00132 mError = i18n("Error"); 00133 return false; 00134 } 00135 00136 bool Lock::unlock() 00137 { 00138 int pid; 00139 QString app; 00140 if ( readLockFile( lockFileName(), pid, app ) ) { 00141 if ( pid == getpid() ) { 00142 QFile::remove( lockFileName() ); 00143 QFile::remove( mLockUniqueName ); 00144 emit unlocked(); 00145 } else { 00146 mError = i18n("Unlock failed. Lock file is owned by other process: %1 (%2)") 00147 .arg( app ).arg( QString::number( pid ) ); 00148 kdDebug() << "Lock::unlock(): " << mError << endl; 00149 return false; 00150 } 00151 } 00152 00153 mError = ""; 00154 return true; 00155 } 00156 00157 QString Lock::error() const 00158 { 00159 return mError; 00160 } 00161 00162 #include "lock.moc"