aboutsummaryrefslogtreecommitdiff
path: root/fsck.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2018-04-03 21:19:44 +0200
committerJakob Unterwurzacher2018-04-03 21:24:48 +0200
commit4e5783591f9874e2c7336598c96ebd2c5840bd5b (patch)
tree589e9381ad3868eb1eb7dc384fdca4c18cda901b /fsck.go
parent8b443c8484f5fdcedbec2a689a7d66d2a277b26e (diff)
fsck: report skipped corrupt files
OpenDir and ListXAttr skip over corrupt entries, readFileID treats files the are too small as empty. This improves usability in the face of corruption, but hides the problem in a log message instead of putting it in the return code. Create a channel to report these corruptions to fsck so it can report them to the user. Also update the manpage and the changelog with the -fsck option. Closes https://github.com/rfjakob/gocryptfs/issues/191
Diffstat (limited to 'fsck.go')
-rw-r--r--fsck.go52
1 files changed, 47 insertions, 5 deletions
diff --git a/fsck.go b/fsck.go
index 9eff72e..d1dc7e5 100644
--- a/fsck.go
+++ b/fsck.go
@@ -6,6 +6,7 @@ import (
"path/filepath"
"sort"
"strings"
+ "sync"
"syscall"
"github.com/hanwen/go-fuse/fuse"
@@ -19,17 +20,34 @@ type fsckObj struct {
fs *fusefrontend.FS
// List of corrupt files
corruptList []string
+ // Protects corruptList
+ corruptListLock sync.Mutex
}
func (ck *fsckObj) markCorrupt(path string) {
+ ck.corruptListLock.Lock()
ck.corruptList = append(ck.corruptList, path)
+ ck.corruptListLock.Unlock()
}
// Recursively check dir for corruption
func (ck *fsckObj) dir(path string) {
//fmt.Printf("ck.dir %q\n", path)
ck.xattrs(path)
+ done := make(chan struct{})
+ go func() {
+ for {
+ select {
+ case item := <-ck.fs.CorruptItems:
+ fmt.Printf("fsck: corrupt entry in dir %q: %q\n", path, item)
+ ck.markCorrupt(filepath.Join(path, item))
+ case <-done:
+ return
+ }
+ }
+ }()
entries, status := ck.fs.OpenDir(path, nil)
+ done <- struct{}{}
if !status.Ok() {
ck.markCorrupt(path)
fmt.Printf("fsck: error opening dir %q: %v\n", path, status)
@@ -80,6 +98,19 @@ func (ck *fsckObj) file(path string) {
defer f.Release()
buf := make([]byte, fuse.MAX_KERNEL_WRITE)
var off int64
+ done := make(chan struct{})
+ go func() {
+ for {
+ select {
+ case item := <-ck.fs.CorruptItems:
+ fmt.Printf("fsck: corrupt file %q (inode %s)\n", path, item)
+ ck.markCorrupt(path)
+ case <-done:
+ return
+ }
+ }
+ }()
+ defer func() { done <- struct{}{} }()
for {
result, status := f.Read(buf, off)
if !status.Ok() {
@@ -97,7 +128,20 @@ func (ck *fsckObj) file(path string) {
// Check xattrs on file/dir at path
func (ck *fsckObj) xattrs(path string) {
+ done := make(chan struct{})
+ go func() {
+ for {
+ select {
+ case item := <-ck.fs.CorruptItems:
+ fmt.Printf("fsck: corrupt xattr name on file %q: %q\n", path, item)
+ ck.markCorrupt(path + " xattr:" + item)
+ case <-done:
+ return
+ }
+ }
+ }()
attrs, status := ck.fs.ListXAttr(path, nil)
+ done <- struct{}{}
if !status.Ok() {
fmt.Printf("fsck: error listing xattrs on %q: %v\n", path, status)
ck.markCorrupt(path)
@@ -120,19 +164,17 @@ func fsck(args *argContainer) {
args.allow_other = false
pfs, wipeKeys := initFuseFrontend(args)
fs := pfs.(*fusefrontend.FS)
+ fs.CorruptItems = make(chan string)
ck := fsckObj{
fs: fs,
}
ck.dir("")
wipeKeys()
if len(ck.corruptList) == 0 {
- fmt.Printf("fsck summary: no problems found")
+ fmt.Printf("fsck summary: no problems found\n")
return
}
- fmt.Printf("fsck summary: found %d corrupt files:\n", len(ck.corruptList))
- for _, path := range ck.corruptList {
- fmt.Printf(" %q\n", path)
- }
+ fmt.Printf("fsck summary: %d corrupt files\n", len(ck.corruptList))
os.Exit(exitcodes.FsckErrors)
}