1
// -*- Mode: Go; indent-tabs-mode: t -*-
4
* Copyright (C) 2014-2015 Canonical Ltd
6
* This program is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 3 as
8
* published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
28
// ErrNotLocked is returned when an attempts is made to unlock an
30
var ErrNotLocked = errors.New("not locked")
32
// FileLock is a Lock file object used to serialise access for
33
// privileged operations.
34
type FileLock struct {
39
// NewFileLock creates a new lock object (but does not lock it).
40
func NewFileLock(path string) *FileLock {
41
return &FileLock{Filename: path}
44
// Lock the FileLock object.
45
// Returns ErrAlreadyLocked if an existing lock is in place.
46
func (l *FileLock) Lock(blocking bool) error {
49
// XXX: don't try to create exclusively - we care if the file failed to
50
// be created, but we don't care if it already existed as the lock
51
// _on_ the file is the most important thing.
52
flags := (os.O_CREATE | os.O_WRONLY)
54
f, err := os.OpenFile(l.Filename, flags, 0600)
60
// Note: we don't want to block if the lock is already held.
61
how := syscall.LOCK_EX
63
how |= syscall.LOCK_NB
66
if err = syscall.Flock(int(l.realFile.Fd()), how); err != nil {
67
return ErrAlreadyLocked
73
// Unlock the FileLock object.
74
// Returns ErrNotLocked if no existing lock is in place.
75
func (l *FileLock) Unlock() error {
76
if err := syscall.Flock(int(l.realFile.Fd()), syscall.LOCK_UN); err != nil {
80
if err := l.realFile.Close(); err != nil {
84
filename := l.Filename
90
return os.Remove(filename)