Skip to content

Commit 27777de

Browse files
authored
Adding original flock lib (#10)
* Adding original flock lib * Changes
1 parent c47173b commit 27777de

File tree

11 files changed

+1298
-0
lines changed

11 files changed

+1298
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Compiled Object files, Static and Dynamic libs (Shared Objects)
2+
*.o
3+
*.a
4+
*.so
5+
6+
# Folders
7+
_obj
8+
_test
9+
10+
# Architecture specific extensions/prefixes
11+
*.[568vq]
12+
[568vq].out
13+
14+
*.cgo1.go
15+
*.cgo2.c
16+
_cgo_defun.c
17+
_cgo_gotypes.go
18+
_cgo_export.*
19+
20+
_testmain.go
21+
22+
*.exe
23+
*.test
24+
*.prof

extensions/internal/flock/LICENSE

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Copyright (c) 2015-2020, Tim Heckman
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are met:
6+
7+
* Redistributions of source code must retain the above copyright notice, this
8+
list of conditions and the following disclaimer.
9+
10+
* Redistributions in binary form must reproduce the above copyright notice,
11+
this list of conditions and the following disclaimer in the documentation
12+
and/or other materials provided with the distribution.
13+
14+
* Neither the name of gofrs nor the names of its contributors may be used
15+
to endorse or promote products derived from this software without
16+
specific prior written permission.
17+
18+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# gofrs/flock
2+
3+
[gofrs/flock](https://github.com/gofrs/flock) implements a thread-safe sync.Locker interface for file locking.
4+
5+
The source code has been copied here as we need to modify this library to expose the underlying lock file handle which is needed in msal extensions.

extensions/internal/flock/flock.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright 2015 Tim Heckman. All rights reserved.
2+
// Use of this source code is governed by the BSD 3-Clause
3+
// license that can be found in the LICENSE file.
4+
5+
// Package flock implements a thread-safe interface for file locking.
6+
// It also includes a non-blocking TryLock() function to allow locking
7+
// without blocking execution.
8+
//
9+
// Package flock is released under the BSD 3-Clause License. See the LICENSE file
10+
// for more details.
11+
//
12+
// While using this library, remember that the locking behaviors are not
13+
// guaranteed to be the same on each platform. For example, some UNIX-like
14+
// operating systems will transparently convert a shared lock to an exclusive
15+
// lock. If you Unlock() the flock from a location where you believe that you
16+
// have the shared lock, you may accidentally drop the exclusive lock.
17+
package flock
18+
19+
import (
20+
"context"
21+
"os"
22+
"runtime"
23+
"sync"
24+
"time"
25+
)
26+
27+
// Flock is the struct type to handle file locking. All fields are unexported,
28+
// with access to some of the fields provided by getter methods (Path() and Locked()).
29+
type Flock struct {
30+
path string
31+
m sync.RWMutex
32+
fh *os.File
33+
l bool
34+
r bool
35+
}
36+
37+
// New returns a new instance of *Flock. The only parameter
38+
// it takes is the path to the desired lockfile.
39+
func New(path string) *Flock {
40+
return &Flock{path: path}
41+
}
42+
43+
// NewFlock returns a new instance of *Flock. The only parameter
44+
// it takes is the path to the desired lockfile.
45+
//
46+
// Deprecated: Use New instead.
47+
func NewFlock(path string) *Flock {
48+
return New(path)
49+
}
50+
51+
// Close is equivalent to calling Unlock.
52+
//
53+
// This will release the lock and close the underlying file descriptor.
54+
// It will not remove the file from disk, that's up to your application.
55+
func (f *Flock) Close() error {
56+
return f.Unlock()
57+
}
58+
59+
// Path returns the path as provided in NewFlock().
60+
func (f *Flock) Path() string {
61+
return f.path
62+
}
63+
64+
// Locked returns the lock state (locked: true, unlocked: false).
65+
//
66+
// Warning: by the time you use the returned value, the state may have changed.
67+
func (f *Flock) Locked() bool {
68+
f.m.RLock()
69+
defer f.m.RUnlock()
70+
return f.l
71+
}
72+
73+
// RLocked returns the read lock state (locked: true, unlocked: false).
74+
//
75+
// Warning: by the time you use the returned value, the state may have changed.
76+
func (f *Flock) RLocked() bool {
77+
f.m.RLock()
78+
defer f.m.RUnlock()
79+
return f.r
80+
}
81+
82+
func (f *Flock) String() string {
83+
return f.path
84+
}
85+
86+
// TryLockContext repeatedly tries to take an exclusive lock until one of the
87+
// conditions is met: TryLock succeeds, TryLock fails with error, or Context
88+
// Done channel is closed.
89+
func (f *Flock) TryLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) {
90+
return tryCtx(ctx, f.TryLock, retryDelay)
91+
}
92+
93+
// TryRLockContext repeatedly tries to take a shared lock until one of the
94+
// conditions is met: TryRLock succeeds, TryRLock fails with error, or Context
95+
// Done channel is closed.
96+
func (f *Flock) TryRLockContext(ctx context.Context, retryDelay time.Duration) (bool, error) {
97+
return tryCtx(ctx, f.TryRLock, retryDelay)
98+
}
99+
100+
func tryCtx(ctx context.Context, fn func() (bool, error), retryDelay time.Duration) (bool, error) {
101+
if ctx.Err() != nil {
102+
return false, ctx.Err()
103+
}
104+
for {
105+
if ok, err := fn(); ok || err != nil {
106+
return ok, err
107+
}
108+
select {
109+
case <-ctx.Done():
110+
return false, ctx.Err()
111+
case <-time.After(retryDelay):
112+
// try again
113+
}
114+
}
115+
}
116+
117+
func (f *Flock) setFh() error {
118+
// open a new os.File instance
119+
// create it if it doesn't exist, and open the file read-only.
120+
flags := os.O_CREATE
121+
if runtime.GOOS == "aix" {
122+
// AIX cannot preform write-lock (ie exclusive) on a
123+
// read-only file.
124+
flags |= os.O_RDWR
125+
} else {
126+
flags |= os.O_RDONLY
127+
}
128+
fh, err := os.OpenFile(f.path, flags, os.FileMode(0600))
129+
if err != nil {
130+
return err
131+
}
132+
133+
// set the filehandle on the struct
134+
f.fh = fh
135+
return nil
136+
}
137+
138+
// ensure the file handle is closed if no lock is held
139+
func (f *Flock) ensureFhState() {
140+
if !f.l && !f.r && f.fh != nil {
141+
f.fh.Close()
142+
f.fh = nil
143+
}
144+
}

0 commit comments

Comments
 (0)