Skip to content

Instantly share code, notes, and snippets.

@charlieegan3
Created August 24, 2020 09:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save charlieegan3/ad144b6126d65b42325910267098f8f0 to your computer and use it in GitHub Desktop.
Save charlieegan3/ad144b6126d65b42325910267098f8f0 to your computer and use it in GitHub Desktop.
Dropbox Content Hash
package dropbox
import (
"crypto/sha256"
"fmt"
"os"
"github.com/pkg/errors"
)
// ContentHash performs the dropbox content hash sum for a file on disk
func ContentHash(path string) (string, error) {
file, err := os.Open(path)
if err != nil {
return "", errors.Wrap(err, "failed to open the file for reading")
}
defer file.Close()
fi, err := file.Stat()
if err != nil {
return "", errors.Wrap(err, "failed to check the size of the file")
}
remainingBytes := fi.Size()
blockSize := int64(4 * 1024 * 1024)
// bytes from the shasums of each block
blockSHABytes := []byte{}
for {
// bytes to read this time round
bytesToRead := remainingBytes
// don't read more than a block
if bytesToRead > blockSize {
bytesToRead = blockSize
}
// read that number of bytes
byteSlice := make([]byte, bytesToRead)
bytesRead, err := file.Read(byteSlice)
if err != nil {
return "", errors.Wrap(err, "failed to read block of bytes from file")
}
// update the remainingBytes, less the bytes we just read
remainingBytes -= int64(bytesRead)
// compute the shasum bytes for that block
shaData := sha256.Sum256(byteSlice)
// append the shasum bytes to the shasum bytes for the other blocks
blockSHABytes = append(blockSHABytes, shaData[:]...)
// exit if we don't need to read another block
if int64(bytesRead) < blockSize {
break
}
}
// return a hex formatted string of the concatenated shasums, shasummed again
return fmt.Sprintf("%x", sha256.Sum256(blockSHABytes)), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment