-
-
Notifications
You must be signed in to change notification settings - Fork 170
/
Copy pathcreate_backup.py
145 lines (132 loc) · 4.79 KB
/
create_backup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import xmir_base
import gateway
from gateway import die
import read_info
gw = gateway.Gateway()
dev = read_info.DevInfo(verbose = 0, infolevel = 1)
dev.get_dmesg()
dev.get_part_table()
if not dev.partlist or len(dev.partlist) <= 1:
die("Partition list is empty!")
fn_dir = 'backups/'
fn_old = fn_dir + 'full_dump.old'
fn_local = fn_dir + 'full_dump.bin'
fn_remote = '/tmp/mtd_dump.bin'
a_part = None
pid = None
if len(sys.argv) > 1:
for p, part in enumerate(dev.partlist):
print(' %2d > addr: 0x%08X size: 0x%08X name: "%s"' % (p, part['addr'], part['size'], part['name']))
print(" ")
a_part = input("Enter partition name or mtd number: ")
if a_part != 'a':
try:
i_part = int(a_part)
except:
i_part = None
if i_part is not None:
p = i_part
if p < 0 or p >= len(dev.partlist):
die('Partition "mtd{}" not found!'.format(a_part))
else:
p = dev.get_part_num(a_part)
if p < 0:
die('Partition "{}" not found!'.format(a_part))
name = dev.partlist[p]['name']
name = ''.join(e for e in name if e.isalnum())
fn_old = fn_dir + 'mtd{id}_{name}.old'.format(id=p, name=name)
fn_local = fn_dir + 'mtd{id}_{name}.bin'.format(id=p, name=name)
pid = p
os.makedirs(fn_dir, exist_ok = True)
def backup_and_download(pid, filename, chunk_size = 0, die_on_error = True):
global fn_dir
os.remove(filename) if os.path.exists(filename) else None
with open(filename, 'wb') as file:
pass
part_size = dev.partlist[pid]["size"]
blk_size = 128*1024
if not chunk_size:
chunk_size = 20*1024*1024
if chunk_size % blk_size != 0:
die(f'Incorrect value of chunk_size = {chunk_size}')
max_blocks = chunk_size // blk_size
dump_size = 0
while dump_size < part_size:
if dump_size % blk_size != 0:
die(f'Internal error on backup_and_download (dump_size = {dump_size})')
skip = dump_size // blk_size
fn_local = fn_dir + f'dump_mtd{pid}_{skip}.bin'
os.remove(fn_local) if os.path.exists(fn_local) else None
count = (part_size - dump_size) // blk_size
if count == 0:
count = 1
if count > max_blocks:
count = max_blocks
cmd = f"rm -f {fn_remote} ; dd if=/dev/mtd{pid} of={fn_remote} bs={blk_size} skip={skip} count={count}"
ret = gw.run_cmd(cmd, timeout = 25, die_on_error = False)
if not ret:
print(f'ERROR on execute command: "{cmd}"')
if die_on_error:
sys.exit(1)
return False
print(f'Download file "./{fn_local}"...')
try:
ret = gw.download(fn_remote, fn_local, verbose = 0)
except Exception:
print(f'ERROR: Remote file "{fn_remote}" not found!')
if die_on_error:
sys.exit(1)
return False
if not os.path.exists(fn_local) or os.path.getsize(fn_local) == 0:
print(f'ERROR: File "{fn_local}" not found!')
if die_on_error:
sys.exit(1)
gw.run_cmd("rm -f " + fn_remote)
return False
chunk_size = os.path.getsize(fn_local)
if chunk_size:
with open(fn_local, 'rb') as file:
data = file.read()
with open(filename, 'ab+') as file:
file.write(data)
dump_size += chunk_size
os.remove(fn_local)
pass
gw.run_cmd("rm -f " + fn_remote)
print(f'File "{filename}" created!"')
return True
if pid is not None:
if os.path.exists(fn_dir):
if os.path.exists(fn_local):
if os.path.exists(fn_old):
os.remove(fn_old)
os.rename(fn_local, fn_old)
backup_and_download(pid, fn_local)
print(" ")
print('Backup of "{}" saved to file "./{}"'.format(name, fn_local))
else:
print("Full backup creating...")
for p, part in enumerate(dev.partlist):
if part['addr'] == 0 and part['size'] > 0x00800000: # 8MiB
name = "FULL_DUMP"
else:
name = dev.partlist[p]['name']
name = ''.join(e for e in name if e.isalnum())
addr = dev.partlist[p]['addr']
size = dev.partlist[p]['size']
fn_old = fn_dir + 'mtd{id}_{name}.old'.format(id=p, name=name)
fn_local = fn_dir + 'mtd{id}_{name}.bin'.format(id=p, name=name)
if os.path.exists(fn_dir):
if os.path.exists(fn_local):
if os.path.exists(fn_old):
os.remove(fn_old)
os.rename(fn_local, fn_old)
ret = backup_and_download(p, fn_local, die_on_error = False)
if ret:
print('Backup of "{}" saved to file "./{}"'.format(name, fn_local))
print(" ")
print("Completed!")