+ case EEXIST: /* check if it's time for a lock override */
+ if (!lstat(path, &stbuf) && stbuf.st_size <= 16 /* MAX_locksize */ && locktimeout
+ && !lstat(path, &stbuf) && locktimeout < t - stbuf.st_mtime)
+ /* stat() till unlink() should be atomic, but can't guarantee that. */
+ {
+ if (triedforce)
+ {
+ /* Already tried, force lock override, not trying again */
+ failed = true;
+ break;
+ }
+ else if (S_ISDIR(stbuf.st_mode) || ::unlink(path))
+ {
+ triedforce=true;
+ ::syslog(LOG_ERR, "Forced unlock denied on %s", path);
+ secdebug("atomicfile", "Forced unlock denied on %s", path);
+ }
+ else
+ {
+ ::syslog(LOG_ERR, "Forcing lock on %s", path);
+ secdebug("atomicfile", "Forcing lock on %s", path);
+ sleep(16 /* DEFsuspend */);
+ break;
+ }
+ }
+ else
+ triedforce = false; /* legitimate iteration, clear flag */
+
+ /* Reset retry counter. */
+ retries = 0;
+ sleep(8 /* DEFlocksleep */);
+ break;
+
+ case ENOSPC: /* no space left, treat it as a transient */
+#ifdef EDQUOT /* NFS failure */
+ case EDQUOT: /* maybe it was a short term shortage? */
+#endif
+ case ENOENT:
+ case ENOTDIR:
+ case EIO:
+ /*case EACCES:*/
+ if(++retries < (7 + 1)) /* nfsTRY number of times+1 to ignore spurious NFS errors */
+ sleep(8 /* DEFlocksleep */);
+ else
+ failed = true;
+ break;
+
+#ifdef ENAMETOOLONG
+ case ENAMETOOLONG: /* Filename is too long, shorten and retry */
+ if (mPath.size() > mDir.size() + 8)
+ {
+ secdebug("atomicfile", "Truncating %s and retrying lock", path);
+ mPath.erase(mPath.end() - 1);
+ path = mPath.c_str();
+ /* Reset retry counter. */
+ retries = 0;
+ break;
+ }
+ /* DROPTHROUGH */
+#endif
+ default:
+ failed = true;
+ break;