aboutsummaryrefslogtreecommitdiff
path: root/filesystem
diff options
context:
space:
mode:
Diffstat (limited to 'filesystem')
-rw-r--r--filesystem/filesystem.go37
-rw-r--r--filesystem/filesystem_test.go12
2 files changed, 39 insertions, 10 deletions
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 9bae72b..e0ef110 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -393,24 +393,43 @@ func (m *Mount) AddProtector(data *metadata.ProtectorData) error {
}
// AddLinkedProtector adds a link in this filesystem to the protector metadata
-// in the dest filesystem.
-func (m *Mount) AddLinkedProtector(descriptor string, dest *Mount) error {
+// in the dest filesystem, if one doesn't already exist. On success, the return
+// value is a nil error and a bool that is true iff the link is newly created.
+func (m *Mount) AddLinkedProtector(descriptor string, dest *Mount) (bool, error) {
if err := m.CheckSetup(); err != nil {
- return err
+ return false, err
}
// Check that the link is good (descriptor exists, filesystem has UUID).
if _, err := dest.GetRegularProtector(descriptor); err != nil {
- return err
+ return false, err
+ }
+
+ linkPath := m.linkedProtectorPath(descriptor)
+
+ // Check whether the link already exists.
+ existingLink, err := ioutil.ReadFile(linkPath)
+ if err == nil {
+ existingLinkedMnt, err := getMountFromLink(string(existingLink))
+ if err != nil {
+ return false, err
+ }
+ if existingLinkedMnt != dest {
+ return false, errors.Wrapf(ErrFollowLink, "link %q points to %q, but expected %q",
+ linkPath, existingLinkedMnt.Path, dest.Path)
+ }
+ return false, nil
+ }
+ if !os.IsNotExist(err) {
+ return false, err
}
// Right now, we only make links using UUIDs.
- link, err := makeLink(dest, "UUID")
+ var newLink string
+ newLink, err = makeLink(dest, "UUID")
if err != nil {
- return dest.err(err)
+ return false, dest.err(err)
}
-
- path := m.linkedProtectorPath(descriptor)
- return m.err(m.writeDataAtomic(path, []byte(link)))
+ return true, m.err(m.writeDataAtomic(linkPath, []byte(newLink)))
}
// GetRegularProtector looks up the protector metadata by descriptor. This will
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index b85ead5..4bed96a 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -351,9 +351,19 @@ func TestLinkedProtector(t *testing.T) {
}
// Add the link to the second filesystem
- if err = fakeMnt.AddLinkedProtector(protector.ProtectorDescriptor, realMnt); err != nil {
+ var isNewLink bool
+ if isNewLink, err = fakeMnt.AddLinkedProtector(protector.ProtectorDescriptor, realMnt); err != nil {
t.Fatal(err)
}
+ if !isNewLink {
+ t.Fatal("Link was not new")
+ }
+ if isNewLink, err = fakeMnt.AddLinkedProtector(protector.ProtectorDescriptor, realMnt); err != nil {
+ t.Fatal(err)
+ }
+ if isNewLink {
+ t.Fatal("Link was new")
+ }
// Get the protector though the second system
_, err = fakeMnt.GetRegularProtector(protector.ProtectorDescriptor)