20 #include <klockfile.h>
24 #include <sys/types.h>
25 #ifdef HAVE_SYS_STAT_H
28 #ifdef HAVE_SYS_TIME_H
37 #include <tqtextstream.h>
40 #include <tdeapplication.h>
41 #include <tdecmdlineargs.h>
42 #include <tdeglobal.h>
43 #include <tdetempfile.h>
48 class TDELockFile::TDELockFilePrivate {
54 bool linkCountSupport;
56 KDE_struct_stat statBuf;
60 TQString lockRecoverFile;
65 TDELockFile::TDELockFile(
const TQString &file)
67 d =
new TDELockFilePrivate();
71 d->recoverLock =
false;
72 d->linkCountSupport =
true;
91 d->staleTime = _staleTime;
94 static bool statResultIsEqual(KDE_struct_stat &st_buf1, KDE_struct_stat &st_buf2)
96 #define FIELD_EQ(what) (st_buf1.what == st_buf2.what)
97 return FIELD_EQ(st_dev) && FIELD_EQ(st_ino) &&
98 FIELD_EQ(st_uid) && FIELD_EQ(st_gid) && FIELD_EQ(st_nlink);
102 static bool testLinkCountSupport(
const TQCString &fileName)
104 KDE_struct_stat st_buf;
106 ::link( fileName, fileName+
".test" );
107 int result = KDE_lstat( fileName, &st_buf );
108 ::unlink( fileName+
".test" );
109 return ((result == 0) && (st_buf.st_nlink == 2));
112 static TDELockFile::LockResult lockFile(
const TQString &lockFile, KDE_struct_stat &st_buf,
bool &linkCountSupport)
114 TQCString lockFileName = TQFile::encodeName( lockFile );
115 int result = KDE_lstat( lockFileName, &st_buf );
119 KTempFile uniqueFile(lockFile, TQString::null, 0644);
120 uniqueFile.setAutoDelete(
true);
121 if (uniqueFile.status() != 0)
126 gethostname(hostname, 255);
130 (*(uniqueFile.textStream())) << TQString::number(getpid()) <<
endl
131 << instanceName <<
endl
135 TQCString uniqueName = TQFile::encodeName( uniqueFile.name() );
139 result = ::link( uniqueName, lockFileName );
143 if (!linkCountSupport)
150 KDE_struct_stat st_buf2;
151 result = KDE_lstat( uniqueName, &st_buf2 );
155 result = KDE_lstat( lockFileName, &st_buf );
159 if (!statResultIsEqual(st_buf, st_buf2) || S_ISLNK(st_buf.st_mode) || S_ISLNK(st_buf2.st_mode))
162 if ((st_buf.st_nlink == 1) && (st_buf2.st_nlink == 1) && (st_buf.st_ino != st_buf2.st_ino))
164 linkCountSupport = testLinkCountSupport(uniqueName);
165 if (!linkCountSupport)
174 static TDELockFile::LockResult deleteStaleLock(
const TQString &lockFile, KDE_struct_stat &st_buf,
bool &linkCountSupport)
181 if (ktmpFile.status() != 0)
184 TQCString lckFile = TQFile::encodeName(lockFile);
185 TQCString tmpFile = TQFile::encodeName(ktmpFile.name());
191 if (::link(lckFile, tmpFile) != 0)
200 KDE_struct_stat st_buf1;
201 KDE_struct_stat st_buf2;
202 memcpy(&st_buf1, &st_buf,
sizeof(KDE_struct_stat));
204 if ((KDE_lstat(tmpFile, &st_buf2) == 0) && statResultIsEqual(st_buf1, st_buf2))
206 if ((KDE_lstat(lckFile, &st_buf2) == 0) && statResultIsEqual(st_buf1, st_buf2))
209 tqWarning(
"[tdecore] Deleting stale lockfile %s", lckFile.data());
217 if (linkCountSupport)
219 linkCountSupport = testLinkCountSupport(tmpFile);
222 if (!linkCountSupport &&
223 (KDE_lstat(lckFile, &st_buf2) == 0) &&
224 statResultIsEqual(st_buf, st_buf2))
227 tqWarning(
"[tdecore] Deleting stale lockfile %s", lckFile.data());
234 tqWarning(
"[tdecore] WARNING: Problem deleting stale lockfile %s", lckFile.data());
250 KDE_struct_stat st_buf;
251 result = lockFile(d->file, st_buf, d->linkCountSupport);
254 d->staleTimer = TQTime();
259 d->staleTimer = TQTime();
260 if (--hardErrors == 0)
267 if (!d->staleTimer.isNull() && !statResultIsEqual(d->statBuf, st_buf))
268 d->staleTimer = TQTime();
270 if (!d->staleTimer.isNull())
272 bool isStale =
false;
273 if ((d->pid > 0) && !d->hostname.isEmpty())
278 gethostname(hostname, 255);
281 if (d->hostname == hostname)
284 int res = ::kill(d->pid, 0);
285 if ((res == -1) && (errno == ESRCH))
289 if (d->staleTimer.elapsed() > (d->staleTime*1000))
297 result = deleteStaleLock(d->file, d->statBuf, d->linkCountSupport);
302 d->staleTimer = TQTime();
313 memcpy(&(d->statBuf), &st_buf,
sizeof(KDE_struct_stat));
314 d->staleTimer.start();
317 d->hostname = TQString::null;
318 d->instance = TQString::null;
320 TQFile file(d->file);
321 if (file.open(IO_ReadOnly))
323 TQTextStream ts(&file);
325 d->pid = ts.readLine().toInt();
327 d->instance = ts.readLine();
329 d->hostname = ts.readLine();
344 select(0, 0, 0, 0, &tv);
363 ::unlink(TQFile::encodeName(d->file));
373 hostname = d->hostname;
374 appname = d->instance;
The KTempFile class creates and opens a unique file for temporary use.
static int random()
Generates a uniform random number.
static const char * appName()
Get the appname according to argv[0].
LockResult
Possible return values of the lock function.
@ LockStale
A stale lock has been detected.
@ LockError
The lock could not be acquired due to an error.
@ LockOK
Lock was acquired successfully.
@ LockFail
The lock could not be acquired because it is held by another process.
@ LockForce
Automatically remove a lock when a lock is detected that is stale for more than staleTime() seconds.
@ LockNoBlock
Return immediately, do not wait for the lock to become available.
bool isLocked() const
Returns whether the lock is held or not.
void unlock()
Release the lock.
int staleTime() const
Return the time in seconds after which a lock is considered stale The default is 30.
LockResult lock(int options=0)
Attempt to acquire the lock.
void setStaleTime(int _staleTime)
Set the time in seconds after which a lock is considered stale.
~TDELockFile()
Destroys the object, releasing the lock if held.
bool getLockInfo(int &pid, TQString &hostname, TQString &appname)
Returns the pid, hostname and appname of the process holding the lock after the lock functon has retu...
kdbgstream & endl(kdbgstream &s)
Prints an "\n".
TDEInstance * instance()
Shortcut to KNotifyClient::Instance::current() :)