You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdelibs/kabc/lock.cpp

163 lines
4.0 KiB

/*
This file is part of libkabc.
Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "lock.h"
#include <kapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <ktempfile.h>
#include <qfile.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
using namespace KABC;
Lock::Lock( const QString &identifier )
: mIdentifier( identifier )
{
mIdentifier.replace( "/", "_" );
}
Lock::~Lock()
{
unlock();
}
QString Lock::locksDir()
{
return locateLocal( "data", "kabc/lock/" );
}
bool Lock::readLockFile( const QString &filename, int &pid, QString &app )
{
QFile file( filename );
if ( !file.open( IO_ReadOnly ) ) return false;
QTextStream t( &file );
pid = t.readLine().toInt();
app = t.readLine();
return true;
}
bool Lock::writeLockFile( const QString &filename )
{
QFile file( filename );
if ( !file.open( IO_WriteOnly ) ) return false;
QTextStream t( &file );
t << ::getpid() << endl << QString( KGlobal::instance()->instanceName() );
return true;
}
QString Lock::lockFileName() const
{
return locksDir() + mIdentifier + ".lock";
}
bool Lock::lock()
{
kdDebug(5700) << "Lock::lock()" << endl;
QString lockName = lockFileName();
kdDebug(5700) << "-- lock name: " << lockName << endl;
if ( QFile::exists( lockName ) ) { // check if it is a stale lock file
int pid;
QString app;
if ( !readLockFile( lockFileName(), pid, app ) ) {
mError = i18n("Unable to open lock file.");
return false;
}
int retval = ::kill( pid, 0 );
if ( retval == -1 && errno == ESRCH ) { // process doesn't exists anymore
QFile::remove( lockName );
kdWarning(5700) << "Removed stale lock file from process '" << app << "'"
<< endl;
} else {
QString identifier( mIdentifier );
identifier.replace( '_', '/' );
mError = i18n("The address book '%1' is locked by application '%2'.\nIf you believe this is incorrect, just remove the lock file from '%3'")
.arg( identifier ).arg( app ).arg( locateLocal( "data", "kabc/lock/*.lock" ) );
return false;
}
}
QString lockUniqueName;
lockUniqueName = mIdentifier + kapp->randomString( 8 );
mLockUniqueName = locateLocal( "data", "kabc/lock/" + lockUniqueName );
kdDebug(5700) << "-- lock unique name: " << mLockUniqueName << endl;
// Create unique file
writeLockFile( mLockUniqueName );
// Create lock file
int result = ::link( QFile::encodeName( mLockUniqueName ),
QFile::encodeName( lockName ) );
if ( result == 0 ) {
mError = "";
emit locked();
return true;
}
// TODO: check stat
mError = i18n("Error");
return false;
}
bool Lock::unlock()
{
int pid;
QString app;
if ( readLockFile( lockFileName(), pid, app ) ) {
if ( pid == getpid() ) {
QFile::remove( lockFileName() );
QFile::remove( mLockUniqueName );
emit unlocked();
} else {
mError = i18n("Unlock failed. Lock file is owned by other process: %1 (%2)")
.arg( app ).arg( QString::number( pid ) );
kdDebug() << "Lock::unlock(): " << mError << endl;
return false;
}
}
mError = "";
return true;
}
QString Lock::error() const
{
return mError;
}
#include "lock.moc"