Skip to content

Commit acb325c

Browse files
authored
Merge pull request #8 from desultory/dev
Improve path checks, handling symlinks when targets don't exist
2 parents d5a6af1 + 88def46 commit acb325c

File tree

4 files changed

+16
-9
lines changed

4 files changed

+16
-9
lines changed

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "pycpio"
7-
version = "1.4.1"
7+
version = "1.4.2"
8+
89
authors = [
910
{ name="Desultory", email="[email protected]" },
1011
]

src/pycpio/cpio/data.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def from_dir(path: Path, parent=None, relative=False, *args, **kwargs):
5858
return data
5959

6060
@staticmethod
61-
def from_path(path: Path, relative=False, *args, **kwargs):
61+
def from_path(path: Path, relative=False, resolve_symlink=False, *args, **kwargs):
6262
"""
6363
Create a CPIOData object from a path.
6464
If a name is provided, it will be used instead of the resolved path.
@@ -101,15 +101,14 @@ def from_path(path: Path, relative=False, *args, **kwargs):
101101
if not kwargs.pop("absolute", False):
102102
kwargs["name"] = kwargs["name"].lstrip("/")
103103

104-
# Get the inode number from the path
105-
kwargs["ino"] = path.stat().st_ino
106-
107104
# Get the mode type from the supplied path
108105
kwargs["mode"] = mode_bytes_from_path(path)
109106

110-
# Use the path's uid and gid if not provided
111-
kwargs["uid"] = kwargs.pop("uid", path.stat().st_uid)
112-
kwargs["gid"] = kwargs.pop("gid", path.stat().st_gid)
107+
for stat in ("ino", "uid", "gid"):
108+
try: # Try to get the stat from the kwargs, otherwise, get it from the path
109+
kwargs[stat] = kwargs.pop(stat, getattr(path.stat(), f"st_{stat}"))
110+
except FileNotFoundError:
111+
kwargs[stat] = 0 # If the symlink target doesn't exist, set the stat to 0
113112

114113
header = CPIOHeader(*args, **kwargs)
115114
data = CPIOData.get_subtype(b"", header, *args, **kwargs)

src/pycpio/cpio/symlink.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ def __init__(self, *args, **kwargs):
2727
if kwargs.get("recursive", False):
2828
symlink_path = symlink_path.lstrip("/")
2929
self.data = symlink_path.encode("ascii")
30-
self.header.mtime = path.stat().st_mtime
30+
try:
31+
self.header.mtime = path.stat().st_mtime
32+
except FileNotFoundError:
33+
self.header.mtime = 0 # default to 0 if file not found
3134
elif self.data is None:
3235
raise ValueError("path must be specified for symlinks")
3336

tests/test_cpio.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ def test_newc_from_kwargs(self):
140140
for attr, value in header_data.items():
141141
self.assertEqual(getattr(test_header, attr), value)
142142

143+
def test_invalid_symlink_target(self):
144+
test_symlink = Path(self.workdir.name) / 'test_symlink'
145+
test_symlink.symlink_to('/a/totally/nonexistent/path')
146+
self.cpio.append_recursive(self.workdir.name)
143147

144148
if __name__ == '__main__':
145149
main()

0 commit comments

Comments
 (0)