summaryrefslogtreecommitdiff
path: root/fsck.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2018-04-01 21:23:32 +0200
committerJakob Unterwurzacher2018-04-02 16:38:18 +0200
commitf28d85fad599ffaef9a8e1f353911c81a6605d2f (patch)
tree1acc3514a5dde31e88ad13e8dc48818872e40d0f /fsck.go
parentfb06c65ee90e31d11cf37b3469f7d3336ae51184 (diff)
fsck: add initial implementation
Most corruption cases except xattr should be covered. With test filesystem. The output is still pretty ugly. xattr support will be added in the next commits.
Diffstat (limited to 'fsck.go')
-rw-r--r--fsck.go99
1 files changed, 97 insertions, 2 deletions
diff --git a/fsck.go b/fsck.go
index 645cf91..7741d19 100644
--- a/fsck.go
+++ b/fsck.go
@@ -1,9 +1,104 @@
package main
import (
- "log"
+ "fmt"
+ "os"
+ "path/filepath"
+ "syscall"
+
+ "github.com/hanwen/go-fuse/fuse"
+
+ "github.com/rfjakob/gocryptfs/internal/exitcodes"
+ "github.com/rfjakob/gocryptfs/internal/fusefrontend"
+ "github.com/rfjakob/gocryptfs/internal/tlog"
)
+type fsckObj struct {
+ fs *fusefrontend.FS
+ errorCount int
+}
+
+// Recursively check dir for corruption
+func (ck *fsckObj) dir(path string) {
+ //fmt.Printf("ck.dir %q\n", path)
+ entries, status := ck.fs.OpenDir(path, nil)
+ if !status.Ok() {
+ fmt.Printf("fsck: error opening dir %q: %v\n", path, status)
+ ck.errorCount++
+ return
+ }
+ for _, entry := range entries {
+ if entry.Name == "." || entry.Name == ".." {
+ continue
+ }
+ nextPath := filepath.Join(path, entry.Name)
+ filetype := entry.Mode & syscall.S_IFMT
+ //fmt.Printf(" %q %x\n", entry.Name, entry.Mode)
+ switch filetype {
+ case syscall.S_IFDIR:
+ ck.dir(nextPath)
+ case syscall.S_IFREG:
+ ck.file(nextPath)
+ case syscall.S_IFLNK:
+ ck.symlink(nextPath)
+ case syscall.S_IFIFO, syscall.S_IFSOCK, syscall.S_IFBLK, syscall.S_IFCHR:
+ // nothing to check
+ default:
+ fmt.Printf("fsck: unhandle file type %x\n", filetype)
+ }
+ }
+}
+
+func (ck *fsckObj) symlink(path string) {
+ _, status := ck.fs.Readlink(path, nil)
+ if !status.Ok() {
+ fmt.Printf("fsck: error reading symlink %q: %v\n", path, status)
+ ck.errorCount++
+ }
+}
+
+// check file for corruption
+func (ck *fsckObj) file(path string) {
+ //fmt.Printf("ck.file %q\n", path)
+ f, status := ck.fs.Open(path, syscall.O_RDONLY, nil)
+ if !status.Ok() {
+ fmt.Printf("fsck: error opening file %q: %v\n", path, status)
+ ck.errorCount++
+ return
+ }
+ defer f.Release()
+ buf := make([]byte, fuse.MAX_KERNEL_WRITE)
+ var off int64
+ for {
+ result, status := f.Read(buf, off)
+ if !status.Ok() {
+ fmt.Printf("fsck: error reading file %q at offset %d: %v\n", path, off, status)
+ ck.errorCount++
+ return
+ }
+ // EOF
+ if result.Size() == 0 {
+ return
+ }
+ off += int64(result.Size())
+ }
+}
+
func fsck(args *argContainer) {
- log.Panic("Not yet implemented")
+ if args.reverse {
+ tlog.Fatal.Printf("Running -fsck with -reverse is not supported")
+ os.Exit(exitcodes.Usage)
+ }
+ args.allow_other = false
+ pfs, wipeKeys := initFuseFrontend(args)
+ defer wipeKeys()
+ fs := pfs.(*fusefrontend.FS)
+ ck := fsckObj{
+ fs: fs,
+ }
+ ck.dir("")
+ fmt.Printf("fsck: found %d problems\n", ck.errorCount)
+ if ck.errorCount != 0 {
+ os.Exit(exitcodes.FsckErrors)
+ }
}