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 (at) netscape.com> 40 * Brendan Eich <brendan (at) mozilla.org> 41 * Colin Blake <colin (at) theblakes.com> 42 * Javier Pedemonte <pedemont (at) us.ibm.com> 43 * Mats Palmgren <mats.palmgren (at) 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 59 void FirefoxProfileLock::Init() { 60 lock_fd_ = -1; 61 } 62 63 void 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 76 void FirefoxProfileLock::Unlock() { 77 if (!HasAcquired()) 78 return; 79 close(lock_fd_); 80 lock_fd_ = -1; 81 base::DeleteFile(old_lock_file_, false); 82 } 83 84 bool 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). 95 bool 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