diff options
author | Jakob Unterwurzacher | 2018-04-03 21:19:44 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2018-04-03 21:24:48 +0200 |
commit | 4e5783591f9874e2c7336598c96ebd2c5840bd5b (patch) | |
tree | 589e9381ad3868eb1eb7dc384fdca4c18cda901b /internal | |
parent | 8b443c8484f5fdcedbec2a689a7d66d2a277b26e (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 'internal')
-rw-r--r-- | internal/fusefrontend/file.go | 2 | ||||
-rw-r--r-- | internal/fusefrontend/fs.go | 18 | ||||
-rw-r--r-- | internal/fusefrontend/fs_dir.go | 2 | ||||
-rw-r--r-- | internal/fusefrontend/xattr.go | 1 |
4 files changed, 23 insertions, 0 deletions
diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go index af13170..72319e9 100644 --- a/internal/fusefrontend/file.go +++ b/internal/fusefrontend/file.go @@ -4,6 +4,7 @@ package fusefrontend import ( "bytes" + "fmt" "io" "log" "os" @@ -99,6 +100,7 @@ func (f *file) readFileID() ([]byte, error) { if err == io.EOF && n != 0 { tlog.Warn.Printf("readFileID %d: incomplete file, got %d instead of %d bytes", f.qIno.Ino, n, readLen) + f.fs.reportCorruptItem(fmt.Sprint(f.qIno.Ino)) } return nil, err } diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go index 5f84541..8a3935f 100644 --- a/internal/fusefrontend/fs.go +++ b/internal/fusefrontend/fs.go @@ -38,6 +38,11 @@ type FS struct { // This lock is used by openWriteOnlyFile() to block concurrent opens while // it relaxes the permissions on a file. openWriteOnlyLock sync.RWMutex + // CorruptItems is filled with file or xattr names that have been + // skipped (ignored) because they were corrupt. This is used by fsck + // to inform the user. + // Use the reportCorruptItem() function to push an item. + CorruptItems chan string } var _ pathfs.FileSystem = &FS{} // Verify that interface is implemented. @@ -601,3 +606,16 @@ func (fs *FS) Access(path string, mode uint32, context *fuse.Context) (code fuse } return fuse.ToStatus(syscall.Access(cPath, mode)) } + +func (fs *FS) reportCorruptItem(item string) { + if fs.CorruptItems == nil { + return + } + select { + case fs.CorruptItems <- item: + case <-time.After(1 * time.Second): + tlog.Warn.Printf("BUG: reportCorruptItem: timeout") + //debug.PrintStack() + return + } +} diff --git a/internal/fusefrontend/fs_dir.go b/internal/fusefrontend/fs_dir.go index e13afed..089429e 100644 --- a/internal/fusefrontend/fs_dir.go +++ b/internal/fusefrontend/fs_dir.go @@ -326,6 +326,7 @@ func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, f if err != nil { tlog.Warn.Printf("OpenDir %q: invalid entry %q: Could not read .name: %v", cDirName, cName, err) + fs.reportCorruptItem(cName) errorCount++ continue } @@ -338,6 +339,7 @@ func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, f if err != nil { tlog.Warn.Printf("OpenDir %q: invalid entry %q: %v", cDirName, cName, err) + fs.reportCorruptItem(cName) if runtime.GOOS == "darwin" && cName == dsStoreName { // MacOS creates lots of these files. Log the warning but don't // increment errorCount - does not warrant returning EIO. diff --git a/internal/fusefrontend/xattr.go b/internal/fusefrontend/xattr.go index 1d628b7..faaebd4 100644 --- a/internal/fusefrontend/xattr.go +++ b/internal/fusefrontend/xattr.go @@ -115,6 +115,7 @@ func (fs *FS) ListXAttr(path string, context *fuse.Context) ([]string, fuse.Stat name, err := fs.decryptXattrName(curName) if err != nil { tlog.Warn.Printf("ListXAttr: invalid xattr name %q: %v", curName, err) + fs.reportCorruptItem(curName) continue } names = append(names, name) |