Statistics
| Branch: | Tag: | Revision:

root / image_creator / gpt.py @ bf3a282c

History | View | Annotate | Download (11.8 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 88f83027 Nikos Skalkotos
        """Represents a partition entry in MBR"""
46 331aa0ec Nikos Skalkotos
        format = "<B3sB3sLL"
47 331aa0ec Nikos Skalkotos
48 331aa0ec Nikos Skalkotos
        def __init__(self, raw_part):
49 88f83027 Nikos Skalkotos
            """Create a Partition instance"""
50 c0240ac1 Nikos Skalkotos
            (
51 c0240ac1 Nikos Skalkotos
                self.status,
52 331aa0ec Nikos Skalkotos
                self.start,
53 331aa0ec Nikos Skalkotos
                self.type,
54 331aa0ec Nikos Skalkotos
                self.end,
55 331aa0ec Nikos Skalkotos
                self.first_sector,
56 331aa0ec Nikos Skalkotos
                self.sector_count
57 331aa0ec Nikos Skalkotos
            ) = struct.unpack(self.format, raw_part)
58 331aa0ec Nikos Skalkotos
59 331aa0ec Nikos Skalkotos
        def pack(self):
60 88f83027 Nikos Skalkotos
            """Pack the partition values into a binary string"""
61 331aa0ec Nikos Skalkotos
            return struct.pack(self.format,
62 f99fe99d Nikos Skalkotos
                               self.status,
63 f99fe99d Nikos Skalkotos
                               self.start,
64 f99fe99d Nikos Skalkotos
                               self.type,
65 f99fe99d Nikos Skalkotos
                               self.end,
66 f99fe99d Nikos Skalkotos
                               self.first_sector,
67 f99fe99d Nikos Skalkotos
                               self.sector_count)
68 331aa0ec Nikos Skalkotos
69 c0240ac1 Nikos Skalkotos
        @staticmethod
70 c0240ac1 Nikos Skalkotos
        def size():
71 c0240ac1 Nikos Skalkotos
            """Returns the size of an MBR partition entry"""
72 c0240ac1 Nikos Skalkotos
            return struct.calcsize(MBR.Partition.format)
73 c0240ac1 Nikos Skalkotos
74 c0240ac1 Nikos Skalkotos
        def __str__(self):
75 331aa0ec Nikos Skalkotos
            start = self.unpack_chs(self.start)
76 331aa0ec Nikos Skalkotos
            end = self.unpack_chs(self.end)
77 c0240ac1 Nikos Skalkotos
            return "%d %s %d %s %d %d" % (self.status, start, self.type, end,
78 f99fe99d Nikos Skalkotos
                                          self.first_sector, self.sector_count)
79 331aa0ec Nikos Skalkotos
80 331aa0ec Nikos Skalkotos
        def unpack_chs(self, chs):
81 c0240ac1 Nikos Skalkotos
            """Unpacks a CHS address string to a tuple."""
82 331aa0ec Nikos Skalkotos
83 331aa0ec Nikos Skalkotos
            assert len(chs) == 3
84 331aa0ec Nikos Skalkotos
85 331aa0ec Nikos Skalkotos
            head = struct.unpack('<B', chs[0])[0]
86 331aa0ec Nikos Skalkotos
            sector = struct.unpack('<B', chs[1])[0] & 0x3f
87 331aa0ec Nikos Skalkotos
            cylinder = (struct.unpack('<B', chs[1])[0] & 0xC0) << 2 | \
88 331aa0ec Nikos Skalkotos
                struct.unpack('<B', chs[2])[0]
89 331aa0ec Nikos Skalkotos
90 331aa0ec Nikos Skalkotos
            return (cylinder, head, sector)
91 331aa0ec Nikos Skalkotos
92 331aa0ec Nikos Skalkotos
        def pack_chs(self, cylinder, head, sector):
93 c0240ac1 Nikos Skalkotos
            """Packs a CHS tuple to an address string."""
94 331aa0ec Nikos Skalkotos
95 331aa0ec Nikos Skalkotos
            assert 1 <= sector <= 63
96 331aa0ec Nikos Skalkotos
            assert 0 <= cylinder <= 1023
97 331aa0ec Nikos Skalkotos
            assert 0 <= head <= 255
98 331aa0ec Nikos Skalkotos
99 331aa0ec Nikos Skalkotos
            byte0 = head
100 331aa0ec Nikos Skalkotos
            byte1 = (cylinder >> 2) & 0xC0 | sector
101 331aa0ec Nikos Skalkotos
            byte2 = cylinder & 0xff
102 331aa0ec Nikos Skalkotos
103 331aa0ec Nikos Skalkotos
            return struct.pack('<BBB', byte0, byte1, byte2)
104 331aa0ec Nikos Skalkotos
105 331aa0ec Nikos Skalkotos
    format = "<444s2x16s16s16s16s2s"
106 331aa0ec Nikos Skalkotos
    """
107 331aa0ec Nikos Skalkotos
    Offset  Length          Contents
108 331aa0ec Nikos Skalkotos
    0       440(max. 446)   code area
109 331aa0ec Nikos Skalkotos
    440     2(optional)     disk signature
110 331aa0ec Nikos Skalkotos
    444     2               Usually nulls
111 331aa0ec Nikos Skalkotos
    446     16              Partition 0
112 331aa0ec Nikos Skalkotos
    462     16              Partition 1
113 331aa0ec Nikos Skalkotos
    478     16              Partition 2
114 331aa0ec Nikos Skalkotos
    494     16              Partition 3
115 331aa0ec Nikos Skalkotos
    510     2               MBR signature
116 331aa0ec Nikos Skalkotos
    """
117 331aa0ec Nikos Skalkotos
    def __init__(self, block):
118 88f83027 Nikos Skalkotos
        """Create an MBR instance"""
119 331aa0ec Nikos Skalkotos
        raw_part = {}
120 f99fe99d Nikos Skalkotos
        (self.code_area,
121 f99fe99d Nikos Skalkotos
         raw_part[0],
122 f99fe99d Nikos Skalkotos
         raw_part[1],
123 f99fe99d Nikos Skalkotos
         raw_part[2],
124 f99fe99d Nikos Skalkotos
         raw_part[3],
125 f99fe99d Nikos Skalkotos
         self.signature) = struct.unpack(self.format, block)
126 331aa0ec Nikos Skalkotos
127 331aa0ec Nikos Skalkotos
        self.part = {}
128 331aa0ec Nikos Skalkotos
        for i in range(4):
129 331aa0ec Nikos Skalkotos
            self.part[i] = self.Partition(raw_part[i])
130 331aa0ec Nikos Skalkotos
131 c0240ac1 Nikos Skalkotos
    @staticmethod
132 c0240ac1 Nikos Skalkotos
    def size():
133 88f83027 Nikos Skalkotos
        """Return the size of a Master Boot Record."""
134 c0240ac1 Nikos Skalkotos
        return struct.calcsize(MBR.format)
135 c0240ac1 Nikos Skalkotos
136 331aa0ec Nikos Skalkotos
    def pack(self):
137 88f83027 Nikos Skalkotos
        """Pack an MBR to a binary string."""
138 331aa0ec Nikos Skalkotos
        return struct.pack(self.format,
139 f99fe99d Nikos Skalkotos
                           self.code_area,
140 f99fe99d Nikos Skalkotos
                           self.part[0].pack(),
141 f99fe99d Nikos Skalkotos
                           self.part[1].pack(),
142 f99fe99d Nikos Skalkotos
                           self.part[2].pack(),
143 f99fe99d Nikos Skalkotos
                           self.part[3].pack(),
144 f99fe99d Nikos Skalkotos
                           self.signature)
145 331aa0ec Nikos Skalkotos
146 c0240ac1 Nikos Skalkotos
    def __str__(self):
147 c0240ac1 Nikos Skalkotos
        ret = ""
148 331aa0ec Nikos Skalkotos
        for i in range(4):
149 c0240ac1 Nikos Skalkotos
            ret += "Partition %d: %s\n" % (i, self.part[i])
150 f99fe99d Nikos Skalkotos
        ret += "Signature: %s %s\n" % (hex(ord(self.signature[0])),
151 f99fe99d Nikos Skalkotos
                                       hex(ord(self.signature[1])))
152 c0240ac1 Nikos Skalkotos
        return ret
153 331aa0ec Nikos Skalkotos
154 331aa0ec Nikos Skalkotos
155 331aa0ec Nikos Skalkotos
class GPTPartitionTable(object):
156 c0240ac1 Nikos Skalkotos
    """Represents a GUID Partition Table."""
157 331aa0ec Nikos Skalkotos
    class GPTHeader(object):
158 c0240ac1 Nikos Skalkotos
        """Represents a GPT Header of a GUID Partition Table."""
159 331aa0ec Nikos Skalkotos
        format = "<8s4sII4xQQQQ16sQIII"
160 331aa0ec Nikos Skalkotos
        """
161 331aa0ec Nikos Skalkotos
        Offset        Length                 Contents
162 331aa0ec Nikos Skalkotos
        0       8 bytes         Signature
163 331aa0ec Nikos Skalkotos
        8       4 bytes         Revision
164 331aa0ec Nikos Skalkotos
        12      4 bytes         Header size in little endian
165 331aa0ec Nikos Skalkotos
        16         4 bytes         CRC32 of header
166 331aa0ec Nikos Skalkotos
        20         4 bytes         Reserved; must be zero
167 331aa0ec Nikos Skalkotos
        24         8 bytes         Current LBA
168 331aa0ec Nikos Skalkotos
        32         8 bytes         Backup LBA
169 331aa0ec Nikos Skalkotos
        40         8 bytes         First usable LBA for partitions
170 331aa0ec Nikos Skalkotos
        48         8 bytes         Last usable LBA
171 331aa0ec Nikos Skalkotos
        56         16 bytes         Disk GUID
172 331aa0ec Nikos Skalkotos
        72         8 bytes         Partition entries starting LBA
173 331aa0ec Nikos Skalkotos
        80         4 bytes         Number of partition entries
174 331aa0ec Nikos Skalkotos
        84         4 bytes         Size of a partition entry
175 331aa0ec Nikos Skalkotos
        88         4 bytes         CRC32 of partition array
176 331aa0ec Nikos Skalkotos
        92         *                 Reserved; must be zeroes
177 331aa0ec Nikos Skalkotos
        LBA    size            Total
178 331aa0ec Nikos Skalkotos
        """
179 331aa0ec Nikos Skalkotos
180 331aa0ec Nikos Skalkotos
        def __init__(self, block):
181 88f83027 Nikos Skalkotos
            """Create a GPTHeader instance"""
182 f99fe99d Nikos Skalkotos
            (self.signature,
183 f99fe99d Nikos Skalkotos
             self.revision,
184 f99fe99d Nikos Skalkotos
             self.hdr_size,
185 f99fe99d Nikos Skalkotos
             self.header_crc32,
186 f99fe99d Nikos Skalkotos
             self.current_lba,
187 f99fe99d Nikos Skalkotos
             self.backup_lba,
188 f99fe99d Nikos Skalkotos
             self.first_usable_lba,
189 f99fe99d Nikos Skalkotos
             self.last_usable_lba,
190 f99fe99d Nikos Skalkotos
             self.uuid,
191 f99fe99d Nikos Skalkotos
             self.part_entry_start,
192 f99fe99d Nikos Skalkotos
             self.part_count,
193 f99fe99d Nikos Skalkotos
             self.part_entry_size,
194 f99fe99d Nikos Skalkotos
             self.part_crc32) = struct.unpack(self.format, block)
195 331aa0ec Nikos Skalkotos
196 331aa0ec Nikos Skalkotos
        def pack(self):
197 c0240ac1 Nikos Skalkotos
            """Packs a GPT Header to a binary string."""
198 331aa0ec Nikos Skalkotos
            return struct.pack(self.format,
199 f99fe99d Nikos Skalkotos
                               self.signature,
200 f99fe99d Nikos Skalkotos
                               self.revision,
201 f99fe99d Nikos Skalkotos
                               self.hdr_size,
202 f99fe99d Nikos Skalkotos
                               self.header_crc32,
203 f99fe99d Nikos Skalkotos
                               self.current_lba,
204 f99fe99d Nikos Skalkotos
                               self.backup_lba,
205 f99fe99d Nikos Skalkotos
                               self.first_usable_lba,
206 f99fe99d Nikos Skalkotos
                               self.last_usable_lba,
207 f99fe99d Nikos Skalkotos
                               self.uuid,
208 f99fe99d Nikos Skalkotos
                               self.part_entry_start,
209 f99fe99d Nikos Skalkotos
                               self.part_count,
210 f99fe99d Nikos Skalkotos
                               self.part_entry_size,
211 f99fe99d Nikos Skalkotos
                               self.part_crc32)
212 331aa0ec Nikos Skalkotos
213 c0240ac1 Nikos Skalkotos
        @staticmethod
214 c0240ac1 Nikos Skalkotos
        def size():
215 88f83027 Nikos Skalkotos
            """Return the size of a GPT Header."""
216 c0240ac1 Nikos Skalkotos
            return struct.calcsize(GPTPartitionTable.GPTHeader.format)
217 c0240ac1 Nikos Skalkotos
218 c0240ac1 Nikos Skalkotos
        def __str__(self):
219 35b13de5 Nikos Skalkotos
            """Print a GPTHeader"""
220 f99fe99d Nikos Skalkotos
            return "Signature: %s\n" % self.signature + \
221 f99fe99d Nikos Skalkotos
                   "Revision: %r\n" % self.revision + \
222 f99fe99d Nikos Skalkotos
                   "Header Size: %d\n" % self.hdr_size + \
223 f99fe99d Nikos Skalkotos
                   "CRC32: %d\n" % self.header_crc32 + \
224 f99fe99d Nikos Skalkotos
                   "Current LBA: %d\n" % self.current_lba + \
225 f99fe99d Nikos Skalkotos
                   "Backup LBA: %d\n" % self.backup_lba + \
226 f99fe99d Nikos Skalkotos
                   "First Usable LBA: %d\n" % self.first_usable_lba + \
227 f99fe99d Nikos Skalkotos
                   "Last Usable LBA: %d\n" % self.last_usable_lba + \
228 f99fe99d Nikos Skalkotos
                   "Disk GUID: %s\n" % uuid.UUID(bytes=self.uuid) + \
229 f99fe99d Nikos Skalkotos
                   "Partition entries starting LBA: %d\n" % \
230 f99fe99d Nikos Skalkotos
                   self.part_entry_start + \
231 f99fe99d Nikos Skalkotos
                   "Number of Partition entries: %d\n" % self.part_count + \
232 f99fe99d Nikos Skalkotos
                   "Size of a partition entry: %d\n" % self.part_entry_size + \
233 f99fe99d Nikos Skalkotos
                   "CRC32 of partition array: %s\n" % self.part_crc32
234 331aa0ec Nikos Skalkotos
235 331aa0ec Nikos Skalkotos
    def __init__(self, disk):
236 88f83027 Nikos Skalkotos
        """Create a GPTPartitionTable instance"""
237 331aa0ec Nikos Skalkotos
        self.disk = disk
238 331aa0ec Nikos Skalkotos
        with open(disk, "rb") as d:
239 5b801534 Nikos Skalkotos
            # MBR (Logical block address 0)
240 331aa0ec Nikos Skalkotos
            lba0 = d.read(BLOCKSIZE)
241 331aa0ec Nikos Skalkotos
            self.mbr = MBR(lba0)
242 c0240ac1 Nikos Skalkotos
243 331aa0ec Nikos Skalkotos
            # Primary GPT Header (LBA 1)
244 c0240ac1 Nikos Skalkotos
            raw_header = d.read(self.GPTHeader.size())
245 c0240ac1 Nikos Skalkotos
            self.primary = self.GPTHeader(raw_header)
246 c0240ac1 Nikos Skalkotos
247 331aa0ec Nikos Skalkotos
            # Partition entries (LBA 2...34)
248 331aa0ec Nikos Skalkotos
            d.seek(self.primary.part_entry_start * BLOCKSIZE)
249 331aa0ec Nikos Skalkotos
            entries_size = self.primary.part_count * \
250 f99fe99d Nikos Skalkotos
                self.primary.part_entry_size
251 331aa0ec Nikos Skalkotos
            self.part_entries = d.read(entries_size)
252 c0240ac1 Nikos Skalkotos
253 331aa0ec Nikos Skalkotos
            # Secondary GPT Header (LBA -1)
254 331aa0ec Nikos Skalkotos
            d.seek(self.primary.backup_lba * BLOCKSIZE)
255 c0240ac1 Nikos Skalkotos
            raw_header = d.read(self.GPTHeader.size())
256 c0240ac1 Nikos Skalkotos
            self.secondary = self.GPTHeader(raw_header)
257 331aa0ec Nikos Skalkotos
258 331aa0ec Nikos Skalkotos
    def size(self):
259 88f83027 Nikos Skalkotos
        """Return the payload size of GPT partitioned device."""
260 c0240ac1 Nikos Skalkotos
        return (self.primary.backup_lba + 1) * BLOCKSIZE
261 331aa0ec Nikos Skalkotos
262 9666a511 Nikos Skalkotos
    def shrink(self, size, old_size):
263 c0240ac1 Nikos Skalkotos
        """Move the secondary GPT Header entries to the address specified by
264 c0240ac1 Nikos Skalkotos
        size parameter.
265 c0240ac1 Nikos Skalkotos
        """
266 331aa0ec Nikos Skalkotos
267 9666a511 Nikos Skalkotos
        # Most partition manipulation programs leave 2048 sector after the last
268 9666a511 Nikos Skalkotos
        # partition
269 9666a511 Nikos Skalkotos
        aligned = size + 2048 * BLOCKSIZE
270 9666a511 Nikos Skalkotos
271 9666a511 Nikos Skalkotos
        # new_size is at least: size + Partition Entries + Secondary GPT Header
272 9666a511 Nikos Skalkotos
        new_size = aligned if aligned <= old_size else \
273 f99fe99d Nikos Skalkotos
            size + len(self.part_entries) + BLOCKSIZE
274 9666a511 Nikos Skalkotos
275 9666a511 Nikos Skalkotos
        assert new_size <= old_size, "The secodary GPT fits in the device"
276 9666a511 Nikos Skalkotos
277 9666a511 Nikos Skalkotos
        if new_size == self.size():
278 9666a511 Nikos Skalkotos
            return new_size
279 331aa0ec Nikos Skalkotos
280 331aa0ec Nikos Skalkotos
        lba_count = new_size // BLOCKSIZE
281 331aa0ec Nikos Skalkotos
282 331aa0ec Nikos Skalkotos
        # Correct MBR
283 c0240ac1 Nikos Skalkotos
        #TODO: Check if the partition tables is hybrid
284 331aa0ec Nikos Skalkotos
        self.mbr.part[0].sector_count = (new_size // BLOCKSIZE) - 1
285 331aa0ec Nikos Skalkotos
286 c0240ac1 Nikos Skalkotos
        # Fix Primary header
287 331aa0ec Nikos Skalkotos
        self.primary.header_crc32 = 0
288 331aa0ec Nikos Skalkotos
        self.primary.backup_lba = lba_count - 1  # LBA-1
289 331aa0ec Nikos Skalkotos
        self.primary.last_usable_lba = lba_count - 34  # LBA-34
290 331aa0ec Nikos Skalkotos
        self.primary.header_crc32 = \
291 f99fe99d Nikos Skalkotos
            binascii.crc32(self.primary.pack()) & 0xffffffff
292 331aa0ec Nikos Skalkotos
293 c0240ac1 Nikos Skalkotos
        # Fix Secondary header
294 331aa0ec Nikos Skalkotos
        self.secondary.header_crc32 = 0
295 331aa0ec Nikos Skalkotos
        self.secondary.current_lba = self.primary.backup_lba
296 331aa0ec Nikos Skalkotos
        self.secondary.last_usable_lba = lba_count - 34  # LBA-34
297 331aa0ec Nikos Skalkotos
        self.secondary.part_entry_start = lba_count - 33  # LBA-33
298 331aa0ec Nikos Skalkotos
        self.secondary.header_crc32 = \
299 f99fe99d Nikos Skalkotos
            binascii.crc32(self.secondary.pack()) & 0xffffffff
300 331aa0ec Nikos Skalkotos
301 331aa0ec Nikos Skalkotos
        # Copy the new partition table back to the device
302 331aa0ec Nikos Skalkotos
        with open(self.disk, "wb") as d:
303 331aa0ec Nikos Skalkotos
            d.write(self.mbr.pack())
304 331aa0ec Nikos Skalkotos
            d.write(self.primary.pack())
305 c0240ac1 Nikos Skalkotos
            d.write('\x00' * (BLOCKSIZE - self.primary.size()))
306 b0376b3f Nikos Skalkotos
            d.write(self.part_entries)
307 331aa0ec Nikos Skalkotos
            d.seek(self.secondary.part_entry_start * BLOCKSIZE)
308 331aa0ec Nikos Skalkotos
            d.write(self.part_entries)
309 331aa0ec Nikos Skalkotos
            d.seek(self.primary.backup_lba * BLOCKSIZE)
310 331aa0ec Nikos Skalkotos
            d.write(self.secondary.pack())
311 c0240ac1 Nikos Skalkotos
            d.write('\x00' * (BLOCKSIZE - self.secondary.size()))
312 331aa0ec Nikos Skalkotos
313 331aa0ec Nikos Skalkotos
        return new_size
314 331aa0ec Nikos Skalkotos
315 331aa0ec Nikos Skalkotos
if __name__ == '__main__':
316 331aa0ec Nikos Skalkotos
    ptable = GPTPartitionTable(sys.argv[1])
317 331aa0ec Nikos Skalkotos
318 c0240ac1 Nikos Skalkotos
    print "MBR:\n%s" % ptable.mbr
319 c0240ac1 Nikos Skalkotos
    print "Primary partition table:\n%s" % ptable.primary
320 c0240ac1 Nikos Skalkotos
    print "Secondary partition table:\n%s" % ptable.secondary
321 331aa0ec Nikos Skalkotos
322 331aa0ec Nikos Skalkotos
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai :