Skip to content

Commit ff4f800

Browse files
committed
Clean and tidy up path module
1 parent 7753dd1 commit ff4f800

File tree

1 file changed

+64
-69
lines changed

1 file changed

+64
-69
lines changed

qiling/os/path.py

Lines changed: 64 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,12 @@
33
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
44
#
55

6-
from typing import Any, Mapping
7-
import ctypes, os, uuid
8-
9-
from pathlib import Path, PurePosixPath, PureWindowsPath, PosixPath, WindowsPath
10-
from unicorn import UcError
6+
import os
7+
from typing import Union
8+
from pathlib import Path, PurePath, PurePosixPath, PureWindowsPath
119

1210
from qiling import Qiling
13-
from qiling.os.windows.wdk_const import *
14-
from qiling.os.windows.structs import *
15-
from qiling.utils import verify_ret
11+
from qiling.const import QL_OS, QL_OS_POSIX
1612

1713
# OH-MY-WIN32 !!!
1814
# Some codes from cygwin.
@@ -25,27 +21,24 @@ class QlPathManager:
2521
def __init__(self, ql: Qiling, cwd: str):
2622
self.ql = ql
2723
self._cwd = cwd
28-
24+
2925
@property
30-
def cwd(self):
26+
def cwd(self) -> str:
3127
return self._cwd
32-
28+
3329
@cwd.setter
34-
def cwd(self, c):
35-
if c[0] != "/":
36-
self.ql.log.warning(f"Sanity check: cur_path doesn't start with a /!")
30+
def cwd(self, c: str) -> None:
31+
if not c.startswith('/'):
32+
self.ql.log.warning(f'Sanity check: path does not start with a forward slash "/"')
33+
3734
self._cwd = c
3835

3936
@staticmethod
40-
def normalize(path):
41-
if type(path) is PurePosixPath:
42-
normalized_path = PurePosixPath()
43-
elif type(path) is PureWindowsPath:
44-
normalized_path = PureWindowsPath()
45-
elif type(path) is PosixPath:
46-
normalized_path = PosixPath()
47-
elif type(path) is WindowsPath:
48-
normalized_path = WindowsPath()
37+
def normalize(path: Union[Path, PurePath]) -> Union[Path, PurePath]:
38+
# expected types: PosixPath, PurePosixPath, WindowsPath, PureWindowsPath
39+
assert isinstance(path, (Path, PurePath)), f'did not expect {type(path).__name__!r} here'
40+
41+
normalized_path = type(path)()
4942

5043
# remove anchor (necessary for Windows UNC paths) and convert to relative path
5144
if path.is_absolute():
@@ -64,101 +57,103 @@ def normalize(path):
6457
return normalized_path
6558

6659
@staticmethod
67-
def convert_win32_to_posix(rootfs, cwd, path):
68-
# rootfs is a concrete path.
69-
rootfs = Path(rootfs)
70-
# cwd and path are pure paths
71-
cwd = PurePosixPath(cwd[1:])
60+
def convert_win32_to_posix(rootfs: Union[str, Path], cwd: str, path: str) -> Path:
61+
_rootfs = Path(rootfs)
62+
_cwd = PurePosixPath(cwd[1:])
7263

73-
result = None
7464
# Things are complicated here.
7565
# See https://docs.microsoft.com/zh-cn/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN
7666
if PureWindowsPath(path).is_absolute():
77-
if (len(path) >= 2 and path[0] == '\\' and path[1] == '\\') or \
78-
(len(path) >= 3 and path[0].isalpha() and path[2] == '\\'): # \\.\PhysicalDrive0 or \\Server\Share\Directory or X:\
67+
if (len(path) >= 2 and path.startswith(r'\\')) or \
68+
(len(path) >= 3 and path[0].isalpha() and path[1:3] == ':\\'): # \\.\PhysicalDrive0 or \\Server\Share\Directory or X:\
7969
# UNC path should be handled in fs mapping. If not, append it to rootfs directly.
8070
pw = PureWindowsPath(path)
81-
result = rootfs / QlPathManager.normalize(pw)
71+
result = _rootfs / QlPathManager.normalize(pw)
8272
else:
8373
# code should never reach here.
84-
result = rootfs / QlPathManager.normalize(path)
74+
result = _rootfs / QlPathManager.normalize(path)
8575
else:
8676
if len(path) >= 3 and path[:3] == r'\\?' or path[:3] == r'\??': # \??\ or \\?\ or \Device\..
8777
# Similair to \\.\, it should be handled in fs mapping.
8878
pw = PureWindowsPath(path)
89-
result = rootfs / QlPathManager.normalize(cwd / pw.relative_to(pw.anchor).as_posix())
79+
result = _rootfs / QlPathManager.normalize(_cwd / pw.relative_to(pw.anchor).as_posix())
9080
else:
9181
# a normal relative path
92-
result = rootfs / QlPathManager.normalize(cwd / PureWindowsPath(path).as_posix())
82+
result = _rootfs / QlPathManager.normalize(_cwd / PureWindowsPath(path).as_posix())
83+
9384
return result
9485

9586
@staticmethod
96-
def convert_posix_to_win32(rootfs, cwd, path):
97-
# rootfs is a concrete path.
98-
rootfs = Path(rootfs)
99-
# cwd and path are pure paths
100-
cwd = PurePosixPath(cwd[1:])
101-
path = PurePosixPath(path)
102-
if path.is_absolute():
103-
return rootfs / QlPathManager.normalize(path)
87+
def convert_posix_to_win32(rootfs: Union[str, Path], cwd: str, path: str) -> Path:
88+
_rootfs = Path(rootfs)
89+
_cwd = PurePosixPath(cwd[1:])
90+
_path = PurePosixPath(path)
91+
92+
if _path.is_absolute():
93+
return _rootfs / QlPathManager.normalize(_path)
10494
else:
105-
return rootfs / QlPathManager.normalize(cwd / path)
95+
return _rootfs / QlPathManager.normalize(_cwd / _path)
10696

10797
@staticmethod
108-
def convert_for_native_os(rootfs, cwd, path):
109-
rootfs = Path(rootfs)
110-
cwd = PurePosixPath(cwd[1:])
111-
path = Path(path)
112-
if path.is_absolute():
113-
return rootfs / QlPathManager.normalize(path)
98+
def convert_for_native_os(rootfs: Union[str, Path], cwd: str, path: str) -> Path:
99+
_rootfs = Path(rootfs)
100+
_cwd = PurePosixPath(cwd[1:])
101+
_path = Path(path)
102+
103+
if _path.is_absolute():
104+
return _rootfs / QlPathManager.normalize(_path)
114105
else:
115-
return rootfs / QlPathManager.normalize(cwd / path.as_posix())
106+
return _rootfs / QlPathManager.normalize(_cwd / _path.as_posix())
116107

117-
def convert_path(self, rootfs, cwd, path):
118-
if (self.ql.ostype == self.ql.platform ) \
119-
or (self.ql.ostype in [QL_OS.LINUX, QL_OS.MACOS] and self.ql.platform in [QL_OS.LINUX, QL_OS.MACOS]):
108+
def convert_path(self, rootfs: Union[str, Path], cwd: str, path: str) -> Path:
109+
emulated_os = self.ql.ostype
110+
hosting_os = self.ql.platform
111+
112+
# emulated os and hosting platform are of the same type
113+
if (emulated_os == hosting_os) or (emulated_os in QL_OS_POSIX and hosting_os in QL_OS_POSIX):
120114
return QlPathManager.convert_for_native_os(rootfs, cwd, path)
121-
elif self.ql.ostype in [QL_OS.LINUX, QL_OS.MACOS] and self.ql.platform == QL_OS.WINDOWS:
115+
116+
elif emulated_os in QL_OS_POSIX and hosting_os == QL_OS.WINDOWS:
122117
return QlPathManager.convert_posix_to_win32(rootfs, cwd, path)
123-
elif self.ql.ostype == QL_OS.WINDOWS and self.ql.platform in [QL_OS.LINUX, QL_OS.MACOS]:
118+
119+
elif emulated_os == QL_OS.WINDOWS and hosting_os in QL_OS_POSIX:
124120
return QlPathManager.convert_win32_to_posix(rootfs, cwd, path)
121+
125122
else:
126-
# Fallback
127123
return QlPathManager.convert_for_native_os(rootfs, cwd, path)
128-
129-
def transform_to_link_path(self, path):
130-
rootfs = self.ql.rootfs
131-
real_path = self.convert_path(rootfs, self.cwd, path)
124+
125+
def transform_to_link_path(self, path: str) -> str:
126+
real_path = self.convert_path(self.ql.rootfs, self.cwd, path)
132127

133128
return str(real_path.absolute())
134129

135-
def transform_to_real_path(self, path):
136-
from types import FunctionType
130+
def transform_to_real_path(self, path: str) -> str:
131+
real_path = self.convert_path(self.ql.rootfs, self.cwd, path)
137132

138-
rootfs = self.ql.rootfs
139-
real_path = self.convert_path(rootfs, self.cwd, path)
140-
141133
if os.path.islink(real_path):
142134
link_path = Path(os.readlink(real_path))
135+
143136
if not link_path.is_absolute():
144137
real_path = Path(os.path.join(os.path.dirname(real_path), link_path))
145138

146139
# resolve multilevel symbolic link
147140
if not os.path.exists(real_path):
148141
path_dirs = link_path.parts
142+
149143
if link_path.is_absolute():
150144
path_dirs = path_dirs[1:]
151145

152-
for i in range(0, len(path_dirs)-1):
146+
for i in range(len(path_dirs) - 1):
153147
path_prefix = os.path.sep.join(path_dirs[:i+1])
154148
real_path_prefix = self.transform_to_real_path(path_prefix)
155149
path_remain = os.path.sep.join(path_dirs[i+1:])
156150
real_path = Path(os.path.join(real_path_prefix, path_remain))
151+
157152
if os.path.exists(real_path):
158153
break
159-
154+
160155
return str(real_path.absolute())
161156

162157
# The `relative path` here refers to the path which is relative to the rootfs.
163-
def transform_to_relative_path(self, path):
158+
def transform_to_relative_path(self, path: str) -> str:
164159
return str(Path(self.cwd) / path)

0 commit comments

Comments
 (0)