partition.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package fileutils2
  15. import (
  16. "fmt"
  17. "regexp"
  18. "strconv"
  19. "strings"
  20. "yunion.io/x/pkg/utils"
  21. regutils "yunion.io/x/onecloud/pkg/util/regutils2"
  22. )
  23. type Partition struct {
  24. Index int
  25. Bootable bool
  26. Start int64
  27. End int64
  28. Count int64
  29. DiskType string
  30. Fs string
  31. DevName string
  32. }
  33. func NewPartition(idx int, bootable bool, start int64, end int64, count int64, diskType string, fs string, devName string) Partition {
  34. return Partition{
  35. Index: idx,
  36. Bootable: bootable,
  37. Start: start,
  38. End: end,
  39. Count: count,
  40. DiskType: diskType,
  41. Fs: fs,
  42. DevName: devName,
  43. }
  44. }
  45. // ParseDiskPartitions parse command `parted -s /dev/sda -- unit s print` result
  46. func ParseDiskPartitions(dev string, lines []string) ([]Partition, string) {
  47. parts := make([]Partition, 0)
  48. labelPattern := `Partition Table:\s+(?P<label>\w+)`
  49. pattern := `(?P<idx>\d+)\s+(?P<start>\d+)s\s+(?P<end>\d+)s\s+(?P<count>\d+)s`
  50. var label string
  51. for _, l := range lines {
  52. if label == "" {
  53. m := regutils.SubGroupMatch(labelPattern, l)
  54. if len(m) != 0 {
  55. label = m["label"]
  56. }
  57. }
  58. m := regutils.SubGroupMatch(pattern, l)
  59. if len(m) != 0 {
  60. idx := m["idx"]
  61. devName := dev
  62. if strings.Contains("0123456789", string(dev[len(dev)-1])) {
  63. devName = fmt.Sprintf("%sp", devName)
  64. }
  65. devName = fmt.Sprintf("%s%s", devName, idx)
  66. start := m["start"]
  67. end := m["end"]
  68. count := m["count"]
  69. data := regexp.MustCompile(`\s+`).Split(strings.TrimSpace(l), -1)
  70. diskType := ""
  71. fs := ""
  72. flag := ""
  73. offset := 0
  74. if len(data) > 4 {
  75. if label == "msdos" {
  76. diskType = data[4]
  77. if len(data) > 5 && isPartedFsString(data[5]) {
  78. fs = data[5]
  79. offset += 1
  80. }
  81. if len(data) > 5+offset {
  82. flag = data[5+offset]
  83. }
  84. } else if label == "gpt" {
  85. if isPartedFsString(data[4]) {
  86. fs = data[4]
  87. offset += 1
  88. }
  89. if len(data) > 4+offset {
  90. diskType = data[4+offset]
  91. }
  92. if len(data) > 4+offset+1 {
  93. flag = data[4+offset+1]
  94. }
  95. }
  96. }
  97. bootable := false
  98. if flag != "" && strings.Contains(flag, "boot") {
  99. bootable = true
  100. }
  101. index, _ := strconv.Atoi(idx)
  102. startI, _ := strconv.Atoi(start)
  103. endI, _ := strconv.Atoi(end)
  104. countI, _ := strconv.Atoi(count)
  105. parts = append(parts, NewPartition(index, bootable, int64(startI), int64(endI), int64(countI), diskType, fs, devName))
  106. }
  107. }
  108. return parts, label
  109. }
  110. func isPartedFsString(fs string) bool {
  111. return utils.IsInStringArray(strings.ToLower(fs),
  112. []string{
  113. "ext2", "ext3", "ext4", "xfs",
  114. "fat16", "fat32",
  115. "hfs", "hfs+", "hfsx",
  116. "linux-swap", "linux-swap(v1)",
  117. "ntfs", "reiserfs", "ufs", "btrfs",
  118. })
  119. }