diff --git a/main.go b/main.go index f19164c..d749517 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,15 @@ +//3456789112345676892123456789312345678941234567895123456789612345678971234567898 + package main -//import "crypto/sha256" +import "crypto/sha256" import "fmt" import "github.com/sirupsen/logrus" - -//import "github.com/pkg/xattr" -import "hash" +import "github.com/multiformats/go-multihash" +import "github.com/mr-tron/base58" +import "github.com/pkg/xattr" import "os" +import "io" import "flag" import "time" @@ -16,6 +19,16 @@ var Builduser string var Buildarch string var log *logrus.Logger +const namespacePrefix = "berlin.sneak.xsum" + +//FIXME(sneak) make this parallelize to NUM_CPUS when processing multiple +//args + +//FIXME(sneak) add a -r (recursive) flag for directories + +//FIXME(sneak) make checking support reading hash algo type from multihash +//instead of assumming sha256 + func main() { os.Exit(xsum()) } @@ -40,11 +53,9 @@ func xsum() int { ) paths := flag.Args() - fmt.Printf("%+v\n", paths) if len(paths) > 1 { paths = paths[1:] } - fmt.Printf("%+v\n", paths) switch flag.Arg(0) { case "cron": return xsfCheckAndUpdate(paths) @@ -67,20 +78,21 @@ func usage() { func xsfCheck(paths []string) int { log.Debugf("check") + log.Fatalf("not implemented") return 0 } -func showError(e *error) { +func showError(e error) { fmt.Fprintf(os.Stderr, "error: %s\n", e) } func xsfUpdate(paths []string) int { log.Debugf("update") for _, path := range paths { - x := NewXsf(path) + x := newXsf(path) err := x.Update() if err != nil { - showError(&err) + showError(err) return -1 } } @@ -96,17 +108,89 @@ func xsfCheckAndUpdate(paths []string) int { return xsfUpdate(paths) } +func HashFile(fp *os.File) (string, error) { + h := sha256.New() + + if _, err := io.Copy(h, fp); err != nil { + return "", err + } + + mHashBuf, err := multihash.EncodeName(h.Sum(nil), "sha1") + + if err != nil { + return "", err + } + + return base58.Encode(mHashBuf), nil +} + +///////////////////////////////////////////////////////////////////////////////// +// type xsf +///////////////////////////////////////////////////////////////////////////////// + type xsf struct { - path string - mtime *time.Time - size int64 - sum *hash.Hash fi *os.FileInfo + fp *os.File + hash string + mtime string + path string + size int64 +} + +///////////////////////////////////////////////////////////////////////////////// +// constructor +///////////////////////////////////////////////////////////////////////////////// + +type xsf struct { + fi *os.FileInfo + fp *os.File + hash string + mtime string + path string + size int64 +} + +func newXsf(path string) *xsf { + x := xsf{} + x.path = path + return &x +} + +func (x *xsf) writeXattrs(fp *os.File) error { + log.Infof("writing xattrs") + + var xn string + var err error + + xn = fmt.Sprintf("%s.%s", namespacePrefix, "mtime") + log.Infof("writing xattr %s=%s", xn, x.mtime) + err = xattr.FSet(fp, xn, []byte(x.mtime)) + if err != nil { + return err + } + + xn = fmt.Sprintf("%s.%s", namespacePrefix, "size") + log.Infof("writing xattr %s=%s", xn, fmt.Sprintf("%d", x.size)) + err = xattr.FSet(fp, xn, []byte(fmt.Sprintf("%d", x.size))) + if err != nil { + return err + } + + xn = fmt.Sprintf("%s.%s", namespacePrefix, "multihash") + log.Infof("writing xattr %s=%s", xn, x.hash) + err = xattr.FSet(fp, xn, []byte(x.hash)) + if err != nil { + return err + } + + return nil } func (x *xsf) Update() error { fp, e1 := os.Open(x.path) defer fp.Close() + log.Infof("updating file") + log.Debugf("path: %s", x.path) if e1 != nil { return e1 } @@ -116,13 +200,24 @@ func (x *xsf) Update() error { return e2 } x.size = fi.Size() - t := fi.ModTime() - x.mtime = &t + log.Debugf("size: %d", x.size) + t := fi.ModTime().UTC().Format(time.RFC3339) + log.Debugf("modtime: %s", t) + x.mtime = t + + log.Debugf("hashing...") + h, e3 := HashFile(fp) + if e3 != nil { + return e3 + } + x.hash = h + log.Debugf("hash: %s", h) + + e4 := x.writeXattrs(fp) + + if e4 != nil { + return e4 + } + return nil } - -func NewXsf(path string) *xsf { - x := xsf{} - x.path = path - return &x -}