1// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/importer/firefox_profile_lock.h" 6 7#include <errno.h> 8#include <fcntl.h> 9#include <sys/stat.h> 10#include <sys/types.h> 11 12#include "base/file_util.h" 13 14// This class is based on Firefox code in: 15// profile/dirserviceprovider/src/nsProfileLock.cpp 16// The license block is: 17 18/* ***** BEGIN LICENSE BLOCK ***** 19* Version: MPL 1.1/GPL 2.0/LGPL 2.1 20* 21* The contents of this file are subject to the Mozilla Public License Version 22* 1.1 (the "License"); you may not use this file except in compliance with 23* the License. You may obtain a copy of the License at 24* http://www.mozilla.org/MPL/ 25* 26* Software distributed under the License is distributed on an "AS IS" basis, 27* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 28* for the specific language governing rights and limitations under the 29* License. 30* 31* The Original Code is mozilla.org code. 32* 33* The Initial Developer of the Original Code is 34* Netscape Communications Corporation. 35* Portions created by the Initial Developer are Copyright (C) 2002 36* the Initial Developer. All Rights Reserved. 37* 38* Contributor(s): 39* Conrad Carlen <ccarlen@netscape.com> 40* Brendan Eich <brendan@mozilla.org> 41* Colin Blake <colin@theblakes.com> 42* Javier Pedemonte <pedemont@us.ibm.com> 43* Mats Palmgren <mats.palmgren@bredband.net> 44* 45* Alternatively, the contents of this file may be used under the terms of 46* either the GNU General Public License Version 2 or later (the "GPL"), or 47* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 48* in which case the provisions of the GPL or the LGPL are applicable instead 49* of those above. If you wish to allow use of your version of this file only 50* under the terms of either the GPL or the LGPL, and not to allow others to 51* use your version of this file under the terms of the MPL, indicate your 52* decision by deleting the provisions above and replace them with the notice 53* and other provisions required by the GPL or the LGPL. If you do not delete 54* the provisions above, a recipient may use your version of this file under 55* the terms of any one of the MPL, the GPL or the LGPL. 56* 57* ***** END LICENSE BLOCK ***** */ 58 59void FirefoxProfileLock::Init() { 60 lock_fd_ = -1; 61} 62 63void FirefoxProfileLock::Lock() { 64 if (HasAcquired()) 65 return; 66 67 bool fcntl_lock = LockWithFcntl(); 68 if (!fcntl_lock) { 69 return; 70 } else if (!HasAcquired()) { 71 old_lock_file_ = lock_file_.DirName().Append(kOldLockFileName); 72 lock_fd_ = open(old_lock_file_.value().c_str(), O_CREAT | O_EXCL, 0644); 73 } 74} 75 76void FirefoxProfileLock::Unlock() { 77 if (!HasAcquired()) 78 return; 79 close(lock_fd_); 80 lock_fd_ = -1; 81 file_util::Delete(old_lock_file_, false); 82} 83 84bool FirefoxProfileLock::HasAcquired() { 85 return (lock_fd_ >= 0); 86} 87 88// This function tries to lock Firefox profile using fcntl(). The return 89// value of this function together with HasAcquired() tells the current status 90// of lock. 91// if return == false: Another process has lock to the profile. 92// if return == true && HasAcquired() == true: successfully acquired the lock. 93// if return == false && HasAcquired() == false: Failed to acquire lock due 94// to some error (so that we can try alternate method of profile lock). 95bool FirefoxProfileLock::LockWithFcntl() { 96 lock_fd_ = open(lock_file_.value().c_str(), O_WRONLY | O_CREAT | O_TRUNC, 97 0666); 98 if (lock_fd_ == -1) 99 return true; 100 101 struct flock lock; 102 lock.l_start = 0; 103 lock.l_len = 0; 104 lock.l_type = F_WRLCK; 105 lock.l_whence = SEEK_SET; 106 lock.l_pid = 0; 107 108 struct flock testlock = lock; 109 if (fcntl(lock_fd_, F_GETLK, &testlock) == -1) { 110 close(lock_fd_); 111 lock_fd_ = -1; 112 return true; 113 } else if (fcntl(lock_fd_, F_SETLK, &lock) == -1) { 114 close(lock_fd_); 115 lock_fd_ = -1; 116 if (errno == EAGAIN || errno == EACCES) 117 return false; 118 else 119 return true; 120 } else { 121 // We have the lock. 122 return true; 123 } 124} 125