2020-09-29 00:34:16 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2020-10-01 13:00:15 +00:00
|
|
|
"bufio"
|
2020-09-29 00:34:16 +00:00
|
|
|
"crypto/sha256"
|
|
|
|
"fmt"
|
2020-10-01 13:00:15 +00:00
|
|
|
"io"
|
2020-09-30 12:56:20 +00:00
|
|
|
"io/ioutil"
|
2020-09-29 00:34:16 +00:00
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
)
|
|
|
|
|
|
|
|
const blobByteLimit = 360_000
|
|
|
|
|
2020-09-30 12:56:20 +00:00
|
|
|
func pathAndFilename(mhash string) (dirPath string, fileName string) {
|
2020-09-29 00:34:16 +00:00
|
|
|
validateMhash(mhash)
|
|
|
|
b32 := mhash[len(BlobSigil):]
|
2020-09-30 12:56:20 +00:00
|
|
|
pathChunks := []string{
|
2020-09-29 00:34:16 +00:00
|
|
|
b32[0:7],
|
|
|
|
b32[7:14],
|
|
|
|
b32[14:21],
|
|
|
|
b32[21:28],
|
|
|
|
b32[28:35],
|
|
|
|
b32[35:42],
|
|
|
|
}
|
2020-09-30 12:56:20 +00:00
|
|
|
|
|
|
|
f := fmt.Sprintf("%s.%s", b32[42:49], b32[49:52])
|
|
|
|
p := path.Join(pigeonBlobDir(), path.Join(pathChunks...))
|
|
|
|
return p, f
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a set of nested set of directories to place a blob
|
|
|
|
// as outlined in bundle spec.
|
|
|
|
func createBlobDirectory(mhash string) string {
|
|
|
|
dirPath, fileName := pathAndFilename(mhash)
|
|
|
|
err := os.MkdirAll(dirPath, 0700)
|
|
|
|
if err != nil {
|
|
|
|
panicf("createBlobDirectory: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return path.Join(dirPath, fileName)
|
2020-09-29 00:34:16 +00:00
|
|
|
}
|
|
|
|
|
2020-11-08 01:29:36 +00:00
|
|
|
// func fileExists(filename string) bool {
|
|
|
|
// info, err := os.Stat(filename)
|
|
|
|
// if os.IsNotExist(err) {
|
|
|
|
// return false
|
|
|
|
// }
|
|
|
|
// return !info.IsDir()
|
|
|
|
// }
|
|
|
|
|
|
|
|
// func blobExists(mhash string) bool {
|
|
|
|
// return fileExists(createBlobDirectory(mhash))
|
|
|
|
// }
|
|
|
|
|
|
|
|
func addBlob(mhash string, data []byte) string {
|
2020-09-29 00:34:16 +00:00
|
|
|
size := len(data)
|
|
|
|
if size > blobByteLimit {
|
|
|
|
panicf("Expected blob smaller than %d. Got: %d", blobByteLimit, size)
|
|
|
|
}
|
2020-09-30 12:56:20 +00:00
|
|
|
blobPath := createBlobDirectory(mhash)
|
|
|
|
write(blobPath, data)
|
2020-10-01 13:00:15 +00:00
|
|
|
return mhash
|
|
|
|
}
|
|
|
|
|
|
|
|
func addBlobFromPipe() string {
|
|
|
|
reader := bufio.NewReader(os.Stdin)
|
|
|
|
var output []byte
|
|
|
|
|
|
|
|
for {
|
|
|
|
input, err := reader.ReadByte()
|
|
|
|
if err != nil && err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
output = append(output, input)
|
|
|
|
}
|
|
|
|
|
2020-11-08 01:29:36 +00:00
|
|
|
return addBlob(getMhashForBytes(output), output)
|
2020-09-29 00:34:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func write(path string, data []byte) {
|
|
|
|
// Open a new file for writing only
|
|
|
|
file, err := os.OpenFile(
|
|
|
|
path,
|
|
|
|
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
|
|
|
0600,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
_, err2 := file.Write(data)
|
|
|
|
if err2 != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-08 01:29:36 +00:00
|
|
|
func getSha256(data []byte) []byte {
|
|
|
|
h := sha256.New()
|
|
|
|
h.Write(data)
|
|
|
|
return h.Sum(nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func getMhashForBytes(data []byte) string {
|
|
|
|
return encodeBlobMhash(getSha256(data))
|
|
|
|
}
|
|
|
|
|
|
|
|
/* getMhashForFile Returns the mHash and data for a path. */
|
|
|
|
func getMhashForFile(path string) (string, []byte) {
|
|
|
|
data, err := ioutil.ReadFile(path)
|
|
|
|
check(err, "Can't open %s", path)
|
|
|
|
return getMhashForBytes(data), data
|
|
|
|
}
|