handler.go 1.8 KB

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