Statistics
| Branch: | Tag: | Revision:

root / image_creator / gpt.py @ 1d413d1e

History | View | Annotate | Download (11.4 kB)

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