Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c45ae7b4e | |||
| c1b8b72cf1 | |||
| bfc7fedbf9 | |||
| 965312f48e | |||
| 237aa46ddd |
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2015 Kyle Isom <kyle@tyrfingr.is>
|
Copyright (c) 2015-2023 Kyle Isom <kyle@tyrfingr.is>
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|||||||
23
README.md
23
README.md
@@ -25,33 +25,46 @@ Contents:
|
|||||||
cruntar/ Untar an archive with hard links, copying instead of
|
cruntar/ Untar an archive with hard links, copying instead of
|
||||||
linking.
|
linking.
|
||||||
csrpubdump/ Dump the public key from an X.509 certificate request.
|
csrpubdump/ Dump the public key from an X.509 certificate request.
|
||||||
|
diskimg/ Write a disk image to a device.
|
||||||
|
eig/ EEPROM image generator.
|
||||||
fragment/ Print a fragment of a file.
|
fragment/ Print a fragment of a file.
|
||||||
jlp/ JSON linter/prettifier.
|
jlp/ JSON linter/prettifier.
|
||||||
kgz/ Custom gzip compressor / decompressor that handles 99%
|
kgz/ Custom gzip compressor / decompressor that handles 99%
|
||||||
of my use cases.
|
of my use cases.
|
||||||
|
parts/ Simple parts database management for my collection of
|
||||||
|
electronic components.
|
||||||
pem2bin/ Dump the binary body of a PEM-encoded block.
|
pem2bin/ Dump the binary body of a PEM-encoded block.
|
||||||
pembody/ Print the body of a PEM certificate.
|
pembody/ Print the body of a PEM certificate.
|
||||||
pemit/ Dump data to a PEM file.
|
pemit/ Dump data to a PEM file.
|
||||||
showimp/ List the external (e.g. non-stdlib and outside the
|
|
||||||
current working directory) imports for a Go file.
|
|
||||||
readchain/ Print the common name for the certificates
|
readchain/ Print the common name for the certificates
|
||||||
in a bundle.
|
in a bundle.
|
||||||
renfnv/ Rename a file to base32-encoded 64-bit FNV-1a hash.
|
renfnv/ Rename a file to base32-encoded 64-bit FNV-1a hash.
|
||||||
rhash/ Compute the digest of remote files.
|
rhash/ Compute the digest of remote files.
|
||||||
showimp Display the external imports in a package.
|
showimp/ List the external (e.g. non-stdlib and outside the
|
||||||
|
current working directory) imports for a Go file.
|
||||||
ski Display the SKI for PEM-encoded TLS material.
|
ski Display the SKI for PEM-encoded TLS material.
|
||||||
|
sprox/ Simple TCP proxy.
|
||||||
stealchain/ Dump the verified chain from a TLS
|
stealchain/ Dump the verified chain from a TLS
|
||||||
connection.
|
connection to a server.
|
||||||
|
stealchain- Dump the verified chain from a TLS
|
||||||
|
server/ connection from a client.
|
||||||
subjhash/ Print or match subject info from a certificate.
|
subjhash/ Print or match subject info from a certificate.
|
||||||
tlskeypair/ Check whether a TLS certificate and key file match.
|
tlskeypair/ Check whether a TLS certificate and key file match.
|
||||||
utc/ Convert times to UTC.
|
utc/ Convert times to UTC.
|
||||||
yamll/ A small YAML linter.
|
yamll/ A small YAML linter.
|
||||||
|
config/ A simple global configuration system where configuration
|
||||||
|
data is pulled from a file or an environment variable
|
||||||
|
transparently.
|
||||||
|
dbg/ A debug printer.
|
||||||
die/ Death of a program.
|
die/ Death of a program.
|
||||||
fileutil/ Common file functions.
|
fileutil/ Common file functions.
|
||||||
lib/ Commonly-useful functions for writing Go programs.
|
lib/ Commonly-useful functions for writing Go programs.
|
||||||
logging/ A logging library.
|
logging/ A logging library.
|
||||||
mwc/ MultiwriteCloser implementation.
|
mwc/ MultiwriteCloser implementation.
|
||||||
|
rand/ Utilities for working with math/rand.
|
||||||
sbuf/ A byte buffer that can be wiped.
|
sbuf/ A byte buffer that can be wiped.
|
||||||
|
seekbuf/ A read-seekable byte buffer.
|
||||||
|
syslog/ Syslog-type logging.
|
||||||
tee/ Emulate tee(1)'s functionality in io.Writers.
|
tee/ Emulate tee(1)'s functionality in io.Writers.
|
||||||
testio/ Various I/O utilities useful during testing.
|
testio/ Various I/O utilities useful during testing.
|
||||||
testutil/ Various utility functions useful during testing.
|
testutil/ Various utility functions useful during testing.
|
||||||
@@ -60,4 +73,4 @@ Contents:
|
|||||||
Each program should have a small README in the directory with more
|
Each program should have a small README in the directory with more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
All code here is licensed under the MIT license.
|
All code here is licensed under the ISC license.
|
||||||
|
|||||||
19
cmd/diskimg/BUILD.bazel
Normal file
19
cmd/diskimg/BUILD.bazel
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "diskimg_lib",
|
||||||
|
srcs = ["main.go"],
|
||||||
|
importpath = "git.wntrmute.dev/kyle/goutils/cmd/diskimg",
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
deps = [
|
||||||
|
"//ahash",
|
||||||
|
"//dbg",
|
||||||
|
"//die",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_binary(
|
||||||
|
name = "diskimg",
|
||||||
|
embed = [":diskimg_lib"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
34
cmd/diskimg/README
Normal file
34
cmd/diskimg/README
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
diskimg: write disk images
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
diskimg [-a algo] [-v] image device
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
-a algo Select the hashing algorithm to use. The default
|
||||||
|
is 'sha256'. Specifying an algorithm of 'list'
|
||||||
|
will print the supported algorithms to standard
|
||||||
|
output and exit with error code 2.
|
||||||
|
-v Enable verbose (debug) output.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
Copying images/server.img to /dev/sda:
|
||||||
|
|
||||||
|
$ sudo diskimg images/server.img /dev/sda
|
||||||
|
|
||||||
|
Write a bladerunner node image to /dev/sda:
|
||||||
|
|
||||||
|
$ sudo diskimg -v ~/code/bladerunner/packer/build/cm4-cnode-ubuntu-22.04.2.img /dev/sda
|
||||||
|
opening image /home/kyle/code/bladerunner/packer/build/cm4-cnode-ubuntu-22.04.2.img for read
|
||||||
|
/home/kyle/code/bladerunner/packer/build/cm4-cnode-ubuntu-22.04.2.img 416d4c8f890904167419e3d488d097e9c847273376b650546fdb1f6f9809c184
|
||||||
|
opening device /dev/sda for rw
|
||||||
|
writing /home/kyle/code/bladerunner/packer/build/cm4-cnode-ubuntu-22.04.2.img -> /dev/sda
|
||||||
|
wrote 4151312384 bytes to /dev/sda
|
||||||
|
syncing /dev/sda
|
||||||
|
verifying the image was written successfully
|
||||||
|
OK
|
||||||
|
|
||||||
|
Motivation:
|
||||||
|
|
||||||
|
I wanted to write something like balena's Etcher, but commandline only.
|
||||||
|
|
||||||
116
cmd/diskimg/main.go
Normal file
116
cmd/diskimg/main.go
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.wntrmute.dev/kyle/goutils/ahash"
|
||||||
|
"git.wntrmute.dev/kyle/goutils/dbg"
|
||||||
|
"git.wntrmute.dev/kyle/goutils/die"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultHashAlgorithm = "sha256"
|
||||||
|
|
||||||
|
var (
|
||||||
|
hAlgo string
|
||||||
|
debug = dbg.New()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func openImage(imageFile string) (image *os.File, hash []byte, err error) {
|
||||||
|
image, err = os.Open(imageFile)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, err = ahash.SumReader(hAlgo, image)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = image.Seek(0, 0)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
debug.Printf("%s %x\n", imageFile, hash)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func openDevice(devicePath string) (device *os.File, err error) {
|
||||||
|
fi, err := os.Stat(devicePath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
device, err = os.OpenFile(devicePath, os.O_RDWR|os.O_SYNC, fi.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.StringVar(&hAlgo, "a", defaultHashAlgorithm, "default hash algorithm")
|
||||||
|
flag.BoolVar(&debug.Enabled, "v", false, "enable debug logging")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if hAlgo == "list" {
|
||||||
|
fmt.Println("Supported hashing algorithms:")
|
||||||
|
for _, algo := range ahash.SecureHashList() {
|
||||||
|
fmt.Printf("\t- %s\n", algo)
|
||||||
|
}
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if flag.NArg() != 2 {
|
||||||
|
die.With("usage: diskimg image device")
|
||||||
|
}
|
||||||
|
|
||||||
|
imageFile := flag.Arg(0)
|
||||||
|
devicePath := flag.Arg(1)
|
||||||
|
|
||||||
|
debug.Printf("opening image %s for read\n", imageFile)
|
||||||
|
image, hash, err := openImage(imageFile)
|
||||||
|
if image != nil {
|
||||||
|
defer image.Close()
|
||||||
|
}
|
||||||
|
die.If(err)
|
||||||
|
|
||||||
|
debug.Printf("opening device %s for rw\n", devicePath)
|
||||||
|
device, err := openDevice(devicePath)
|
||||||
|
if device != nil {
|
||||||
|
defer device.Close()
|
||||||
|
}
|
||||||
|
die.If(err)
|
||||||
|
|
||||||
|
debug.Printf("writing %s -> %s\n", imageFile, devicePath)
|
||||||
|
n, err := io.Copy(device, image)
|
||||||
|
die.If(err)
|
||||||
|
debug.Printf("wrote %d bytes to %s\n", n, devicePath)
|
||||||
|
|
||||||
|
debug.Printf("syncing %s\n", devicePath)
|
||||||
|
err = device.Sync()
|
||||||
|
die.If(err)
|
||||||
|
|
||||||
|
debug.Println("verifying the image was written successfully")
|
||||||
|
_, err = device.Seek(0, 0)
|
||||||
|
die.If(err)
|
||||||
|
|
||||||
|
deviceHash, err := ahash.SumLimitedReader(hAlgo, device, n)
|
||||||
|
die.If(err)
|
||||||
|
|
||||||
|
if !bytes.Equal(deviceHash, hash) {
|
||||||
|
fmt.Fprintln(os.Stderr, "Hash mismatch:")
|
||||||
|
fmt.Fprintf(os.Stderr, "\t%s: %s\n", imageFile, hash)
|
||||||
|
fmt.Fprintf(os.Stderr, "\t%s: %s\n", devicePath, deviceHash)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
debug.Println("OK")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
@@ -9,11 +9,11 @@ go_library(
|
|||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "dbg_test",
|
name = "dbg_test",
|
||||||
|
size = "small",
|
||||||
srcs = ["dbg_test.go"],
|
srcs = ["dbg_test.go"],
|
||||||
embed = [":dbg"],
|
embed = [":dbg"],
|
||||||
deps = [
|
deps = [
|
||||||
"//testio",
|
"//testio",
|
||||||
"@com_github_stretchr_testify//require",
|
"@com_github_stretchr_testify//require",
|
||||||
],
|
],
|
||||||
size = "small",
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -110,8 +110,8 @@ go_library(
|
|||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "lib_test",
|
name = "lib_test",
|
||||||
|
size = "small",
|
||||||
srcs = ["lib_test.go"],
|
srcs = ["lib_test.go"],
|
||||||
embed = [":lib"],
|
embed = [":lib"],
|
||||||
deps = ["//assert"],
|
deps = ["//assert"],
|
||||||
size = "small",
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ go_library(
|
|||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "logging_test",
|
name = "logging_test",
|
||||||
|
size = "small",
|
||||||
srcs = [
|
srcs = [
|
||||||
"example_test.go",
|
"example_test.go",
|
||||||
"log_test.go",
|
"log_test.go",
|
||||||
],
|
],
|
||||||
embed = [":logging"],
|
embed = [":logging"],
|
||||||
size = "small",
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ go_library(
|
|||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "mwc_test",
|
name = "mwc_test",
|
||||||
|
size = "small",
|
||||||
srcs = ["mwc_test.go"],
|
srcs = ["mwc_test.go"],
|
||||||
embed = [":mwc"],
|
embed = [":mwc"],
|
||||||
deps = [
|
deps = [
|
||||||
"//assert",
|
"//assert",
|
||||||
"//testio",
|
"//testio",
|
||||||
],
|
],
|
||||||
size = "small",
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ go_library(
|
|||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "rand_test",
|
name = "rand_test",
|
||||||
|
size = "small",
|
||||||
srcs = ["rand_test.go"],
|
srcs = ["rand_test.go"],
|
||||||
embed = [":rand"],
|
embed = [":rand"],
|
||||||
size = "small",
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ go_library(
|
|||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "sbuf_test",
|
name = "sbuf_test",
|
||||||
|
size = "small",
|
||||||
srcs = ["sbuf_test.go"],
|
srcs = ["sbuf_test.go"],
|
||||||
embed = [":sbuf"],
|
embed = [":sbuf"],
|
||||||
deps = ["@org_golang_x_crypto//nacl/box"],
|
deps = ["@org_golang_x_crypto//nacl/box"],
|
||||||
size = "small",
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "seekbuf",
|
name = "seekbuf",
|
||||||
@@ -6,3 +6,11 @@ go_library(
|
|||||||
importpath = "git.wntrmute.dev/kyle/goutils/seekbuf",
|
importpath = "git.wntrmute.dev/kyle/goutils/seekbuf",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "seekbuf_test",
|
||||||
|
srcs = ["seekbuf_test.go"],
|
||||||
|
embed = [":seekbuf"],
|
||||||
|
deps = ["//assert"],
|
||||||
|
size = "small"
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// seekbuf implements a read-seekable buffer.
|
||||||
package seekbuf
|
package seekbuf
|
||||||
|
|
||||||
import "io"
|
import "io"
|
||||||
@@ -40,7 +41,7 @@ func (b *Buffer) Seek(pos int) {
|
|||||||
|
|
||||||
// Rewind resets the read pointer to 0.
|
// Rewind resets the read pointer to 0.
|
||||||
func (b *Buffer) Rewind() {
|
func (b *Buffer) Rewind() {
|
||||||
b.pos = 0
|
b.Seek(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close clears all the data out of the buffer and sets the read position to 0.
|
// Close clears all the data out of the buffer and sets the read position to 0.
|
||||||
@@ -49,3 +50,8 @@ func (b *Buffer) Close() error {
|
|||||||
b.pos = 0
|
b.pos = 0
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Len returns the length of data remaining to be read.
|
||||||
|
func (b *Buffer) Len() int {
|
||||||
|
return len(b.data[b.pos:])
|
||||||
|
}
|
||||||
|
|||||||
39
seekbuf/seekbuf_test.go
Normal file
39
seekbuf/seekbuf_test.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package seekbuf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.wntrmute.dev/kyle/goutils/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSeeking(t *testing.T) {
|
||||||
|
partA := []byte("hello, ")
|
||||||
|
partB := []byte("world!")
|
||||||
|
|
||||||
|
buf := New(partA)
|
||||||
|
assert.BoolT(t, buf.Len() == len(partA), fmt.Sprintf("on init: have length %d, want length %d", buf.Len(), len(partA)))
|
||||||
|
|
||||||
|
b := make([]byte, 32)
|
||||||
|
|
||||||
|
n, err := buf.Read(b)
|
||||||
|
assert.NoErrorT(t, err)
|
||||||
|
assert.BoolT(t, buf.Len() == 0, fmt.Sprintf("after reading 1: have length %d, want length 0", buf.Len()))
|
||||||
|
assert.BoolT(t, n == len(partA), fmt.Sprintf("after reading 2: have length %d, want length %d", n, len(partA)))
|
||||||
|
|
||||||
|
n, err = buf.Write(partB)
|
||||||
|
assert.NoErrorT(t, err)
|
||||||
|
assert.BoolT(t, n == len(partB), fmt.Sprintf("after writing: have length %d, want length %d", n, len(partB)))
|
||||||
|
|
||||||
|
n, err = buf.Read(b)
|
||||||
|
assert.NoErrorT(t, err)
|
||||||
|
assert.BoolT(t, buf.Len() == 0, fmt.Sprintf("after rereading 1: have length %d, want length 0", buf.Len()))
|
||||||
|
assert.BoolT(t, n == len(partB), fmt.Sprintf("after rereading 2: have length %d, want length %d", n, len(partB)))
|
||||||
|
|
||||||
|
partsLen := len(partA) + len(partB)
|
||||||
|
buf.Rewind()
|
||||||
|
assert.BoolT(t, buf.Len() == partsLen, fmt.Sprintf("after rewinding: have length %d, want length %d", buf.Len(), partsLen))
|
||||||
|
|
||||||
|
buf.Close()
|
||||||
|
assert.BoolT(t, buf.Len() == 0, fmt.Sprintf("after closing, have length %d, want length 0", buf.Len()))
|
||||||
|
}
|
||||||
9
syslog/BUILD.bazel
Normal file
9
syslog/BUILD.bazel
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "log",
|
||||||
|
srcs = ["logger.go"],
|
||||||
|
importpath = "git.wntrmute.dev/kyle/kdhcp/log",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = ["@com_github_hashicorp_go_syslog//:go-syslog"],
|
||||||
|
)
|
||||||
257
syslog/logger.go
Normal file
257
syslog/logger.go
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
// syslog is a syslog-type facility for logging.
|
||||||
|
package syslog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
gsyslog "github.com/hashicorp/go-syslog"
|
||||||
|
)
|
||||||
|
|
||||||
|
type logger struct {
|
||||||
|
l gsyslog.Syslogger
|
||||||
|
p gsyslog.Priority
|
||||||
|
}
|
||||||
|
|
||||||
|
func (log *logger) printf(p gsyslog.Priority, format string, args ...interface{}) {
|
||||||
|
if !strings.HasSuffix(format, "\n") {
|
||||||
|
format += "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
if p <= log.p {
|
||||||
|
fmt.Printf("%s [%s] ", prioritiev[p], timestamp())
|
||||||
|
fmt.Printf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if log.l != nil {
|
||||||
|
log.l.WriteLevel(p, []byte(fmt.Sprintf(format, args...)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (log *logger) print(p gsyslog.Priority, args ...interface{}) {
|
||||||
|
if p <= log.p {
|
||||||
|
fmt.Printf("%s [%s] ", prioritiev[p], timestamp())
|
||||||
|
fmt.Print(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if log.l != nil {
|
||||||
|
log.l.WriteLevel(p, []byte(fmt.Sprint(args...)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (log *logger) println(p gsyslog.Priority, args ...interface{}) {
|
||||||
|
if p <= log.p {
|
||||||
|
fmt.Printf("%s [%s] ", prioritiev[p], timestamp())
|
||||||
|
fmt.Println(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if log.l != nil {
|
||||||
|
log.l.WriteLevel(p, []byte(fmt.Sprintln(args...)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (log *logger) adjustPriority(level string) error {
|
||||||
|
priority, ok := priorities[level]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("log: unknown priority %s", level)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.p = priority
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var log = &logger{p: gsyslog.LOG_WARNING}
|
||||||
|
|
||||||
|
var priorities = map[string]gsyslog.Priority{
|
||||||
|
"EMERG": gsyslog.LOG_EMERG,
|
||||||
|
"ALERT": gsyslog.LOG_ALERT,
|
||||||
|
"CRIT": gsyslog.LOG_CRIT,
|
||||||
|
"ERR": gsyslog.LOG_ERR,
|
||||||
|
"WARNING": gsyslog.LOG_WARNING,
|
||||||
|
"NOTICE": gsyslog.LOG_NOTICE,
|
||||||
|
"INFO": gsyslog.LOG_INFO,
|
||||||
|
"DEBUG": gsyslog.LOG_DEBUG,
|
||||||
|
}
|
||||||
|
|
||||||
|
var prioritiev = map[gsyslog.Priority]string{
|
||||||
|
gsyslog.LOG_EMERG: "EMERG",
|
||||||
|
gsyslog.LOG_ALERT: "ALERT",
|
||||||
|
gsyslog.LOG_CRIT: "CRIT",
|
||||||
|
gsyslog.LOG_ERR: "ERR",
|
||||||
|
gsyslog.LOG_WARNING: "WARNING",
|
||||||
|
gsyslog.LOG_NOTICE: "NOTICE",
|
||||||
|
gsyslog.LOG_INFO: "INFO",
|
||||||
|
gsyslog.LOG_DEBUG: "DEBUG",
|
||||||
|
}
|
||||||
|
|
||||||
|
func timestamp() string {
|
||||||
|
return time.Now().Format("2006-01-02 15:04:05 MST")
|
||||||
|
}
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
Level string
|
||||||
|
Tag string
|
||||||
|
Facility string
|
||||||
|
WriteSyslog bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultOptions returns a sane set of defaults for syslog, using the program
|
||||||
|
// name as the tag name. withSyslog controls whether logs should be sent to
|
||||||
|
// syslog, too.
|
||||||
|
func DefaultOptions(tag string, withSyslog bool) {
|
||||||
|
if tag == "" {
|
||||||
|
tag = os.Args[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DefaultOptions{
|
||||||
|
Level: "WARNING",
|
||||||
|
Tag: tag,
|
||||||
|
Facility: "daemon",
|
||||||
|
WriteSyslog: withSyslog,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultDefaultOptions returns a sane set of debug defaults for syslog,
|
||||||
|
// using the program name as the tag name. withSyslog controls whether logs
|
||||||
|
// should be sent to syslog, too.
|
||||||
|
func DefaultDebugOptions(tag string, withSyslog bool) {
|
||||||
|
if tag == "" {
|
||||||
|
tag = os.Args[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DefaultOptions{
|
||||||
|
Level: "DEBUG",
|
||||||
|
Facility: "daemon",
|
||||||
|
WriteSyslog: withSyslog,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Setup(opts *Options) error {
|
||||||
|
priority, ok := priorities[opts.Level]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("log: unknown priority %s", level)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.p = priority
|
||||||
|
|
||||||
|
var err error
|
||||||
|
log.l, err = gsyslog.NewLogger(priority, opts.Facility, opts.Tag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Debug(args ...interface{}) {
|
||||||
|
log.print(gsyslog.LOG_DEBUG, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Info(args ...interface{}) {
|
||||||
|
log.print(gsyslog.LOG_INFO, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Notice(args ...interface{}) {
|
||||||
|
log.print(gsyslog.LOG_NOTICE, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Warning(args ...interface{}) {
|
||||||
|
log.print(gsyslog.LOG_WARNING, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Err(args ...interface{}) {
|
||||||
|
log.print(gsyslog.LOG_ERR, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Crit(args ...interface{}) {
|
||||||
|
log.print(gsyslog.LOG_CRIT, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Alert(args ...interface{}) {
|
||||||
|
log.print(gsyslog.LOG_ALERT, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Emerg(args ...interface{}) {
|
||||||
|
log.print(gsyslog.LOG_EMERG, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Debugln(args ...interface{}) {
|
||||||
|
log.println(gsyslog.LOG_DEBUG, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Infoln(args ...interface{}) {
|
||||||
|
log.println(gsyslog.LOG_INFO, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Noticeln(args ...interface{}) {
|
||||||
|
log.println(gsyslog.LOG_NOTICE, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Warningln(args ...interface{}) {
|
||||||
|
log.print(gsyslog.LOG_WARNING, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Errln(args ...interface{}) {
|
||||||
|
log.println(gsyslog.LOG_ERR, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Critln(args ...interface{}) {
|
||||||
|
log.println(gsyslog.LOG_CRIT, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Alertln(args ...interface{}) {
|
||||||
|
log.println(gsyslog.LOG_ALERT, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Emergln(args ...interface{}) {
|
||||||
|
log.println(gsyslog.LOG_EMERG, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Debugf(format string, args ...interface{}) {
|
||||||
|
log.printf(gsyslog.LOG_DEBUG, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Infof(format string, args ...interface{}) {
|
||||||
|
log.printf(gsyslog.LOG_INFO, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Noticef(format string, args ...interface{}) {
|
||||||
|
log.printf(gsyslog.LOG_NOTICE, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Warningf(format string, args ...interface{}) {
|
||||||
|
log.printf(gsyslog.LOG_WARNING, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Errf(format string, args ...interface{}) {
|
||||||
|
log.printf(gsyslog.LOG_ERR, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Critf(format string, args ...interface{}) {
|
||||||
|
log.printf(gsyslog.LOG_CRIT, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Alertf(format string, args ...interface{}) {
|
||||||
|
log.printf(gsyslog.LOG_ALERT, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Emergf(format string, args ...interface{}) {
|
||||||
|
log.printf(gsyslog.LOG_EMERG, format, args...)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fatal(args ...interface{}) {
|
||||||
|
log.println(gsyslog.LOG_ERR, args...)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fatalf(format string, args ...interface{}) {
|
||||||
|
log.printf(gsyslog.LOG_ERR, format, args...)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChangePriority(level string) error {
|
||||||
|
return log.adjustPriority(level)
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ go_library(
|
|||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "testio_test",
|
name = "testio_test",
|
||||||
|
size = "small",
|
||||||
srcs = ["testio_test.go"],
|
srcs = ["testio_test.go"],
|
||||||
embed = [":testio"],
|
embed = [":testio"],
|
||||||
size = "small",
|
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user