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  }