func (a *acdb) walk(path string, info os.FileInfo, errIn error) error { a.Log(acd.DebugLoud, "[TRC] walk") if errIn != nil { fmt.Printf("skipping %v error: %v\n", path, errIn) return nil } var ( payload []byte digest *[sha256.Size]byte err error ) switch { case info.Mode()&os.ModeDir == os.ModeDir: // dir err = a.me.Dir(path, info) if err != nil { break } case info.Mode()&os.ModeSymlink == os.ModeSymlink: // symlink err = a.me.Symlink(path, info) if err != nil { break } case info.Mode().IsRegular() && info.Size() == 0: // zero sized file err = a.me.File(path, info, "", nil) if err != nil { break } case info.Mode().IsRegular(): // regular file // external pointer AND digest digest, err = goutil.FileHMACSHA256(path, a.keys.Dedup[:]) if err != nil { break } payload, err = shared.FileNaClEncrypt(path, a.compress, &a.keys.Data) if err != nil { break } mime, _, err := goutil.FileCompressible(path) if err != nil { break } err = a.me.File(path, info, mime, digest) if err != nil { break } default: fmt.Printf("skipping %v: unsuported file type\n", path) return nil } if err != nil { fmt.Printf("skipping %v: %v\n", path, err) return nil } var d, ds string if digest != nil { d = hex.EncodeToString(digest[:]) } if digest != nil { asset, err := a.c.UploadJSON(a.dataID, d, payload) if err != nil { if e, ok := acd.IsCombinedError(err); ok { if e.StatusCode != http.StatusConflict { fmt.Printf("skipping %v: %v\n", path, err) return nil } ds += " deduped " } else { fmt.Printf("should not happen %T: %v\n", err, err) return nil } } else { ds += " new " } _ = asset } if a.verbose { if digest != nil { ds += "=> " + d } fmt.Printf("%v %15v %v%v\n", info.Mode(), info.Size(), path, ds) } return nil }
func FileNaClEncrypt(filename string, compress bool, key *[KeySize]byte) ([]byte, error) { fd, err := goutil.FileSHA256(filename) if err != nil { return nil, err } // test compressible var comp bool payloadHeader := Header{ Version: Version, Digest: *fd, Compression: CompNone, } payloadHeader.MimeType, comp, err = goutil.FileCompressible(filename) if err != nil { return nil, err } if compress { if comp { payloadHeader.Compression = CompGZIP } } else { comp = false } // set up reader f, err := os.Open(filename) if err != nil { return nil, err } defer func() { _ = f.Close() }() fi, err := f.Stat() if err != nil { return nil, err } payloadHeader.Size = uint64(fi.Size()) // encode payload [nonce][blob] var payload bytes.Buffer pw := bufio.NewWriter(&payload) // nonce nonce, err := NaClNonce() if err != nil { return nil, err } _, err = pw.Write(nonce[:]) if err != nil { return nil, err } // create payload var b bytes.Buffer // can't encode directly into b because of appended 0x0a _, err = xdr.Marshal(&b, payloadHeader) if err != nil { return nil, err } var w io.Writer if comp { // per https://github.com/klauspost/pgzip use pgzip on > 1MB if fi.Size() > 1024*1024 { w = pgzip.NewWriter(&b) } else { w = gzip.NewWriter(&b) } } else { w = bufio.NewWriter(&b) } // file content _, err = io.Copy(w, f) if err != nil { return nil, err } _, ok := w.(io.WriteCloser) if ok { w.(io.WriteCloser).Close() } else { w.(*bufio.Writer).Flush() } // encrypt encryptedPayload := secretbox.Seal(nil, b.Bytes(), nonce, key) // append encryptedPayload to payload pw.Write(encryptedPayload) pw.Flush() return payload.Bytes(), nil }