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