utils.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package utils
  2. import (
  3. "encoding/json"
  4. "io"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. "unsafe"
  9. "golang.org/x/sys/unix"
  10. )
  11. const (
  12. exitSignalOffset = 128
  13. )
  14. // ResolveRootfs ensures that the current working directory is
  15. // not a symlink and returns the absolute path to the rootfs
  16. func ResolveRootfs(uncleanRootfs string) (string, error) {
  17. rootfs, err := filepath.Abs(uncleanRootfs)
  18. if err != nil {
  19. return "", err
  20. }
  21. return filepath.EvalSymlinks(rootfs)
  22. }
  23. // ExitStatus returns the correct exit status for a process based on if it
  24. // was signaled or exited cleanly
  25. func ExitStatus(status unix.WaitStatus) int {
  26. if status.Signaled() {
  27. return exitSignalOffset + int(status.Signal())
  28. }
  29. return status.ExitStatus()
  30. }
  31. // WriteJSON writes the provided struct v to w using standard json marshaling
  32. func WriteJSON(w io.Writer, v interface{}) error {
  33. data, err := json.Marshal(v)
  34. if err != nil {
  35. return err
  36. }
  37. _, err = w.Write(data)
  38. return err
  39. }
  40. // CleanPath makes a path safe for use with filepath.Join. This is done by not
  41. // only cleaning the path, but also (if the path is relative) adding a leading
  42. // '/' and cleaning it (then removing the leading '/'). This ensures that a
  43. // path resulting from prepending another path will always resolve to lexically
  44. // be a subdirectory of the prefixed path. This is all done lexically, so paths
  45. // that include symlinks won't be safe as a result of using CleanPath.
  46. func CleanPath(path string) string {
  47. // Deal with empty strings nicely.
  48. if path == "" {
  49. return ""
  50. }
  51. // Ensure that all paths are cleaned (especially problematic ones like
  52. // "/../../../../../" which can cause lots of issues).
  53. path = filepath.Clean(path)
  54. // If the path isn't absolute, we need to do more processing to fix paths
  55. // such as "../../../../<etc>/some/path". We also shouldn't convert absolute
  56. // paths to relative ones.
  57. if !filepath.IsAbs(path) {
  58. path = filepath.Clean(string(os.PathSeparator) + path)
  59. // This can't fail, as (by definition) all paths are relative to root.
  60. path, _ = filepath.Rel(string(os.PathSeparator), path)
  61. }
  62. // Clean the path again for good measure.
  63. return filepath.Clean(path)
  64. }
  65. // SearchLabels searches a list of key-value pairs for the provided key and
  66. // returns the corresponding value. The pairs must be separated with '='.
  67. func SearchLabels(labels []string, query string) string {
  68. for _, l := range labels {
  69. parts := strings.SplitN(l, "=", 2)
  70. if len(parts) < 2 {
  71. continue
  72. }
  73. if parts[0] == query {
  74. return parts[1]
  75. }
  76. }
  77. return ""
  78. }
  79. // Annotations returns the bundle path and user defined annotations from the
  80. // libcontainer state. We need to remove the bundle because that is a label
  81. // added by libcontainer.
  82. func Annotations(labels []string) (bundle string, userAnnotations map[string]string) {
  83. userAnnotations = make(map[string]string)
  84. for _, l := range labels {
  85. parts := strings.SplitN(l, "=", 2)
  86. if len(parts) < 2 {
  87. continue
  88. }
  89. if parts[0] == "bundle" {
  90. bundle = parts[1]
  91. } else {
  92. userAnnotations[parts[0]] = parts[1]
  93. }
  94. }
  95. return
  96. }
  97. func GetIntSize() int {
  98. return int(unsafe.Sizeof(1))
  99. }