aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/fscrypt/fscrypt.go4
-rw-r--r--filesystem/filesystem.go44
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