2d01d5f2d4
The messages we print through tlog sometimes do, sometimes do not contain a trailing newline. The stdlib logger usually drops trailing newlines automatically, but tlog postfixes ColorReset to the caller's message, so the logger logic does not work when we print colored output. Drop the newlines on our own, and add a test. Fixes the blank lines in fsck output: ~/go/src/github.com/rfjakob/gocryptfs/tests/fsck$ ./run_fsck.bash Reading password from extpass program Decrypting master key OpenDir "": invalid entry "invalid_file_name.3": illegal base64 data at input byte 17 OpenDir "": invalid entry "invalid_file_name_2": bad message fsck: corrupt entry in dir "": "invalid_file_name.3" fsck: corrupt entry in dir "": "invalid_file_name_2" OpenDir "": invalid entry "invalid_file_name____1": bad message fsck: corrupt entry in dir "": "invalid_file_name____1" doRead 4327225: corrupt block #0: stupidgcm: message authentication failed fsck: error reading file "corrupt_file" (inum 4327225): 5=input/output error cipherSize 40 < overhead 50: corrupt file doRead 4327074: corrupt header: ParseHeader: invalid version, want=2 have=22616 cipherSize 40 < overhead 50: corrupt file fsck: error reading file "corrupt_file_2" (inum 4327074): 5=input/output error Readlink "s-P7PcQDUcVkoeMDnC3EYA": decrypting target failed: stupidgcm: message authentication failed fsck: error reading symlink "corrupt_symlink": 5=input/output error Readlink "iI0MtUdzELPeOAZYwYZFee169hpGgd3l2PXQBcc9sl4": decrypting target failed: illegal base64 data at input byte 0 fsck: error reading symlink "corrupt_symlink_2": 5=input/output error OpenDir "yrwcjj2qoC4IYvhw9sbfRg": could not read gocryptfs.diriv: wanted 16 bytes, got 17 fsck: error opening dir "diriv_too_long": 5=input/output error OpenDir "trqecbMNXdzLqzpk7fSfKw": could not read gocryptfs.diriv: wanted 16 bytes, got 3 fsck: error opening dir "diriv_too_short": 5=input/output error cipherSize 8 < header size 18: corrupt file readFileID 4327049: incomplete file, got 8 instead of 19 bytes fsck: corrupt file "incomplete_file_1" (inode 4327049) readFileID 4327038: incomplete file, got 18 instead of 19 bytes fsck: corrupt file "incomplete_file_2" (inode 4327038) cipherSize 1 < header size 18: corrupt file readFileID 4327063: incomplete file, got 1 instead of 19 bytes fsck: corrupt file "incomplete_file_3" (inode 4327063) fsck: error opening dir "missing_diriv": 2=no such file or directory ListXAttr: invalid xattr name "user.gocryptfs.0a5e7yWl0SGUGeWB0Sy2K0": bad message fsck: corrupt xattr name on file "xattr_corrupt_name": "user.gocryptfs.0a5e7yWl0SGUGeWB0Sy2K0" GetXAttr: stupidgcm: message authentication failed fsck: error reading xattr "user.foo" from "xattr_corrupt_value": 5=input/output error fsck summary: 15 corrupt files
197 lines
4.5 KiB
Go
197 lines
4.5 KiB
Go
// Package tlog is a "toggled logger" that can be enabled and disabled and
|
|
// provides coloring.
|
|
package tlog
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"log/syslog"
|
|
"os"
|
|
|
|
"golang.org/x/crypto/ssh/terminal"
|
|
)
|
|
|
|
const (
|
|
// ProgramName is used in log reports.
|
|
ProgramName = "gocryptfs"
|
|
wpanicMsg = "-wpanic turns this warning into a panic: "
|
|
)
|
|
|
|
// Escape sequences for terminal colors. These are set in init() if and only
|
|
// if stdout is a terminal. Otherwise they are empty strings.
|
|
var (
|
|
// ColorReset is used to reset terminal colors.
|
|
ColorReset string
|
|
// ColorGrey is a terminal color setting string.
|
|
ColorGrey string
|
|
// ColorRed is a terminal color setting string.
|
|
ColorRed string
|
|
// ColorGreen is a terminal color setting string.
|
|
ColorGreen string
|
|
// ColorYellow is a terminal color setting string.
|
|
ColorYellow string
|
|
)
|
|
|
|
// JSONDump writes the object in json form.
|
|
func JSONDump(obj interface{}) string {
|
|
b, err := json.MarshalIndent(obj, "", "\t")
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
|
|
return string(b)
|
|
}
|
|
|
|
// toggledLogger - a Logger than can be enabled and disabled
|
|
type toggledLogger struct {
|
|
// Enable or disable output
|
|
Enabled bool
|
|
// Panic after logging a message, useful in regression tests
|
|
Wpanic bool
|
|
// Private prefix and postfix are used for coloring
|
|
prefix string
|
|
postfix string
|
|
|
|
Logger *log.Logger
|
|
}
|
|
|
|
// trimNewline removes one trailing newline from "msg"
|
|
func trimNewline(msg string) string {
|
|
if len(msg) == 0 {
|
|
return msg
|
|
}
|
|
if msg[len(msg)-1] == '\n' {
|
|
return msg[:len(msg)-1]
|
|
}
|
|
return msg
|
|
}
|
|
|
|
func (l *toggledLogger) Printf(format string, v ...interface{}) {
|
|
if !l.Enabled {
|
|
return
|
|
}
|
|
msg := trimNewline(fmt.Sprintf(format, v...))
|
|
l.Logger.Printf(l.prefix + msg + l.postfix)
|
|
if l.Wpanic {
|
|
l.Logger.Panic(wpanicMsg + msg)
|
|
}
|
|
}
|
|
func (l *toggledLogger) Println(v ...interface{}) {
|
|
if !l.Enabled {
|
|
return
|
|
}
|
|
msg := trimNewline(fmt.Sprint(v...))
|
|
l.Logger.Println(l.prefix + msg + l.postfix)
|
|
if l.Wpanic {
|
|
l.Logger.Panic(wpanicMsg + msg)
|
|
}
|
|
}
|
|
|
|
// Debug logs debug messages
|
|
// Can be enabled by passing "-d"
|
|
var Debug *toggledLogger
|
|
|
|
// Info logs informational message
|
|
// Can be disabled by passing "-q"
|
|
var Info *toggledLogger
|
|
|
|
// Warn logs warnings,
|
|
// meaning nothing serious by itself but might indicate problems.
|
|
// Passing "-wpanic" will make this function panic after printing the message.
|
|
var Warn *toggledLogger
|
|
|
|
// Fatal error, we are about to exit
|
|
var Fatal *toggledLogger
|
|
|
|
func init() {
|
|
if terminal.IsTerminal(int(os.Stdout.Fd())) {
|
|
ColorReset = "\033[0m"
|
|
ColorGrey = "\033[2m"
|
|
ColorRed = "\033[31m"
|
|
ColorGreen = "\033[32m"
|
|
ColorYellow = "\033[33m"
|
|
}
|
|
|
|
Debug = &toggledLogger{
|
|
Logger: log.New(os.Stdout, "", 0),
|
|
}
|
|
Info = &toggledLogger{
|
|
Enabled: true,
|
|
Logger: log.New(os.Stdout, "", 0),
|
|
}
|
|
Warn = &toggledLogger{
|
|
Enabled: true,
|
|
Logger: log.New(os.Stderr, "", 0),
|
|
prefix: ColorYellow,
|
|
postfix: ColorReset,
|
|
}
|
|
Fatal = &toggledLogger{
|
|
Enabled: true,
|
|
Logger: log.New(os.Stderr, "", 0),
|
|
prefix: ColorRed,
|
|
postfix: ColorReset,
|
|
}
|
|
}
|
|
|
|
// SwitchToSyslog redirects the output of this logger to syslog.
|
|
func (l *toggledLogger) SwitchToSyslog(p syslog.Priority) {
|
|
w, err := syslog.New(p, ProgramName)
|
|
if err != nil {
|
|
Warn.Printf("SwitchToSyslog: %v", err)
|
|
} else {
|
|
l.Logger.SetOutput(w)
|
|
}
|
|
}
|
|
|
|
// SwitchLoggerToSyslog redirects the default log.Logger that the go-fuse lib uses
|
|
// to syslog.
|
|
func SwitchLoggerToSyslog(p syslog.Priority) {
|
|
w, err := syslog.New(p, ProgramName)
|
|
if err != nil {
|
|
Warn.Printf("SwitchLoggerToSyslog: %v", err)
|
|
} else {
|
|
log.SetPrefix("go-fuse: ")
|
|
// Disable printing the timestamp, syslog already provides that
|
|
log.SetFlags(0)
|
|
log.SetOutput(w)
|
|
}
|
|
}
|
|
|
|
// PrintMasterkeyReminder reminds the user that he should store the master key in
|
|
// a safe place.
|
|
func PrintMasterkeyReminder(key []byte) {
|
|
if !Info.Enabled {
|
|
// Quiet mode
|
|
return
|
|
}
|
|
if !terminal.IsTerminal(int(os.Stdout.Fd())) {
|
|
// We don't want the master key to end up in a log file
|
|
Info.Printf("Not running on a terminal, suppressing master key display\n")
|
|
return
|
|
}
|
|
h := hex.EncodeToString(key)
|
|
var hChunked string
|
|
// Try to make it less scary by splitting it up in chunks
|
|
for i := 0; i < len(h); i += 8 {
|
|
hChunked += h[i : i+8]
|
|
if i < 52 {
|
|
hChunked += "-"
|
|
}
|
|
if i == 24 {
|
|
hChunked += "\n "
|
|
}
|
|
}
|
|
Info.Printf(`
|
|
Your master key is:
|
|
|
|
%s
|
|
|
|
If the gocryptfs.conf file becomes corrupted or you ever forget your password,
|
|
there is only one hope for recovery: The master key. Print it to a piece of
|
|
paper and store it in a drawer. This message is only printed once.
|
|
|
|
`, ColorGrey+hChunked+ColorReset)
|
|
}
|