github.com/Cloud-Foundations/Dominator@v0.3.4/lib/mbr/impl.go (about) 1 package mbr 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 ) 8 9 func decode(file *os.File) (*Mbr, error) { 10 var mbr Mbr 11 if _, err := file.ReadAt(mbr.raw[:], 0); err != nil { 12 return nil, err 13 } 14 if mbr.raw[0x1FE] == 0x55 && mbr.raw[0x1FF] == 0xAA { 15 return &mbr, nil 16 } 17 return nil, nil 18 } 19 20 func read32LE(address []byte) uint64 { 21 return uint64(address[0]) + 22 uint64(address[1])<<8 + 23 uint64(address[2])<<16 + 24 uint64(address[3])<<24 25 } 26 27 func write32LE(address []byte, value uint64) { 28 address[0] = byte(value & 0xff) 29 address[1] = byte((value >> 8) & 0xff) 30 address[2] = byte((value >> 16) & 0xff) 31 address[3] = byte((value >> 24) & 0xff) 32 } 33 34 func writeDefault(filename string, tableType TableType) error { 35 label, err := tableType.lookupString() 36 if err != nil { 37 return err 38 } 39 fmt.Printf("making table type: %d (%s)\n", tableType, label) 40 cmd := exec.Command("parted", "-s", "-a", "optimal", filename, 41 "mklabel", label, 42 "mkpart", "primary", "ext2", "1", "100%", 43 "set", "1", "boot", "on", 44 ) 45 output, err := cmd.CombinedOutput() 46 if err != nil { 47 return fmt.Errorf("error partitioning: %s: %s: %s", 48 filename, err, output) 49 } 50 return nil 51 } 52 53 func (mbr *Mbr) getPartitionOffset(index uint) uint64 { 54 partitionOffset := 0x1BE + 0x10*index 55 return 512 * read32LE(mbr.raw[partitionOffset+8:]) 56 } 57 58 func (mbr *Mbr) getPartitionSize(index uint) uint64 { 59 partitionOffset := 0x1BE + 0x10*index 60 return 512 * read32LE(mbr.raw[partitionOffset+12:]) 61 } 62 63 func (mbr *Mbr) setPartitionOffset(index uint, offset uint64) error { 64 if index >= mbr.GetNumPartitions() { 65 return fmt.Errorf("invalid partition index: %d", index) 66 } 67 offsetSector := offset >> 9 68 if offsetSector<<9 != offset { 69 return fmt.Errorf("offset: %d is not an integral multiple of blocks", 70 offset) 71 } 72 partitionOffset := 0x1BE + 0x10*index 73 write32LE(mbr.raw[partitionOffset+8:], offsetSector) 74 return nil 75 } 76 77 func (mbr *Mbr) setPartitionSize(index uint, size uint64) error { 78 if index >= mbr.GetNumPartitions() { 79 return fmt.Errorf("invalid partition index: %d", index) 80 } 81 sizeSector := size >> 9 82 if sizeSector<<9 != size { 83 return fmt.Errorf("size: %d is not an integral multiple of blocks", 84 size) 85 } 86 partitionOffset := 0x1BE + 0x10*index 87 write32LE(mbr.raw[partitionOffset+12:], sizeSector) 88 return nil 89 } 90 91 func (mbr *Mbr) write(filename string) error { 92 if file, err := os.OpenFile(filename, os.O_WRONLY, 0622); err != nil { 93 return err 94 } else { 95 defer file.Close() 96 if length, err := file.Write(mbr.raw[:]); err != nil { 97 return err 98 } else if length != len(mbr.raw) { 99 return fmt.Errorf("short write: %d", length) 100 } 101 return nil 102 } 103 }