root / image_creator / gpt.py @ 67b70375
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 : |