github.com/hugelgupf/u-root@v0.0.0-20191023214958-4807c632154c/pkg/ulog/klog_linux.go (about) 1 // Copyright 2019 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ulog 6 7 import ( 8 "fmt" 9 "os" 10 "sync/atomic" 11 12 "golang.org/x/sys/unix" 13 ) 14 15 // KernelLog is a logger that prints to the kernel syslog buffer. 16 // 17 // If the syslog buffer cannot be written to, KernelLog falls back to Log. 18 var KernelLog = &KLog{ 19 // Default log level is Info. 20 LogLevel: uintptr(KLogInfo), 21 } 22 23 func init() { 24 KernelLog.Reinit() 25 } 26 27 // KLog is a logger to the kernel syslog buffer. 28 type KLog struct { 29 // FD for /dev/kmsg if it was openable. 30 *os.File 31 32 // LogLevel is the LogLevel to print with. 33 // 34 // Should only be accessed atomically. 35 LogLevel uintptr 36 } 37 38 // Reinit reopens the /dev/kmsg file. 39 func (k *KLog) Reinit() { 40 f, _ := os.OpenFile("/dev/kmsg", os.O_RDWR, 0) 41 KernelLog.File = f 42 } 43 44 // writeString returns true iff it was able to write the log to /dev/kmsg. 45 func (k *KLog) writeString(s string) bool { 46 if k.File == nil { 47 return false 48 } 49 if _, err := k.File.WriteString(fmt.Sprintf("<%d>%s", atomic.LoadUintptr(&k.LogLevel), s)); err != nil { 50 return false 51 } 52 return true 53 } 54 55 // Printf formats according to a format specifier and writes to kernel logging. 56 func (k *KLog) Printf(format string, v ...interface{}) { 57 if !k.writeString(fmt.Sprintf(format, v...)) { 58 Log.Printf(format, v...) 59 } 60 } 61 62 // Print formats using the default operands for v and writes to kernel logging. 63 func (k *KLog) Print(v ...interface{}) { 64 if !k.writeString(fmt.Sprint(v...)) { 65 Log.Print(v...) 66 } 67 } 68 69 // KLogLevel are the log levels used by printk. 70 type KLogLevel uintptr 71 72 // These are the log levels used by printk as described in syslog(2). 73 const ( 74 KLogEmergency KLogLevel = 0 75 KLogAlert KLogLevel = 1 76 KLogCritical KLogLevel = 2 77 KLogError KLogLevel = 3 78 KLogWarning KLogLevel = 4 79 KLogNotice KLogLevel = 5 80 KLogInfo KLogLevel = 6 81 KLogDebug KLogLevel = 7 82 ) 83 84 const ( 85 _SYSLOG_ACTION_READ_ALL = 3 86 _SYSLOG_ACTION_READ_CLEAR = 4 87 _SYSLOG_ACTION_CLEAR = 5 88 _SYSLOG_ACTION_CONSOLE_LEVEL = 8 89 ) 90 91 // SetConsoleLogLevel sets the console level with syslog(2). 92 // 93 // After this call, only messages with a level value lower than the one 94 // specified will be printed to console by the kernel. 95 func (k *KLog) SetConsoleLogLevel(level KLogLevel) error { 96 if _, _, err := unix.Syscall(unix.SYS_SYSLOG, _SYSLOG_ACTION_CONSOLE_LEVEL, 0, uintptr(level)); err != 0 { 97 return fmt.Errorf("could not set syslog level to %d: %v", level, err) 98 } 99 return nil 100 } 101 102 // SetLogLevel sets the level that Printf and Print log to syslog with. 103 func (k *KLog) SetLogLevel(level KLogLevel) { 104 atomic.StoreUintptr(&k.LogLevel, uintptr(level)) 105 } 106 107 // ClearLog clears kernel logs back to empty. 108 func (k *KLog) ClearLog() error { 109 _, err := unix.Klogctl(_SYSLOG_ACTION_CLEAR, nil) 110 return err 111 } 112 113 // Read reads from the tail of the kernel log. 114 func (k *KLog) Read(b []byte) (int, error) { 115 return unix.Klogctl(_SYSLOG_ACTION_READ_ALL, b) 116 } 117 118 // ReadClear reads from the tail of the kernel log and clears what was read. 119 func (k *KLog) ReadClear(b []byte) (int, error) { 120 return unix.Klogctl(_SYSLOG_ACTION_READ_CLEAR, b) 121 }