Profile sharing - changes to profile dirserviceprovider, a component to control whether sharing is enabled. bug=202474, rs=dougt/sr=darin/a=asa
git-svn-id: svn://10.0.0.236/trunk@142041 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -33,6 +33,10 @@ ifdef MOZ_XUL
|
||||
DIRS += printingui
|
||||
endif
|
||||
|
||||
ifdef MOZ_PROFILESHARING
|
||||
DIRS += profilesharingsetup
|
||||
endif
|
||||
|
||||
DIRS += build
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
@@ -59,6 +59,10 @@ REQUIRES = js \
|
||||
xuldoc \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_PROFILESHARING
|
||||
REQUIRES += profilesharingsetup
|
||||
endif
|
||||
|
||||
CPPSRCS = nsModule.cpp
|
||||
|
||||
SHARED_LIBRARY_LIBS = \
|
||||
@@ -85,6 +89,11 @@ LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../commandhandler/src \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_PROFILESHARING
|
||||
SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)profilesharingsetup_s.$(LIB_SUFFIX)
|
||||
LOCAL_INCLUDES += -I$(srcdir)/../profilesharingsetup/src
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_GFX_TOOLKIT),os2)
|
||||
LOCAL_INCLUDES += -I$(srcdir)/../printingui/src/os2
|
||||
endif
|
||||
|
||||
@@ -69,7 +69,12 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPromptService, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSConsoleService)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintingPromptService, Init)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
#include "nsProfileSharingSetup.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsProfileSharingSetup)
|
||||
#endif
|
||||
|
||||
static const nsModuleComponentInfo gComponents[] = {
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
@@ -88,6 +93,9 @@ static const nsModuleComponentInfo gComponents[] = {
|
||||
{ "Command Params", NS_COMMAND_PARAMS_CID, NS_COMMAND_PARAMS_CONTRACTID, nsCommandParamsConstructor },
|
||||
{ "Command Group", NS_CONTROLLER_COMMAND_GROUP_CID, NS_CONTROLLER_COMMAND_GROUP_CONTRACTID, nsControllerCommandGroupConstructor },
|
||||
{ "Base Command Controller", NS_BASECOMMANDCONTROLLER_CID, NS_BASECOMMANDCONTROLLER_CONTRACTID, nsBaseCommandControllerConstructor }
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
,{ "Profile Sharing Setup", NS_PROFILESHARINGSETUP_CID, NS_PROFILESHARINGSETUP_CONTRACTID, nsProfileSharingSetupConstructor }
|
||||
#endif
|
||||
};
|
||||
|
||||
NS_IMPL_NSGETMODULE(embedcomponents, gComponents)
|
||||
|
||||
46
mozilla/embedding/components/profilesharingsetup/Makefile.in
Normal file
46
mozilla/embedding/components/profilesharingsetup/Makefile.in
Normal file
@@ -0,0 +1,46 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2003
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = public src
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
@@ -0,0 +1,53 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2003
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = profilesharingsetup
|
||||
XPIDL_MODULE = profilesharingsetup
|
||||
GRE_MODULE = 1
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIProfileSharingSetup.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Conrad Carlen (ccarlen@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[uuid(2f977d57-5485-11d4-87e2-0010a4e75ef2)]
|
||||
interface nsIProfileSharingSetup : nsISupports
|
||||
{
|
||||
/**
|
||||
* enableSharing must be called by the application in order to use
|
||||
* profile sharing. It should be called as early as possible in the
|
||||
* startup sequence - before any use of profile data. If enabled,
|
||||
* sharing is enabled for all modules that support it.
|
||||
*
|
||||
* @param aClientName A non-versioned identifier of the current
|
||||
* application within the suite of applications
|
||||
* which share this profile. It is used to separate
|
||||
* the client's non-shared data from shared data
|
||||
* within the profile directory. Example: "browser"
|
||||
* or "mail" - not "ProductX 1.3b5"
|
||||
*/
|
||||
void enableSharing(in AString aClientName);
|
||||
|
||||
/**
|
||||
* sharingEnabled and clientName
|
||||
*
|
||||
* Attributes to be used by sharing-enabled components
|
||||
*/
|
||||
readonly attribute boolean isSharingEnabled;
|
||||
readonly attribute AString clientName;
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2003
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = profilesharingsetup
|
||||
LIBRARY_NAME = profilesharingsetup_s
|
||||
REQUIRES = xpcom \
|
||||
string \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsProfileSharingSetup.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Conrad Carlen <ccarlen@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsProfileSharingSetup.h"
|
||||
|
||||
//*****************************************************************************
|
||||
// nsProfileSharingSetup::nsProfileSharingSetup
|
||||
//*****************************************************************************
|
||||
|
||||
nsProfileSharingSetup::nsProfileSharingSetup() :
|
||||
mSharingGloballyEnabled(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
nsProfileSharingSetup::~nsProfileSharingSetup()
|
||||
{
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// nsProfileSharingSetup::nsISupports
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsProfileSharingSetup,
|
||||
nsIProfileSharingSetup)
|
||||
|
||||
//*****************************************************************************
|
||||
// nsProfileSharingSetup::nsIProfileSharingSetup
|
||||
//*****************************************************************************
|
||||
|
||||
/* void enableSharing (in AString aClientName); */
|
||||
NS_IMETHODIMP nsProfileSharingSetup::EnableSharing(const nsAString& aClientName)
|
||||
{
|
||||
mSharingGloballyEnabled = PR_TRUE;
|
||||
mClientName = aClientName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute boolean isSharingEnabled; */
|
||||
NS_IMETHODIMP nsProfileSharingSetup::GetIsSharingEnabled(PRBool *aSharingEnabled)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSharingEnabled);
|
||||
*aSharingEnabled = mSharingGloballyEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute AString clientName; */
|
||||
NS_IMETHODIMP nsProfileSharingSetup::GetClientName(nsAString& aClientName)
|
||||
{
|
||||
aClientName = mClientName;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Conrad Carlen <ccarlen@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsProfileSharingSetup_h__
|
||||
#define nsProfileSharingSetup_h__
|
||||
|
||||
#include "nsIProfileSharingSetup.h"
|
||||
#include "nsString.h"
|
||||
|
||||
|
||||
// {2f977d58-5485-11d4-87e2-0010a4e75ef2}
|
||||
#define NS_PROFILESHARINGSETUP_CID \
|
||||
{ 0x2f977d58, 0x5485, 0x11d4, { 0x87, 0xe2, 0x00, 0x10, 0xa4, 0xe7, 0x5e, 0xf2 } }
|
||||
|
||||
#define NS_PROFILESHARINGSETUP_CONTRACTID \
|
||||
"@mozilla.org/embedcomp/profile-sharing-setup;1"
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// nsProfileSharingSetup
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
class nsProfileSharingSetup: public nsIProfileSharingSetup
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPROFILESHARINGSETUP
|
||||
|
||||
public:
|
||||
nsProfileSharingSetup();
|
||||
|
||||
protected:
|
||||
virtual ~nsProfileSharingSetup();
|
||||
|
||||
protected:
|
||||
PRPackedBool mSharingGloballyEnabled;
|
||||
nsString mClientName;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -107,6 +107,7 @@ res/dtd/xhtml11.dtd
|
||||
components/libgklayout.dylib
|
||||
components/libhtmlpars.dylib
|
||||
components/layout_xul.xpt
|
||||
components/layout_xul_tree.xpt
|
||||
components/content_base.xpt
|
||||
components/layout_base.xpt
|
||||
|
||||
@@ -186,6 +187,7 @@ components/libuconv.dylib
|
||||
components/libi18n.dylib
|
||||
components/uconv.xpt
|
||||
components/unicharutil.xpt
|
||||
components/intl.xpt
|
||||
|
||||
res/language.properties
|
||||
res/langGroups.properties
|
||||
|
||||
@@ -63,7 +63,8 @@ res/dtd/xhtml11.dtd
|
||||
components/libgklayout.so
|
||||
components/libhtmlpars.so
|
||||
components/layout_base.xpt
|
||||
components/layout_xul.xpt
|
||||
components/layout_xul.xpt
|
||||
components/layout_xul_tree.xpt
|
||||
components/content_base.xpt
|
||||
|
||||
; Imaging:
|
||||
@@ -133,6 +134,7 @@ components/libuconv.so
|
||||
components/libi18n.so
|
||||
components/uconv.xpt
|
||||
components/unicharutil.xpt
|
||||
components/intl.xpt
|
||||
|
||||
;
|
||||
; DOM:
|
||||
|
||||
@@ -76,7 +76,8 @@ moz_art_lgpl.dll
|
||||
components\gklayout.dll
|
||||
components\gkparser.dll
|
||||
components\layout_base.xpt
|
||||
components\layout_xul.xpt
|
||||
components\layout_xul.xpt
|
||||
components\layout_xul_tree.xpt
|
||||
components\content_base.xpt
|
||||
|
||||
;
|
||||
@@ -147,6 +148,7 @@ components\locale.xpt
|
||||
components\uconv.dll
|
||||
components\uconv.xpt
|
||||
components\unicharutil.xpt
|
||||
components\intl.xpt
|
||||
|
||||
; dom
|
||||
components\jsdom.dll
|
||||
|
||||
@@ -65,6 +65,7 @@ REQUIRES = xpcom \
|
||||
appshell \
|
||||
uconv \
|
||||
windowwatcher \
|
||||
profdirserviceprovider \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
||||
@@ -42,13 +42,10 @@ VPATH = @srcdir@
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = profdirserviceprovider
|
||||
|
||||
EXPORTS = \
|
||||
nsProfileDirServiceProvider.h \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -43,13 +43,14 @@
|
||||
|
||||
// Forward Declarations
|
||||
class nsIAtom;
|
||||
class nsProfileLock;
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// nsProfileDirServiceProvider - The nsIDirectoryServiceProvider implementation used for
|
||||
// profile-relative file locations.
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
class nsProfileDirServiceProvider: public nsIDirectoryServiceProvider
|
||||
class nsProfileDirServiceProvider: public nsIDirectoryServiceProvider
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDIRECTORYSERVICEPROVIDER
|
||||
@@ -95,7 +96,8 @@ protected:
|
||||
|
||||
nsresult Initialize();
|
||||
nsresult InitProfileDir(nsIFile* profileDir);
|
||||
nsresult EnsureProfileFileExists(nsIFile *aFile);
|
||||
nsresult InitNonSharedProfileDir();
|
||||
nsresult EnsureProfileFileExists(nsIFile *aFile, nsIFile *destDir);
|
||||
nsresult UndefineFileLocations();
|
||||
|
||||
protected:
|
||||
@@ -117,8 +119,13 @@ protected:
|
||||
static nsIAtom* sApp_NewsDirectory50;
|
||||
static nsIAtom* sApp_MessengerFolderCache50;
|
||||
|
||||
PRPackedBool mNotifyObservers;
|
||||
nsCOMPtr<nsIFile> mProfileDir;
|
||||
nsProfileLock* mProfileDirLock;
|
||||
PRPackedBool mNotifyObservers;
|
||||
|
||||
PRPackedBool mSharingEnabled;
|
||||
nsString mNonSharedDirName;
|
||||
nsCOMPtr<nsIFile> mNonSharedProfileDir;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -46,11 +46,18 @@ LIBRARY_NAME = profdirserviceprovider_s
|
||||
REQUIRES = xpcom \
|
||||
string \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_PROFILESHARING
|
||||
REQUIRES += transmngr \
|
||||
profilesharingsetup \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
CPPSRCS = nsProfileDirServiceProvider.cpp
|
||||
CPPSRCS = nsProfileDirServiceProvider.cpp \
|
||||
nsProfileLock.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsProfileDirServiceProvider.h"
|
||||
#include "nsProfileLock.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsStaticAtom.h"
|
||||
#include "nsILocalFile.h"
|
||||
@@ -46,6 +47,11 @@
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
#include "nsIProfileSharingSetup.h"
|
||||
#include "tmITransactionService.h"
|
||||
#endif
|
||||
|
||||
// File Name Defines
|
||||
|
||||
#define PREFS_FILE_50_NAME NS_LITERAL_CSTRING("prefs.js")
|
||||
@@ -86,13 +92,15 @@ nsIAtom* nsProfileDirServiceProvider::sApp_MessengerFolderCache50;
|
||||
//*****************************************************************************
|
||||
|
||||
nsProfileDirServiceProvider::nsProfileDirServiceProvider(PRBool aNotifyObservers) :
|
||||
mNotifyObservers(aNotifyObservers)
|
||||
mNotifyObservers(aNotifyObservers), mProfileDirLock(nsnull),
|
||||
mSharingEnabled(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
nsProfileDirServiceProvider::~nsProfileDirServiceProvider()
|
||||
{
|
||||
delete mProfileDirLock;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@@ -105,6 +113,7 @@ nsProfileDirServiceProvider::SetProfileDir(nsIFile* aProfileDir)
|
||||
NS_WARNING("Setting profile dir to same as current");
|
||||
return NS_OK;
|
||||
}
|
||||
mProfileDirLock->Unlock();
|
||||
UndefineFileLocations();
|
||||
}
|
||||
mProfileDir = aProfileDir;
|
||||
@@ -115,6 +124,33 @@ nsProfileDirServiceProvider::SetProfileDir(nsIFile* aProfileDir)
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
if (mSharingEnabled) {
|
||||
nsCOMPtr<tmITransactionService> transServ =
|
||||
do_GetService("@mozilla.org/transaction/service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCAutoString nativePath;
|
||||
rv = mProfileDir->GetNativePath(nativePath);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = transServ->Init(nativePath);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Unable to initialize transaction service");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Lock the non-shared sub-dir if we are sharing,
|
||||
// the whole profile dir if we are not.
|
||||
nsCOMPtr<nsILocalFile> dirToLock;
|
||||
if (mSharingEnabled)
|
||||
dirToLock = do_QueryInterface(mNonSharedProfileDir);
|
||||
else
|
||||
dirToLock = do_QueryInterface(mProfileDir);
|
||||
rv = mProfileDirLock->Lock(dirToLock);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (mNotifyObservers) {
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService("@mozilla.org/observer-service;1");
|
||||
@@ -161,7 +197,8 @@ nsProfileDirServiceProvider::Shutdown()
|
||||
// nsProfileDirServiceProvider::nsISupports
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsProfileDirServiceProvider, nsIDirectoryServiceProvider)
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsProfileDirServiceProvider,
|
||||
nsIDirectoryServiceProvider)
|
||||
|
||||
//*****************************************************************************
|
||||
// nsProfileDirServiceProvider::nsIDirectoryServiceProvider
|
||||
@@ -179,7 +216,20 @@ nsProfileDirServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFi
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*persistant = PR_TRUE;
|
||||
|
||||
nsIFile* domainDir = mProfileDir;
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
// If the prop is prefixed with NS_SHARED,
|
||||
// the location is in the shared domain.
|
||||
PRBool bUseShared = PR_FALSE;
|
||||
if (strncmp(prop, NS_SHARED, sizeof(NS_SHARED)-1) == 0) {
|
||||
prop += (sizeof(NS_SHARED)-1);
|
||||
bUseShared = PR_TRUE;
|
||||
}
|
||||
if (!bUseShared && mNonSharedProfileDir)
|
||||
domainDir = mNonSharedProfileDir;
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIFile> localFile;
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
@@ -187,91 +237,91 @@ nsProfileDirServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFi
|
||||
NS_ENSURE_TRUE(inAtom, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (inAtom == sApp_PrefsDirectory50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
}
|
||||
else if (inAtom == sApp_PreferencesFile50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = localFile->AppendNative(PREFS_FILE_50_NAME);
|
||||
}
|
||||
else if (inAtom == sApp_UserProfileDirectory50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
}
|
||||
else if (inAtom == sApp_UserChromeDirectory) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = localFile->AppendNative(USER_CHROME_DIR_50_NAME);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = EnsureProfileFileExists(localFile);
|
||||
rv = EnsureProfileFileExists(localFile, domainDir);
|
||||
}
|
||||
}
|
||||
else if (inAtom == sApp_LocalStore50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = localFile->AppendNative(LOCAL_STORE_FILE_50_NAME);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = EnsureProfileFileExists(localFile);
|
||||
rv = EnsureProfileFileExists(localFile, domainDir);
|
||||
}
|
||||
}
|
||||
else if (inAtom == sApp_History50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = localFile->AppendNative(HISTORY_FILE_50_NAME);
|
||||
}
|
||||
else if (inAtom == sApp_UsersPanels50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = localFile->AppendNative(PANELS_FILE_50_NAME);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = EnsureProfileFileExists(localFile);
|
||||
rv = EnsureProfileFileExists(localFile, domainDir);
|
||||
}
|
||||
}
|
||||
else if (inAtom == sApp_UsersMimeTypes50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = localFile->AppendNative(MIME_TYPES_FILE_50_NAME);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = EnsureProfileFileExists(localFile);
|
||||
rv = EnsureProfileFileExists(localFile, domainDir);
|
||||
}
|
||||
}
|
||||
else if (inAtom == sApp_BookmarksFile50) {
|
||||
#ifdef XP_MACOSX
|
||||
*persistant = PR_FALSE; // See bug 192124
|
||||
#endif
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = localFile->AppendNative(BOOKMARKS_FILE_50_NAME);
|
||||
}
|
||||
else if (inAtom == sApp_DownloadsFile50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = localFile->AppendNative(DOWNLOADS_FILE_50_NAME);
|
||||
}
|
||||
else if (inAtom == sApp_SearchFile50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = localFile->AppendNative(SEARCH_FILE_50_NAME);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = EnsureProfileFileExists(localFile);
|
||||
rv = EnsureProfileFileExists(localFile, domainDir);
|
||||
}
|
||||
}
|
||||
else if (inAtom == sApp_MailDirectory50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = localFile->AppendNative(MAIL_DIR_50_NAME);
|
||||
}
|
||||
else if (inAtom == sApp_ImapMailDirectory50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = localFile->AppendNative(IMAP_MAIL_DIR_50_NAME);
|
||||
}
|
||||
else if (inAtom == sApp_NewsDirectory50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = localFile->AppendNative(NEWS_DIR_50_NAME);
|
||||
}
|
||||
else if (inAtom == sApp_MessengerFolderCache50) {
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localFile));
|
||||
rv = domainDir->Clone(getter_AddRefs(localFile));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = localFile->AppendNative(MSG_FOLDER_CACHE_DIR_50_NAME);
|
||||
}
|
||||
@@ -291,6 +341,22 @@ nsProfileDirServiceProvider::GetFile(const char *prop, PRBool *persistant, nsIFi
|
||||
nsresult
|
||||
nsProfileDirServiceProvider::Initialize()
|
||||
{
|
||||
mProfileDirLock = new nsProfileLock;
|
||||
if (!mProfileDirLock)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
#ifdef MOZ_PROFILESHARING
|
||||
nsCOMPtr<nsIProfileSharingSetup> sharingSetup =
|
||||
do_GetService("@mozilla.org/embedcomp/profile-sharing-setup;1");
|
||||
if (sharingSetup) {
|
||||
PRBool tempBool;
|
||||
if (NS_SUCCEEDED(sharingSetup->GetIsSharingEnabled(&tempBool)))
|
||||
mSharingEnabled = tempBool;
|
||||
if (mSharingEnabled)
|
||||
sharingSetup->GetClientName(mNonSharedDirName);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const nsStaticAtom provider_atoms[] = {
|
||||
{ NS_APP_PREFS_50_DIR, &sApp_PrefsDirectory50 },
|
||||
{ NS_APP_PREFS_50_FILE, &sApp_PreferencesFile50 },
|
||||
@@ -310,7 +376,7 @@ nsProfileDirServiceProvider::Initialize()
|
||||
{ NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR, nsnull },
|
||||
};
|
||||
|
||||
// Make our directory atoms
|
||||
// Register our directory atoms
|
||||
NS_RegisterStaticAtoms(provider_atoms, NS_ARRAY_LENGTH(provider_atoms));
|
||||
|
||||
return NS_OK;
|
||||
@@ -371,12 +437,50 @@ nsProfileDirServiceProvider::InitProfileDir(nsIFile *profileDir)
|
||||
if (!isDir)
|
||||
return NS_ERROR_FILE_NOT_DIRECTORY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
if (!mNonSharedDirName.IsEmpty())
|
||||
rv = InitNonSharedProfileDir();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsProfileDirServiceProvider::EnsureProfileFileExists(nsIFile *aFile)
|
||||
nsProfileDirServiceProvider::InitNonSharedProfileDir()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
NS_ENSURE_STATE(mProfileDir);
|
||||
NS_ENSURE_STATE(!mNonSharedDirName.IsEmpty());
|
||||
|
||||
nsCOMPtr<nsIFile> localDir;
|
||||
rv = mProfileDir->Clone(getter_AddRefs(localDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = localDir->Append(mNonSharedDirName);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PRBool exists;
|
||||
rv = localDir->Exists(&exists);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (!exists) {
|
||||
rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
|
||||
}
|
||||
else {
|
||||
PRBool isDir;
|
||||
rv = localDir->IsDirectory(&isDir);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (!isDir)
|
||||
rv = NS_ERROR_FILE_NOT_DIRECTORY;
|
||||
}
|
||||
}
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mNonSharedProfileDir = localDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsProfileDirServiceProvider::EnsureProfileFileExists(nsIFile *aFile, nsIFile *destDir)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool exists;
|
||||
@@ -406,7 +510,7 @@ nsProfileDirServiceProvider::EnsureProfileFileExists(nsIFile *aFile)
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return defaultsFile->CopyTo(mProfileDir, nsString());
|
||||
return defaultsFile->CopyTo(destDir, nsString());
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
||||
743
mozilla/profile/dirserviceprovider/src/nsProfileLock.cpp
Normal file
743
mozilla/profile/dirserviceprovider/src/nsProfileLock.cpp
Normal file
@@ -0,0 +1,743 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Conrad Carlen <ccarlen@netscape.com>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
* Colin Blake <colin@theblakes.com>
|
||||
* Javier Pedemonte <pedemont@us.ibm.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsProfileLock.h"
|
||||
#include "nsLiteralString.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#if defined(XP_MAC) || defined(XP_MACOSX)
|
||||
#include <Processes.h>
|
||||
#include <CFBundle.h>
|
||||
#endif
|
||||
|
||||
#ifdef XP_UNIX
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include "prnetdb.h"
|
||||
#include "prsystem.h"
|
||||
#include "prprf.h"
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
#include <rmsdef.h>
|
||||
#endif
|
||||
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX) /* Don't use symlink-based locking on OS X */
|
||||
#define USE_SYMLINK_LOCKING
|
||||
#endif
|
||||
|
||||
// **********************************************************************
|
||||
// class nsProfileLock
|
||||
// **********************************************************************
|
||||
|
||||
#if defined (XP_MAC) && TARGET_CARBON
|
||||
|
||||
// The following functions and definitions are used in order to allow
|
||||
// a CFM build to use the same locking scheme as a Mach-0 build.
|
||||
|
||||
static CFBundleRef getBundle(CFStringRef frameworkPath)
|
||||
{
|
||||
CFBundleRef bundle = NULL;
|
||||
|
||||
// Make a CFURLRef from the CFString representation of the bundle's path.
|
||||
// See the Core Foundation URL Services chapter for details.
|
||||
CFURLRef bundleURL = CFURLCreateWithFileSystemPath(NULL, frameworkPath, kCFURLPOSIXPathStyle, true);
|
||||
if (bundleURL != NULL) {
|
||||
bundle = CFBundleCreate(NULL, bundleURL);
|
||||
if (bundle != NULL)
|
||||
CFBundleLoadExecutable(bundle);
|
||||
CFRelease(bundleURL);
|
||||
}
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
static void* getSystemFunction(CFStringRef functionName)
|
||||
{
|
||||
static CFBundleRef systemBundle = getBundle(CFSTR("/System/Library/Frameworks/System.framework"));
|
||||
if (systemBundle) return CFBundleGetFunctionPointerForName(systemBundle, functionName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// From <sys/types.h>
|
||||
typedef int64_t off_t; /* file offset */
|
||||
typedef int32_t pid_t; /* process id */
|
||||
|
||||
// From <sys/errno.h>
|
||||
#define EAGAIN 35 /* Resource temporarily unavailable */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
|
||||
// From <sys/fcntl.h>
|
||||
#define O_RDONLY 0x0000 /* open for reading only */
|
||||
#define O_WRONLY 0x0001 /* open for writing only */
|
||||
#define O_RDWR 0x0002 /* open for reading and writing */
|
||||
|
||||
#define O_CREAT 0x0200 /* create if nonexistant */
|
||||
#define O_TRUNC 0x0400 /* truncate to zero length */
|
||||
#define O_EXCL 0x0800 /* error if already exists */
|
||||
|
||||
#define F_RDLCK 1 /* shared or read lock */
|
||||
#define F_UNLCK 2 /* unlock */
|
||||
#define F_WRLCK 3 /* exclusive or write lock */
|
||||
|
||||
#define F_SETLK 8 /* set record locking information */
|
||||
|
||||
struct flock {
|
||||
off_t l_start; /* starting offset */
|
||||
off_t l_len; /* len = 0 means until end of file */
|
||||
pid_t l_pid; /* lock owner */
|
||||
short l_type; /* lock type: read/write, etc. */
|
||||
short l_whence; /* type of l_start */
|
||||
};
|
||||
|
||||
// Proc ptr types of the procs we import from System framework
|
||||
typedef int (*open_proc_ptr) (const char *, int, ...);
|
||||
typedef int (*close_proc_ptr) (int);
|
||||
typedef int (*fcntl_proc_ptr) (int, int, ...);
|
||||
typedef int* (*error_proc_ptr) ();
|
||||
|
||||
static open_proc_ptr bsd_open = (open_proc_ptr) getSystemFunction(CFSTR("open"));
|
||||
static close_proc_ptr bsd_close = (close_proc_ptr) getSystemFunction(CFSTR("close"));
|
||||
static fcntl_proc_ptr bsd_fcntl = (fcntl_proc_ptr) getSystemFunction(CFSTR("fcntl"));
|
||||
static error_proc_ptr bsd_error = (error_proc_ptr) getSystemFunction(CFSTR("__error"));
|
||||
|
||||
#endif /* XP_MAC && TARGET_CARBON */
|
||||
|
||||
nsProfileLock::nsProfileLock() :
|
||||
mHaveLock(PR_FALSE)
|
||||
#if defined (XP_MAC) && TARGET_CARBON
|
||||
,mLockFileDesc(-1)
|
||||
#elif 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
|
||||
}
|
||||
|
||||
|
||||
nsProfileLock::nsProfileLock(nsProfileLock& src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
|
||||
nsProfileLock& nsProfileLock::operator=(nsProfileLock& rhs)
|
||||
{
|
||||
Unlock();
|
||||
|
||||
mHaveLock = rhs.mHaveLock;
|
||||
rhs.mHaveLock = PR_FALSE;
|
||||
|
||||
#if defined (XP_MAC)
|
||||
mLockFile = rhs.mLockFile;
|
||||
rhs.mLockFile = nsnull;
|
||||
#if TARGET_CARBON
|
||||
mLockFileDesc = rhs.mLockFileDesc;
|
||||
rhs.mLockFileDesc = -1;
|
||||
#endif
|
||||
#elif 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;
|
||||
}
|
||||
|
||||
|
||||
nsProfileLock::~nsProfileLock()
|
||||
{
|
||||
Unlock();
|
||||
}
|
||||
|
||||
|
||||
#if defined (XP_UNIX)
|
||||
|
||||
static int setupPidLockCleanup;
|
||||
|
||||
PRCList nsProfileLock::mPidLockList =
|
||||
PR_INIT_STATIC_CLIST(&nsProfileLock::mPidLockList);
|
||||
|
||||
void nsProfileLock::RemovePidLockFiles()
|
||||
{
|
||||
while (!PR_CLIST_IS_EMPTY(&mPidLockList))
|
||||
{
|
||||
nsProfileLock *lock = NS_STATIC_CAST(nsProfileLock*, mPidLockList.next);
|
||||
lock->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
static struct sigaction SIGHUP_oldact;
|
||||
static struct sigaction SIGINT_oldact;
|
||||
static struct sigaction SIGQUIT_oldact;
|
||||
static struct sigaction SIGILL_oldact;
|
||||
static struct sigaction SIGABRT_oldact;
|
||||
static struct sigaction SIGSEGV_oldact;
|
||||
static struct sigaction SIGTERM_oldact;
|
||||
|
||||
void nsProfileLock::FatalSignalHandler(int signo)
|
||||
{
|
||||
// Remove any locks still held.
|
||||
RemovePidLockFiles();
|
||||
|
||||
// Chain to the old handler, which may exit.
|
||||
struct sigaction *oldact = nsnull;
|
||||
|
||||
switch (signo) {
|
||||
case SIGHUP:
|
||||
oldact = &SIGHUP_oldact;
|
||||
break;
|
||||
case SIGINT:
|
||||
oldact = &SIGINT_oldact;
|
||||
break;
|
||||
case SIGQUIT:
|
||||
oldact = &SIGQUIT_oldact;
|
||||
break;
|
||||
case SIGILL:
|
||||
oldact = &SIGILL_oldact;
|
||||
break;
|
||||
case SIGABRT:
|
||||
oldact = &SIGABRT_oldact;
|
||||
break;
|
||||
case SIGSEGV:
|
||||
oldact = &SIGSEGV_oldact;
|
||||
break;
|
||||
case SIGTERM:
|
||||
oldact = &SIGTERM_oldact;
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("bad signo");
|
||||
break;
|
||||
}
|
||||
|
||||
if (oldact &&
|
||||
oldact->sa_handler &&
|
||||
oldact->sa_handler != SIG_DFL &&
|
||||
oldact->sa_handler != SIG_IGN)
|
||||
{
|
||||
oldact->sa_handler(signo);
|
||||
}
|
||||
|
||||
// Backstop exit call, just in case.
|
||||
_exit(signo);
|
||||
}
|
||||
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
nsresult nsProfileLock::Lock(nsILocalFile* aFile)
|
||||
{
|
||||
#if defined (XP_MAC) || 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;
|
||||
NS_ENSURE_STATE(!mHaveLock);
|
||||
|
||||
PRBool isDir;
|
||||
rv = aFile->IsDirectory(&isDir);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!isDir)
|
||||
return NS_ERROR_FILE_NOT_DIRECTORY;
|
||||
|
||||
nsCOMPtr<nsILocalFile> lockFile;
|
||||
rv = aFile->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_MAC) || defined(XP_MACOSX)
|
||||
#if defined(XP_MACOSX)
|
||||
nsCAutoString filePath;
|
||||
rv = lockFile->GetNativePath(filePath);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mLockFileDesc = open(filePath.get(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (mLockFileDesc == -1)
|
||||
{
|
||||
NS_ERROR("Failed to open lock file.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
struct flock lock;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0; // len = 0 means entire file
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
if (fcntl(mLockFileDesc, F_SETLK, &lock) == -1)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EACCES)
|
||||
return NS_ERROR_FILE_ACCESS_DENIED;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mHaveLock = PR_TRUE;
|
||||
#elif TARGET_CARBON
|
||||
if (bsd_open && bsd_close && bsd_fcntl && bsd_error) // FALSE for TARGET_CARBON on OS9
|
||||
{
|
||||
// We need a UTF-8 Posix path to pass to open.
|
||||
CFURLRef lockFileCFURL;
|
||||
nsCOMPtr<nsILocalFileMac> lockMacFile(do_QueryInterface(lockFile));
|
||||
if (!lockMacFile)
|
||||
return NS_ERROR_FAILURE;
|
||||
rv = lockMacFile->GetCFURL(&lockFileCFURL);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// On OSX, even if we're a CFM app, this will return a UTF-8 Posix path.
|
||||
Boolean gotPath;
|
||||
UInt8 pathBuf[1024];
|
||||
gotPath = ::CFURLGetFileSystemRepresentation(lockFileCFURL, false, pathBuf, sizeof(pathBuf));
|
||||
::CFRelease(lockFileCFURL);
|
||||
if (!gotPath)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mLockFileDesc = bsd_open((char *)pathBuf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (mLockFileDesc == -1)
|
||||
{
|
||||
NS_ERROR("Failed to open lock file.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
struct flock lock;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0; // len = 0 means entire file
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
|
||||
if (bsd_fcntl(mLockFileDesc, F_SETLK, &lock) == -1)
|
||||
{
|
||||
int *errno_ptr = bsd_error();
|
||||
if (*errno_ptr == EAGAIN || *errno_ptr == EACCES)
|
||||
return NS_ERROR_FILE_ACCESS_DENIED;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mHaveLock = PR_TRUE;
|
||||
}
|
||||
#endif /* TARGET_CARBON */
|
||||
|
||||
// Even if we're using fcntl locking, check for the old-style lock.
|
||||
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.
|
||||
|
||||
#if !TARGET_CARBON
|
||||
rv = lockFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0, &fd);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
static LockProcessInfo sSelfInfo;
|
||||
static PRBool sSelfInfoInited;
|
||||
|
||||
if (!sSelfInfoInited)
|
||||
{
|
||||
ProcessSerialNumber psn;
|
||||
if (::GetCurrentProcess(&psn) == noErr)
|
||||
{
|
||||
processInfo.processAppSpec = nsnull;
|
||||
processInfo.processName = nsnull;
|
||||
processInfo.processInfoLength = sizeof(ProcessInfoRec);
|
||||
if (::GetProcessInformation(&psn, &processInfo) == noErr)
|
||||
{
|
||||
sSelfInfo.psn = processInfo.processNumber;
|
||||
sSelfInfo.launchDate = processInfo.processLaunchDate;
|
||||
sSelfInfoInited = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!sSelfInfoInited)
|
||||
{
|
||||
PR_Close(fd);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ioBytes = PR_Write(fd, &sSelfInfo, sizeof(LockProcessInfo));
|
||||
PR_Close(fd);
|
||||
if (ioBytes != sizeof(LockProcessInfo))
|
||||
return NS_ERROR_FAILURE;
|
||||
mLockFile = lockFile;
|
||||
#endif /* !TARGET_CARBON */
|
||||
#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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
#elif defined(XP_UNIX)
|
||||
#ifdef USE_SYMLINK_LOCKING
|
||||
nsCOMPtr<nsILocalFile> oldLockFile;
|
||||
rv = aFile->Clone((nsIFile **)((void **)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 the 4.x-compatible symlink technique, which works with NFS
|
||||
// without depending on (broken or missing, too often) lockd.
|
||||
struct in_addr inaddr;
|
||||
inaddr.s_addr = INADDR_LOOPBACK;
|
||||
|
||||
char hostname[256];
|
||||
PRStatus status = PR_GetSystemInfo(PR_SI_HOSTNAME, hostname, sizeof hostname);
|
||||
if (status == PR_SUCCESS)
|
||||
{
|
||||
char netdbbuf[PR_NETDB_BUF_SIZE];
|
||||
PRHostEnt hostent;
|
||||
status = PR_GetHostByName(hostname, netdbbuf, sizeof netdbbuf, &hostent);
|
||||
if (status == PR_SUCCESS)
|
||||
memcpy(&inaddr, hostent.h_addr, sizeof inaddr);
|
||||
}
|
||||
|
||||
char *signature =
|
||||
PR_smprintf("%s:%lu", inet_ntoa(inaddr), (unsigned long)getpid());
|
||||
const char *oldFileName = oldFilePath.get();
|
||||
int symlink_rv, symlink_errno, tries = 0;
|
||||
|
||||
// use ns4.x-compatible symlinks if the FS supports them
|
||||
while ((symlink_rv = symlink(signature, oldFileName)) < 0)
|
||||
{
|
||||
symlink_errno = errno;
|
||||
if (symlink_errno != EEXIST)
|
||||
break;
|
||||
|
||||
// the link exists; see if it's from this machine, and if
|
||||
// so if the process is still active
|
||||
char buf[1024];
|
||||
int len = readlink(oldFileName, buf, sizeof buf - 1);
|
||||
if (len > 0)
|
||||
{
|
||||
buf[len] = '\0';
|
||||
char *colon = strchr(buf, ':');
|
||||
if (colon)
|
||||
{
|
||||
*colon++ = '\0';
|
||||
unsigned long addr = inet_addr(buf);
|
||||
if (addr != (unsigned long) -1)
|
||||
{
|
||||
char *after = nsnull;
|
||||
pid_t pid = strtol(colon, &after, 0);
|
||||
if (pid != 0 && *after == '\0')
|
||||
{
|
||||
if (addr != inaddr.s_addr)
|
||||
{
|
||||
// Remote lock: give up even if stuck.
|
||||
break;
|
||||
}
|
||||
|
||||
// kill(pid,0) is a neat trick to check if a
|
||||
// process exists
|
||||
if (kill(pid, 0) == 0 || errno != ESRCH)
|
||||
{
|
||||
// Local process appears to be alive, ass-u-me it
|
||||
// is another Mozilla instance, or a compatible
|
||||
// derivative, that's currently using the profile.
|
||||
// XXX need an "are you Mozilla?" protocol
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lock seems to be bogus: try to claim it. Give up after a large
|
||||
// number of attempts (100 comes from the 4.x codebase).
|
||||
(void) unlink(oldFileName);
|
||||
if (++tries > 100)
|
||||
break;
|
||||
}
|
||||
|
||||
PR_smprintf_free(signature);
|
||||
signature = nsnull;
|
||||
|
||||
if (symlink_rv == 0)
|
||||
{
|
||||
// We exclusively created the symlink: record its name for eventual
|
||||
// unlock-via-unlink.
|
||||
mPidLockFileName = strdup(oldFileName);
|
||||
if (mPidLockFileName)
|
||||
{
|
||||
PR_APPEND_LINK(this, &mPidLockList);
|
||||
if (!setupPidLockCleanup++)
|
||||
{
|
||||
// Clean up on normal termination.
|
||||
atexit(RemovePidLockFiles);
|
||||
|
||||
// Clean up on abnormal termination, using POSIX sigaction.
|
||||
// Don't arm a handler if the signal is being ignored, e.g.,
|
||||
// because mozilla is run via nohup.
|
||||
struct sigaction act, oldact;
|
||||
act.sa_handler = FatalSignalHandler;
|
||||
act.sa_flags = 0;
|
||||
sigfillset(&act.sa_mask);
|
||||
|
||||
#define CATCH_SIGNAL(signame) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (sigaction(signame, NULL, &oldact) == 0 && \
|
||||
oldact.sa_handler != SIG_IGN) \
|
||||
{ \
|
||||
sigaction(signame, &act, &signame##_oldact); \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
CATCH_SIGNAL(SIGHUP);
|
||||
CATCH_SIGNAL(SIGINT);
|
||||
CATCH_SIGNAL(SIGQUIT);
|
||||
CATCH_SIGNAL(SIGILL);
|
||||
CATCH_SIGNAL(SIGABRT);
|
||||
CATCH_SIGNAL(SIGSEGV);
|
||||
CATCH_SIGNAL(SIGTERM);
|
||||
|
||||
#undef CATCH_SIGNAL
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (symlink_errno != EEXIST)
|
||||
#endif /* USE_SYMLINK_LOCKING */
|
||||
{
|
||||
// Symlinks aren't supported (for example, on Win32 SAMBA servers).
|
||||
// F_SETLK is not well supported on all NFS servers, which is why we
|
||||
// try symlinks first.
|
||||
nsCAutoString filePath;
|
||||
rv = lockFile->GetNativePath(filePath);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mLockFileDesc = open(filePath.get(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (mLockFileDesc == -1)
|
||||
{
|
||||
NS_ERROR("Failed to open lock file.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
struct flock lock;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0; // len = 0 means entire file
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
if (fcntl(mLockFileDesc, F_SETLK, &lock) == -1)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EACCES)
|
||||
return NS_ERROR_FILE_ACCESS_DENIED;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
#ifdef USE_SYMLINK_LOCKING
|
||||
else
|
||||
{
|
||||
// Couldn't create the symlink (but symlink(2) is supported).
|
||||
// This error code will cause the right dialog to be displayed.
|
||||
return NS_ERROR_FILE_ACCESS_DENIED;
|
||||
}
|
||||
#endif /* USE_SYMLINK_LOCKING */
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
mHaveLock = PR_TRUE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsProfileLock::Unlock()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mHaveLock)
|
||||
{
|
||||
#if defined (XP_MAC)
|
||||
if (mLockFile)
|
||||
rv = mLockFile->Remove(PR_FALSE);
|
||||
#if TARGET_CARBON
|
||||
if (mLockFileDesc != -1)
|
||||
{
|
||||
bsd_close(mLockFileDesc);
|
||||
mLockFileDesc = -1;
|
||||
}
|
||||
#endif
|
||||
#elif 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;
|
||||
}
|
||||
97
mozilla/profile/dirserviceprovider/src/nsProfileLock.h
Normal file
97
mozilla/profile/dirserviceprovider/src/nsProfileLock.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Conrad Carlen <ccarlen@netscape.com>
|
||||
* Brendan Eich <brendan@mozilla.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __nsProfileLock_h___
|
||||
#define __nsProfileLock_h___
|
||||
|
||||
#include "nsILocalFile.h"
|
||||
|
||||
#if defined (XP_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined (XP_OS2)
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSFILEMGR
|
||||
#include <os2.h>
|
||||
#endif
|
||||
|
||||
#if defined (XP_UNIX)
|
||||
#include "prclist.h"
|
||||
#endif
|
||||
|
||||
class nsProfileLock
|
||||
#if defined (XP_UNIX)
|
||||
: public PRCList
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
nsProfileLock();
|
||||
nsProfileLock(nsProfileLock& src);
|
||||
|
||||
~nsProfileLock();
|
||||
|
||||
nsProfileLock& operator=(nsProfileLock& rhs);
|
||||
|
||||
nsresult Lock(nsILocalFile* aFile);
|
||||
nsresult Unlock();
|
||||
|
||||
private:
|
||||
PRPackedBool mHaveLock;
|
||||
|
||||
#if defined (XP_MAC)
|
||||
#if TARGET_CARBON
|
||||
int mLockFileDesc;
|
||||
#endif
|
||||
nsCOMPtr<nsILocalFile> mLockFile;
|
||||
#elif defined (XP_WIN)
|
||||
HANDLE mLockFileHandle;
|
||||
#elif defined (XP_OS2)
|
||||
LHANDLE mLockFileHandle;
|
||||
#elif defined (XP_UNIX)
|
||||
static void RemovePidLockFiles();
|
||||
static void FatalSignalHandler(int signo);
|
||||
static PRCList mPidLockList;
|
||||
char* mPidLockFileName;
|
||||
int mLockFileDesc;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif /* __nsProfileLock_h___ */
|
||||
@@ -30,14 +30,14 @@ MODULE = profile
|
||||
GRE_MODULE = 1
|
||||
|
||||
SDK_XPIDLSRCS = \
|
||||
nsIProfile.idl \
|
||||
$(NULL)
|
||||
nsIProfile.idl \
|
||||
nsIProfileChangeStatus.idl \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIProfileInternal.idl \
|
||||
nsIProfileStartupListener.idl \
|
||||
nsIProfileChangeStatus.idl \
|
||||
$(NULL)
|
||||
nsIProfileInternal.idl \
|
||||
nsIProfileStartupListener.idl \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
EXPORTS = \
|
||||
|
||||
@@ -54,6 +54,8 @@ CPPSRCS = nsProfile.cpp \
|
||||
nsProfileAccess.cpp \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../dirserviceprovider/src
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsProfile.h"
|
||||
#include "nsProfileLock.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
|
||||
@@ -1221,12 +1222,12 @@ nsProfile::SetCurrentProfile(const PRUnichar * aCurrentProfile)
|
||||
}
|
||||
|
||||
// Do the profile switch
|
||||
localLock.Unlock(); // gDirServiceProvider will get and hold its own lock
|
||||
gDirServiceProvider->SetProfileDir(profileDir);
|
||||
mCurrentProfileName.Assign(aCurrentProfile);
|
||||
gProfileDataAccess->SetCurrentProfile(aCurrentProfile);
|
||||
gProfileDataAccess->mProfileDataChanged = PR_TRUE;
|
||||
gProfileDataAccess->UpdateRegistry(nsnull);
|
||||
mCurrentProfileLock = localLock;
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
mCurrentProfileAvailable = PR_TRUE;
|
||||
@@ -1330,7 +1331,6 @@ NS_IMETHODIMP nsProfile::ShutDownCurrentProfile(PRUint32 shutDownType)
|
||||
UpdateCurrentProfileModTime(PR_TRUE);
|
||||
mCurrentProfileAvailable = PR_FALSE;
|
||||
mCurrentProfileName.Truncate(0);
|
||||
mCurrentProfileLock.Unlock();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -2460,6 +2460,7 @@ NS_IMETHODIMP nsProfile::VetoChange()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsProfile::GetRegStrings(const PRUnichar *aProfileName,
|
||||
PRUnichar **aRegString,
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
#define _MAX_LENGTH 256
|
||||
|
||||
class nsProfile: public nsIProfileInternal,
|
||||
public nsIProfileChangeStatus
|
||||
public nsIProfileChangeStatus
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPROFILE
|
||||
@@ -93,7 +93,6 @@ private:
|
||||
|
||||
nsString mCurrentProfileName;
|
||||
PRBool mCurrentProfileAvailable;
|
||||
nsProfileLock mCurrentProfileLock;
|
||||
|
||||
PRBool mIsUILocaleSpecified;
|
||||
nsCString mUILocaleName;
|
||||
|
||||
@@ -1588,678 +1588,3 @@ nsresult ProfileStruct::EnsureDirPathExists(nsILocalFile *aDir, PRBool *wasCreat
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// **********************************************************************
|
||||
// class nsProfileLock
|
||||
// **********************************************************************
|
||||
|
||||
#if defined (XP_MAC) && TARGET_CARBON
|
||||
|
||||
// The following functions and definitions are used in order to allow
|
||||
// a CFM build to use the same locking scheme as a Mach-0 build.
|
||||
|
||||
static CFBundleRef getBundle(CFStringRef frameworkPath)
|
||||
{
|
||||
CFBundleRef bundle = NULL;
|
||||
|
||||
// Make a CFURLRef from the CFString representation of the bundle's path.
|
||||
// See the Core Foundation URL Services chapter for details.
|
||||
CFURLRef bundleURL = CFURLCreateWithFileSystemPath(NULL, frameworkPath, kCFURLPOSIXPathStyle, true);
|
||||
if (bundleURL != NULL) {
|
||||
bundle = CFBundleCreate(NULL, bundleURL);
|
||||
if (bundle != NULL)
|
||||
CFBundleLoadExecutable(bundle);
|
||||
CFRelease(bundleURL);
|
||||
}
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
static void* getSystemFunction(CFStringRef functionName)
|
||||
{
|
||||
static CFBundleRef systemBundle = getBundle(CFSTR("/System/Library/Frameworks/System.framework"));
|
||||
if (systemBundle) return CFBundleGetFunctionPointerForName(systemBundle, functionName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// From <sys/types.h>
|
||||
typedef int64_t off_t; /* file offset */
|
||||
typedef int32_t pid_t; /* process id */
|
||||
|
||||
// From <sys/errno.h>
|
||||
#define EAGAIN 35 /* Resource temporarily unavailable */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
|
||||
// From <sys/fcntl.h>
|
||||
#define O_RDONLY 0x0000 /* open for reading only */
|
||||
#define O_WRONLY 0x0001 /* open for writing only */
|
||||
#define O_RDWR 0x0002 /* open for reading and writing */
|
||||
|
||||
#define O_CREAT 0x0200 /* create if nonexistant */
|
||||
#define O_TRUNC 0x0400 /* truncate to zero length */
|
||||
#define O_EXCL 0x0800 /* error if already exists */
|
||||
|
||||
#define F_RDLCK 1 /* shared or read lock */
|
||||
#define F_UNLCK 2 /* unlock */
|
||||
#define F_WRLCK 3 /* exclusive or write lock */
|
||||
|
||||
#define F_SETLK 8 /* set record locking information */
|
||||
|
||||
struct flock {
|
||||
off_t l_start; /* starting offset */
|
||||
off_t l_len; /* len = 0 means until end of file */
|
||||
pid_t l_pid; /* lock owner */
|
||||
short l_type; /* lock type: read/write, etc. */
|
||||
short l_whence; /* type of l_start */
|
||||
};
|
||||
|
||||
// Proc ptr types of the procs we import from System framework
|
||||
typedef int (*open_proc_ptr) (const char *, int, ...);
|
||||
typedef int (*close_proc_ptr) (int);
|
||||
typedef int (*fcntl_proc_ptr) (int, int, ...);
|
||||
typedef int* (*error_proc_ptr) ();
|
||||
|
||||
static open_proc_ptr bsd_open = (open_proc_ptr) getSystemFunction(CFSTR("open"));
|
||||
static close_proc_ptr bsd_close = (close_proc_ptr) getSystemFunction(CFSTR("close"));
|
||||
static fcntl_proc_ptr bsd_fcntl = (fcntl_proc_ptr) getSystemFunction(CFSTR("fcntl"));
|
||||
static error_proc_ptr bsd_error = (error_proc_ptr) getSystemFunction(CFSTR("__error"));
|
||||
|
||||
#endif /* XP_MAC && TARGET_CARBON */
|
||||
|
||||
nsProfileLock::nsProfileLock() :
|
||||
mHaveLock(PR_FALSE)
|
||||
#if defined (XP_MAC) && TARGET_CARBON
|
||||
,mLockFileDesc(-1)
|
||||
#elif 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
|
||||
}
|
||||
|
||||
|
||||
nsProfileLock::nsProfileLock(nsProfileLock& src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
|
||||
nsProfileLock& nsProfileLock::operator=(nsProfileLock& rhs)
|
||||
{
|
||||
Unlock();
|
||||
|
||||
mHaveLock = rhs.mHaveLock;
|
||||
rhs.mHaveLock = PR_FALSE;
|
||||
|
||||
#if defined (XP_MAC)
|
||||
mLockFile = rhs.mLockFile;
|
||||
rhs.mLockFile = nsnull;
|
||||
#if TARGET_CARBON
|
||||
mLockFileDesc = rhs.mLockFileDesc;
|
||||
rhs.mLockFileDesc = -1;
|
||||
#endif
|
||||
#elif 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;
|
||||
}
|
||||
|
||||
|
||||
nsProfileLock::~nsProfileLock()
|
||||
{
|
||||
Unlock();
|
||||
}
|
||||
|
||||
|
||||
#if defined (XP_UNIX)
|
||||
|
||||
static int setupPidLockCleanup;
|
||||
|
||||
PRCList nsProfileLock::mPidLockList =
|
||||
PR_INIT_STATIC_CLIST(&nsProfileLock::mPidLockList);
|
||||
|
||||
void nsProfileLock::RemovePidLockFiles()
|
||||
{
|
||||
while (!PR_CLIST_IS_EMPTY(&mPidLockList))
|
||||
{
|
||||
nsProfileLock *lock = NS_STATIC_CAST(nsProfileLock*, mPidLockList.next);
|
||||
lock->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
static struct sigaction SIGHUP_oldact;
|
||||
static struct sigaction SIGINT_oldact;
|
||||
static struct sigaction SIGQUIT_oldact;
|
||||
static struct sigaction SIGILL_oldact;
|
||||
static struct sigaction SIGABRT_oldact;
|
||||
static struct sigaction SIGSEGV_oldact;
|
||||
static struct sigaction SIGTERM_oldact;
|
||||
|
||||
void nsProfileLock::FatalSignalHandler(int signo)
|
||||
{
|
||||
// Remove any locks still held.
|
||||
RemovePidLockFiles();
|
||||
|
||||
// Chain to the old handler, which may exit.
|
||||
struct sigaction *oldact = nsnull;
|
||||
|
||||
switch (signo) {
|
||||
case SIGHUP:
|
||||
oldact = &SIGHUP_oldact;
|
||||
break;
|
||||
case SIGINT:
|
||||
oldact = &SIGINT_oldact;
|
||||
break;
|
||||
case SIGQUIT:
|
||||
oldact = &SIGQUIT_oldact;
|
||||
break;
|
||||
case SIGILL:
|
||||
oldact = &SIGILL_oldact;
|
||||
break;
|
||||
case SIGABRT:
|
||||
oldact = &SIGABRT_oldact;
|
||||
break;
|
||||
case SIGSEGV:
|
||||
oldact = &SIGSEGV_oldact;
|
||||
break;
|
||||
case SIGTERM:
|
||||
oldact = &SIGTERM_oldact;
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("bad signo");
|
||||
break;
|
||||
}
|
||||
|
||||
if (oldact &&
|
||||
oldact->sa_handler &&
|
||||
oldact->sa_handler != SIG_DFL &&
|
||||
oldact->sa_handler != SIG_IGN)
|
||||
{
|
||||
oldact->sa_handler(signo);
|
||||
}
|
||||
|
||||
// Backstop exit call, just in case.
|
||||
_exit(signo);
|
||||
}
|
||||
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
nsresult nsProfileLock::Lock(nsILocalFile* aFile)
|
||||
{
|
||||
#if defined (XP_MAC) || 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;
|
||||
NS_ENSURE_STATE(!mHaveLock);
|
||||
|
||||
PRBool isDir;
|
||||
rv = aFile->IsDirectory(&isDir);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!isDir)
|
||||
return NS_ERROR_FILE_NOT_DIRECTORY;
|
||||
|
||||
nsCOMPtr<nsILocalFile> lockFile;
|
||||
rv = aFile->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_MAC) || defined(XP_MACOSX)
|
||||
#if defined(XP_MACOSX)
|
||||
nsCAutoString filePath;
|
||||
rv = lockFile->GetNativePath(filePath);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mLockFileDesc = open(filePath.get(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (mLockFileDesc == -1)
|
||||
{
|
||||
NS_ERROR("Failed to open lock file.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
struct flock lock;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0; // len = 0 means entire file
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
if (fcntl(mLockFileDesc, F_SETLK, &lock) == -1)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EACCES)
|
||||
return NS_ERROR_FILE_ACCESS_DENIED;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mHaveLock = PR_TRUE;
|
||||
#elif TARGET_CARBON
|
||||
if (bsd_open && bsd_close && bsd_fcntl && bsd_error) // FALSE for TARGET_CARBON on OS9
|
||||
{
|
||||
// We need a UTF-8 Posix path to pass to open.
|
||||
CFURLRef lockFileCFURL;
|
||||
nsCOMPtr<nsILocalFileMac> lockMacFile(do_QueryInterface(lockFile));
|
||||
if (!lockMacFile)
|
||||
return NS_ERROR_FAILURE;
|
||||
rv = lockMacFile->GetCFURL(&lockFileCFURL);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// On OSX, even if we're a CFM app, this will return a UTF-8 Posix path.
|
||||
Boolean gotPath;
|
||||
UInt8 pathBuf[1024];
|
||||
gotPath = ::CFURLGetFileSystemRepresentation(lockFileCFURL, false, pathBuf, sizeof(pathBuf));
|
||||
::CFRelease(lockFileCFURL);
|
||||
if (!gotPath)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mLockFileDesc = bsd_open((char *)pathBuf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (mLockFileDesc == -1)
|
||||
{
|
||||
NS_ERROR("Failed to open lock file.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
struct flock lock;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0; // len = 0 means entire file
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
|
||||
if (bsd_fcntl(mLockFileDesc, F_SETLK, &lock) == -1)
|
||||
{
|
||||
int *errno_ptr = bsd_error();
|
||||
if (*errno_ptr == EAGAIN || *errno_ptr == EACCES)
|
||||
return NS_ERROR_FILE_ACCESS_DENIED;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mHaveLock = PR_TRUE;
|
||||
}
|
||||
#endif /* TARGET_CARBON */
|
||||
|
||||
// Even if we're using fcntl locking, check for the old-style lock.
|
||||
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.
|
||||
|
||||
#if !TARGET_CARBON
|
||||
rv = lockFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0, &fd);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
static LockProcessInfo sSelfInfo;
|
||||
static PRBool sSelfInfoInited;
|
||||
|
||||
if (!sSelfInfoInited)
|
||||
{
|
||||
ProcessSerialNumber psn;
|
||||
if (::GetCurrentProcess(&psn) == noErr)
|
||||
{
|
||||
processInfo.processAppSpec = nsnull;
|
||||
processInfo.processName = nsnull;
|
||||
processInfo.processInfoLength = sizeof(ProcessInfoRec);
|
||||
if (::GetProcessInformation(&psn, &processInfo) == noErr)
|
||||
{
|
||||
sSelfInfo.psn = processInfo.processNumber;
|
||||
sSelfInfo.launchDate = processInfo.processLaunchDate;
|
||||
sSelfInfoInited = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!sSelfInfoInited)
|
||||
{
|
||||
PR_Close(fd);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ioBytes = PR_Write(fd, &sSelfInfo, sizeof(LockProcessInfo));
|
||||
PR_Close(fd);
|
||||
if (ioBytes != sizeof(LockProcessInfo))
|
||||
return NS_ERROR_FAILURE;
|
||||
mLockFile = lockFile;
|
||||
#endif /* !TARGET_CARBON */
|
||||
#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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
#elif defined(XP_UNIX)
|
||||
#ifdef USE_SYMLINK_LOCKING
|
||||
nsCOMPtr<nsILocalFile> oldLockFile;
|
||||
rv = aFile->Clone((nsIFile **)((void **)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 the 4.x-compatible symlink technique, which works with NFS
|
||||
// without depending on (broken or missing, too often) lockd.
|
||||
struct in_addr inaddr;
|
||||
inaddr.s_addr = INADDR_LOOPBACK;
|
||||
|
||||
char hostname[256];
|
||||
PRStatus status = PR_GetSystemInfo(PR_SI_HOSTNAME, hostname, sizeof hostname);
|
||||
if (status == PR_SUCCESS)
|
||||
{
|
||||
char netdbbuf[PR_NETDB_BUF_SIZE];
|
||||
PRHostEnt hostent;
|
||||
status = PR_GetHostByName(hostname, netdbbuf, sizeof netdbbuf, &hostent);
|
||||
if (status == PR_SUCCESS)
|
||||
memcpy(&inaddr, hostent.h_addr, sizeof inaddr);
|
||||
}
|
||||
|
||||
char *signature =
|
||||
PR_smprintf("%s:%lu", inet_ntoa(inaddr), (unsigned long)getpid());
|
||||
const char *oldFileName = oldFilePath.get();
|
||||
int symlink_rv, symlink_errno, tries = 0;
|
||||
|
||||
// use ns4.x-compatible symlinks if the FS supports them
|
||||
while ((symlink_rv = symlink(signature, oldFileName)) < 0)
|
||||
{
|
||||
symlink_errno = errno;
|
||||
if (symlink_errno != EEXIST)
|
||||
break;
|
||||
|
||||
// the link exists; see if it's from this machine, and if
|
||||
// so if the process is still active
|
||||
char buf[1024];
|
||||
int len = readlink(oldFileName, buf, sizeof buf - 1);
|
||||
if (len > 0)
|
||||
{
|
||||
buf[len] = '\0';
|
||||
char *colon = strchr(buf, ':');
|
||||
if (colon)
|
||||
{
|
||||
*colon++ = '\0';
|
||||
unsigned long addr = inet_addr(buf);
|
||||
if (addr != (unsigned long) -1)
|
||||
{
|
||||
char *after = nsnull;
|
||||
pid_t pid = strtol(colon, &after, 0);
|
||||
if (pid != 0 && *after == '\0')
|
||||
{
|
||||
if (addr != inaddr.s_addr)
|
||||
{
|
||||
// Remote lock: give up even if stuck.
|
||||
break;
|
||||
}
|
||||
|
||||
// kill(pid,0) is a neat trick to check if a
|
||||
// process exists
|
||||
if (kill(pid, 0) == 0 || errno != ESRCH)
|
||||
{
|
||||
// Local process appears to be alive, ass-u-me it
|
||||
// is another Mozilla instance, or a compatible
|
||||
// derivative, that's currently using the profile.
|
||||
// XXX need an "are you Mozilla?" protocol
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lock seems to be bogus: try to claim it. Give up after a large
|
||||
// number of attempts (100 comes from the 4.x codebase).
|
||||
(void) unlink(oldFileName);
|
||||
if (++tries > 100)
|
||||
break;
|
||||
}
|
||||
|
||||
PR_smprintf_free(signature);
|
||||
signature = nsnull;
|
||||
|
||||
if (symlink_rv == 0)
|
||||
{
|
||||
// We exclusively created the symlink: record its name for eventual
|
||||
// unlock-via-unlink.
|
||||
mPidLockFileName = strdup(oldFileName);
|
||||
if (mPidLockFileName)
|
||||
{
|
||||
PR_APPEND_LINK(this, &mPidLockList);
|
||||
if (!setupPidLockCleanup++)
|
||||
{
|
||||
// Clean up on normal termination.
|
||||
atexit(RemovePidLockFiles);
|
||||
|
||||
// Clean up on abnormal termination, using POSIX sigaction.
|
||||
// Don't arm a handler if the signal is being ignored, e.g.,
|
||||
// because mozilla is run via nohup.
|
||||
struct sigaction act, oldact;
|
||||
act.sa_handler = FatalSignalHandler;
|
||||
act.sa_flags = 0;
|
||||
sigfillset(&act.sa_mask);
|
||||
|
||||
#define CATCH_SIGNAL(signame) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (sigaction(signame, NULL, &oldact) == 0 && \
|
||||
oldact.sa_handler != SIG_IGN) \
|
||||
{ \
|
||||
sigaction(signame, &act, &signame##_oldact); \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
CATCH_SIGNAL(SIGHUP);
|
||||
CATCH_SIGNAL(SIGINT);
|
||||
CATCH_SIGNAL(SIGQUIT);
|
||||
CATCH_SIGNAL(SIGILL);
|
||||
CATCH_SIGNAL(SIGABRT);
|
||||
CATCH_SIGNAL(SIGSEGV);
|
||||
CATCH_SIGNAL(SIGTERM);
|
||||
|
||||
#undef CATCH_SIGNAL
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (symlink_errno != EEXIST)
|
||||
#endif /* USE_SYMLINK_LOCKING */
|
||||
{
|
||||
// Symlinks aren't supported (for example, on Win32 SAMBA servers).
|
||||
// F_SETLK is not well supported on all NFS servers, which is why we
|
||||
// try symlinks first.
|
||||
nsCAutoString filePath;
|
||||
rv = lockFile->GetNativePath(filePath);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mLockFileDesc = open(filePath.get(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (mLockFileDesc == -1)
|
||||
{
|
||||
NS_ERROR("Failed to open lock file.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
struct flock lock;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0; // len = 0 means entire file
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
if (fcntl(mLockFileDesc, F_SETLK, &lock) == -1)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EACCES)
|
||||
return NS_ERROR_FILE_ACCESS_DENIED;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
#ifdef USE_SYMLINK_LOCKING
|
||||
else
|
||||
{
|
||||
// Couldn't create the symlink (but symlink(2) is supported).
|
||||
// This error code will cause the right dialog to be displayed.
|
||||
return NS_ERROR_FILE_ACCESS_DENIED;
|
||||
}
|
||||
#endif /* USE_SYMLINK_LOCKING */
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
mHaveLock = PR_TRUE;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsProfileLock::Unlock()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mHaveLock)
|
||||
{
|
||||
#if defined (XP_MAC)
|
||||
if (mLockFile)
|
||||
rv = mLockFile->Remove(PR_FALSE);
|
||||
#if TARGET_CARBON
|
||||
if (mLockFileDesc != -1)
|
||||
{
|
||||
bsd_close(mLockFileDesc);
|
||||
mLockFileDesc = -1;
|
||||
}
|
||||
#endif
|
||||
#elif 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;
|
||||
}
|
||||
|
||||
@@ -176,45 +176,5 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#include "prclist.h"
|
||||
|
||||
class nsProfileLock
|
||||
#if defined (XP_UNIX)
|
||||
: public PRCList
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
nsProfileLock();
|
||||
nsProfileLock(nsProfileLock& src);
|
||||
|
||||
~nsProfileLock();
|
||||
|
||||
nsProfileLock& operator=(nsProfileLock& rhs);
|
||||
|
||||
nsresult Lock(nsILocalFile* aFile);
|
||||
nsresult Unlock();
|
||||
|
||||
private:
|
||||
PRPackedBool mHaveLock;
|
||||
|
||||
#if defined (XP_MAC)
|
||||
#if TARGET_CARBON
|
||||
int mLockFileDesc;
|
||||
#endif
|
||||
nsCOMPtr<nsILocalFile> mLockFile;
|
||||
#elif defined (XP_WIN)
|
||||
HANDLE mLockFileHandle;
|
||||
#elif defined (XP_OS2)
|
||||
LHANDLE mLockFileHandle;
|
||||
#elif defined (XP_UNIX)
|
||||
static void RemovePidLockFiles();
|
||||
static void FatalSignalHandler(int signo);
|
||||
static PRCList mPidLockList;
|
||||
char* mPidLockFileName;
|
||||
int mLockFileDesc;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // __nsProfileAccess_h___
|
||||
|
||||
|
||||
@@ -83,6 +83,13 @@
|
||||
// These locations are typically provided by the profile mgr
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// In a shared profile environment, prefixing a profile-relative
|
||||
// key with NS_SHARED returns a location that is shared by
|
||||
// other users of the profile. Without this prefix, the consumer
|
||||
// has exclusive access to this location.
|
||||
|
||||
#define NS_SHARED "SHARED"
|
||||
|
||||
#define NS_APP_PREFS_50_DIR "PrefD" // Directory which contains user prefs
|
||||
#define NS_APP_PREFS_50_FILE "PrefF"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user