Skip to content

Commit 6474e5e

Browse files
committed
WIP: support mmap as source for package
Based on suggestion from @qkaiser. This will make it easier to integrate with unblob (see onekey-sec/unblob#1244).
1 parent b9cad15 commit 6474e5e

File tree

2 files changed

+50
-5
lines changed

2 files changed

+50
-5
lines changed

src/pymsi/package.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import copy
22
import io
3+
import mmap
34
from pathlib import Path
45
from typing import Iterator, Optional, Union
56

@@ -18,13 +19,14 @@
1819

1920

2021
class Package:
21-
def __init__(self, path_or_bytesio: Union[Path, io.BytesIO]):
22-
if isinstance(path_or_bytesio, io.BytesIO):
23-
self.path = None
24-
self.file = path_or_bytesio
25-
else:
22+
# TODO: consider typing.BinaryIO
23+
def __init__(self, path_or_bytesio: Union[Path, io.BytesIO, mmap.mmap]):
24+
if isinstance(path_or_bytesio, Path):
2625
self.path = path_or_bytesio.resolve(True)
2726
self.file = self.path.open("rb")
27+
else:
28+
self.path = None
29+
self.file = path_or_bytesio
2830
self.tables = {}
2931
self.ole = None
3032
self.summary = None

tests/io.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import pytest
2+
import mmap
3+
4+
from pathlib import Path
5+
6+
import pymsi
7+
8+
def read_package(path_or_bytesio):
9+
with pymsi.Package(path_or_bytesio) as package:
10+
msi = pymsi.Msi(package)
11+
msi.pretty_print()
12+
13+
# Function to read a package using Path
14+
def read_package_path(file_path):
15+
path = Path(file_path)
16+
return read_package(path)
17+
18+
# Function to read a package using with open
19+
def read_package_with_open(file_path):
20+
with open(file_path, "rb") as f:
21+
return read_package(f)
22+
23+
# Function to read a package using mmap
24+
def read_package_mmap(file_path):
25+
with open(file_path, "r+b") as f:
26+
mm = mmap.mmap(f.fileno(), 0)
27+
return read_package(mm)
28+
29+
# Test cases
30+
@pytest.mark.parametrize("read_package_func", [
31+
read_package_path,
32+
read_package_with_open,
33+
read_package_mmap
34+
])
35+
def test_read_package(read_package_func):
36+
test_file = "powertoys.msi"
37+
38+
read_package_func(test_file)
39+
40+
# TODO: add some test?
41+
42+
if __name__ == "__main__":
43+
pytest.main()

0 commit comments

Comments
 (0)