]> git.apps.os.sepia.ceph.com Git - fscrypt.git/commitdiff
cmd/fscrypt: add FSCRYPT_CONSISTENT_OUTPUT environmental variable
authorEric Biggers <ebiggers@google.com>
Sat, 9 May 2020 21:04:47 +0000 (14:04 -0700)
committerEric Biggers <ebiggers@google.com>
Sat, 9 May 2020 21:04:47 +0000 (14:04 -0700)
Allow setting FSCRYPT_CONSISTENT_OUTPUT=1 in the environment to cause
policies and protectors to sorted by last modification time.  The CLI
tests need this to make the output of 'fscrypt' ordered in a consistent
way with regard to the operations performed.

cmd/fscrypt/fscrypt.go
filesystem/filesystem.go

index bbe16bb22ac07bafecff7ae319b3b31ed8d4b6dd..aa5b6f42f56499b6560b8638708af79853d0ca1d 100644 (file)
@@ -33,6 +33,7 @@ import (
        "github.com/urfave/cli"
 
        "github.com/google/fscrypt/actions"
+       "github.com/google/fscrypt/filesystem"
 )
 
 // Current version of the program (set by Makefile)
@@ -49,6 +50,9 @@ func main() {
        if rootmnt := os.Getenv("FSCRYPT_ROOT_MNT"); rootmnt != "" {
                actions.LoginProtectorMountpoint = rootmnt
        }
+       if consistent := os.Getenv("FSCRYPT_CONSISTENT_OUTPUT"); consistent == "1" {
+               filesystem.SortDescriptorsByLastMtime = true
+       }
 
        // Create our command line application
        app := cli.NewApp()
index ecdeae1f7557091a87b7bae699d040c1d4fd7516..e01f9ff964dcd59bd75532efc031821aaf906642 100644 (file)
@@ -38,7 +38,9 @@ import (
        "log"
        "os"
        "path/filepath"
+       "sort"
        "strings"
+       "time"
 
        "github.com/golang/protobuf/proto"
        "github.com/pkg/errors"
@@ -63,6 +65,11 @@ var (
        ErrCorruptMetadata = util.SystemError("on-disk metadata is corrupt")
 )
 
+// SortDescriptorsByLastMtime indicates whether descriptors are sorted by last
+// modification time when being listed.  This can be set to true to get
+// consistent output for testing.
+var SortDescriptorsByLastMtime = false
+
 // Mount contains information for a specific mounted filesystem.
 //     Path           - Absolute path where the directory is mounted
 //     FilesystemType - Type of the mounted filesystem, e.g. "ext4"
@@ -534,6 +541,37 @@ func (m *Mount) ListPolicies() ([]string, error) {
        return policies, m.err(err)
 }
 
+type namesAndTimes struct {
+       names []string
+       times []time.Time
+}
+
+func (c namesAndTimes) Len() int {
+       return len(c.names)
+}
+
+func (c namesAndTimes) Less(i, j int) bool {
+       return c.times[i].Before(c.times[j])
+}
+
+func (c namesAndTimes) Swap(i, j int) {
+       c.names[i], c.names[j] = c.names[j], c.names[i]
+       c.times[i], c.times[j] = c.times[j], c.times[i]
+}
+
+func sortFileListByLastMtime(directoryPath string, names []string) error {
+       c := namesAndTimes{names: names, times: make([]time.Time, len(names))}
+       for i, name := range names {
+               fi, err := os.Lstat(filepath.Join(directoryPath, name))
+               if err != nil {
+                       return err
+               }
+               c.times[i] = fi.ModTime()
+       }
+       sort.Sort(c)
+       return nil
+}
+
 // listDirectory returns a list of descriptors for a metadata directory,
 // including files which are links to other filesystem's metadata.
 func (m *Mount) listDirectory(directoryPath string) ([]string, error) {
@@ -549,6 +587,12 @@ func (m *Mount) listDirectory(directoryPath string) ([]string, error) {
                return nil, err
        }
 
+       if SortDescriptorsByLastMtime {
+               if err := sortFileListByLastMtime(directoryPath, names); err != nil {
+                       return nil, err
+               }
+       }
+
        descriptors := make([]string, 0, len(names))
        for _, name := range names {
                // Be sure to include links as well