Skip to content

Commit

Permalink
Add program
Browse files Browse the repository at this point in the history
  • Loading branch information
lotusirous committed Dec 13, 2021
1 parent b04e5b4 commit 66ea699
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 1 deletion.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
# fp
# FP

A filepath utility

```
$ fp
usage: fp [file or directory]
Flags:
-v print the file hash in (md5, sha1, sha256)
```
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/lotusirous/fp

go 1.17
12 changes: 12 additions & 0 deletions goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
env:
- GO111MODULE=on
before:
hooks:
- go mod download
- go mod tidy
builds:
- env:
- CGO_ENABLED=0
goos: [darwin, linux]
goarch: [386, arm, amd64, arm64]
mod_timestamp: '{{ .CommitTimestamp }}'
105 changes: 105 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package main

import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
"errors"
"flag"
"fmt"
"hash"
"io"
"os"
"path/filepath"
)

// Digest hashes a file for a given path
func Digest(h hash.Hash, loc string) (string, error) {
file, err := os.Open(loc)
if err != nil {
return "", err
}
defer file.Close()

buf := make([]byte, 1024)
if _, err := io.CopyBuffer(h, file, buf); err != nil {
return "", err
}

return hex.EncodeToString(h.Sum(nil)), nil
}

// ReadFileInfo gets the abs path and follows the link
func ReadFileInfo(path string) (string, os.FileInfo, error) {
abs, err := filepath.Abs(path)
if err != nil {
return "", nil, err
}
linkAbs, err := filepath.EvalSymlinks(abs)
if err != nil {
return "", nil, err
}
fi, err := os.Stat(linkAbs)
if errors.Is(err, os.ErrNotExist) {
return "", nil, err
} else if err != nil {
return "", nil, err
}

return linkAbs, fi, nil
}

func usage() {
fmt.Fprintf(os.Stderr, "usage: fp [file or directory]\n")
fmt.Fprintf(os.Stderr, "Flags:\n")
flag.PrintDefaults()
os.Exit(2)
}

func exit(w io.Writer, a ...interface{}) {
fmt.Fprintln(w, a...)
os.Exit(1)
}

var (
verbose = flag.Bool("v", false, `print the file hash in (md5, sha1, sha256)`)
)

func main() {
flag.Usage = usage
flag.Parse()
if flag.NArg() == 0 {
flag.Usage()
}

fd := os.Stdout // default writer
path := flag.Arg(0)

abs, fi, err := ReadFileInfo(path)
if err != nil {
exit(fd, "Cannot resolve the path: ", err)
}

fmt.Fprintf(fd, "PATH: %s\n", abs)
if fi.IsDir() {
os.Exit(0)
}

if *verbose {
hashes := map[string]hash.Hash{
"MD5": md5.New(),
"SHA1": sha1.New(),
"SHA256": sha256.New(),
}
for name, hf := range hashes {
if v, err := Digest(hf, abs); err != nil {
fmt.Fprintf(fd, "Cannot digest %s: %v", name, err)
os.Exit(1)
} else {
fmt.Fprintf(fd, "%s: %s\n", name, v)
}
}
}

}

0 comments on commit 66ea699

Please sign in to comment.