forked from openwrt-xiaomi/xmir-patcher
-
Notifications
You must be signed in to change notification settings - Fork 0
/
envbuffer.py
102 lines (85 loc) · 2.63 KB
/
envbuffer.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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import re
import types
import binascii
class EnvBuffer():
addr = None
data = None # partition dump
offset = None # ENV offset in partition
len = 0
max_size = None
var = {} # key=value
encoding = 'latin_1'
crc_prefix = True
delim = '\x00'
def __init__(self, data = None, delim = '\x00', crc_prefix = True, encoding = 'latin_1'):
self.encoding = encoding
self.delim = delim
self.crc_prefix = crc_prefix
self.var = {}
if data is not None:
prefix_len = 4 if crc_prefix else 0
if isinstance(data, str):
self.var = self.parse_env(data, delim)
else:
end = data.find((delim + delim).encode(encoding), prefix_len)
if (end > prefix_len):
data = data[prefix_len:end+1]
self.var = self.parse_env_b(data, delim, encoding)
def parse_env_b(self, data, delim, encoding = 'latin_1'):
dict = {}
self.len = len(data)
data = data.split(delim.encode('latin_1'))
for i, s in enumerate(data):
s = s.strip()
if len(s) < 1:
continue
x = s.find(b'=')
if x == 0:
continue
if x >= 1:
key = s[0:x].decode(encoding)
val = s[x+1:].decode(encoding)
dict[key.strip()] = val.strip()
else:
key = s.decode(encoding)
dict[key.strip()] = None
return dict
def parse_env(self, data, delim):
dict = {}
self.len = len(data)
data = data.split(delim)
for i, s in enumerate(data):
s = s.strip()
if len(s) < 1:
continue
x = s.find('=')
if x == 0:
continue
if x >= 1:
key = (s[0:x]).strip()
if key:
dict[key] = (s[x+1:]).strip()
else:
dict[s.strip()] = None
return dict
def set_env(self, key, value):
self.var[key] = value
def pack(self, bufsize, crc_prefix = None, encoding = None):
crc_prefix = crc_prefix if crc_prefix is not None else self.crc_prefix
encoding = encoding if encoding is not None else self.encoding
buf = b''
if self.var:
for i, (k, v) in enumerate(self.var.items()):
v = '' if (v is None) else ('=' + v)
buf += (k + v + '\x00').encode(encoding)
if len(buf) + 64 > bufsize:
raise OSError("Buffer overflow")
prefix_len = 4 if crc_prefix else 0
buf += b'\x00' * (bufsize - len(buf) - prefix_len)
crc = binascii.crc32(buf)
buf = (crc).to_bytes(4, byteorder='little') + buf
return buf