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 <kapplication.h> 41 #include <kcmdlineargs.h> 43 #include <ktempfile.h> 48 class KLockFile::KLockFilePrivate {
54 bool linkCountSupport;
56 KDE_struct_stat statBuf;
60 TQString lockRecoverFile;
65 KLockFile::KLockFile(
const TQString &file)
67 d =
new KLockFilePrivate();
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 KLockFile::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);
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 KLockFile::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 qWarning(
"[kdecore] 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 qWarning(
"[kdecore] Deleting stale lockfile %s", lckFile.data());
234 qWarning(
"[kdecore] 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 lock could not be acquired due to an error.
void setAutoDelete(bool autoDelete)
Turn automatic deletion on or off.
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...
TQTextStream * textStream()
Returns the TQTextStream for writing.
~KLockFile()
Destroys the object, releasing the lock if held.
LockResult
Possible return values of the lock function.
The lock could not be acquired because it is held by another process.
void setStaleTime(int _staleTime)
Set the time in seconds after which a lock is considered stale.
Automatically remove a lock when a lock is detected that is stale for more than staleTime() seconds...
LockResult lock(int options=0)
Attempt to acquire the lock.
Return immediately, do not wait for the lock to become available.
A stale lock has been detected.
int status() const
Returns the status of the file based on errno.
static const char * appName()
Get the appname according to argv[0].
The KTempFile class creates and opens a unique file for temporary use.
Lock was acquired successfully.
static int random()
Generates a uniform random number.
void unlink()
Unlinks the file from the directory.
int staleTime() const
Return the time in seconds after which a lock is considered stale The default is 30.
TQString name() const
Returns the full path and name of the file.
bool close()
Closes the file.
void unlock()
Release the lock.
KInstance * instance()
Shortcut to KNotifyClient::Instance::current() :)
kndbgstream & endl(kndbgstream &s)
Does nothing.
bool isLocked() const
Returns whether the lock is held or not.