Skip to content

Commit

Permalink
fs: add xattr support
Browse files Browse the repository at this point in the history
  • Loading branch information
doronz88 committed Mar 6, 2022
1 parent fb613cd commit aa7029d
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/rpcclient/rpcclient/darwin/fs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import List, Mapping

from rpcclient.common import path_to_str
from rpcclient.exceptions import BadReturnValueError
from rpcclient.fs import Fs, DirEntry, ScandirIterator
Expand Down Expand Up @@ -55,6 +57,48 @@ def scandir(self, path: str = '.'):
raise BadReturnValueError(f'failed to opendir(): {path} ({self._client.last_error})')
return DarwinScandirIterator(path, dp, self._client)

@path_to_str('path')
def setxattr(self, path: str, name: str, value: bytes):
""" set an extended attribute value """
count = self._client.symbols.setxattr(path, name, value, len(value), 0, 0).c_int64
if count == -1:
raise BadReturnValueError(f'failed to setxattr(): {path} ({self._client.last_error})')

@path_to_str('path')
def removexattr(self, path: str, name: str):
""" remove an extended attribute value """
count = self._client.symbols.removexattr(path, name, 0).c_int64
if count == -1:
raise BadReturnValueError(f'failed to removexattr(): {path} ({self._client.last_error})')

@path_to_str('path')
def listxattr(self, path: str) -> List[str]:
""" list extended attribute names """
max_buf_len = 1024
with self._client.safe_malloc(max_buf_len) as xattributes_names:
count = self._client.symbols.listxattr(path, xattributes_names, max_buf_len, 0).c_int64
if count == -1:
raise BadReturnValueError(f'failed to listxattr(): {path} ({self._client.last_error})')
return [s.decode() for s in xattributes_names.peek(count).split(b'\x00')[:-1]]

@path_to_str('path')
def getxattr(self, path: str, name: str) -> bytes:
""" get an extended attribute value """
max_buf_len = 1024
with self._client.safe_malloc(max_buf_len) as value:
count = self._client.symbols.getxattr(path, name, value, max_buf_len, 0, 0).c_int64
if count == -1:
raise BadReturnValueError(f'failed to getxattr(): {path} ({self._client.last_error})')
return value.peek(count)

@path_to_str('path')
def dictxattr(self, path: str) -> Mapping[str, bytes]:
""" get a dictionary of all extended attributes """
result = {}
for k in self.listxattr(path):
result[k] = self.getxattr(path, k)
return result

@path_to_str('path')
def statfs(self, path: str):
with self._client.safe_malloc(statfs64.sizeof()) as buf:
Expand Down
9 changes: 9 additions & 0 deletions src/rpcclient/tests/test_fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,12 @@ def test_walk(client, tmp_path):
(tmp_path / 'dir_b' / 'b1.txt').touch()
(tmp_path / 'dir_b' / 'b2.txt').touch()
assert list(os.walk(tmp_path)) == list(client.fs.walk(tmp_path))


def test_xattr(client, tmp_path):
client.fs.setxattr(tmp_path, 'KEY', b'VALUE')
assert client.fs.getxattr(tmp_path, 'KEY') == b'VALUE'
assert client.fs.listxattr(tmp_path) == ['KEY']
assert client.fs.dictxattr(tmp_path) == {'KEY': b'VALUE'}
client.fs.removexattr(tmp_path, 'KEY')
assert client.fs.listxattr(tmp_path) == []

0 comments on commit aa7029d

Please sign in to comment.