-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommon.go
119 lines (99 loc) · 1.84 KB
/
common.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package main
import (
"crypto/md5"
"fmt"
"io"
"net/url"
"os"
)
const DATE_FMT = "2006-01-02 15:04"
type FileType string
const (
BYTE = 1 << (10 * iota)
KB
MB
GB
TB
)
const (
DIR FileType = "DIR"
FILE FileType = "FILE"
)
type S3Path struct {
Scheme string
Bucket string
Path string
}
type FileInfo struct {
Path string
Etag string
Type FileType
}
func NewS3Path(path string) (*S3Path, error) {
u, err := url.Parse(path)
if err != nil {
return nil, err
}
if u.Scheme != "s3" {
return nil, fmt.Errorf("Invalid URI scheme must be s3://")
}
uri := S3Path{
Scheme: u.Scheme,
Bucket: u.Host,
Path: u.Path,
}
if uri.Scheme == "s3" && uri.Path != "" {
uri.Path = uri.Path[1:]
}
return &uri, nil
}
func AmazonEtagHash(path string) (string, error) {
const BLOCK_SIZE = 1024 * 1024 * 5 // 5MB
const START_BLOCKS = 1024 * 1024 * 16 // 16MB
fd, err := os.Open(path)
if err != nil {
return "", err
}
defer fd.Close()
info, err := fd.Stat()
if err != nil {
return "", err
}
hasher := md5.New()
count := 0
if info.Size() > START_BLOCKS {
for err != io.EOF {
count += 1
parthasher := md5.New()
var size int64
size, err = io.CopyN(parthasher, fd, BLOCK_SIZE)
if err != nil && err != io.EOF {
return "", err
}
if size != 0 {
hasher.Write(parthasher.Sum(nil))
}
}
} else {
if _, err := io.Copy(hasher, fd); err != nil {
return "", err
}
}
hash := fmt.Sprintf("%x", hasher.Sum(nil))
if count != 0 {
hash += fmt.Sprintf("-%d", count)
}
return hash, nil
}
func HumanReadByteSize(size float64) string {
if size > TB {
return fmt.Sprintf("%fT", size/TB)
} else if size > GB {
return fmt.Sprintf("%fG", size/GB)
} else if size > MB {
return fmt.Sprintf("%fM", size/MB)
} else if size > KB {
return fmt.Sprintf("%fKB", size/KB)
}
return fmt.Sprintf("%fB", size)
}