Skip to content

Instantly share code, notes, and snippets.

@plavjanik
Created August 30, 2022 14:33
Show Gist options
  • Save plavjanik/ffb611e87affe7c8cc7744025d14cb91 to your computer and use it in GitHub Desktop.
Save plavjanik/ffb611e87affe7c8cc7744025d14cb91 to your computer and use it in GitHub Desktop.
md5sum in Golang
package main
import (
"crypto/md5"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"
)
func main() {
if len(os.Args) < 2 {
help()
} else if os.Args[1] == "-h" || os.Args[1] == "--help" {
help()
} else if os.Args[1] == "-c" || os.Args[1] == "--check" {
if len(os.Args) == 2 {
help()
}
checkHashesInFile(os.Args[2])
} else {
determineHashForFile(os.Args[1:])
}
}
func checkHashesInFile(argFile string) {
md5bytes, err := ioutil.ReadFile(argFile)
if err != nil {
error(fmt.Sprintf("failed to read file %s: %v", argFile, err))
}
splitBySpace := regexp.MustCompile(`\s+`)
failedFiles := 0
totalFiles := 0
for _, line := range strings.Split(strings.TrimSuffix(string(md5bytes), "\n"), "\n") {
columns := splitBySpace.Split(string(line), -1)
if len(columns) != 2 {
error(fmt.Sprintf("could not parse check file: each line should have two columns 'md5_hash file_name' but it is: '%s'", line))
}
argPath := filepath.Dir(argFile)
fullPath := ""
if len(argPath) > 0 {
fullPath = argPath + string(filepath.Separator)
}
fullPath += columns[1]
md5sum := md5hash(fullPath)
if md5sum == columns[0] {
fmt.Printf("%s: OK\n", columns[1])
} else {
fmt.Printf("%s: FAILED\n", columns[1])
failedFiles += 1
}
totalFiles += 1
}
if failedFiles > 0 {
fmt.Printf("md5sum: WARNING: %d of %d computed checksums did NOT match\n", failedFiles, totalFiles)
os.Exit(1)
}
}
func determineHashForFile(files []string) {
for _, arg := range files {
md5sum := md5hash(arg)
fmt.Printf("%s %s\n", md5sum, filepath.Base(arg))
}
}
func md5hash(file string) string {
f, err := os.Open(file)
if err != nil {
error(fmt.Sprintf("failed to open file for read: %v", err))
}
defer f.Close()
h := md5.New()
if _, err := io.Copy(h, f); err != nil {
error(fmt.Sprintf("failed to process file content with MD5 hashing function: %v", err))
}
return fmt.Sprintf("%x", h.Sum(nil))
}
func help() {
fmt.Println("Usage: md5sum [<option>] <file> [<file> [...] ]")
fmt.Println(" md5sum [<option>] --check <file>")
fmt.Println()
fmt.Println(" -c, --check <file> Check MD5 sums from <file>")
fmt.Println(" -h, --help Display this help message and exit")
fmt.Println()
}
func error(errMsg string) {
fmt.Println("Error:", errMsg)
os.Exit(1)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment