diff --git a/mozilla/embedding/components/Makefile.in b/mozilla/embedding/components/Makefile.in index eb705a8b930..d96fa187e68 100644 --- a/mozilla/embedding/components/Makefile.in +++ b/mozilla/embedding/components/Makefile.in @@ -33,6 +33,10 @@ ifdef MOZ_XUL DIRS += printingui endif +ifdef MOZ_PROFILESHARING +DIRS += profilesharingsetup +endif + DIRS += build include $(topsrcdir)/config/rules.mk diff --git a/mozilla/embedding/components/build/Makefile.in b/mozilla/embedding/components/build/Makefile.in index ca2a5ac4ace..b8e38ce9290 100644 --- a/mozilla/embedding/components/build/Makefile.in +++ b/mozilla/embedding/components/build/Makefile.in @@ -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 diff --git a/mozilla/embedding/components/build/nsModule.cpp b/mozilla/embedding/components/build/nsModule.cpp index 5fba2c0ac32..5bb46a71d25 100644 --- a/mozilla/embedding/components/build/nsModule.cpp +++ b/mozilla/embedding/components/build/nsModule.cpp @@ -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) diff --git a/mozilla/embedding/components/profilesharingsetup/Makefile.in b/mozilla/embedding/components/profilesharingsetup/Makefile.in new file mode 100644 index 00000000000..6c9b188dd43 --- /dev/null +++ b/mozilla/embedding/components/profilesharingsetup/Makefile.in @@ -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 diff --git a/mozilla/embedding/components/profilesharingsetup/public/Makefile.in b/mozilla/embedding/components/profilesharingsetup/public/Makefile.in new file mode 100644 index 00000000000..112c6074fbc --- /dev/null +++ b/mozilla/embedding/components/profilesharingsetup/public/Makefile.in @@ -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 + diff --git a/mozilla/embedding/components/profilesharingsetup/public/nsIProfileSharingSetup.idl b/mozilla/embedding/components/profilesharingsetup/public/nsIProfileSharingSetup.idl new file mode 100644 index 00000000000..74000f0b538 --- /dev/null +++ b/mozilla/embedding/components/profilesharingsetup/public/nsIProfileSharingSetup.idl @@ -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; +}; diff --git a/mozilla/embedding/components/profilesharingsetup/src/Makefile.in b/mozilla/embedding/components/profilesharingsetup/src/Makefile.in new file mode 100644 index 00000000000..6a8d03c3b7d --- /dev/null +++ b/mozilla/embedding/components/profilesharingsetup/src/Makefile.in @@ -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 + diff --git a/mozilla/embedding/components/profilesharingsetup/src/nsProfileSharingSetup.cpp b/mozilla/embedding/components/profilesharingsetup/src/nsProfileSharingSetup.cpp new file mode 100644 index 00000000000..d534d592eef --- /dev/null +++ b/mozilla/embedding/components/profilesharingsetup/src/nsProfileSharingSetup.cpp @@ -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 + * + * 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; +} diff --git a/mozilla/embedding/components/profilesharingsetup/src/nsProfileSharingSetup.h b/mozilla/embedding/components/profilesharingsetup/src/nsProfileSharingSetup.h new file mode 100644 index 00000000000..8ace5a9d8e3 --- /dev/null +++ b/mozilla/embedding/components/profilesharingsetup/src/nsProfileSharingSetup.h @@ -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 + * + * 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 diff --git a/mozilla/embedding/config/basebrowser-mac-macho b/mozilla/embedding/config/basebrowser-mac-macho index f5652ce1682..889d12094bc 100644 --- a/mozilla/embedding/config/basebrowser-mac-macho +++ b/mozilla/embedding/config/basebrowser-mac-macho @@ -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 diff --git a/mozilla/embedding/config/basebrowser-unix b/mozilla/embedding/config/basebrowser-unix index b94e5003364..576d673bf0f 100644 --- a/mozilla/embedding/config/basebrowser-unix +++ b/mozilla/embedding/config/basebrowser-unix @@ -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: diff --git a/mozilla/embedding/config/basebrowser-win b/mozilla/embedding/config/basebrowser-win index ae7aac76dc5..686fa917192 100644 --- a/mozilla/embedding/config/basebrowser-win +++ b/mozilla/embedding/config/basebrowser-win @@ -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 diff --git a/mozilla/profile/build/Makefile.in b/mozilla/profile/build/Makefile.in index d6d9fb92501..e9f7077c0a6 100644 --- a/mozilla/profile/build/Makefile.in +++ b/mozilla/profile/build/Makefile.in @@ -65,6 +65,7 @@ REQUIRES = xpcom \ appshell \ uconv \ windowwatcher \ + profdirserviceprovider \ $(NULL) CPPSRCS = \ diff --git a/mozilla/profile/dirserviceprovider/public/Makefile.in b/mozilla/profile/dirserviceprovider/public/Makefile.in index 3ad22416481..163e5aa51d5 100755 --- a/mozilla/profile/dirserviceprovider/public/Makefile.in +++ b/mozilla/profile/dirserviceprovider/public/Makefile.in @@ -42,13 +42,10 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk MODULE = profdirserviceprovider + EXPORTS = \ nsProfileDirServiceProvider.h \ $(NULL) include $(topsrcdir)/config/rules.mk - - - - diff --git a/mozilla/profile/dirserviceprovider/public/nsProfileDirServiceProvider.h b/mozilla/profile/dirserviceprovider/public/nsProfileDirServiceProvider.h index bc89f5d658d..714b7f83435 100755 --- a/mozilla/profile/dirserviceprovider/public/nsProfileDirServiceProvider.h +++ b/mozilla/profile/dirserviceprovider/public/nsProfileDirServiceProvider.h @@ -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 mProfileDir; + nsProfileLock* mProfileDirLock; + PRPackedBool mNotifyObservers; + + PRPackedBool mSharingEnabled; + nsString mNonSharedDirName; + nsCOMPtr mNonSharedProfileDir; }; diff --git a/mozilla/profile/dirserviceprovider/src/Makefile.in b/mozilla/profile/dirserviceprovider/src/Makefile.in index 34415765247..3f5240fc465 100755 --- a/mozilla/profile/dirserviceprovider/src/Makefile.in +++ b/mozilla/profile/dirserviceprovider/src/Makefile.in @@ -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 - diff --git a/mozilla/profile/dirserviceprovider/src/nsProfileDirServiceProvider.cpp b/mozilla/profile/dirserviceprovider/src/nsProfileDirServiceProvider.cpp index eb2b603b9a3..c649b51f0df 100755 --- a/mozilla/profile/dirserviceprovider/src/nsProfileDirServiceProvider.cpp +++ b/mozilla/profile/dirserviceprovider/src/nsProfileDirServiceProvider.cpp @@ -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 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 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 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 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 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 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 diff --git a/mozilla/profile/dirserviceprovider/src/nsProfileLock.cpp b/mozilla/profile/dirserviceprovider/src/nsProfileLock.cpp new file mode 100644 index 00000000000..39261aab51f --- /dev/null +++ b/mozilla/profile/dirserviceprovider/src/nsProfileLock.cpp @@ -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 + * Brendan Eich + * Colin Blake + * Javier Pedemonte + * + * 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 +#include +#endif + +#ifdef XP_UNIX +#include +#include +#include +#include +#include +#include "prnetdb.h" +#include "prsystem.h" +#include "prprf.h" +#endif + +#ifdef VMS +#include +#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 +typedef int64_t off_t; /* file offset */ +typedef int32_t pid_t; /* process id */ + +// From +#define EAGAIN 35 /* Resource temporarily unavailable */ +#define EACCES 13 /* Permission denied */ + +// From +#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 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 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 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; +} diff --git a/mozilla/profile/dirserviceprovider/src/nsProfileLock.h b/mozilla/profile/dirserviceprovider/src/nsProfileLock.h new file mode 100644 index 00000000000..e22a4c10fa3 --- /dev/null +++ b/mozilla/profile/dirserviceprovider/src/nsProfileLock.h @@ -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 + * Brendan Eich + * + * 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 +#endif + +#if defined (XP_OS2) +#define INCL_DOSERRORS +#define INCL_DOSFILEMGR +#include +#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 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___ */ diff --git a/mozilla/profile/public/Makefile.in b/mozilla/profile/public/Makefile.in index a80b2b18a8d..05619532844 100644 --- a/mozilla/profile/public/Makefile.in +++ b/mozilla/profile/public/Makefile.in @@ -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 = \ diff --git a/mozilla/profile/src/Makefile.in b/mozilla/profile/src/Makefile.in index eb5e8590224..7959d67f003 100644 --- a/mozilla/profile/src/Makefile.in +++ b/mozilla/profile/src/Makefile.in @@ -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 diff --git a/mozilla/profile/src/nsProfile.cpp b/mozilla/profile/src/nsProfile.cpp index 72b7b85b721..736dad8b8bf 100644 --- a/mozilla/profile/src/nsProfile.cpp +++ b/mozilla/profile/src/nsProfile.cpp @@ -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, diff --git a/mozilla/profile/src/nsProfile.h b/mozilla/profile/src/nsProfile.h index ec4aa18d57b..b562290166a 100644 --- a/mozilla/profile/src/nsProfile.h +++ b/mozilla/profile/src/nsProfile.h @@ -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; diff --git a/mozilla/profile/src/nsProfileAccess.cpp b/mozilla/profile/src/nsProfileAccess.cpp index 4b37bde47f2..d21f9e59e0a 100644 --- a/mozilla/profile/src/nsProfileAccess.cpp +++ b/mozilla/profile/src/nsProfileAccess.cpp @@ -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 -typedef int64_t off_t; /* file offset */ -typedef int32_t pid_t; /* process id */ - -// From -#define EAGAIN 35 /* Resource temporarily unavailable */ -#define EACCES 13 /* Permission denied */ - -// From -#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 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 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 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; -} diff --git a/mozilla/profile/src/nsProfileAccess.h b/mozilla/profile/src/nsProfileAccess.h index 7005b91aa9f..3b69d0d7c89 100644 --- a/mozilla/profile/src/nsProfileAccess.h +++ b/mozilla/profile/src/nsProfileAccess.h @@ -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 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___ diff --git a/mozilla/xpcom/io/nsAppDirectoryServiceDefs.h b/mozilla/xpcom/io/nsAppDirectoryServiceDefs.h index a4cf67da274..010e959374e 100755 --- a/mozilla/xpcom/io/nsAppDirectoryServiceDefs.h +++ b/mozilla/xpcom/io/nsAppDirectoryServiceDefs.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"