forked from gopasspw/gopass
/
fsck.go
91 lines (76 loc) · 2.22 KB
/
fsck.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package fs
import (
"context"
"os"
"path/filepath"
"syscall"
"github.com/gopasspw/gopass/pkg/ctxutil"
"github.com/gopasspw/gopass/pkg/fsutil"
"github.com/gopasspw/gopass/pkg/out"
)
// Fsck checks the storage integrity
func (s *Store) Fsck(ctx context.Context) error {
pcb := ctxutil.GetProgressCallback(ctx)
entries, err := s.List(ctx, "")
if err != nil {
return err
}
dirs := make(map[string]struct{}, len(entries))
for _, entry := range entries {
pcb()
out.Debug(ctx, "file.Fsck() - Checking %s", entry)
filename := filepath.Join(s.path, entry)
dirs[filepath.Dir(filename)] = struct{}{}
if err := s.fsckCheckFile(ctx, filename); err != nil {
return err
}
}
for dir := range dirs {
if err := s.fsckCheckDir(ctx, dir); err != nil {
return err
}
}
return nil
}
func (s *Store) fsckCheckFile(ctx context.Context, filename string) error {
fi, err := os.Stat(filename)
if err != nil {
return err
}
if fi.Mode().Perm()&0177 == 0 {
return nil
}
out.Yellow(ctx, "Permissions too wide: %s (%s)", filename, fi.Mode().String())
np := uint32(fi.Mode().Perm() & 0600)
out.Green(ctx, " Fixing permissions from %s to %s", fi.Mode().Perm().String(), os.FileMode(np).Perm().String())
if err := syscall.Chmod(filename, np); err != nil {
out.Error(ctx, " Failed to set permissions for %s to rw-------: %s", filename, err)
}
return nil
}
func (s *Store) fsckCheckDir(ctx context.Context, dirname string) error {
fi, err := os.Stat(dirname)
if err != nil {
return err
}
// check if any group or other perms are set,
// i.e. check for perms other than rwx------
if fi.Mode().Perm()&077 != 0 {
out.Yellow(ctx, "Permissions too wide %s on dir %s", fi.Mode().Perm().String(), dirname)
np := uint32(fi.Mode().Perm() & 0700)
out.Green(ctx, " Fixing permissions from %s to %s", fi.Mode().Perm().String(), os.FileMode(np).Perm().String())
if err := syscall.Chmod(dirname, np); err != nil {
out.Error(ctx, " Failed to set permissions for %s to rwx------: %s", dirname, err)
}
}
// check for empty folders
isEmpty, err := fsutil.IsEmptyDir(dirname)
if err != nil {
return err
}
if isEmpty {
out.Error(ctx, "Folder %s is empty. Removing", dirname)
return os.Remove(dirname)
}
return nil
}