Statistics
| Branch: | Tag: | Revision:

root / image_creator / gpt.py @ 12c97404

History | View | Annotate | Download (11.9 kB)

1 121f3bc0 Nikos Skalkotos
#!/usr/bin/env python
2 121f3bc0 Nikos Skalkotos
# -*- coding: utf-8 -*-
3 121f3bc0 Nikos Skalkotos
#
4 331aa0ec Nikos Skalkotos
# Copyright 2012 GRNET S.A. All rights reserved.
5 331aa0ec Nikos Skalkotos
#
6 331aa0ec Nikos Skalkotos
# Redistribution and use in source and binary forms, with or
7 331aa0ec Nikos Skalkotos
# without modification, are permitted provided that the following
8 331aa0ec Nikos Skalkotos
# conditions are met:
9 331aa0ec Nikos Skalkotos
#
10 331aa0ec Nikos Skalkotos
#   1. Redistributions of source code must retain the above
11 331aa0ec Nikos Skalkotos
#      copyright notice, this list of conditions and the following
12 331aa0ec Nikos Skalkotos
#      disclaimer.
13 331aa0ec Nikos Skalkotos
#
14 331aa0ec Nikos Skalkotos
#   2. Redistributions in binary form must reproduce the above
15 331aa0ec Nikos Skalkotos
#      copyright notice, this list of conditions and the following
16 331aa0ec Nikos Skalkotos
#      disclaimer in the documentation and/or other materials
17 331aa0ec Nikos Skalkotos
#      provided with the distribution.
18 331aa0ec Nikos Skalkotos
#
19 331aa0ec Nikos Skalkotos
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
20 331aa0ec Nikos Skalkotos
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 331aa0ec Nikos Skalkotos
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 331aa0ec Nikos Skalkotos
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
23 331aa0ec Nikos Skalkotos
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 331aa0ec Nikos Skalkotos
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 331aa0ec Nikos Skalkotos
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 331aa0ec Nikos Skalkotos
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 331aa0ec Nikos Skalkotos
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 331aa0ec Nikos Skalkotos
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 331aa0ec Nikos Skalkotos
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 331aa0ec Nikos Skalkotos
# POSSIBILITY OF SUCH DAMAGE.
31 331aa0ec Nikos Skalkotos
#
32 331aa0ec Nikos Skalkotos
# The views and conclusions contained in the software and
33 331aa0ec Nikos Skalkotos
# documentation are those of the authors and should not be
34 331aa0ec Nikos Skalkotos
# interpreted as representing official policies, either expressed
35 331aa0ec Nikos Skalkotos
# or implied, of GRNET S.A.
36 331aa0ec Nikos Skalkotos
37 121f3bc0 Nikos Skalkotos
"""This module provides the code for handling GUID partition tables"""
38 121f3bc0 Nikos Skalkotos
39 331aa0ec Nikos Skalkotos
import struct
40 331aa0ec Nikos Skalkotos
import sys
41 331aa0ec Nikos Skalkotos
import uuid
42 331aa0ec Nikos Skalkotos
import binascii
43 331aa0ec Nikos Skalkotos
44 331aa0ec Nikos Skalkotos
BLOCKSIZE = 512
45 331aa0ec Nikos Skalkotos
46 331aa0ec Nikos Skalkotos
47 331aa0ec Nikos Skalkotos
class MBR(object):
48 c0240ac1 Nikos Skalkotos
    """Represents a Master Boot Record."""
49 331aa0ec Nikos Skalkotos
    class Partition(object):
50 88f83027 Nikos Skalkotos
        """Represents a partition entry in MBR"""
51 331aa0ec Nikos Skalkotos
        format = "<B3sB3sLL"
52 331aa0ec Nikos Skalkotos
53 331aa0ec Nikos Skalkotos
        def __init__(self, raw_part):
54 88f83027 Nikos Skalkotos
            """Create a Partition instance"""
55 c0240ac1 Nikos Skalkotos
            (
56 c0240ac1 Nikos Skalkotos
                self.status,
57 331aa0ec Nikos Skalkotos
                self.start,
58 331aa0ec Nikos Skalkotos
                self.type,
59 331aa0ec Nikos Skalkotos
                self.end,
60 331aa0ec Nikos Skalkotos
                self.first_sector,
61 331aa0ec Nikos Skalkotos
                self.sector_count
62 331aa0ec Nikos Skalkotos
            ) = struct.unpack(self.format, raw_part)
63 331aa0ec Nikos Skalkotos
64 331aa0ec Nikos Skalkotos
        def pack(self):
65 88f83027 Nikos Skalkotos
            """Pack the partition values into a binary string"""
66 331aa0ec Nikos Skalkotos
            return struct.pack(self.format,
67 f99fe99d Nikos Skalkotos
                               self.status,
68 f99fe99d Nikos Skalkotos
                               self.start,
69 f99fe99d Nikos Skalkotos
                               self.type,
70 f99fe99d Nikos Skalkotos
                               self.end,
71 f99fe99d Nikos Skalkotos
                               self.first_sector,
72 f99fe99d Nikos Skalkotos
                               self.sector_count)
73 331aa0ec Nikos Skalkotos
74 c0240ac1 Nikos Skalkotos
        @staticmethod
75 c0240ac1 Nikos Skalkotos
        def size():
76 c0240ac1 Nikos Skalkotos
            """Returns the size of an MBR partition entry"""
77 c0240ac1 Nikos Skalkotos
            return struct.calcsize(MBR.Partition.format)
78 c0240ac1 Nikos Skalkotos
79 c0240ac1 Nikos Skalkotos
        def __str__(self):
80 331aa0ec Nikos Skalkotos
            start = self.unpack_chs(self.start)
81 331aa0ec Nikos Skalkotos
            end = self.unpack_chs(self.end)
82 c0240ac1 Nikos Skalkotos
            return "%d %s %d %s %d %d" % (self.status, start, self.type, end,
83 f99fe99d Nikos Skalkotos
                                          self.first_sector, self.sector_count)
84 331aa0ec Nikos Skalkotos
85 331aa0ec Nikos Skalkotos
        def unpack_chs(self, chs):
86 c0240ac1 Nikos Skalkotos
            """Unpacks a CHS address string to a tuple."""
87 331aa0ec Nikos Skalkotos
88 331aa0ec Nikos Skalkotos
            assert len(chs) == 3
89 331aa0ec Nikos Skalkotos
90 331aa0ec Nikos Skalkotos
            head = struct.unpack('<B', chs[0])[0]
91 331aa0ec Nikos Skalkotos
            sector = struct.unpack('<B', chs[1])[0] & 0x3f
92 331aa0ec Nikos Skalkotos
            cylinder = (struct.unpack('<B', chs[1])[0] & 0xC0) << 2 | \
93 331aa0ec Nikos Skalkotos
                struct.unpack('<B', chs[2])[0]
94 331aa0ec Nikos Skalkotos
95 331aa0ec Nikos Skalkotos
            return (cylinder, head, sector)
96 331aa0ec Nikos Skalkotos
97 331aa0ec Nikos Skalkotos
        def pack_chs(self, cylinder, head, sector):
98 c0240ac1 Nikos Skalkotos
            """Packs a CHS tuple to an address string."""
99 331aa0ec Nikos Skalkotos
100 331aa0ec Nikos Skalkotos
            assert 1 <= sector <= 63
101 331aa0ec Nikos Skalkotos
            assert 0 <= cylinder <= 1023
102 331aa0ec Nikos Skalkotos
            assert 0 <= head <= 255
103 331aa0ec Nikos Skalkotos
104 331aa0ec Nikos Skalkotos
            byte0 = head
105 331aa0ec Nikos Skalkotos
            byte1 = (cylinder >> 2) & 0xC0 | sector
106 331aa0ec Nikos Skalkotos
            byte2 = cylinder & 0xff
107 331aa0ec Nikos Skalkotos
108 331aa0ec Nikos Skalkotos
            return struct.pack('<BBB', byte0, byte1, byte2)
109 331aa0ec Nikos Skalkotos
110 331aa0ec Nikos Skalkotos
    format = "<444s2x16s16s16s16s2s"
111 331aa0ec Nikos Skalkotos
    """
112 331aa0ec Nikos Skalkotos
    Offset  Length          Contents
113 331aa0ec Nikos Skalkotos
    0       440(max. 446)   code area
114 331aa0ec Nikos Skalkotos
    440     2(optional)     disk signature
115 331aa0ec Nikos Skalkotos
    444     2               Usually nulls
116 331aa0ec Nikos Skalkotos
    446     16              Partition 0
117 331aa0ec Nikos Skalkotos
    462     16              Partition 1
118 331aa0ec Nikos Skalkotos
    478     16              Partition 2
119 331aa0ec Nikos Skalkotos
    494     16              Partition 3
120 331aa0ec Nikos Skalkotos
    510     2               MBR signature
121 331aa0ec Nikos Skalkotos
    """
122 331aa0ec Nikos Skalkotos
    def __init__(self, block):
123 88f83027 Nikos Skalkotos
        """Create an MBR instance"""
124 331aa0ec Nikos Skalkotos
        raw_part = {}
125 f99fe99d Nikos Skalkotos
        (self.code_area,
126 f99fe99d Nikos Skalkotos
         raw_part[0],
127 f99fe99d Nikos Skalkotos
         raw_part[1],
128 f99fe99d Nikos Skalkotos
         raw_part[2],
129 f99fe99d Nikos Skalkotos
         raw_part[3],
130 f99fe99d Nikos Skalkotos
         self.signature) = struct.unpack(self.format, block)
131 331aa0ec Nikos Skalkotos
132 331aa0ec Nikos Skalkotos
        self.part = {}
133 331aa0ec Nikos Skalkotos
        for i in range(4):
134 331aa0ec Nikos Skalkotos
            self.part[i] = self.Partition(raw_part[i])
135 331aa0ec Nikos Skalkotos
136 c0240ac1 Nikos Skalkotos
    @staticmethod
137 c0240ac1 Nikos Skalkotos
    def size():
138 88f83027 Nikos Skalkotos
        """Return the size of a Master Boot Record."""
139 c0240ac1 Nikos Skalkotos
        return struct.calcsize(MBR.format)
140 c0240ac1 Nikos Skalkotos
141 331aa0ec Nikos Skalkotos
    def pack(self):
142 88f83027 Nikos Skalkotos
        """Pack an MBR to a binary string."""
143 331aa0ec Nikos Skalkotos
        return struct.pack(self.format,
144 f99fe99d Nikos Skalkotos
                           self.code_area,
145 f99fe99d Nikos Skalkotos
                           self.part[0].pack(),
146 f99fe99d Nikos Skalkotos
                           self.part[1].pack(),
147 f99fe99d Nikos Skalkotos
                           self.part[2].pack(),
148 f99fe99d Nikos Skalkotos
                           self.part[3].pack(),
149 f99fe99d Nikos Skalkotos
                           self.signature)
150 331aa0ec Nikos Skalkotos
151 c0240ac1 Nikos Skalkotos
    def __str__(self):
152 c0240ac1 Nikos Skalkotos
        ret = ""
153 331aa0ec Nikos Skalkotos
        for i in range(4):
154 c0240ac1 Nikos Skalkotos
            ret += "Partition %d: %s\n" % (i, self.part[i])
155 f99fe99d Nikos Skalkotos
        ret += "Signature: %s %s\n" % (hex(ord(self.signature[0])),
156 f99fe99d Nikos Skalkotos
                                       hex(ord(self.signature[1])))
157 c0240ac1 Nikos Skalkotos
        return ret
158 331aa0ec Nikos Skalkotos
159 331aa0ec Nikos Skalkotos
160 331aa0ec Nikos Skalkotos
class GPTPartitionTable(object):
161 c0240ac1 Nikos Skalkotos
    """Represents a GUID Partition Table."""
162 331aa0ec Nikos Skalkotos
    class GPTHeader(object):
163 c0240ac1 Nikos Skalkotos
        """Represents a GPT Header of a GUID Partition Table."""
164 331aa0ec Nikos Skalkotos
        format = "<8s4sII4xQQQQ16sQIII"
165 331aa0ec Nikos Skalkotos
        """
166 331aa0ec Nikos Skalkotos
        Offset        Length                 Contents
167 331aa0ec Nikos Skalkotos
        0       8 bytes         Signature
168 331aa0ec Nikos Skalkotos
        8       4 bytes         Revision
169 331aa0ec Nikos Skalkotos
        12      4 bytes         Header size in little endian
170 331aa0ec Nikos Skalkotos
        16         4 bytes         CRC32 of header
171 331aa0ec Nikos Skalkotos
        20         4 bytes         Reserved; must be zero
172 331aa0ec Nikos Skalkotos
        24         8 bytes         Current LBA
173 331aa0ec Nikos Skalkotos
        32         8 bytes         Backup LBA
174 331aa0ec Nikos Skalkotos
        40         8 bytes         First usable LBA for partitions
175 331aa0ec Nikos Skalkotos
        48         8 bytes         Last usable LBA
176 331aa0ec Nikos Skalkotos
        56         16 bytes         Disk GUID
177 331aa0ec Nikos Skalkotos
        72         8 bytes         Partition entries starting LBA
178 331aa0ec Nikos Skalkotos
        80         4 bytes         Number of partition entries
179 331aa0ec Nikos Skalkotos
        84         4 bytes         Size of a partition entry
180 331aa0ec Nikos Skalkotos
        88         4 bytes         CRC32 of partition array
181 331aa0ec Nikos Skalkotos
        92         *                 Reserved; must be zeroes
182 331aa0ec Nikos Skalkotos
        LBA    size            Total
183 331aa0ec Nikos Skalkotos
        """
184 331aa0ec Nikos Skalkotos
185 331aa0ec Nikos Skalkotos
        def __init__(self, block):
186 88f83027 Nikos Skalkotos
            """Create a GPTHeader instance"""
187 f99fe99d Nikos Skalkotos
            (self.signature,
188 f99fe99d Nikos Skalkotos
             self.revision,
189 f99fe99d Nikos Skalkotos
             self.hdr_size,
190 f99fe99d Nikos Skalkotos
             self.header_crc32,
191 f99fe99d Nikos Skalkotos
             self.current_lba,
192 f99fe99d Nikos Skalkotos
             self.backup_lba,
193 f99fe99d Nikos Skalkotos
             self.first_usable_lba,
194 f99fe99d Nikos Skalkotos
             self.last_usable_lba,
195 f99fe99d Nikos Skalkotos
             self.uuid,
196 f99fe99d Nikos Skalkotos
             self.part_entry_start,
197 f99fe99d Nikos Skalkotos
             self.part_count,
198 f99fe99d Nikos Skalkotos
             self.part_entry_size,
199 f99fe99d Nikos Skalkotos
             self.part_crc32) = struct.unpack(self.format, block)
200 331aa0ec Nikos Skalkotos
201 331aa0ec Nikos Skalkotos
        def pack(self):
202 c0240ac1 Nikos Skalkotos
            """Packs a GPT Header to a binary string."""
203 331aa0ec Nikos Skalkotos
            return struct.pack(self.format,
204 f99fe99d Nikos Skalkotos
                               self.signature,
205 f99fe99d Nikos Skalkotos
                               self.revision,
206 f99fe99d Nikos Skalkotos
                               self.hdr_size,
207 f99fe99d Nikos Skalkotos
                               self.header_crc32,
208 f99fe99d Nikos Skalkotos
                               self.current_lba,
209 f99fe99d Nikos Skalkotos
                               self.backup_lba,
210 f99fe99d Nikos Skalkotos
                               self.first_usable_lba,
211 f99fe99d Nikos Skalkotos
                               self.last_usable_lba,
212 f99fe99d Nikos Skalkotos
                               self.uuid,
213 f99fe99d Nikos Skalkotos
                               self.part_entry_start,
214 f99fe99d Nikos Skalkotos
                               self.part_count,
215 f99fe99d Nikos Skalkotos
                               self.part_entry_size,
216 f99fe99d Nikos Skalkotos
                               self.part_crc32)
217 331aa0ec Nikos Skalkotos
218 c0240ac1 Nikos Skalkotos
        @staticmethod
219 c0240ac1 Nikos Skalkotos
        def size():
220 88f83027 Nikos Skalkotos
            """Return the size of a GPT Header."""
221 c0240ac1 Nikos Skalkotos
            return struct.calcsize(GPTPartitionTable.GPTHeader.format)
222 c0240ac1 Nikos Skalkotos
223 c0240ac1 Nikos Skalkotos
        def __str__(self):
224 35b13de5 Nikos Skalkotos
            """Print a GPTHeader"""
225 f99fe99d Nikos Skalkotos
            return "Signature: %s\n" % self.signature + \
226 f99fe99d Nikos Skalkotos
                   "Revision: %r\n" % self.revision + \
227 f99fe99d Nikos Skalkotos
                   "Header Size: %d\n" % self.hdr_size + \
228 f99fe99d Nikos Skalkotos
                   "CRC32: %d\n" % self.header_crc32 + \
229 f99fe99d Nikos Skalkotos
                   "Current LBA: %d\n" % self.current_lba + \
230 f99fe99d Nikos Skalkotos
                   "Backup LBA: %d\n" % self.backup_lba + \
231 f99fe99d Nikos Skalkotos
                   "First Usable LBA: %d\n" % self.first_usable_lba + \
232 f99fe99d Nikos Skalkotos
                   "Last Usable LBA: %d\n" % self.last_usable_lba + \
233 f99fe99d Nikos Skalkotos
                   "Disk GUID: %s\n" % uuid.UUID(bytes=self.uuid) + \
234 f99fe99d Nikos Skalkotos
                   "Partition entries starting LBA: %d\n" % \
235 f99fe99d Nikos Skalkotos
                   self.part_entry_start + \
236 f99fe99d Nikos Skalkotos
                   "Number of Partition entries: %d\n" % self.part_count + \
237 f99fe99d Nikos Skalkotos
                   "Size of a partition entry: %d\n" % self.part_entry_size + \
238 f99fe99d Nikos Skalkotos
                   "CRC32 of partition array: %s\n" % self.part_crc32
239 331aa0ec Nikos Skalkotos
240 331aa0ec Nikos Skalkotos
    def __init__(self, disk):
241 88f83027 Nikos Skalkotos
        """Create a GPTPartitionTable instance"""
242 331aa0ec Nikos Skalkotos
        self.disk = disk
243 331aa0ec Nikos Skalkotos
        with open(disk, "rb") as d:
244 5b801534 Nikos Skalkotos
            # MBR (Logical block address 0)
245 331aa0ec Nikos Skalkotos
            lba0 = d.read(BLOCKSIZE)
246 331aa0ec Nikos Skalkotos
            self.mbr = MBR(lba0)
247 c0240ac1 Nikos Skalkotos
248 331aa0ec Nikos Skalkotos
            # Primary GPT Header (LBA 1)
249 c0240ac1 Nikos Skalkotos
            raw_header = d.read(self.GPTHeader.size())
250 c0240ac1 Nikos Skalkotos
            self.primary = self.GPTHeader(raw_header)
251 c0240ac1 Nikos Skalkotos
252 331aa0ec Nikos Skalkotos
            # Partition entries (LBA 2...34)
253 331aa0ec Nikos Skalkotos
            d.seek(self.primary.part_entry_start * BLOCKSIZE)
254 331aa0ec Nikos Skalkotos
            entries_size = self.primary.part_count * \
255 f99fe99d Nikos Skalkotos
                self.primary.part_entry_size
256 331aa0ec Nikos Skalkotos
            self.part_entries = d.read(entries_size)
257 c0240ac1 Nikos Skalkotos
258 331aa0ec Nikos Skalkotos
            # Secondary GPT Header (LBA -1)
259 331aa0ec Nikos Skalkotos
            d.seek(self.primary.backup_lba * BLOCKSIZE)
260 c0240ac1 Nikos Skalkotos
            raw_header = d.read(self.GPTHeader.size())
261 c0240ac1 Nikos Skalkotos
            self.secondary = self.GPTHeader(raw_header)
262 331aa0ec Nikos Skalkotos
263 331aa0ec Nikos Skalkotos
    def size(self):
264 88f83027 Nikos Skalkotos
        """Return the payload size of GPT partitioned device."""
265 c0240ac1 Nikos Skalkotos
        return (self.primary.backup_lba + 1) * BLOCKSIZE
266 331aa0ec Nikos Skalkotos
267 9666a511 Nikos Skalkotos
    def shrink(self, size, old_size):
268 c0240ac1 Nikos Skalkotos
        """Move the secondary GPT Header entries to the address specified by
269 c0240ac1 Nikos Skalkotos
        size parameter.
270 c0240ac1 Nikos Skalkotos
        """
271 331aa0ec Nikos Skalkotos
272 9666a511 Nikos Skalkotos
        # Most partition manipulation programs leave 2048 sector after the last
273 9666a511 Nikos Skalkotos
        # partition
274 9666a511 Nikos Skalkotos
        aligned = size + 2048 * BLOCKSIZE
275 9666a511 Nikos Skalkotos
276 9666a511 Nikos Skalkotos
        # new_size is at least: size + Partition Entries + Secondary GPT Header
277 9666a511 Nikos Skalkotos
        new_size = aligned if aligned <= old_size else \
278 f99fe99d Nikos Skalkotos
            size + len(self.part_entries) + BLOCKSIZE
279 9666a511 Nikos Skalkotos
280 9666a511 Nikos Skalkotos
        assert new_size <= old_size, "The secodary GPT fits in the device"
281 9666a511 Nikos Skalkotos
282 9666a511 Nikos Skalkotos
        if new_size == self.size():
283 9666a511 Nikos Skalkotos
            return new_size
284 331aa0ec Nikos Skalkotos
285 331aa0ec Nikos Skalkotos
        lba_count = new_size // BLOCKSIZE
286 331aa0ec Nikos Skalkotos
287 331aa0ec Nikos Skalkotos
        # Correct MBR
288 c0240ac1 Nikos Skalkotos
        #TODO: Check if the partition tables is hybrid
289 331aa0ec Nikos Skalkotos
        self.mbr.part[0].sector_count = (new_size // BLOCKSIZE) - 1
290 331aa0ec Nikos Skalkotos
291 c0240ac1 Nikos Skalkotos
        # Fix Primary header
292 331aa0ec Nikos Skalkotos
        self.primary.header_crc32 = 0
293 331aa0ec Nikos Skalkotos
        self.primary.backup_lba = lba_count - 1  # LBA-1
294 331aa0ec Nikos Skalkotos
        self.primary.last_usable_lba = lba_count - 34  # LBA-34
295 331aa0ec Nikos Skalkotos
        self.primary.header_crc32 = \
296 f99fe99d Nikos Skalkotos
            binascii.crc32(self.primary.pack()) & 0xffffffff
297 331aa0ec Nikos Skalkotos
298 c0240ac1 Nikos Skalkotos
        # Fix Secondary header
299 331aa0ec Nikos Skalkotos
        self.secondary.header_crc32 = 0
300 331aa0ec Nikos Skalkotos
        self.secondary.current_lba = self.primary.backup_lba
301 331aa0ec Nikos Skalkotos
        self.secondary.last_usable_lba = lba_count - 34  # LBA-34
302 331aa0ec Nikos Skalkotos
        self.secondary.part_entry_start = lba_count - 33  # LBA-33
303 331aa0ec Nikos Skalkotos
        self.secondary.header_crc32 = \
304 f99fe99d Nikos Skalkotos
            binascii.crc32(self.secondary.pack()) & 0xffffffff
305 331aa0ec Nikos Skalkotos
306 331aa0ec Nikos Skalkotos
        # Copy the new partition table back to the device
307 331aa0ec Nikos Skalkotos
        with open(self.disk, "wb") as d:
308 331aa0ec Nikos Skalkotos
            d.write(self.mbr.pack())
309 331aa0ec Nikos Skalkotos
            d.write(self.primary.pack())
310 c0240ac1 Nikos Skalkotos
            d.write('\x00' * (BLOCKSIZE - self.primary.size()))
311 b0376b3f Nikos Skalkotos
            d.write(self.part_entries)
312 331aa0ec Nikos Skalkotos
            d.seek(self.secondary.part_entry_start * BLOCKSIZE)
313 331aa0ec Nikos Skalkotos
            d.write(self.part_entries)
314 331aa0ec Nikos Skalkotos
            d.seek(self.primary.backup_lba * BLOCKSIZE)
315 331aa0ec Nikos Skalkotos
            d.write(self.secondary.pack())
316 c0240ac1 Nikos Skalkotos
            d.write('\x00' * (BLOCKSIZE - self.secondary.size()))
317 331aa0ec Nikos Skalkotos
318 331aa0ec Nikos Skalkotos
        return new_size
319 331aa0ec Nikos Skalkotos
320 331aa0ec Nikos Skalkotos
if __name__ == '__main__':
321 331aa0ec Nikos Skalkotos
    ptable = GPTPartitionTable(sys.argv[1])
322 331aa0ec Nikos Skalkotos
323 c0240ac1 Nikos Skalkotos
    print "MBR:\n%s" % ptable.mbr
324 c0240ac1 Nikos Skalkotos
    print "Primary partition table:\n%s" % ptable.primary
325 c0240ac1 Nikos Skalkotos
    print "Secondary partition table:\n%s" % ptable.secondary
326 331aa0ec Nikos Skalkotos
327 331aa0ec Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :