kabc
lock.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "lock.h"
00022
00023 #include <krandom.h>
00024 #include <kcomponentdata.h>
00025 #include <kdebug.h>
00026 #include <klocale.h>
00027 #include <kstandarddirs.h>
00028
00029 #include <QtCore/QFile>
00030 #include <QtCore/QTextStream>
00031
00032 #include <errno.h>
00033 #include <signal.h>
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <unistd.h>
00037
00038 using namespace KABC;
00039
00040 class Lock::Private
00041 {
00042 public:
00043 Private( const QString &identifier )
00044 : mIdentifier( identifier )
00045 {
00046 mIdentifier.replace( "/", "_" );
00047 }
00048
00049 QString mIdentifier;
00050 QString mLockUniqueName;
00051 QString mError;
00052 };
00053
00054 Lock::Lock( const QString &identifier )
00055 : d( new Private( identifier ) )
00056 {
00057 }
00058
00059 Lock::~Lock()
00060 {
00061 unlock();
00062
00063 delete d;
00064 }
00065
00066 QString Lock::locksDir()
00067 {
00068 return KStandardDirs::locateLocal( "data", "kabc/lock/" );
00069 }
00070
00071 bool Lock::readLockFile( const QString &filename, int &pid, QString &app )
00072 {
00073 QFile file( filename );
00074 if ( !file.open( QIODevice::ReadOnly ) ) {
00075 return false;
00076 }
00077
00078 QTextStream t( &file );
00079 t >> pid >> ws >> app;
00080
00081 return true;
00082 }
00083
00084 bool Lock::writeLockFile( const QString &filename )
00085 {
00086 QFile file( filename );
00087 if ( !file.open( QIODevice::WriteOnly ) ) {
00088 return false;
00089 }
00090
00091 QTextStream t( &file );
00092 t << ::getpid() << endl << QString( KGlobal::mainComponent().componentName() );
00093
00094 return true;
00095 }
00096
00097 QString Lock::lockFileName() const
00098 {
00099 return locksDir() + d->mIdentifier + ".lock";
00100 }
00101
00102 bool Lock::lock()
00103 {
00104 QString lockName = lockFileName();
00105 kDebug(5700) << "-- lock name:" << lockName;
00106
00107 if ( QFile::exists( lockName ) ) {
00108 int pid;
00109 QString app;
00110
00111 if ( !readLockFile( lockFileName(), pid, app ) ) {
00112 d->mError = i18n( "Unable to open lock file." );
00113 return false;
00114 }
00115
00116 int retval = ::kill( pid, 0 );
00117 if ( retval == -1 && errno == ESRCH ) {
00118 QFile::remove( lockName );
00119 kWarning(5700) << "Removed stale lock file from process '" << app << "'";
00120 } else {
00121 QString identifier( d->mIdentifier );
00122 identifier.replace( '_', '/' );
00123
00124 d->mError = i18n( "The resource '%1' is locked by application '%2'.", identifier, app );
00125 return false;
00126 }
00127 }
00128
00129 QString lockUniqueName;
00130 lockUniqueName = d->mIdentifier + KRandom::randomString( 8 );
00131 d->mLockUniqueName = KStandardDirs::locateLocal( "data", "kabc/lock/" + lockUniqueName );
00132 kDebug(5700) << "-- lock unique name:" << d->mLockUniqueName;
00133
00134
00135 writeLockFile( d->mLockUniqueName );
00136
00137
00138 int result = ::link( QFile::encodeName( d->mLockUniqueName ),
00139 QFile::encodeName( lockName ) );
00140
00141 if ( result == 0 ) {
00142 d->mError.clear();
00143 emit locked();
00144 return true;
00145 }
00146
00147
00148
00149 d->mError = i18n( "Error" );
00150 return false;
00151 }
00152
00153 bool Lock::unlock()
00154 {
00155 int pid;
00156 QString app;
00157 if ( readLockFile( lockFileName(), pid, app ) ) {
00158 if ( pid == getpid() ) {
00159 QFile::remove( lockFileName() );
00160 QFile::remove( d->mLockUniqueName );
00161 emit unlocked();
00162 } else {
00163 d->mError = i18n( "Unlock failed. Lock file is owned by other process: %1 (%2)", app, pid );
00164 kDebug(5700) << d->mError;
00165 return false;
00166 }
00167 }
00168
00169 d->mError.clear();
00170
00171 return true;
00172 }
00173
00174 QString Lock::error() const
00175 {
00176 return d->mError;
00177 }
00178
00179 #include "lock.moc"