37#include <QtCore/QDate>
38#include <QtCore/QFile>
74class KLockFile::Private
80 linkCountSupport(true),
97 void writeIntoLockFile(QFile& file,
const KComponentData& componentData);
105 bool linkCountSupport;
108 KDE_struct_stat statBuf;
117 : d(new Private(componentData))
119 d->m_fileName = file;
138 d->staleTime = _staleTime;
142 const KDE_struct_stat &st_buf2)
144#define FIELD_EQ(what) (st_buf1.what == st_buf2.what)
151 const KDE_struct_stat& st_buf2 )
153 return !(st_buf1 == st_buf2);
158 KDE_struct_stat st_buf;
161 if(!::link( fileName, QByteArray(fileName+
".test") )) {
162 result = KDE_lstat( fileName, &st_buf );
163 ::unlink( QByteArray(fileName+
".test") );
165 return (result < 0 || ((result == 0) && (st_buf.st_nlink == 2)));
168void KLockFile::Private::writeIntoLockFile(QFile& file,
const KComponentData& componentData)
170 file.setPermissions(QFile::ReadUser|QFile::WriteUser|QFile::ReadGroup|QFile::ReadOther);
174 gethostname(hostname, 255);
176 m_hostname = QString::fromLocal8Bit(hostname);
179 QTextStream stream(&file);
182 stream << QString::number(m_pid) << endl
183 << m_componentName << endl
184 << m_hostname << endl;
188void KLockFile::Private::readLockFile()
192 m_componentName.clear();
194 QFile file(m_fileName);
195 if (file.open(QIODevice::ReadOnly))
197 QTextStream ts(&file);
199 m_pid = ts.readLine().toInt();
201 m_componentName = ts.readLine();
203 m_hostname = ts.readLine();
209 const QByteArray lockFileName = QFile::encodeName( m_fileName );
210 int result = KDE_lstat( lockFileName, &st_buf );
216 uniqueFile.setFileTemplate(m_fileName);
217 if (!uniqueFile.open())
220 writeIntoLockFile(uniqueFile, m_componentData);
222 QByteArray uniqueName = QFile::encodeName( uniqueFile.fileName() );
225 result = ::link( uniqueName, lockFileName );
229 if (!linkCountSupport)
232 KDE_struct_stat st_buf2;
233 result = KDE_lstat( uniqueName, &st_buf2 );
237 result = KDE_lstat( lockFileName, &st_buf );
241 if (st_buf != st_buf2 || S_ISLNK(st_buf.st_mode) || S_ISLNK(st_buf2.st_mode))
245 if ((st_buf2.st_nlink > 1 ||
246 ((st_buf.st_nlink == 1) && (st_buf2.st_nlink == 1))) && (st_buf.st_ino != st_buf2.st_ino))
249 if (!linkCountSupport)
258bool KLockFile::Private::isNfs()
const
267 return lockFileWithLink(st_buf);
270 return lockFileOExcl(st_buf);
275 const QByteArray lockFileName = QFile::encodeName( m_fileName );
277 int fd = KDE_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0644);
279 if (errno == EEXIST) {
281 if (KDE_lstat(lockFileName, &st_buf) != 0) {
295 if (!m_file.open(fd, QIODevice::WriteOnly)) {
299 writeIntoLockFile(m_file, m_componentData);
302 const int result = KDE_lstat(QFile::encodeName(m_fileName), &st_buf);
311 return deleteStaleLockWithLink();
316 qWarning(
"WARNING: deleting stale lockfile %s", qPrintable(m_fileName));
317 QFile::remove(m_fileName);
328 ktmpFile->setFileTemplate(m_fileName);
329 if (!ktmpFile->open()) {
334 const QByteArray lckFile = QFile::encodeName(m_fileName);
335 const QByteArray tmpFile = QFile::encodeName(ktmpFile->fileName());
339 if (::link(lckFile, tmpFile) != 0)
344 KDE_struct_stat st_buf1;
345 KDE_struct_stat st_buf2;
346 memcpy(&st_buf1, &statBuf,
sizeof(KDE_struct_stat));
348 if ((KDE_lstat(tmpFile, &st_buf2) == 0) && st_buf1 == st_buf2)
350 if ((KDE_lstat(lckFile, &st_buf2) == 0) && st_buf1 == st_buf2)
353 qWarning(
"WARNING: deleting stale lockfile %s", lckFile.data());
361 if (linkCountSupport)
366 if (!linkCountSupport)
369 qWarning(
"WARNING: deleting stale lockfile %s", lckFile.data());
371 if (::unlink(lckFile) < 0) {
372 qWarning(
"WARNING: Problem deleting stale lockfile %s: %s", lckFile.data(),
380 qWarning(
"WARNING: Problem deleting stale lockfile %s", lckFile.data());
396 KDE_struct_stat st_buf;
398 result = d->lockFile(st_buf);
402 d->staleTimer = QTime();
407 d->staleTimer = QTime();
408 if (--hardErrors == 0)
415 if (!d->staleTimer.isNull() && d->statBuf != st_buf)
416 d->staleTimer = QTime();
418 if (d->staleTimer.isNull())
420 memcpy(&(d->statBuf), &st_buf,
sizeof(KDE_struct_stat));
421 d->staleTimer.start();
426 bool isStale =
false;
427 if ((d->m_pid > 0) && !d->m_hostname.isEmpty())
432 gethostname(hostname, 255);
435 if (d->m_hostname == QLatin1String(hostname))
438 int res = ::kill(d->m_pid, 0);
439 if ((res == -1) && (errno == ESRCH))
443 if (d->staleTimer.elapsed() > (d->staleTime*1000))
451 result = d->deleteStaleLock();
456 d->staleTimer = QTime();
475 select(0, 0, 0, 0, &tv);
491 ::unlink(QFile::encodeName(d->m_fileName));
492 if (d->mustCloseFd) {
493 close(d->m_file.handle());
494 d->mustCloseFd =
false;
507 hostname = d->m_hostname;
508 appname = d->m_componentName;
QString componentName() const
Returns the name of the component.
bool getLockInfo(int &pid, QString &hostname, QString &appname)
Returns the pid, hostname and appname of the process holding the lock after the lock functon has retu...
LockResult
Possible return values of the lock function.
@ LockStale
A stale lock has been detected.
@ LockFail
The lock could not be acquired because it is held by another process.
@ LockOK
Lock was acquired successfully.
@ LockError
The lock could not be acquired due to an error.
void unlock()
Release the lock.
~KLockFile()
Destroys the object, releasing the lock if held.
void setStaleTime(int _staleTime)
Set the time in seconds after which a lock is considered stale.
KLockFile(const QString &file, const KComponentData &componentName=KGlobal::mainComponent())
LockResult lock(LockFlags flags=LockFlags())
Attempt to acquire the lock.
bool isLocked() const
Returns whether the lock is held or not.
int staleTime() const
Return the time in seconds after which a lock is considered stale The default is 30.
@ NoBlockFlag
Return immediately, do not wait for the lock to become available.
@ ForceFlag
Automatically remove a lock when a lock is detected that is stale for more than staleTime() seconds,...
A QTemporaryFile that will save in the KDE temp directory.
static bool operator!=(const KDE_struct_stat &st_buf1, const KDE_struct_stat &st_buf2)
static bool testLinkCountSupport(const QByteArray &fileName)
static bool operator==(const KDE_struct_stat &st_buf1, const KDE_struct_stat &st_buf2)
Type fileSystemType(const QString &path)
int random()
Generates a uniform random number.