diff options
| -rw-r--r-- | actions/policy.go | 2 | ||||
| -rw-r--r-- | filesystem/filesystem.go | 37 | ||||
| -rw-r--r-- | filesystem/filesystem_test.go | 12 |
3 files changed, 40 insertions, 11 deletions
diff --git a/actions/policy.go b/actions/policy.go index 41e108e..9d644c1 100644 --- a/actions/policy.go +++ b/actions/policy.go @@ -315,7 +315,7 @@ func (policy *Policy) AddProtector(protector *Protector) error { // to it on the policy's filesystem. if policy.Context.Mount != protector.Context.Mount { log.Printf("policy on %s\n protector on %s\n", policy.Context.Mount, protector.Context.Mount) - err := policy.Context.Mount.AddLinkedProtector( + _, err := policy.Context.Mount.AddLinkedProtector( protector.Descriptor(), protector.Context.Mount) if err != nil { return err 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) |