コード例 #1
0
ファイル: acdbackup.go プロジェクト: jcvernaleo/acdb
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
}
コード例 #2
0
ファイル: shared.go プロジェクト: jcvernaleo/acdb
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
}