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);
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 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;