diff options
| author | Eric Biggers <ebiggers@google.com> | 2020-05-09 14:04:47 -0700 |
|---|---|---|
| committer | Eric Biggers <ebiggers@google.com> | 2020-05-09 14:04:47 -0700 |
| commit | 5716215ceae3ab8b49a7b2ba410cb51a82c3176b (patch) | |
| tree | 8e5e6bd181dee4c8e99db7604a954b9030d52a0c | |
| parent | 8ff53630f1cc90ae23835e9571f9096e211dce67 (diff) | |
cmd/fscrypt: add FSCRYPT_CONSISTENT_OUTPUT environmental variable
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.
| -rw-r--r-- | cmd/fscrypt/fscrypt.go | 4 | ||||
| -rw-r--r-- | filesystem/filesystem.go | 44 |
2 files changed, 48 insertions, 0 deletions
diff --git a/cmd/fscrypt/fscrypt.go b/cmd/fscrypt/fscrypt.go index bbe16bb..aa5b6f4 100644 --- a/cmd/fscrypt/fscrypt.go +++ b/cmd/fscrypt/fscrypt.go @@ -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() diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index ecdeae1..e01f9ff 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -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 |