]> git.saurik.com Git - apple/security.git/blobdiff - cdsa/cdsa_utilities/AtomicFile.cpp
Security-222.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / AtomicFile.cpp
diff --git a/cdsa/cdsa_utilities/AtomicFile.cpp b/cdsa/cdsa_utilities/AtomicFile.cpp
deleted file mode 100644 (file)
index bbde563..0000000
+++ /dev/null
@@ -1,884 +0,0 @@
-/*
- * Copyright (c) 2000-2001, 2003 Apple Computer, Inc. All Rights Reserved.
- * 
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- * 
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
- * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
- * specific language governing rights and limitations under the License.
- */
-
-
-#include <Security/AtomicFile.h>
-
-#include <Security/devrandom.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <syslog.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-
-#define kAtomicFileMaxBlockSize INT_MAX
-
-
-//
-//  AtomicFile.cpp - Description t.b.d.
-//
-AtomicFile::AtomicFile(const std::string &inPath) :
-       mPath(inPath)
-{
-       pathSplit(inPath, mDir, mFile);
-}
-
-AtomicFile::~AtomicFile()
-{
-}
-
-// Aquire the write lock and remove the file.
-void
-AtomicFile::performDelete()
-{
-       AtomicLockedFile lock(*this);
-       if (::unlink(mPath.c_str()) != 0)
-       {
-               int error = errno;
-               secdebug("atomicfile", "unlink %s: %s", mPath.c_str(), strerror(error));
-        if (error == ENOENT)
-                       CssmError::throwMe(CSSMERR_DL_DATASTORE_DOESNOT_EXIST);
-               else
-                       UnixError::throwMe(error);
-       }
-}
-
-// Aquire the write lock and rename the file (and bump the version and stuff).
-void
-AtomicFile::rename(const std::string &inNewPath)
-{
-       const char *path = mPath.c_str();
-       const char *newPath = inNewPath.c_str();
-
-       // @@@ lock the destination file too.
-       AtomicLockedFile lock(*this);
-       if (::rename(path, newPath) != 0)
-       {
-               int error = errno;
-               secdebug("atomicfile", "rename(%s, %s): %s", path, newPath, strerror(error));
-               UnixError::throwMe(error);
-       }
-}
-
-// Lock the file for writing and return a newly created AtomicTempFile.
-RefPointer<AtomicTempFile>
-AtomicFile::create(mode_t mode)
-{
-       const char *path = mPath.c_str();
-
-       // First make sure the directory to this file exists and is writable
-       mkpath(mDir);
-
-       RefPointer<AtomicLockedFile> lock(new AtomicLockedFile(*this));
-       int fileRef = ropen(path, O_WRONLY|O_CREAT|O_EXCL, mode);
-    if (fileRef == -1)
-    {
-        int error = errno;
-               secdebug("atomicfile", "open %s: %s", path, strerror(error));
-
-        // Do the obvious error code translations here.
-               // @@@ Consider moving these up a level.
-        if (error == EACCES)
-                       CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED);
-        else if (error == EEXIST)
-                       CssmError::throwMe(CSSMERR_DL_DATASTORE_ALREADY_EXISTS);
-               else
-                       UnixError::throwMe(error);
-    }
-       rclose(fileRef);
-
-       try
-       {
-               // Now that we have created the lock and the new db file create a tempfile
-               // object.
-               RefPointer<AtomicTempFile> temp(new AtomicTempFile(*this, lock, mode));
-               secdebug("atomicfile", "%p created %s", this, path);
-               return temp;
-       }
-       catch (...)
-       {
-               // Creating the temp file failed so remove the db file we just created too.
-               if (::unlink(path) == -1)
-               {
-                       secdebug("atomicfile", "unlink %s: %s", path, strerror(errno));
-               }
-               throw;
-       }
-}
-
-// Lock the database file for writing and return a newly created AtomicTempFile.
-RefPointer<AtomicTempFile>
-AtomicFile::write()
-{
-       RefPointer<AtomicLockedFile> lock(new AtomicLockedFile(*this));
-       return new AtomicTempFile(*this, lock);
-}
-
-// Return a bufferedFile containing current version of the file for reading.
-RefPointer<AtomicBufferedFile>
-AtomicFile::read()
-{
-       return new AtomicBufferedFile(mPath);
-}
-
-mode_t
-AtomicFile::mode() const
-{
-       const char *path = mPath.c_str();
-       struct stat st;
-       if (::stat(path, &st) == -1)
-       {
-               int error = errno;
-               secdebug("atomicfile", "stat %s: %s", path, strerror(error));
-               UnixError::throwMe(error);
-       }
-       return st.st_mode;
-}
-
-// Split full into a dir and file component.
-void
-AtomicFile::pathSplit(const std::string &inFull, std::string &outDir, std::string &outFile)
-{
-       std::string::size_type slash, len = inFull.size();
-       slash = inFull.rfind('/');
-       if (slash == std::string::npos)
-       {
-               outDir = "";
-               outFile = inFull;
-       }
-       else if (slash + 1 == len)
-       {
-               outDir = inFull;
-               outFile = "";
-       }
-       else
-       {
-               outDir = inFull.substr(0, slash + 1);
-               outFile = inFull.substr(slash + 1, len);
-       }
-}
-
-//
-// Make sure the directory up to inDir exists inDir *must* end in a slash.
-//
-void
-AtomicFile::mkpath(const std::string &inDir, mode_t mode)
-{
-       for (std::string::size_type pos = 0; (pos = inDir.find('/', pos + 1)) != std::string::npos;)
-       {
-               std::string path = inDir.substr(0, pos);
-               const char *cpath = path.c_str();
-               struct stat sb;
-               if (::stat(cpath, &sb))
-               {
-                       if (errno != ENOENT || ::mkdir(cpath, mode))
-                               UnixError::throwMe(errno);
-               }
-               else if (!S_ISDIR(sb.st_mode))
-                       CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED);  // @@@ Should be is a directory
-       }
-}
-
-int
-AtomicFile::ropen(const char *const name, int flags, mode_t mode)
-{
-       int fd, tries_left = 4 /* kNoResRetry */;
-       do
-       {
-               fd = ::open(name, flags, mode);
-       } while (fd < 0 && (errno == EINTR || errno == ENFILE && --tries_left >= 0));
-
-       return fd;
-}
-
-int
-AtomicFile::rclose(int fd)
-{
-       int result;
-       do
-       {
-               result = ::close(fd);
-       } while(result && errno == EINTR);
-
-       return result;
-}
-
-//
-// AtomicBufferedFile - This represents an instance of a file opened for reading.
-// The file is read into memory and closed after this is done.
-// The memory is released when this object is destroyed.
-//
-AtomicBufferedFile::AtomicBufferedFile(const std::string &inPath) :
-       mPath(inPath),
-       mFileRef(-1),
-       mBuffer(NULL),
-       mLength(0)
-{
-}
-
-AtomicBufferedFile::~AtomicBufferedFile()
-{
-       if (mFileRef >= 0)
-       {
-               AtomicFile::rclose(mFileRef);
-               secdebug("atomicfile", "%p closed %s", this, mPath.c_str());
-       }
-
-       if (mBuffer)
-       {
-               secdebug("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer);
-               free(mBuffer);
-       }
-}
-
-//
-// Open the file and return the length in bytes.
-//
-off_t
-AtomicBufferedFile::open()
-{
-       const char *path = mPath.c_str();
-       if (mFileRef >= 0)
-       {
-               secdebug("atomicfile", "open %s: already open, closing and reopening", path);
-               close();
-       }
-
-       mFileRef = AtomicFile::ropen(path, O_RDONLY, 0);
-    if (mFileRef == -1)
-    {
-        int error = errno;
-               secdebug("atomicfile", "open %s: %s", path, strerror(error));
-
-        // Do the obvious error code translations here.
-               // @@@ Consider moving these up a level.
-        if (error == ENOENT)
-                       CssmError::throwMe(CSSMERR_DL_DATASTORE_DOESNOT_EXIST);
-               else if (error == EACCES)
-                       CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED);
-               else
-                       UnixError::throwMe(error);
-    }
-
-       mLength = ::lseek(mFileRef, 0, SEEK_END);
-       if (mLength == -1)
-       {
-               int error = errno;
-               secdebug("atomicfile", "lseek(%s, END): %s", path, strerror(error));
-               AtomicFile::rclose(mFileRef);
-               UnixError::throwMe(error);
-       }
-
-       secdebug("atomicfile", "%p opened %s: %qd bytes", this, path, mLength);
-
-       return mLength;
-}
-
-//
-// Read the file starting at inOffset for inLength bytes into the buffer and return
-// a pointer to it.  On return outLength contain the actual number of bytes read, it
-// will only ever be less than inLength if EOF was reached, and it will never be more
-// than inLength.
-//
-const uint8 *
-AtomicBufferedFile::read(off_t inOffset, off_t inLength, off_t &outLength)
-{
-       if (mFileRef < 0)
-       {
-               secdebug("atomicfile", "read %s: file yet not opened, opening", mPath.c_str());
-               open();
-       }
-
-       off_t bytesLeft = inLength;
-       uint8 *ptr;
-       if (mBuffer)
-       {
-               secdebug("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer);
-               free(mBuffer);
-       }
-
-       mBuffer = ptr = reinterpret_cast<uint8 *>(malloc(bytesLeft));
-       secdebug("atomicfile", "%p allocated %s buffer %p size %qd", this, mPath.c_str(), mBuffer, bytesLeft);
-       off_t pos = inOffset;
-       while (bytesLeft)
-       {
-               size_t toRead = bytesLeft > kAtomicFileMaxBlockSize ? kAtomicFileMaxBlockSize : size_t(bytesLeft);
-               ssize_t bytesRead = ::pread(mFileRef, ptr, toRead, pos);
-               if (bytesRead == -1)
-               {
-                       int error = errno;
-                       if (error == EINTR)
-                       {
-                               // We got interrupted by a signal, so try again.
-                               secdebug("atomicfile", "pread %s: interrupted, retrying", mPath.c_str());
-                               continue;
-                       }
-
-                       secdebug("atomicfile", "pread %s: %s", mPath.c_str(), strerror(error));
-                       free(mBuffer);
-                       mBuffer = NULL;
-                       UnixError::throwMe(error);
-               }
-
-               // Read returning 0 means EOF was reached so we're done.
-               if (bytesRead == 0)
-                       break;
-
-               secdebug("atomicfile", "%p read %s: %d bytes to %p", this, mPath.c_str(), bytesRead, ptr);
-
-               bytesLeft -= bytesRead;
-               ptr += bytesRead;
-               pos += bytesRead;
-       }
-
-       // Compute length
-       outLength = ptr - mBuffer;
-
-       return mBuffer;
-}
-
-void
-AtomicBufferedFile::close()
-{
-       if (mFileRef < 0)
-       {
-               secdebug("atomicfile", "close %s: already closed", mPath.c_str());
-       }
-       else
-       {
-               int result = AtomicFile::rclose(mFileRef);
-               mFileRef = -1;
-               if (result == -1)
-               {
-                       int error = errno;
-                       secdebug("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno));
-                       UnixError::throwMe(error);
-               }
-
-               secdebug("atomicfile", "%p closed %s", this, mPath.c_str());
-       }
-}
-
-
-//
-// AtomicTempFile - A temporary file to write changes to.
-//
-AtomicTempFile::AtomicTempFile(AtomicFile &inFile, const RefPointer<AtomicLockedFile> &inLockedFile, mode_t mode) :
-       mFile(inFile),
-       mLockedFile(inLockedFile),
-       mCreating(true)
-{
-       create(mode);
-}
-
-AtomicTempFile::AtomicTempFile(AtomicFile &inFile, const RefPointer<AtomicLockedFile> &inLockedFile) :
-       mFile(inFile),
-       mLockedFile(inLockedFile),
-       mCreating(false)
-{
-       create(mFile.mode());
-}
-
-AtomicTempFile::~AtomicTempFile()
-{
-       // rollback if we didn't commit yet.
-       if (mFileRef >= 0)
-               rollback();
-}
-
-//
-// Open the file and return the length in bytes.
-//
-void
-AtomicTempFile::create(mode_t mode)
-{
-       mPath = mFile.dir() + "," + mFile.file();
-       const char *path = mPath.c_str();
-
-       mFileRef = AtomicFile::ropen(path, O_WRONLY|O_CREAT|O_TRUNC, mode);
-    if (mFileRef == -1)
-    {
-        int error = errno;
-               secdebug("atomicfile", "open %s: %s", path, strerror(error));
-
-        // Do the obvious error code translations here.
-               // @@@ Consider moving these up a level.
-        if (error == EACCES)
-                       CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED);
-               else
-                       UnixError::throwMe(error);
-    }
-
-       secdebug("atomicfile", "%p created %s", this, path);
-}
-
-void
-AtomicTempFile::write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const uint32 inData)
-{
-    uint32 aData = htonl(inData);
-    write(inOffsetType, inOffset, reinterpret_cast<uint8 *>(&aData), sizeof(aData));
-}
-
-void
-AtomicTempFile::write(AtomicFile::OffsetType inOffsetType, off_t inOffset,
-                                 const uint32 *inData, uint32 inCount)
-{
-#ifdef HOST_LONG_IS_NETWORK_LONG
-    // Optimize this for the case where hl == nl
-    const uint32 *aBuffer = inData;
-#else
-    auto_array<uint32> aBuffer(inCount);
-    for (uint32 i = 0; i < inCount; i++)
-        aBuffer.get()[i] = htonl(inData[i]);
-#endif
-
-    write(inOffsetType, inOffset, reinterpret_cast<const uint8 *>(aBuffer.get()),
-         inCount * sizeof(*inData));
-}
-
-void
-AtomicTempFile::write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const uint8 *inData, size_t inLength)
-{
-       off_t pos;
-       if (inOffsetType == AtomicFile::FromEnd)
-       {
-               pos = ::lseek(mFileRef, 0, SEEK_END);
-               if (pos == -1)
-               {
-                       int error = errno;
-                       secdebug("atomicfile", "lseek(%s, %qd): %s", mPath.c_str(), inOffset, strerror(error));
-                       UnixError::throwMe(error);
-               }
-       }
-       else if (inOffsetType == AtomicFile::FromStart)
-               pos = inOffset;
-       else
-               CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
-
-       off_t bytesLeft = inLength;
-       const uint8 *ptr = inData;
-       while (bytesLeft)
-       {
-               size_t toWrite = bytesLeft > kAtomicFileMaxBlockSize ? kAtomicFileMaxBlockSize : size_t(bytesLeft);
-               ssize_t bytesWritten = ::pwrite(mFileRef, ptr, toWrite, pos);
-               if (bytesWritten == -1)
-               {
-                       int error = errno;
-                       if (error == EINTR)
-                       {
-                               // We got interrupted by a signal, so try again.
-                               secdebug("atomicfile", "write %s: interrupted, retrying", mPath.c_str());
-                               continue;
-                       }
-
-                       secdebug("atomicfile", "write %s: %s", mPath.c_str(), strerror(error));
-                       UnixError::throwMe(error);
-               }
-
-               // Write returning 0 is bad mmkay.
-               if (bytesWritten == 0)
-               {
-                       secdebug("atomicfile", "write %s: 0 bytes written", mPath.c_str());
-                       CssmError::throwMe(CSSMERR_DL_INTERNAL_ERROR);
-               }
-
-               secdebug("atomicfile", "%p wrote %s %d bytes from %p", this, mPath.c_str(), bytesWritten, ptr);
-
-               bytesLeft -= bytesWritten;
-               ptr += bytesWritten;
-               pos += bytesWritten;
-       }
-}
-
-void
-AtomicTempFile::fsync()
-{
-       if (mFileRef < 0)
-       {
-               secdebug("atomicfile", "fsync %s: already closed", mPath.c_str());
-       }
-       else
-       {
-               int result;
-               do
-               {
-                       result = ::fsync(mFileRef);
-               } while (result && errno == EINTR);
-
-               if (result == -1)
-               {
-                       int error = errno;
-                       secdebug("atomicfile", "fsync %s: %s", mPath.c_str(), strerror(errno));
-                       UnixError::throwMe(error);
-               }
-
-               secdebug("atomicfile", "%p fsynced %s", this, mPath.c_str());
-       }
-}
-
-void
-AtomicTempFile::close()
-{
-       if (mFileRef < 0)
-       {
-               secdebug("atomicfile", "close %s: already closed", mPath.c_str());
-       }
-       else
-       {
-               int result = AtomicFile::rclose(mFileRef);
-               mFileRef = -1;
-               if (result == -1)
-               {
-                       int error = errno;
-                       secdebug("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno));
-                       UnixError::throwMe(error);
-               }
-
-               secdebug("atomicfile", "%p closed %s", this, mPath.c_str());
-       }
-}
-
-// Commit the current create or write and close the write file.  Note that a throw during the commit does an automatic rollback.
-void
-AtomicTempFile::commit()
-{
-       try
-       {
-               fsync();
-               close();
-               const char *oldPath = mPath.c_str();
-               const char *newPath = mFile.path().c_str();
-               if (::rename(oldPath, newPath) == -1)
-               {
-                       int error = errno;
-                       secdebug("atomicfile", "rename (%s, %s): %s", oldPath, newPath, strerror(errno));
-                       UnixError::throwMe(error);
-               }
-
-               // Unlock the lockfile
-               mLockedFile = NULL;
-
-               secdebug("atomicfile", "%p commited %s", this, oldPath);
-       }
-       catch (...)
-       {
-               rollback();
-               throw;
-       }
-}
-
-// Rollback the current create or write (happens automatically if commit() isn't called before the destructor is.
-void
-AtomicTempFile::rollback() throw()
-{
-       if (mFileRef >= 0)
-       {
-               AtomicFile::rclose(mFileRef);
-               mFileRef = -1;
-       }
-
-       // @@@ Log errors if this fails.
-       const char *path = mPath.c_str();
-       if (::unlink(path) == -1)
-       {
-               secdebug("atomicfile", "unlink %s: %s", path, strerror(errno));
-               // rollback can't throw
-       }
-
-       // @@@ Think about this.  Depending on how we do locking we might not need this.
-       if (mCreating)
-       {
-               const char *path = mFile.path().c_str();
-               if (::unlink(path) == -1)
-               {
-                       secdebug("atomicfile", "unlink %s: %s", path, strerror(errno));
-                       // rollback can't throw
-               }
-       }
-}
-
-
-//
-// An advisory write lock for inFile.
-//
-AtomicLockedFile::AtomicLockedFile(AtomicFile &inFile) :
-       mDir(inFile.dir()),
-       mPath(inFile.dir() + "lck~" + inFile.file())
-{
-       lock();
-}
-
-AtomicLockedFile::~AtomicLockedFile()
-{
-       unlock();
-}
-
-std::string
-AtomicLockedFile::unique(mode_t mode)
-{
-       static const int randomPart = 16;
-       DevRandomGenerator randomGen;
-       std::string::size_type dirSize = mDir.size();
-       std::string fullname(dirSize + randomPart + 2, '\0');
-       fullname.replace(0, dirSize, mDir);
-       fullname[dirSize] = '~'; /* UNIQ_PREFIX */
-       char buf[randomPart];
-       struct stat filebuf;
-       int result, fd = -1;
-
-       for (int retries = 0; retries < 10; ++retries)
-       {
-               /* Make a random filename. */
-               randomGen.random(buf, randomPart);
-               for (int ix = 0; ix < randomPart; ++ix)
-               {
-                       char ch = buf[ix] & 0x3f;
-                       fullname[ix + dirSize + 1] = ch +
-                               ( ch < 26            ? 'A'
-                               : ch < 26 + 26       ? 'a' - 26
-                               : ch < 26 + 26 + 10  ? '0' - 26 - 26
-                               : ch == 26 + 26 + 10 ? '-' - 26 - 26 - 10
-                               :                      '_' - 26 - 26 - 11);
-               }
-
-               result = lstat(fullname.c_str(), &filebuf);
-               if (result && errno == ENAMETOOLONG)
-               {
-                       do
-                               fullname.erase(fullname.end() - 1);
-                       while((result = lstat(fullname.c_str(), &filebuf)) && errno == ENAMETOOLONG && fullname.size() > dirSize + 8);
-               }       /* either it stopped being a problem or we ran out of filename */
-
-               if (result && errno == ENOENT)
-               {
-                       fd = AtomicFile::ropen(fullname.c_str(), O_WRONLY|O_CREAT|O_EXCL, mode);
-                       if (fd >= 0 || errno != EEXIST)
-                               break;
-               }
-       }
-
-       if (fd < 0)
-       {
-               int error = errno;
-               ::syslog(LOG_ERR, "Couldn't create temp file %s: %s", fullname.c_str(), strerror(error));
-               secdebug("atomicfile", "Couldn't create temp file %s: %s", fullname.c_str(), strerror(error));
-               UnixError::throwMe(error);
-       }
-
-       /* @@@ Check for EINTR. */
-       write(fd, "0", 1); /* pid 0, `works' across networks */
-
-       AtomicFile::rclose(fd);
-
-       return fullname;
-}
-
-/* Return 0 on success and 1 on failure if st is set to the result of stat(old) and -1 on failure if the stat(old) failed. */
-int
-AtomicLockedFile::rlink(const char *const old, const char *const newn, struct stat &sto)
-{
-       int result = ::link(old,newn);
-       if (result)
-       {
-               int serrno = errno;
-               if (::lstat(old, &sto) == 0)
-               {
-                       struct stat stn;
-                       if (::lstat(newn, &stn) == 0
-                               && sto.st_dev == stn.st_dev
-                               && sto.st_ino == stn.st_ino
-                               && sto.st_uid == stn.st_uid
-                               && sto.st_gid == stn.st_gid
-                               && !S_ISLNK(sto.st_mode))
-                       {
-                               /* Link failed but files are the same so the link really went ok. */
-                               return 0;
-                       }
-                       else
-                               result = 1;
-               }
-               errno = serrno; /* Restore errno from link() */
-       }
-
-       return result;
-}
-
-/* NFS-resistant rename()
- * rename with fallback for systems that don't support it
- * Note that this does not preserve the contents of the file. */
-int
-AtomicLockedFile::myrename(const char *const old, const char *const newn)
-{
-       struct stat stbuf;
-       int fd = -1;
-       int ret;
-
-       /* Try a real hardlink */
-       ret = rlink(old, newn, stbuf);
-       if (ret > 0)
-       {
-               if (stbuf.st_nlink < 2 && (errno == EXDEV || errno == ENOTSUP))
-               {
-                       /* Hard link failed so just create a new file with O_EXCL instead.  */
-                       fd = AtomicFile::ropen(newn, O_WRONLY|O_CREAT|O_EXCL, stbuf.st_mode);
-                       if (fd >= 0)
-                               ret = 0;
-               }
-       }
-
-       /* We want the errno from the link or the ropen, not that of the unlink. */
-       int serrno = errno;
-
-       /* Unlink the temp file. */
-       ::unlink(old);
-       if (fd > 0)
-               AtomicFile::rclose(fd);
-
-       errno = serrno;
-       return ret;
-}
-
-int
-AtomicLockedFile::xcreat(const char *const name, mode_t mode, time_t &tim)
-{
-       std::string uniqueName = unique(mode);
-       const char *uniquePath = uniqueName.c_str();
-       struct stat stbuf;       /* return the filesystem time to the caller */
-       stat(uniquePath, &stbuf);
-       tim = stbuf.st_mtime;
-       return myrename(uniquePath, name);
-}
-
-void
-AtomicLockedFile::lock(mode_t mode)
-{
-       const char *path = mPath.c_str();
-       bool triedforce = false;
-       struct stat stbuf;
-       time_t t, locktimeout = 1024; /* DEFlocktimeout, 17 minutes. */
-       bool doSyslog = false;
-       bool failed = false;
-       int retries = 0;
-
-       while (!failed)
-       {
-               /* Don't syslog first time through. */
-               if (doSyslog)
-                       ::syslog(LOG_NOTICE, "Locking %s", path);
-               else
-                       doSyslog = true;
-
-               secdebug("atomicfile", "Locking %s", path);          /* in order to cater for clock skew: get */
-               if (!xcreat(path, mode, t))    /* time t from the filesystem */
-               {
-                       /* lock acquired, hurray! */
-                       break;
-               }
-               switch(errno)
-               {
-               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;
-               }
-       }
-
-       if (failed)
-       {
-               int error = errno;
-               ::syslog(LOG_ERR, "Lock failure on %s: %s", path, strerror(error));
-               secdebug("atomicfile", "Lock failure on %s: %s", path, strerror(error));
-               UnixError::throwMe(error);
-       }
-}
-
-void
-AtomicLockedFile::unlock() throw()
-{
-       const char *path = mPath.c_str();
-       if (::unlink(path) == -1)
-       {
-               secdebug("atomicfile", "unlink %s: %s", path, strerror(errno));
-               // unlock can't throw
-       }
-}
-
-
-#undef kAtomicFileMaxBlockSize