sysreadfile.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // Copyright 2018 The Prometheus Authors
  2. // Licensed under the Apache License, Version 2.0 (the "License");
  3. // you may not use this file except in compliance with the License.
  4. // You may obtain a copy of the License at
  5. //
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. //go:build (linux || darwin) && !appengine
  14. // +build linux darwin
  15. // +build !appengine
  16. package util
  17. import (
  18. "bytes"
  19. "os"
  20. "strconv"
  21. "strings"
  22. "syscall"
  23. )
  24. // SysReadFile is a simplified os.ReadFile that invokes syscall.Read directly.
  25. // https://github.com/prometheus/node_exporter/pull/728/files
  26. //
  27. // Note that this function will not read files larger than 128 bytes.
  28. func SysReadFile(file string) (string, error) {
  29. f, err := os.Open(file)
  30. if err != nil {
  31. return "", err
  32. }
  33. defer f.Close()
  34. // On some machines, hwmon drivers are broken and return EAGAIN. This causes
  35. // Go's os.ReadFile implementation to poll forever.
  36. //
  37. // Since we either want to read data or bail immediately, do the simplest
  38. // possible read using syscall directly.
  39. const sysFileBufferSize = 128
  40. b := make([]byte, sysFileBufferSize)
  41. n, err := syscall.Read(int(f.Fd()), b)
  42. if err != nil {
  43. return "", err
  44. }
  45. return string(bytes.TrimSpace(b[:n])), nil
  46. }
  47. // SysReadUintFromFile reads a file using SysReadFile and attempts to parse a uint64 from it.
  48. func SysReadUintFromFile(path string) (uint64, error) {
  49. data, err := SysReadFile(path)
  50. if err != nil {
  51. return 0, err
  52. }
  53. return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
  54. }
  55. // SysReadIntFromFile reads a file using SysReadFile and attempts to parse a int64 from it.
  56. func SysReadIntFromFile(path string) (int64, error) {
  57. data, err := SysReadFile(path)
  58. if err != nil {
  59. return 0, err
  60. }
  61. return strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64)
  62. }