Add an abstraction to handle file permissions for the remote.

Signed-off-by: Luca Vizzarro <luca.vizza...@arm.com>
Reviewed-by: Paul Szczepanek <paul.szczepa...@arm.com>
---
 dts/framework/testbed_model/os_session.py    | 34 ++++++++++++++++++++
 dts/framework/testbed_model/posix_session.py | 11 ++++++-
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/dts/framework/testbed_model/os_session.py 
b/dts/framework/testbed_model/os_session.py
index 354c607357..869d575f0e 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/framework/testbed_model/os_session.py
@@ -26,6 +26,7 @@
 from abc import ABC, abstractmethod
 from collections.abc import Iterable
 from dataclasses import dataclass
+from enum import Flag, auto
 from pathlib import Path, PurePath, PurePosixPath
 
 from framework.config.node import NodeConfiguration
@@ -44,6 +45,33 @@
 from .port import Port
 
 
+class FilePermissions(Flag):
+    """The permissions for a file and/or directory."""
+
+    #:
+    OTHERS_EXECUTE = auto()
+    #:
+    OTHERS_WRITE = auto()
+    #:
+    OTHERS_READ = auto()
+    #:
+    GROUP_EXECUTE = auto()
+    #:
+    GROUP_WRITE = auto()
+    #:
+    GROUP_READ = auto()
+    #:
+    OWNER_EXECUTE = auto()
+    #:
+    OWNER_WRITE = auto()
+    #:
+    OWNER_READ = auto()
+
+    def to_octal(self) -> str:
+        """Convert this flag to an octal representation."""
+        return format(self.value, "03o")
+
+
 @dataclass(slots=True, frozen=True)
 class OSSessionInfo:
     """Supplemental OS session information.
@@ -313,6 +341,12 @@ def copy_dir_to(
                 These patterns are used with `fnmatch.fnmatch` to filter out 
files.
         """
 
+    @abstractmethod
+    def change_permissions(
+        self, remote_path: PurePath, permissions: FilePermissions, recursive: 
bool = False
+    ) -> None:
+        """Change the permissions of the given path."""
+
     @abstractmethod
     def remove_remote_file(self, remote_file_path: str | PurePath, force: bool 
= True) -> None:
         """Remove remote file, by default remove forcefully.
diff --git a/dts/framework/testbed_model/posix_session.py 
b/dts/framework/testbed_model/posix_session.py
index 2d2701e1cf..fcd2faad6b 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/framework/testbed_model/posix_session.py
@@ -26,7 +26,7 @@
 )
 
 from .cpu import Architecture
-from .os_session import OSSession, OSSessionInfo
+from .os_session import FilePermissions, OSSession, OSSessionInfo
 
 
 class PosixSession(OSSession):
@@ -146,6 +146,15 @@ def copy_dir_to(
         self.extract_remote_tarball(remote_tar_path)
         self.remove_remote_file(remote_tar_path)
 
+    def change_permissions(
+        self, remote_path: PurePath, permissions: FilePermissions, recursive: 
bool = False
+    ) -> None:
+        """Overrides :meth:`~.os_session.OSSession.change_permissions`."""
+        self.send_command(
+            f"chmod {'-R ' if recursive else ''}{permissions.to_octal()} 
{remote_path}",
+            privileged=True,
+        )
+
     def remove_remote_file(self, remote_file_path: str | PurePath, force: bool 
= True) -> None:
         """Overrides :meth:`~.os_session.OSSession.remove_remote_dir`."""
         opts = PosixSession.combine_short_options(f=force)
-- 
2.43.0

Reply via email to