Skip to content

Commit 10648b8

Browse files
committed
add setters to the properties of ArchiveEntry
1 parent 611eabe commit 10648b8

2 files changed

Lines changed: 98 additions & 20 deletions

File tree

libarchive/entry.py

Lines changed: 92 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from contextlib import contextmanager
22
from ctypes import c_char_p, create_string_buffer
3+
import math
34

45
from . import ffi
56

@@ -38,6 +39,10 @@ def __str__(self):
3839
def filetype(self):
3940
return ffi.entry_filetype(self._entry_p)
4041

42+
@filetype.setter
43+
def filetype(self, value):
44+
ffi.entry_set_filetype(self._entry_p, value)
45+
4146
@property
4247
def uid(self):
4348
return ffi.entry_uid(self._entry_p)
@@ -89,16 +94,6 @@ def islnk(self):
8994
def issym(self):
9095
return self.filetype & 0o170000 == 0o120000
9196

92-
def _linkpath(self):
93-
return (ffi.entry_symlink_w(self._entry_p) or
94-
ffi.entry_hardlink_w(self._entry_p) or
95-
ffi.entry_symlink(self._entry_p) or
96-
ffi.entry_hardlink(self._entry_p))
97-
98-
# aliases to get the same api as tarfile
99-
linkpath = property(_linkpath)
100-
linkname = property(_linkpath)
101-
10297
@property
10398
def isreg(self):
10499
return self.filetype & 0o170000 == 0o100000
@@ -121,6 +116,16 @@ def atime(self):
121116
nsec_val = ffi.entry_atime_nsec(self._entry_p)
122117
return format_time(sec_val, nsec_val)
123118

119+
@atime.setter
120+
def atime(self, value):
121+
if isinstance(value, int):
122+
self.set_atime(value)
123+
elif isinstance(value, tuple):
124+
self.set_atime(*value)
125+
else:
126+
seconds, fraction = math.modf(value)
127+
self.set_atime(int(seconds), int(fraction * 1_000_000_000))
128+
124129
def set_atime(self, timestamp_sec, timestamp_nsec):
125130
return ffi.entry_set_atime(self._entry_p,
126131
timestamp_sec, timestamp_nsec)
@@ -131,6 +136,16 @@ def mtime(self):
131136
nsec_val = ffi.entry_mtime_nsec(self._entry_p)
132137
return format_time(sec_val, nsec_val)
133138

139+
@mtime.setter
140+
def mtime(self, value):
141+
if isinstance(value, int):
142+
self.set_mtime(value)
143+
elif isinstance(value, tuple):
144+
self.set_mtime(*value)
145+
else:
146+
seconds, fraction = math.modf(value)
147+
self.set_mtime(int(seconds), int(fraction * 1_000_000_000))
148+
134149
def set_mtime(self, timestamp_sec, timestamp_nsec):
135150
return ffi.entry_set_mtime(self._entry_p,
136151
timestamp_sec, timestamp_nsec)
@@ -141,6 +156,16 @@ def ctime(self):
141156
nsec_val = ffi.entry_ctime_nsec(self._entry_p)
142157
return format_time(sec_val, nsec_val)
143158

159+
@ctime.setter
160+
def ctime(self, value):
161+
if isinstance(value, int):
162+
self.set_ctime(value)
163+
elif isinstance(value, tuple):
164+
self.set_ctime(*value)
165+
else:
166+
seconds, fraction = math.modf(value)
167+
self.set_ctime(int(seconds), int(fraction * 1_000_000_000))
168+
144169
def set_ctime(self, timestamp_sec, timestamp_nsec):
145170
return ffi.entry_set_ctime(self._entry_p,
146171
timestamp_sec, timestamp_nsec)
@@ -151,43 +176,91 @@ def birthtime(self):
151176
nsec_val = ffi.entry_birthtime_nsec(self._entry_p)
152177
return format_time(sec_val, nsec_val)
153178

154-
def set_birthtime(self, timestamp_sec, timestamp_nsec):
155-
return ffi.entry_set_birthtime(self._entry_p,
156-
timestamp_sec, timestamp_nsec)
179+
@birthtime.setter
180+
def birthtime(self, value):
181+
if isinstance(value, int):
182+
self.set_birthtime(value)
183+
elif isinstance(value, tuple):
184+
self.set_birthtime(*value)
185+
else:
186+
seconds, fraction = math.modf(value)
187+
self.set_birthtime(int(seconds), int(fraction * 1_000_000_000))
188+
189+
def set_birthtime(self, timestamp_sec, timestamp_nsec=0):
190+
return ffi.entry_set_birthtime(
191+
self._entry_p, timestamp_sec, timestamp_nsec
192+
)
157193

158-
def _getpathname(self):
194+
@property
195+
def pathname(self):
159196
return (ffi.entry_pathname_w(self._entry_p) or
160197
ffi.entry_pathname(self._entry_p))
161198

162-
def _setpathname(self, value):
199+
@pathname.setter
200+
def pathname(self, value):
163201
if not isinstance(value, bytes):
164202
value = value.encode('utf8')
165203
ffi.entry_update_pathname_utf8(self._entry_p, c_char_p(value))
166204

167-
pathname = property(_getpathname, _setpathname)
168-
# aliases to get the same api as tarfile
169-
path = property(_getpathname, _setpathname)
170-
name = property(_getpathname, _setpathname)
205+
@property
206+
def linkpath(self):
207+
return (ffi.entry_symlink_w(self._entry_p) or
208+
ffi.entry_hardlink_w(self._entry_p) or
209+
ffi.entry_symlink(self._entry_p) or
210+
ffi.entry_hardlink(self._entry_p))
211+
212+
@linkpath.setter
213+
def linkpath(self, value):
214+
ffi.entry_update_link_utf8(self._entry_p, value)
215+
216+
# aliases for compatibility with the standard `tarfile` module
217+
path = property(pathname.fget, pathname.fset, doc="alias of pathname")
218+
name = path
219+
linkname = property(linkpath.fget, linkpath.fset, doc="alias of linkpath")
171220

172221
@property
173222
def size(self):
174223
if ffi.entry_size_is_set(self._entry_p):
175224
return ffi.entry_size(self._entry_p)
176225

226+
@size.setter
227+
def size(self, value):
228+
ffi.entry_set_size(self._entry_p, value)
229+
177230
@property
178231
def mode(self):
179232
return ffi.entry_mode(self._entry_p)
180233

234+
@mode.setter
235+
def mode(self, value):
236+
ffi.entry_set_mode(self._entry_p, value)
237+
181238
@property
182239
def strmode(self):
183240
# note we strip the mode because archive_entry_strmode
184241
# returns a trailing space: strcpy(bp, "?rwxrwxrwx ");
185242
return ffi.entry_strmode(self._entry_p).strip()
186243

244+
@property
245+
def perm(self):
246+
return ffi.entry_perm(self._entry_p)
247+
248+
@perm.setter
249+
def perm(self, value):
250+
ffi.entry_set_perm(self._entry_p, value)
251+
187252
@property
188253
def rdevmajor(self):
189254
return ffi.entry_rdevmajor(self._entry_p)
190255

256+
@rdevmajor.setter
257+
def rdevmajor(self, value):
258+
ffi.entry_set_rdevmajor(self._entry_p, value)
259+
191260
@property
192261
def rdevminor(self):
193262
return ffi.entry_rdevminor(self._entry_p)
263+
264+
@rdevminor.setter
265+
def rdevminor(self, value):
266+
ffi.entry_set_rdevminor(self._entry_p, value)

libarchive/ffi.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ def get_write_filter_function(filter_name):
184184
ffi('entry_size_is_set', [c_archive_entry_p], c_int)
185185
ffi('entry_mode', [c_archive_entry_p], c_int)
186186
ffi('entry_strmode', [c_archive_entry_p], c_char_p)
187+
ffi('entry_perm', [c_archive_entry_p], c_int)
187188
ffi('entry_hardlink', [c_archive_entry_p], c_char_p)
188189
ffi('entry_hardlink_w', [c_archive_entry_p], c_wchar_p)
189190
ffi('entry_symlink', [c_archive_entry_p], c_char_p)
@@ -197,13 +198,17 @@ def get_write_filter_function(filter_name):
197198
ffi('entry_set_filetype', [c_archive_entry_p, c_uint], None)
198199
ffi('entry_set_uid', [c_archive_entry_p, c_longlong], None)
199200
ffi('entry_set_gid', [c_archive_entry_p, c_longlong], None)
201+
ffi('entry_set_mode', [c_archive_entry_p, c_int], None)
200202
ffi('entry_set_perm', [c_archive_entry_p, c_int], None)
201203
ffi('entry_set_atime', [c_archive_entry_p, c_time_t, c_long], None)
202204
ffi('entry_set_mtime', [c_archive_entry_p, c_time_t, c_long], None)
203205
ffi('entry_set_ctime', [c_archive_entry_p, c_time_t, c_long], None)
204206
ffi('entry_set_birthtime', [c_archive_entry_p, c_time_t, c_long], None)
207+
ffi('entry_set_rdevmajor', [c_archive_entry_p, c_uint], None)
208+
ffi('entry_set_rdevminor', [c_archive_entry_p, c_uint], None)
205209

206-
ffi('entry_update_pathname_utf8', [c_archive_entry_p, c_char_p], None)
210+
ffi('entry_update_pathname_utf8', [c_archive_entry_p, c_char_p], c_int, check_int)
211+
ffi('entry_update_link_utf8', [c_archive_entry_p, c_char_p], c_int, check_int)
207212

208213
ffi('entry_clear', [c_archive_entry_p], c_archive_entry_p)
209214
ffi('entry_free', [c_archive_entry_p], None)

0 commit comments

Comments
 (0)