handler.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package syspolicy
  4. import (
  5. "errors"
  6. "sync/atomic"
  7. )
  8. var (
  9. handlerUsed atomic.Bool
  10. handler Handler = defaultHandler{}
  11. )
  12. // Handler reads system policies from OS-specific storage.
  13. type Handler interface {
  14. // ReadString reads the policy settings value string given the key.
  15. ReadString(key string) (string, error)
  16. // ReadUInt64 reads the policy settings uint64 value given the key.
  17. ReadUInt64(key string) (uint64, error)
  18. // ReadBool reads the policy setting's boolean value, given the key.
  19. ReadBoolean(key string) (bool, error)
  20. }
  21. // ErrNoSuchKey is returned when the specified key does not have a value set.
  22. var ErrNoSuchKey = errors.New("no such key")
  23. // defaultHandler is the catch all syspolicy type for anything that isn't windows or apple.
  24. type defaultHandler struct{}
  25. func (defaultHandler) ReadString(_ string) (string, error) {
  26. return "", ErrNoSuchKey
  27. }
  28. func (defaultHandler) ReadUInt64(_ string) (uint64, error) {
  29. return 0, ErrNoSuchKey
  30. }
  31. func (defaultHandler) ReadBoolean(_ string) (bool, error) {
  32. return false, ErrNoSuchKey
  33. }
  34. // markHandlerInUse is called before handler methods are called.
  35. func markHandlerInUse() {
  36. handlerUsed.Store(true)
  37. }
  38. // RegisterHandler initializes the policy handler and ensures registration will happen once.
  39. func RegisterHandler(h Handler) {
  40. // Technically this assignment is not concurrency safe, but in the
  41. // event that there was any risk of a data race, we will panic due to
  42. // the CompareAndSwap failing.
  43. handler = h
  44. if !handlerUsed.CompareAndSwap(false, true) {
  45. panic("handler was already used before registration")
  46. }
  47. }