25 #include <sys/types.h>
26 #ifdef HAVE_SYS_STAT_H
29 #ifdef HAVE_SYS_TIME_H
37 #include <QtCore/QDate>
38 #include <QtCore/QFile>
39 #include <QTextStream>
74 class 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)));
168 void 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;
188 void 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)
258 bool 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;
The lock could not be acquired due to an error.
KLockFile(const QString &file, const KComponentData &componentName=KGlobal::mainComponent())
~KLockFile()
Destroys the object, releasing the lock if held.
static bool operator==(const KDE_struct_stat &st_buf1, const KDE_struct_stat &st_buf2)
LockResult
Possible return values of the lock function.
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.
LockResult lock(LockFlags flags=LockFlags())
Attempt to acquire the lock.
int staleTime() const
Return the time in seconds after which a lock is considered stale The default is 30.
The lock could not be acquired because it is held by another process.
Type fileSystemType(const QString &path)
int random()
Generates a uniform random number.
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...
void setStaleTime(int _staleTime)
Set the time in seconds after which a lock is considered stale.
A stale lock has been detected.
QString componentName() const
Returns the name of the component.
static bool testLinkCountSupport(const QByteArray &fileName)
Lock was acquired successfully.
bool isLocked() const
Returns whether the lock is held or not.
void unlock()
Release the lock.
Return immediately, do not wait for the lock to become available.
static bool operator!=(const KDE_struct_stat &st_buf1, const KDE_struct_stat &st_buf2)