LCOV - app.info - objdir/toolkit/profile/nsProfileLock.cpp

LCOV - code coverage report
| Current view: | directory - objdir/toolkit/profile - nsProfileLock.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 214 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 12 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 2002
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *   Conrad Carlen <ccarlen@netscape.com>
          24                 :  *   Brendan Eich <brendan@mozilla.org>
          25                 :  *   Colin Blake <colin@theblakes.com>
          26                 :  *   Javier Pedemonte <pedemont@us.ibm.com>
          27                 :  *   Mats Palmgren <mats.palmgren@bredband.net>
          28                 :  *
          29                 :  * Alternatively, the contents of this file may be used under the terms of
          30                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          31                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          33                 :  * of those above. If you wish to allow use of your version of this file only
          34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          35                 :  * use your version of this file under the terms of the MPL, indicate your
          36                 :  * decision by deleting the provisions above and replace them with the notice
          37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          38                 :  * the provisions above, a recipient may use your version of this file under
          39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          40                 :  *
          41                 :  * ***** END LICENSE BLOCK ***** */
          42                 :
          43                 : #include "nsProfileStringTypes.h"
          44                 : #include "nsProfileLock.h"
          45                 : #include "nsCOMPtr.h"
          46                 :
          47                 : #if defined(XP_MACOSX)
          48                 : #include <Carbon/Carbon.h>
          49                 : #include <CoreFoundation/CoreFoundation.h>
          50                 : #endif
          51                 :
          52                 : #ifdef XP_UNIX
          53                 : #include <unistd.h>
          54                 : #include <fcntl.h>
          55                 : #include <errno.h>
          56                 : #include <signal.h>
          57                 : #include <stdlib.h>
          58                 : #include "prnetdb.h"
          59                 : #include "prsystem.h"
          60                 : #include "prprf.h"
          61                 : #include "prenv.h"
          62                 : #endif
          63                 :
          64                 : #ifdef VMS
          65                 : #include <rmsdef.h>
          66                 : #endif
          67                 :
          68                 : // **********************************************************************
          69                 : // class nsProfileLock
          70                 : //
          71                 : // This code was moved from profile/src/nsProfileAccess.
          72                 : // **********************************************************************
          73                 :
          74                 : #if defined (XP_UNIX)
          75                 : static bool sDisableSignalHandling = false;
          76                 : #endif
          77                 :
          78               0 : nsProfileLock::nsProfileLock() :
          79                 :     mHaveLock(false),
          80                 :     mReplacedLockTime(0)
          81                 : #if defined (XP_WIN)
          82                 :     ,mLockFileHandle(INVALID_HANDLE_VALUE)
          83                 : #elif defined (XP_OS2)
          84                 :     ,mLockFileHandle(-1)
          85                 : #elif defined (XP_UNIX)
          86                 :     ,mPidLockFileName(nsnull)
          87               0 :     ,mLockFileDesc(-1)
          88                 : #endif
          89                 : {
          90                 : #if defined (XP_UNIX)
          91               0 :     next = prev = this;
          92               0 :     sDisableSignalHandling = PR_GetEnv("MOZ_DISABLE_SIG_HANDLER") ? true : false;
          93                 : #endif
          94               0 : }
          95                 :
          96                 :
          97               0 : nsProfileLock::nsProfileLock(nsProfileLock& src)
          98                 : {
          99               0 :     *this = src;
         100               0 : }
         101                 :
         102                 :
         103               0 : nsProfileLock& nsProfileLock::operator=(nsProfileLock& rhs)
         104                 : {
         105               0 :     Unlock();
         106                 :
         107               0 :     mHaveLock = rhs.mHaveLock;
         108               0 :     rhs.mHaveLock = false;
         109                 :
         110                 : #if defined (XP_WIN)
         111                 :     mLockFileHandle = rhs.mLockFileHandle;
         112                 :     rhs.mLockFileHandle = INVALID_HANDLE_VALUE;
         113                 : #elif defined (XP_OS2)
         114                 :     mLockFileHandle = rhs.mLockFileHandle;
         115                 :     rhs.mLockFileHandle = -1;
         116                 : #elif defined (XP_UNIX)
         117               0 :     mLockFileDesc = rhs.mLockFileDesc;
         118               0 :     rhs.mLockFileDesc = -1;
         119               0 :     mPidLockFileName = rhs.mPidLockFileName;
         120               0 :     rhs.mPidLockFileName = nsnull;
         121               0 :     if (mPidLockFileName)
         122                 :     {
         123                 :         // rhs had a symlink lock, therefore it was on the list.
         124               0 :         PR_REMOVE_LINK(&rhs);
         125               0 :         PR_APPEND_LINK(this, &mPidLockList);
         126                 :     }
         127                 : #endif
         128                 :
         129               0 :     return *this;
         130                 : }
         131                 :
         132                 :
         133               0 : nsProfileLock::~nsProfileLock()
         134                 : {
         135               0 :     Unlock();
         136               0 : }
         137                 :
         138                 :
         139                 : #if defined (XP_UNIX)
         140                 :
         141                 : static int setupPidLockCleanup;
         142                 :
         143                 : PRCList nsProfileLock::mPidLockList =
         144                 :     PR_INIT_STATIC_CLIST(&nsProfileLock::mPidLockList);
         145                 :
         146               0 : void nsProfileLock::RemovePidLockFiles(bool aFatalSignal)
         147                 : {
         148               0 :     while (!PR_CLIST_IS_EMPTY(&mPidLockList))
         149                 :     {
         150               0 :         nsProfileLock *lock = static_cast<nsProfileLock*>(mPidLockList.next);
         151               0 :         lock->Unlock(aFatalSignal);
         152                 :     }
         153               0 : }
         154                 :
         155                 : static struct sigaction SIGHUP_oldact;
         156                 : static struct sigaction SIGINT_oldact;
         157                 : static struct sigaction SIGQUIT_oldact;
         158                 : static struct sigaction SIGILL_oldact;
         159                 : static struct sigaction SIGABRT_oldact;
         160                 : static struct sigaction SIGSEGV_oldact;
         161                 : static struct sigaction SIGTERM_oldact;
         162                 :
         163               0 : void nsProfileLock::FatalSignalHandler(int signo
         164                 : #ifdef SA_SIGINFO
         165                 :                                        , siginfo_t *info, void *context
         166                 : #endif
         167                 :                                        )
         168                 : {
         169                 :     // Remove any locks still held.
         170               0 :     RemovePidLockFiles(true);
         171                 :
         172                 :     // Chain to the old handler, which may exit.
         173               0 :     struct sigaction *oldact = nsnull;
         174                 :
         175               0 :     switch (signo) {
         176                 :       case SIGHUP:
         177               0 :         oldact = &SIGHUP_oldact;
         178               0 :         break;
         179                 :       case SIGINT:
         180               0 :         oldact = &SIGINT_oldact;
         181               0 :         break;
         182                 :       case SIGQUIT:
         183               0 :         oldact = &SIGQUIT_oldact;
         184               0 :         break;
         185                 :       case SIGILL:
         186               0 :         oldact = &SIGILL_oldact;
         187               0 :         break;
         188                 :       case SIGABRT:
         189               0 :         oldact = &SIGABRT_oldact;
         190               0 :         break;
         191                 :       case SIGSEGV:
         192               0 :         oldact = &SIGSEGV_oldact;
         193               0 :         break;
         194                 :       case SIGTERM:
         195               0 :         oldact = &SIGTERM_oldact;
         196               0 :         break;
         197                 :       default:
         198               0 :         NS_NOTREACHED("bad signo");
         199               0 :         break;
         200                 :     }
         201                 :
         202               0 :     if (oldact) {
         203               0 :         if (oldact->sa_handler == SIG_DFL) {
         204                 :             // Make sure the default sig handler is executed
         205                 :             // We need it to get Mozilla to dump core.
         206               0 :             sigaction(signo,oldact,NULL);
         207                 :
         208                 :             // Now that we've restored the default handler, unmask the
         209                 :             // signal and invoke it.
         210                 :
         211                 :             sigset_t unblock_sigs;
         212               0 :             sigemptyset(&unblock_sigs);
         213               0 :             sigaddset(&unblock_sigs, signo);
         214                 :
         215               0 :             sigprocmask(SIG_UNBLOCK, &unblock_sigs, NULL);
         216                 :
         217               0 :             raise(signo);
         218                 :         }
         219                 : #ifdef SA_SIGINFO
         220               0 :         else if (oldact->sa_sigaction &&
         221                 :                  (oldact->sa_flags & SA_SIGINFO) == SA_SIGINFO) {
         222               0 :             oldact->sa_sigaction(signo, info, context);
         223                 :         }
         224                 : #endif
         225               0 :         else if (oldact->sa_handler && oldact->sa_handler != SIG_IGN)
         226                 :         {
         227               0 :             oldact->sa_handler(signo);
         228                 :         }
         229                 :     }
         230                 :
         231                 :     // Backstop exit call, just in case.
         232               0 :     _exit(signo);
         233                 : }
         234                 :
         235               0 : nsresult nsProfileLock::LockWithFcntl(nsILocalFile *aLockFile)
         236                 : {
         237               0 :     nsresult rv = NS_OK;
         238                 :
         239               0 :     nsCAutoString lockFilePath;
         240               0 :     rv = aLockFile->GetNativePath(lockFilePath);
         241               0 :     if (NS_FAILED(rv)) {
         242               0 :         NS_ERROR("Could not get native path");
         243               0 :         return rv;
         244                 :     }
         245                 :
         246               0 :     aLockFile->GetLastModifiedTime(&mReplacedLockTime);
         247                 :
         248               0 :     mLockFileDesc = open(PromiseFlatCString(lockFilePath).get(),
         249               0 :                           O_WRONLY | O_CREAT | O_TRUNC, 0666);
         250               0 :     if (mLockFileDesc != -1)
         251                 :     {
         252                 :         struct flock lock;
         253               0 :         lock.l_start = 0;
         254               0 :         lock.l_len = 0; // len = 0 means entire file
         255               0 :         lock.l_type = F_WRLCK;
         256               0 :         lock.l_whence = SEEK_SET;
         257                 :
         258                 :         // If fcntl(F_GETLK) fails then the server does not support/allow fcntl(),
         259                 :         // return failure rather than access denied in this case so we fallback
         260                 :         // to using a symlink lock, bug 303633.
         261               0 :         struct flock testlock = lock;
         262               0 :         if (fcntl(mLockFileDesc, F_GETLK, &testlock) == -1)
         263                 :         {
         264               0 :             close(mLockFileDesc);
         265               0 :             mLockFileDesc = -1;
         266               0 :             rv = NS_ERROR_FAILURE;
         267                 :         }
         268               0 :         else if (fcntl(mLockFileDesc, F_SETLK, &lock) == -1)
         269                 :         {
         270               0 :             close(mLockFileDesc);
         271               0 :             mLockFileDesc = -1;
         272                 :
         273                 :             // With OS X, on NFS, errno == ENOTSUP
         274                 :             // XXX Check for that and return specific rv for it?
         275                 : #ifdef DEBUG
         276               0 :             printf("fcntl(F_SETLK) failed. errno = %d\n", errno);
         277                 : #endif
         278               0 :             if (errno == EAGAIN || errno == EACCES)
         279               0 :                 rv = NS_ERROR_FILE_ACCESS_DENIED;
         280                 :             else
         281               0 :                 rv = NS_ERROR_FAILURE;
         282                 :         }
         283                 :         else
         284               0 :             mHaveLock = true;
         285                 :     }
         286                 :     else
         287                 :     {
         288               0 :         NS_ERROR("Failed to open lock file.");
         289               0 :         rv = NS_ERROR_FAILURE;
         290                 :     }
         291               0 :     return rv;
         292                 : }
         293                 :
         294               0 : static bool IsSymlinkStaleLock(struct in_addr* aAddr, const char* aFileName,
         295                 :                                  bool aHaveFcntlLock)
         296                 : {
         297                 :     // the link exists; see if it's from this machine, and if
         298                 :     // so if the process is still active
         299                 :     char buf[1024];
         300               0 :     int len = readlink(aFileName, buf, sizeof buf - 1);
         301               0 :     if (len > 0)
         302                 :     {
         303               0 :         buf[len] = '\0';
         304               0 :         char *colon = strchr(buf, ':');
         305               0 :         if (colon)
         306                 :         {
         307               0 :             *colon++ = '\0';
         308               0 :             unsigned long addr = inet_addr(buf);
         309               0 :             if (addr != (unsigned long) -1)
         310                 :             {
         311               0 :                 if (colon[0] == '+' && aHaveFcntlLock) {
         312                 :                     // This lock was placed by a Firefox build which would have
         313                 :                     // taken the fnctl lock, and we've already taken the fcntl lock,
         314                 :                     // so the process that created this obsolete lock must be gone
         315               0 :                     return true;
         316                 :                 }
         317                 :
         318               0 :                 char *after = nsnull;
         319               0 :                 pid_t pid = strtol(colon, &after, 0);
         320               0 :                 if (pid != 0 && *after == '\0')
         321                 :                 {
         322               0 :                     if (addr != aAddr->s_addr)
         323                 :                     {
         324                 :                         // Remote lock: give up even if stuck.
         325               0 :                         return false;
         326                 :                     }
         327                 :
         328                 :                     // kill(pid,0) is a neat trick to check if a
         329                 :                     // process exists
         330               0 :                     if (kill(pid, 0) == 0 || errno != ESRCH)
         331                 :                     {
         332                 :                         // Local process appears to be alive, ass-u-me it
         333                 :                         // is another Mozilla instance, or a compatible
         334                 :                         // derivative, that's currently using the profile.
         335                 :                         // XXX need an "are you Mozilla?" protocol
         336               0 :                         return false;
         337                 :                     }
         338                 :                 }
         339                 :             }
         340                 :         }
         341                 :     }
         342               0 :     return true;
         343                 : }
         344                 :
         345               0 : nsresult nsProfileLock::LockWithSymlink(nsILocalFile *aLockFile, bool aHaveFcntlLock)
         346                 : {
         347                 :     nsresult rv;
         348               0 :     nsCAutoString lockFilePath;
         349               0 :     rv = aLockFile->GetNativePath(lockFilePath);
         350               0 :     if (NS_FAILED(rv)) {
         351               0 :         NS_ERROR("Could not get native path");
         352               0 :         return rv;
         353                 :     }
         354                 :
         355                 :     // don't replace an existing lock time if fcntl already got one
         356               0 :     if (!mReplacedLockTime)
         357               0 :         aLockFile->GetLastModifiedTimeOfLink(&mReplacedLockTime);
         358                 :
         359                 :     struct in_addr inaddr;
         360               0 :     inaddr.s_addr = htonl(INADDR_LOOPBACK);
         361                 :
         362                 :     char hostname[256];
         363               0 :     PRStatus status = PR_GetSystemInfo(PR_SI_HOSTNAME, hostname, sizeof hostname);
         364               0 :     if (status == PR_SUCCESS)
         365                 :     {
         366                 :         char netdbbuf[PR_NETDB_BUF_SIZE];
         367                 :         PRHostEnt hostent;
         368               0 :         status = PR_GetHostByName(hostname, netdbbuf, sizeof netdbbuf, &hostent);
         369               0 :         if (status == PR_SUCCESS)
         370               0 :             memcpy(&inaddr, hostent.h_addr, sizeof inaddr);
         371                 :     }
         372                 :
         373                 :     char *signature =
         374                 :         PR_smprintf("%s:%s%lu", inet_ntoa(inaddr), aHaveFcntlLock ? "+" : "",
         375               0 :                     (unsigned long)getpid());
         376               0 :     const nsPromiseFlatCString& flat = PromiseFlatCString(lockFilePath);
         377               0 :     const char *fileName = flat.get();
         378               0 :     int symlink_rv, symlink_errno = 0, tries = 0;
         379                 :
         380                 :     // use ns4.x-compatible symlinks if the FS supports them
         381               0 :     while ((symlink_rv = symlink(signature, fileName)) < 0)
         382                 :     {
         383               0 :         symlink_errno = errno;
         384               0 :         if (symlink_errno != EEXIST)
         385               0 :             break;
         386                 :
         387               0 :         if (!IsSymlinkStaleLock(&inaddr, fileName, aHaveFcntlLock))
         388               0 :             break;
         389                 :
         390                 :         // Lock seems to be bogus: try to claim it.  Give up after a large
         391                 :         // number of attempts (100 comes from the 4.x codebase).
         392               0 :         (void) unlink(fileName);
         393               0 :         if (++tries > 100)
         394               0 :             break;
         395                 :     }
         396                 :
         397               0 :     PR_smprintf_free(signature);
         398               0 :     signature = nsnull;
         399                 :
         400               0 :     if (symlink_rv == 0)
         401                 :     {
         402                 :         // We exclusively created the symlink: record its name for eventual
         403                 :         // unlock-via-unlink.
         404               0 :         rv = NS_OK;
         405               0 :         mHaveLock = true;
         406               0 :         mPidLockFileName = strdup(fileName);
         407               0 :         if (mPidLockFileName)
         408                 :         {
         409               0 :             PR_APPEND_LINK(this, &mPidLockList);
         410               0 :             if (!setupPidLockCleanup++)
         411                 :             {
         412                 :                 // Clean up on normal termination.
         413                 :                 // This instanciates a dummy class, and will trigger the class
         414                 :                 // destructor when libxul is unloaded. This is equivalent to atexit(),
         415                 :                 // but gracefully handles dlclose().
         416               0 :                 static RemovePidLockFilesExiting r;
         417                 :
         418                 :                 // Clean up on abnormal termination, using POSIX sigaction.
         419                 :                 // Don't arm a handler if the signal is being ignored, e.g.,
         420                 :                 // because mozilla is run via nohup.
         421               0 :                 if (!sDisableSignalHandling) {
         422                 :                     struct sigaction act, oldact;
         423                 : #ifdef SA_SIGINFO
         424               0 :                     act.sa_sigaction = FatalSignalHandler;
         425               0 :                     act.sa_flags = SA_SIGINFO;
         426                 : #else
         427                 :                     act.sa_handler = FatalSignalHandler;
         428                 : #endif
         429               0 :                     sigfillset(&act.sa_mask);
         430                 :
         431                 : #define CATCH_SIGNAL(signame)                                           \
         432                 : PR_BEGIN_MACRO                                                          \
         433                 :   if (sigaction(signame, NULL, &oldact) == 0 &&                         \
         434                 :       oldact.sa_handler != SIG_IGN)                                     \
         435                 :   {                                                                     \
         436                 :       sigaction(signame, &act, &signame##_oldact);                      \
         437                 :   }                                                                     \
         438                 :   PR_END_MACRO
         439                 :
         440               0 :                     CATCH_SIGNAL(SIGHUP);
         441               0 :                     CATCH_SIGNAL(SIGINT);
         442               0 :                     CATCH_SIGNAL(SIGQUIT);
         443               0 :                     CATCH_SIGNAL(SIGILL);
         444               0 :                     CATCH_SIGNAL(SIGABRT);
         445               0 :                     CATCH_SIGNAL(SIGSEGV);
         446               0 :                     CATCH_SIGNAL(SIGTERM);
         447                 :
         448                 : #undef CATCH_SIGNAL
         449                 :                 }
         450                 :             }
         451                 :         }
         452                 :     }
         453               0 :     else if (symlink_errno == EEXIST)
         454               0 :         rv = NS_ERROR_FILE_ACCESS_DENIED;
         455                 :     else
         456                 :     {
         457                 : #ifdef DEBUG
         458               0 :         printf("symlink() failed. errno = %d\n", errno);
         459                 : #endif
         460               0 :         rv = NS_ERROR_FAILURE;
         461                 :     }
         462               0 :     return rv;
         463                 : }
         464                 : #endif /* XP_UNIX */
         465                 :
         466               0 : nsresult nsProfileLock::GetReplacedLockTime(PRInt64 *aResult) {
         467               0 :     *aResult = mReplacedLockTime;
         468               0 :     return NS_OK;
         469                 : }
         470                 :
         471               0 : nsresult nsProfileLock::Lock(nsILocalFile* aProfileDir,
         472                 :                              nsIProfileUnlocker* *aUnlocker)
         473                 : {
         474                 : #if defined (XP_MACOSX)
         475                 :     NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, ".parentlock");
         476                 :     NS_NAMED_LITERAL_STRING(OLD_LOCKFILE_NAME, "parent.lock");
         477                 : #elif defined (XP_UNIX)
         478               0 :     NS_NAMED_LITERAL_STRING(OLD_LOCKFILE_NAME, "lock");
         479               0 :     NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, ".parentlock");
         480                 : #else
         481                 :     NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, "parent.lock");
         482                 : #endif
         483                 :
         484                 :     nsresult rv;
         485               0 :     if (aUnlocker)
         486               0 :         *aUnlocker = nsnull;
         487                 :
         488               0 :     NS_ENSURE_STATE(!mHaveLock);
         489                 :
         490                 :     bool isDir;
         491               0 :     rv = aProfileDir->IsDirectory(&isDir);
         492               0 :     if (NS_FAILED(rv))
         493               0 :         return rv;
         494               0 :     if (!isDir)
         495               0 :         return NS_ERROR_FILE_NOT_DIRECTORY;
         496                 :
         497               0 :     nsCOMPtr<nsILocalFile> lockFile;
         498               0 :     rv = aProfileDir->Clone((nsIFile **)((void **)getter_AddRefs(lockFile)));
         499               0 :     if (NS_FAILED(rv))
         500               0 :         return rv;
         501                 :
         502               0 :     rv = lockFile->Append(LOCKFILE_NAME);
         503               0 :     if (NS_FAILED(rv))
         504               0 :         return rv;
         505                 :
         506                 : #if defined(XP_MACOSX)
         507                 :     // First, try locking using fcntl. It is more reliable on
         508                 :     // a local machine, but may not be supported by an NFS server.
         509                 :
         510                 :     rv = LockWithFcntl(lockFile);
         511                 :     if (NS_FAILED(rv) && (rv != NS_ERROR_FILE_ACCESS_DENIED))
         512                 :     {
         513                 :         // If that failed for any reason other than NS_ERROR_FILE_ACCESS_DENIED,
         514                 :         // assume we tried an NFS that does not support it. Now, try with symlink.
         515                 :         rv = LockWithSymlink(lockFile, false);
         516                 :     }
         517                 :
         518                 :     if (NS_SUCCEEDED(rv))
         519                 :     {
         520                 :         // Check for the old-style lock used by pre-mozilla 1.3 builds.
         521                 :         // Those builds used an earlier check to prevent the application
         522                 :         // from launching if another instance was already running. Because
         523                 :         // of that, we don't need to create an old-style lock as well.
         524                 :         struct LockProcessInfo
         525                 :         {
         526                 :             ProcessSerialNumber psn;
         527                 :             unsigned long launchDate;
         528                 :         };
         529                 :
         530                 :         PRFileDesc *fd = nsnull;
         531                 :         PRInt32 ioBytes;
         532                 :         ProcessInfoRec processInfo;
         533                 :         LockProcessInfo lockProcessInfo;
         534                 :
         535                 :         rv = lockFile->SetLeafName(OLD_LOCKFILE_NAME);
         536                 :         if (NS_FAILED(rv))
         537                 :             return rv;
         538                 :         rv = lockFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
         539                 :         if (NS_SUCCEEDED(rv))
         540                 :         {
         541                 :             ioBytes = PR_Read(fd, &lockProcessInfo, sizeof(LockProcessInfo));
         542                 :             PR_Close(fd);
         543                 :
         544                 :             if (ioBytes == sizeof(LockProcessInfo))
         545                 :             {
         546                 : #ifdef __LP64__
         547                 :                 processInfo.processAppRef = NULL;
         548                 : #else
         549                 :                 processInfo.processAppSpec = NULL;
         550                 : #endif
         551                 :                 processInfo.processName = NULL;
         552                 :                 processInfo.processInfoLength = sizeof(ProcessInfoRec);
         553                 :                 if (::GetProcessInformation(&lockProcessInfo.psn, &processInfo) == noErr &&
         554                 :                     processInfo.processLaunchDate == lockProcessInfo.launchDate)
         555                 :                 {
         556                 :                     return NS_ERROR_FILE_ACCESS_DENIED;
         557                 :                 }
         558                 :             }
         559                 :             else
         560                 :             {
         561                 :                 NS_WARNING("Could not read lock file - ignoring lock");
         562                 :             }
         563                 :         }
         564                 :         rv = NS_OK; // Don't propagate error from OpenNSPRFileDesc.
         565                 :     }
         566                 : #elif defined(XP_UNIX)
         567                 :     // Get the old lockfile name
         568               0 :     nsCOMPtr<nsILocalFile> oldLockFile;
         569               0 :     rv = aProfileDir->Clone((nsIFile **)((void **)getter_AddRefs(oldLockFile)));
         570               0 :     if (NS_FAILED(rv))
         571               0 :         return rv;
         572               0 :     rv = oldLockFile->Append(OLD_LOCKFILE_NAME);
         573               0 :     if (NS_FAILED(rv))
         574               0 :         return rv;
         575                 :
         576                 :     // First, try locking using fcntl. It is more reliable on
         577                 :     // a local machine, but may not be supported by an NFS server.
         578               0 :     rv = LockWithFcntl(lockFile);
         579               0 :     if (NS_SUCCEEDED(rv)) {
         580                 :         // Check to see whether there is a symlink lock held by an older
         581                 :         // Firefox build, and also place our own symlink lock --- but
         582                 :         // mark it "obsolete" so that other newer builds can break the lock
         583                 :         // if they obtain the fcntl lock
         584               0 :         rv = LockWithSymlink(oldLockFile, true);
         585                 :
         586                 :         // If the symlink failed for some reason other than it already
         587                 :         // exists, then something went wrong e.g. the file system
         588                 :         // doesn't support symlinks, or we don't have permission to
         589                 :         // create a symlink there.  In such cases we should just
         590                 :         // continue because it's unlikely there is an old build
         591                 :         // running with a symlink there and we've already successfully
         592                 :         // placed a fcntl lock.
         593               0 :         if (rv != NS_ERROR_FILE_ACCESS_DENIED)
         594               0 :             rv = NS_OK;
         595                 :     }
         596               0 :     else if (rv != NS_ERROR_FILE_ACCESS_DENIED)
         597                 :     {
         598                 :         // If that failed for any reason other than NS_ERROR_FILE_ACCESS_DENIED,
         599                 :         // assume we tried an NFS that does not support it. Now, try with symlink
         600                 :         // using the old symlink path
         601               0 :         rv = LockWithSymlink(oldLockFile, false);
         602                 :     }
         603                 :
         604                 : #elif defined(XP_WIN)
         605                 :     nsAutoString filePath;
         606                 :     rv = lockFile->GetPath(filePath);
         607                 :     if (NS_FAILED(rv))
         608                 :         return rv;
         609                 :
         610                 :     lockFile->GetLastModifiedTime(&mReplacedLockTime);
         611                 :
         612                 :     // always create the profile lock and never delete it so we can use its
         613                 :     // modification timestamp to detect startup crashes
         614                 :     mLockFileHandle = CreateFileW(filePath.get(),
         615                 :                                   GENERIC_READ | GENERIC_WRITE,
         616                 :                                   0, // no sharing - of course
         617                 :                                   nsnull,
         618                 :                                   CREATE_ALWAYS,
         619                 :                                   nsnull,
         620                 :                                   nsnull);
         621                 :     if (mLockFileHandle == INVALID_HANDLE_VALUE) {
         622                 :         // XXXbsmedberg: provide a profile-unlocker here!
         623                 :         return NS_ERROR_FILE_ACCESS_DENIED;
         624                 :     }
         625                 : #elif defined(XP_OS2)
         626                 :     nsCAutoString filePath;
         627                 :     rv = lockFile->GetNativePath(filePath);
         628                 :     if (NS_FAILED(rv))
         629                 :         return rv;
         630                 :
         631                 :     lockFile->GetLastModifiedTime(&mReplacedLockTime);
         632                 :
         633                 :     ULONG   ulAction = 0;
         634                 :     APIRET  rc;
         635                 :     rc = DosOpen(filePath.get(),
         636                 :                   &mLockFileHandle,
         637                 :                   &ulAction,
         638                 :                   0,
         639                 :                   FILE_NORMAL,
         640                 :                   OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
         641                 :                   OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE | OPEN_FLAGS_NOINHERIT,
         642                 :                   0 );
         643                 :     if (rc != NO_ERROR)
         644                 :     {
         645                 :         mLockFileHandle = -1;
         646                 :         return NS_ERROR_FILE_ACCESS_DENIED;
         647                 :     }
         648                 : #elif defined(VMS)
         649                 :     nsCAutoString filePath;
         650                 :     rv = lockFile->GetNativePath(filePath);
         651                 :     if (NS_FAILED(rv))
         652                 :         return rv;
         653                 :
         654                 :     lockFile->GetLastModifiedTime(&mReplacedLockTime);
         655                 :
         656                 :     mLockFileDesc = open_noshr(filePath.get(), O_CREAT, 0666);
         657                 :     if (mLockFileDesc == -1)
         658                 :     {
         659                 :         if ((errno == EVMSERR) && (vaxc$errno == RMS$_FLK))
         660                 :         {
         661                 :             return NS_ERROR_FILE_ACCESS_DENIED;
         662                 :         }
         663                 :         else
         664                 :         {
         665                 :             NS_ERROR("Failed to open lock file.");
         666                 :             return NS_ERROR_FAILURE;
         667                 :         }
         668                 :     }
         669                 : #endif
         670                 :
         671               0 :     mHaveLock = true;
         672                 :
         673               0 :     return rv;
         674                 : }
         675                 :
         676                 :
         677               0 : nsresult nsProfileLock::Unlock(bool aFatalSignal)
         678                 : {
         679               0 :     nsresult rv = NS_OK;
         680                 :
         681               0 :     if (mHaveLock)
         682                 :     {
         683                 : #if defined (XP_WIN)
         684                 :         if (mLockFileHandle != INVALID_HANDLE_VALUE)
         685                 :         {
         686                 :             CloseHandle(mLockFileHandle);
         687                 :             mLockFileHandle = INVALID_HANDLE_VALUE;
         688                 :         }
         689                 : #elif defined (XP_OS2)
         690                 :         if (mLockFileHandle != -1)
         691                 :         {
         692                 :             DosClose(mLockFileHandle);
         693                 :             mLockFileHandle = -1;
         694                 :         }
         695                 : #elif defined (XP_UNIX)
         696               0 :         if (mPidLockFileName)
         697                 :         {
         698               0 :             PR_REMOVE_LINK(this);
         699               0 :             (void) unlink(mPidLockFileName);
         700                 :
         701                 :             // Only free mPidLockFileName if we're not in the fatal signal
         702                 :             // handler.  The problem is that a call to free() might be the
         703                 :             // cause of this fatal signal.  If so, calling free() might cause
         704                 :             // us to wait on the malloc implementation's lock.  We're already
         705                 :             // holding this lock, so we'll deadlock. See bug 522332.
         706               0 :             if (!aFatalSignal)
         707               0 :                 free(mPidLockFileName);
         708               0 :             mPidLockFileName = nsnull;
         709                 :         }
         710               0 :         else if (mLockFileDesc != -1)
         711                 :         {
         712               0 :             close(mLockFileDesc);
         713               0 :             mLockFileDesc = -1;
         714                 :             // Don't remove it
         715                 :         }
         716                 : #endif
         717                 :
         718               0 :         mHaveLock = false;
         719                 :     }
         720                 :
         721               0 :     return rv;
         722                 : }

Generated by: LCOV version 1.7