Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Private Attributes
nsProfileLock Class Reference

#include <nsProfileLock.h>

List of all members.

Public Member Functions

 nsProfileLock ()
 nsProfileLock (nsProfileLock &src)
 ~nsProfileLock ()
nsProfileLockoperator= (nsProfileLock &rhs)
nsresult Lock (nsILocalFile *aProfileDir, nsIProfileUnlocker **aUnlocker)
 Attempt to lock a profile directory.
nsresult Unlock ()

Private Attributes

PRPackedBool mHaveLock

Detailed Description

Definition at line 61 of file nsProfileLock.h.


Constructor & Destructor Documentation

Definition at line 73 of file nsProfileLock.cpp.

                             :
    mHaveLock(PR_FALSE)
#if defined (XP_WIN)
    ,mLockFileHandle(INVALID_HANDLE_VALUE)
#elif defined (XP_OS2)
    ,mLockFileHandle(-1)
#elif defined (XP_UNIX)
    ,mPidLockFileName(nsnull)
    ,mLockFileDesc(-1)
#endif
{
#if defined (XP_UNIX)
    next = prev = this;
#endif
}

Definition at line 90 of file nsProfileLock.cpp.

{
    *this = src;
}

Definition at line 126 of file nsProfileLock.cpp.

{
    Unlock();
}

Here is the call graph for this function:


Member Function Documentation

nsresult nsProfileLock::Lock ( nsILocalFile aProfileDir,
nsIProfileUnlocker **  aUnlocker 
)

Attempt to lock a profile directory.

Parameters:
aProfileDir[in] The profile directory to lock.
aUnlocker[out] Optional. This is only returned when locking fails with NS_ERROR_FILE_ACCESS_DENIED, and may not be returned at all.
Exceptions:
NS_ERROR_FILE_ACCESS_DENIEDif the profile is locked.

Definition at line 421 of file nsProfileLock.cpp.

{
#if defined (XP_MACOSX)
    NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, ".parentlock");
    NS_NAMED_LITERAL_STRING(OLD_LOCKFILE_NAME, "parent.lock");
#elif defined (XP_UNIX)
    NS_NAMED_LITERAL_STRING(OLD_LOCKFILE_NAME, "lock");
    NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, ".parentlock");
#else
    NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, "parent.lock");
#endif

    nsresult rv;
    if (aUnlocker)
        *aUnlocker = nsnull;

    NS_ENSURE_STATE(!mHaveLock);

    PRBool isDir;
    rv = aProfileDir->IsDirectory(&isDir);
    if (NS_FAILED(rv))
        return rv;
    if (!isDir)
        return NS_ERROR_FILE_NOT_DIRECTORY;

    nsCOMPtr<nsILocalFile> lockFile;
    rv = aProfileDir->Clone((nsIFile **)((void **)getter_AddRefs(lockFile)));
    if (NS_FAILED(rv))
        return rv;

    rv = lockFile->Append(LOCKFILE_NAME);
    if (NS_FAILED(rv))
        return rv;
        
#if defined(XP_MACOSX)
    // First, try locking using fcntl. It is more reliable on
    // a local machine, but may not be supported by an NFS server.
    nsCAutoString filePath;
    rv = lockFile->GetNativePath(filePath);
    if (NS_FAILED(rv))
        return rv;

    rv = LockWithFcntl(filePath);
    if (NS_FAILED(rv) && (rv != NS_ERROR_FILE_ACCESS_DENIED))
    {
        // If that failed for any reason other than NS_ERROR_FILE_ACCESS_DENIED,
        // assume we tried an NFS that does not support it. Now, try with symlink.
        rv = LockWithSymlink(filePath, PR_FALSE);
    }
    
    if (NS_SUCCEEDED(rv))
    {
        // Check for the old-style lock used by pre-mozilla 1.3 builds.
        // Those builds used an earlier check to prevent the application
        // from launching if another instance was already running. Because
        // of that, we don't need to create an old-style lock as well.
        struct LockProcessInfo
        {
            ProcessSerialNumber psn;
            unsigned long launchDate;
        };

        PRFileDesc *fd = nsnull;
        PRInt32 ioBytes;
        ProcessInfoRec processInfo;
        LockProcessInfo lockProcessInfo;

        rv = lockFile->SetLeafName(OLD_LOCKFILE_NAME);
        if (NS_FAILED(rv))
            return rv;
        rv = lockFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
        if (NS_SUCCEEDED(rv))
        {
            ioBytes = PR_Read(fd, &lockProcessInfo, sizeof(LockProcessInfo));
            PR_Close(fd);

            if (ioBytes == sizeof(LockProcessInfo))
            {
                processInfo.processAppSpec = nsnull;
                processInfo.processName = nsnull;
                processInfo.processInfoLength = sizeof(ProcessInfoRec);
                if (::GetProcessInformation(&lockProcessInfo.psn, &processInfo) == noErr &&
                    processInfo.processLaunchDate == lockProcessInfo.launchDate)
                {
                    return NS_ERROR_FILE_ACCESS_DENIED;
                }
            }
            else
            {
                NS_WARNING("Could not read lock file - ignoring lock");
            }
        }
        rv = NS_OK; // Don't propagate error from OpenNSPRFileDesc.
    }
#elif defined(XP_UNIX)
    nsCAutoString filePath;
    rv = lockFile->GetNativePath(filePath);
    if (NS_FAILED(rv))
        return rv;

    // Get the old lockfile name
    nsCOMPtr<nsIFile> oldLockFile;
    rv = aProfileDir->Clone(getter_AddRefs(oldLockFile));
    if (NS_FAILED(rv))
        return rv;
    rv = oldLockFile->Append(OLD_LOCKFILE_NAME);
    if (NS_FAILED(rv))
        return rv;
    nsCAutoString oldFilePath;
    rv = oldLockFile->GetNativePath(oldFilePath);
    if (NS_FAILED(rv))
        return rv;

    // First, try locking using fcntl. It is more reliable on
    // a local machine, but may not be supported by an NFS server.
    rv = LockWithFcntl(filePath);
    if (NS_SUCCEEDED(rv)) {
        // Check to see whether there is a symlink lock held by an older
        // Firefox build, and also place our own symlink lock --- but
        // mark it "obsolete" so that other newer builds can break the lock
        // if they obtain the fcntl lock
        rv = LockWithSymlink(oldFilePath, PR_TRUE);

        // If the symlink failed for some reason other than it already
        // exists, then something went wrong e.g. the file system
        // doesn't support symlinks, or we don't have permission to
        // create a symlink there.  In such cases we should just
        // continue because it's unlikely there is an old build
        // running with a symlink there and we've already successfully
        // placed a fcntl lock.
        if (rv != NS_ERROR_FILE_ACCESS_DENIED)
            rv = NS_OK;
    }
    else if (rv != NS_ERROR_FILE_ACCESS_DENIED)
    {
        // If that failed for any reason other than NS_ERROR_FILE_ACCESS_DENIED,
        // assume we tried an NFS that does not support it. Now, try with symlink
        // using the old symlink path
        rv = LockWithSymlink(oldFilePath, PR_FALSE);
    }

#elif defined(XP_WIN)
    nsCAutoString filePath;
    rv = lockFile->GetNativePath(filePath);
    if (NS_FAILED(rv))
        return rv;
    mLockFileHandle = CreateFile(filePath.get(),
                                 GENERIC_READ | GENERIC_WRITE,
                                 0, // no sharing - of course
                                 nsnull,
                                 OPEN_ALWAYS,
                                 FILE_FLAG_DELETE_ON_CLOSE,
                                 nsnull);
    if (mLockFileHandle == INVALID_HANDLE_VALUE) {
        // XXXbsmedberg: provide a profile-unlocker here!
        return NS_ERROR_FILE_ACCESS_DENIED;
    }
#elif defined(XP_OS2)
    nsCAutoString filePath;
    rv = lockFile->GetNativePath(filePath);
    if (NS_FAILED(rv))
        return rv;

    ULONG   ulAction = 0;
    APIRET  rc;
    rc = DosOpen(filePath.get(),
                  &mLockFileHandle,
                  &ulAction,
                  0,
                  FILE_NORMAL,
                  OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
                  OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE | OPEN_FLAGS_NOINHERIT,
                  0 );
    if (rc != NO_ERROR)
    {
        mLockFileHandle = -1;
        return NS_ERROR_FILE_ACCESS_DENIED;
    }
#elif defined(VMS)
    nsCAutoString filePath;
    rv = lockFile->GetNativePath(filePath);
    if (NS_FAILED(rv))
        return rv;

    mLockFileDesc = open_noshr(filePath.get(), O_CREAT, 0666);
    if (mLockFileDesc == -1)
    {
       if ((errno == EVMSERR) && (vaxc$errno == RMS$_FLK))
       {
           return NS_ERROR_FILE_ACCESS_DENIED;
       }
       else
       {
           NS_ERROR("Failed to open lock file.");
           return NS_ERROR_FAILURE;
       }
    }
#endif

    mHaveLock = PR_TRUE;

    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsProfileLock & nsProfileLock::operator= ( nsProfileLock rhs)

Definition at line 96 of file nsProfileLock.cpp.

{
    Unlock();

    mHaveLock = rhs.mHaveLock;
    rhs.mHaveLock = PR_FALSE;

#if defined (XP_WIN)
    mLockFileHandle = rhs.mLockFileHandle;
    rhs.mLockFileHandle = INVALID_HANDLE_VALUE;
#elif defined (XP_OS2)
    mLockFileHandle = rhs.mLockFileHandle;
    rhs.mLockFileHandle = -1;
#elif defined (XP_UNIX)
    mLockFileDesc = rhs.mLockFileDesc;
    rhs.mLockFileDesc = -1;
    mPidLockFileName = rhs.mPidLockFileName;
    rhs.mPidLockFileName = nsnull;
    if (mPidLockFileName)
    {
        // rhs had a symlink lock, therefore it was on the list.
        PR_REMOVE_LINK(&rhs);
        PR_APPEND_LINK(this, &mPidLockList);
    }
#endif

    return *this;
}

Here is the call graph for this function:

Definition at line 627 of file nsProfileLock.cpp.

{
    nsresult rv = NS_OK;

    if (mHaveLock)
    {
#if defined (XP_WIN)
        if (mLockFileHandle != INVALID_HANDLE_VALUE)
        {
            CloseHandle(mLockFileHandle);
            mLockFileHandle = INVALID_HANDLE_VALUE;
        }
#elif defined (XP_OS2)
        if (mLockFileHandle != -1)
        {
            DosClose(mLockFileHandle);
            mLockFileHandle = -1;
        }
#elif defined (XP_UNIX)
        if (mPidLockFileName)
        {
            PR_REMOVE_LINK(this);
            (void) unlink(mPidLockFileName);
            free(mPidLockFileName);
            mPidLockFileName = nsnull;
        }
        else if (mLockFileDesc != -1)
        {
            close(mLockFileDesc);
            mLockFileDesc = -1;
            // Don't remove it
        }
#endif

        mHaveLock = PR_FALSE;
    }

    return rv;
}

Here is the caller graph for this function:


Member Data Documentation

Definition at line 87 of file nsProfileLock.h.


The documentation for this class was generated from the following files: