1 '''Get image information, such as partition table, block id fstab etc.
6 from subprocess import check_output, CalledProcessError
7 from itertools import islice, chain
11 "Parse output of parted command"
12 column = re.compile(r'([A-Z][a-z\s]*?)((?=[A-Z])|$)')
17 Disk /home/xxx/tmp/images/small.raw: 839909376B
18 Sector size (logical/physical): 512B/512B
19 Partition Table: msdos
21 Number Start End Size Type File system Flags
22 1 1048576B 34602495B 33553920B primary ext4 boot
23 2 34603008B 839909375B 805306368B primary ext4
28 for line in output.splitlines():
33 key, val = line.split(':', 1)
34 headers[key.lower()] = val.strip()
35 elif state == 'title':
38 for col, _ in column.findall(line):
39 title = col.rstrip().lower()
40 getter = slice(start, start+len(col))
41 titles.append((title, getter))
45 part = dict([(title, line[getter].strip())
46 for title, getter in titles])
47 for title in ('start',): # start, end, size
48 part[title] = int(part[title][:-1]) # remove tailing "B"
49 part['number'] = int(part['number'])
53 cmd = ['parted', img, '-s', 'unit B print']
54 output = check_output(cmd)
58 def blkid(img, offset_in_bytes):
59 "Parse output of blkid command"
62 sdb.raw: LABEL="boot" UUID="2995b233-ff79-4719-806d-d7f42b34a133" \
63 VERSION="1.0" TYPE="ext4" USAGE="filesystem"
65 output = output.splitlines()[0].split(': ', 1)[1]
67 for item in output.split():
68 key, val = item.split('=', 1)
69 info[key.lower()] = val[1:-1] # remove double quotes
72 cmd = ['blkid', '-p', '-O', str(offset_in_bytes), '-o', 'full', img]
73 output = check_output(cmd)
78 "Parse output of gdisk"
79 cmd = ['gdisk', '-l', img]
83 GPT fdisk (gdisk) version 0.8.1
91 Found valid GPT with protective MBR; using GPT.
92 Disk tizen_20131115.3_ivi-efi-i586-sdb.raw: 7809058 sectors, 3.7 GiB
93 Logical sector size: 512 bytes
94 Disk identifier (GUID): 4A6D60CE-C42D-4A81-B82B-120624CE867E
95 Partition table holds up to 128 entries
96 First usable sector is 34, last usable sector is 7809024
97 Partitions will be aligned on 2048-sector boundaries
98 Total free space is 2049 sectors (1.0 MiB)
100 Number Start (sector) End (sector) Size Code Name
101 1 2048 133085 64.0 MiB EF00 primary
102 2 133120 7809023 3.7 GiB 0700 primary
104 lines = output.splitlines()
106 line = [i for i in lines if i.startswith('Logical sector size:')]
108 raise Exception("Can't find sector size from gdisk output:%s:%s"
109 % (" ".join(cmd), output))
110 size = int(line[0].split(':', 1)[1].strip().split()[0])
115 if not line.startswith(' ') or \
116 not line.lstrip().split()[0].isdigit():
118 number, start, _ = line.lstrip().split(None, 2)
119 parts.append(dict(number=int(number), start=int(start)*size))
122 output = check_output(cmd)
128 A dict representing fstab file.
129 Key is <mount point>, corresponding value is its whole entry
131 def __init__(self, filename):
132 with open(filename) as stream:
133 output = stream.read()
134 data = self._parse(output)
135 super(FSTab, self).__init__(data)
137 FS = re.compile(r'/dev/sd[a-z](\d+)|UUID=(.*)')
139 def _parse(self, output):
140 '''Parse fstab in this format:
141 <file system> <mount point> <type> <options> <dump> <pass>
144 for line in output.splitlines():
145 fstype, mountpoint, _ = line.split(None, 2)
146 mres = self.FS.match(fstype)
150 number, uuid = mres.group(1), mres.group(2)
152 item = {"number": number}
154 item = {"uuid": uuid}
156 mountpoints[mountpoint] = item
160 def guess(cls, paths):
161 '''Guess fstab location from all partitions of the image
163 guess1 = (os.path.join(path, 'etc', 'fstab') for path in paths)
164 guess2 = (os.path.join(path, 'fstab') for path in paths)
165 guesses = chain(guess1, guess2)
166 exists = filter(os.path.exists, guesses)
167 one = list(islice(exists, 1))
168 return cls(one[0]) if one else None
171 def get_partition_info(img):
172 '''Get partition table information of image'''
175 except CalledProcessError as err:
176 print(err, file=sys.stderr)
177 # Sometimes parted could failed with error
178 # like this, then we try gdisk.
179 # "Error during translation: Invalid or incomplete
180 # multibyte or wide character"
183 part['blkid'] = blkid(img, part['start'])