smbclientng.core.LocalFileIO

  1#!/usr/bin/env python3
  2# -*- coding: utf-8 -*-
  3# File name          : LocalFileIO.py
  4# Author             : Podalirius (@podalirius_)
  5# Date created       : 23 may 2024
  6
  7
  8import os
  9import ntpath
 10from rich.progress import BarColumn, DownloadColumn, Progress, TextColumn, TimeRemainingColumn, TransferSpeedColumn
 11
 12
 13class LocalFileIO(object):
 14    """
 15    Class LocalFileIO is designed to handle local file input/output operations within the smbclient-ng tool.
 16    It provides functionalities to open, read, write, and manage progress of file operations based on the expected size of the file.
 17
 18    Attributes:
 19        mode (str): The mode in which the file should be opened (e.g., 'rb', 'wb').
 20        path (str): The path to the file that needs to be handled.
 21        expected_size (int, optional): The expected size of the file in bytes. This is used to display progress.
 22        debug (bool): Flag to enable debug mode which provides additional output during operations.
 23
 24    Methods:
 25        __init__(self, mode, path=None, expected_size=None, debug=False): Initializes the LocalFileIO instance.
 26        write(self, data): Writes data to the file and updates the progress bar if expected size is provided.
 27        read(self, size): Reads data from the file up to the specified size and updates the progress bar if expected size is provided.
 28    """
 29
 30    def __init__(self, mode, path=None, expected_size=None, keepRemotePath=False, debug=False):
 31        super(LocalFileIO, self).__init__()
 32        self.mode = mode
 33        # Convert remote path format to local operating system path format 
 34        self.path = path.replace(ntpath.sep, os.path.sep)
 35        self.dir = None
 36        self.debug = False
 37        self.expected_size = expected_size
 38        self.keepRemotePath = keepRemotePath
 39
 40        # Write to local (read remote)
 41        if self.mode in ["wb"]:
 42            self.dir = '.' + os.path.sep
 43            if keepRemotePath:
 44                self.dir += os.path.dirname(self.path)
 45
 46            if not os.path.exists(self.dir):
 47                if self.debug:
 48                    print("[debug] Creating local directory '%s'" % self.dir)
 49                os.makedirs(self.dir)
 50
 51            if self.debug:
 52                print("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode))
 53            
 54            self.fd = open(self.dir + os.path.sep + os.path.basename(self.path), self.mode)
 55
 56        # Write to remote (read local)
 57        elif self.mode in ["rb"]:
 58            if ntpath.sep in self.path:
 59                self.dir = os.path.dirname(self.path)
 60
 61            if self.debug:
 62                print("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode))
 63            self.fd = open(self.path, self.mode)
 64
 65            if self.expected_size is None:
 66                self.expected_size = os.path.getsize(filename=self.path)
 67
 68        # Create progress bar
 69        if self.expected_size is not None:
 70            self.__progress = Progress(
 71                TextColumn("[bold blue]{task.description}", justify="right"),
 72                BarColumn(bar_width=None),
 73                "[progress.percentage]{task.percentage:>3.1f}%",
 74                "•",
 75                DownloadColumn(),
 76                "•",
 77                TransferSpeedColumn(),
 78                "•",
 79                TimeRemainingColumn(),
 80            )
 81            self.__progress.start()
 82            self.__task = self.__progress.add_task(
 83                description="'%s'" % os.path.basename(self.path),
 84                start=True,
 85                total=self.expected_size,
 86                visible=True
 87            )
 88
 89    def write(self, data):
 90        """
 91        Writes data to the file.
 92
 93        This method writes the specified data to the file and updates the progress bar with the amount of data written if the expected size is set.
 94
 95        Args:
 96            data (bytes): The data to be written to the file.
 97
 98        Returns:
 99            int: The number of bytes written.
100        """
101
102        if self.expected_size is not None:
103            self.__progress.update(self.__task, advance=len(data))
104        return self.fd.write(data)
105    
106    def read(self, size):
107        """
108        Reads a specified amount of data from the file.
109
110        This method reads data from the file based on the size specified. It also updates the progress bar with the amount of data read if the expected size is set.
111
112        Args:
113            size (int): The number of bytes to read from the file.
114
115        Returns:
116            bytes: The data read from the file.
117        """
118
119        read_data = self.fd.read(size)
120        if self.expected_size is not None:
121            self.__progress.update(self.__task, advance=len(read_data))
122        return read_data
123
124    def close(self, remove=False):
125        """
126        Closes the file descriptor and optionally removes the file.
127
128        This method ensures that the file descriptor is properly closed and the file is removed if specified.
129        It also stops the progress bar if it was initiated and cleans up the object by deleting it.
130
131        Args:
132            remove (bool): If True, the file at the path will be removed after closing the file descriptor.
133        """
134
135        self.fd.close()
136
137        if remove:
138            os.remove(path=self.path)
139
140        if self.expected_size is not None:
141            self.__progress.stop()
142        
143        del self
144
145    def set_error(self, message):
146        """
147        Sets an error message in the progress bar's description and modifies the progress bar to show only essential columns.
148
149        This method is used to communicate error states or important messages directly in the progress bar interface.
150        It updates the task description with the provided message and simplifies the progress bar to show only the text
151        and download columns, removing other elements like speed and time remaining which may not be relevant in an error state.
152
153        Args:
154            message (str): The error or status message to display in the progress bar.
155        """
156
157        self.__progress.tasks[0].description = message
158        self.__progress.columns = [
159            TextColumn("[bold blue]{task.description}", justify="right"),
160            BarColumn(bar_width=None),
161            "•",
162            DownloadColumn(),
163        ]
164        self.__progress.update(self.__task, advance=0)
class LocalFileIO:
 14class LocalFileIO(object):
 15    """
 16    Class LocalFileIO is designed to handle local file input/output operations within the smbclient-ng tool.
 17    It provides functionalities to open, read, write, and manage progress of file operations based on the expected size of the file.
 18
 19    Attributes:
 20        mode (str): The mode in which the file should be opened (e.g., 'rb', 'wb').
 21        path (str): The path to the file that needs to be handled.
 22        expected_size (int, optional): The expected size of the file in bytes. This is used to display progress.
 23        debug (bool): Flag to enable debug mode which provides additional output during operations.
 24
 25    Methods:
 26        __init__(self, mode, path=None, expected_size=None, debug=False): Initializes the LocalFileIO instance.
 27        write(self, data): Writes data to the file and updates the progress bar if expected size is provided.
 28        read(self, size): Reads data from the file up to the specified size and updates the progress bar if expected size is provided.
 29    """
 30
 31    def __init__(self, mode, path=None, expected_size=None, keepRemotePath=False, debug=False):
 32        super(LocalFileIO, self).__init__()
 33        self.mode = mode
 34        # Convert remote path format to local operating system path format 
 35        self.path = path.replace(ntpath.sep, os.path.sep)
 36        self.dir = None
 37        self.debug = False
 38        self.expected_size = expected_size
 39        self.keepRemotePath = keepRemotePath
 40
 41        # Write to local (read remote)
 42        if self.mode in ["wb"]:
 43            self.dir = '.' + os.path.sep
 44            if keepRemotePath:
 45                self.dir += os.path.dirname(self.path)
 46
 47            if not os.path.exists(self.dir):
 48                if self.debug:
 49                    print("[debug] Creating local directory '%s'" % self.dir)
 50                os.makedirs(self.dir)
 51
 52            if self.debug:
 53                print("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode))
 54            
 55            self.fd = open(self.dir + os.path.sep + os.path.basename(self.path), self.mode)
 56
 57        # Write to remote (read local)
 58        elif self.mode in ["rb"]:
 59            if ntpath.sep in self.path:
 60                self.dir = os.path.dirname(self.path)
 61
 62            if self.debug:
 63                print("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode))
 64            self.fd = open(self.path, self.mode)
 65
 66            if self.expected_size is None:
 67                self.expected_size = os.path.getsize(filename=self.path)
 68
 69        # Create progress bar
 70        if self.expected_size is not None:
 71            self.__progress = Progress(
 72                TextColumn("[bold blue]{task.description}", justify="right"),
 73                BarColumn(bar_width=None),
 74                "[progress.percentage]{task.percentage:>3.1f}%",
 75                "•",
 76                DownloadColumn(),
 77                "•",
 78                TransferSpeedColumn(),
 79                "•",
 80                TimeRemainingColumn(),
 81            )
 82            self.__progress.start()
 83            self.__task = self.__progress.add_task(
 84                description="'%s'" % os.path.basename(self.path),
 85                start=True,
 86                total=self.expected_size,
 87                visible=True
 88            )
 89
 90    def write(self, data):
 91        """
 92        Writes data to the file.
 93
 94        This method writes the specified data to the file and updates the progress bar with the amount of data written if the expected size is set.
 95
 96        Args:
 97            data (bytes): The data to be written to the file.
 98
 99        Returns:
100            int: The number of bytes written.
101        """
102
103        if self.expected_size is not None:
104            self.__progress.update(self.__task, advance=len(data))
105        return self.fd.write(data)
106    
107    def read(self, size):
108        """
109        Reads a specified amount of data from the file.
110
111        This method reads data from the file based on the size specified. It also updates the progress bar with the amount of data read if the expected size is set.
112
113        Args:
114            size (int): The number of bytes to read from the file.
115
116        Returns:
117            bytes: The data read from the file.
118        """
119
120        read_data = self.fd.read(size)
121        if self.expected_size is not None:
122            self.__progress.update(self.__task, advance=len(read_data))
123        return read_data
124
125    def close(self, remove=False):
126        """
127        Closes the file descriptor and optionally removes the file.
128
129        This method ensures that the file descriptor is properly closed and the file is removed if specified.
130        It also stops the progress bar if it was initiated and cleans up the object by deleting it.
131
132        Args:
133            remove (bool): If True, the file at the path will be removed after closing the file descriptor.
134        """
135
136        self.fd.close()
137
138        if remove:
139            os.remove(path=self.path)
140
141        if self.expected_size is not None:
142            self.__progress.stop()
143        
144        del self
145
146    def set_error(self, message):
147        """
148        Sets an error message in the progress bar's description and modifies the progress bar to show only essential columns.
149
150        This method is used to communicate error states or important messages directly in the progress bar interface.
151        It updates the task description with the provided message and simplifies the progress bar to show only the text
152        and download columns, removing other elements like speed and time remaining which may not be relevant in an error state.
153
154        Args:
155            message (str): The error or status message to display in the progress bar.
156        """
157
158        self.__progress.tasks[0].description = message
159        self.__progress.columns = [
160            TextColumn("[bold blue]{task.description}", justify="right"),
161            BarColumn(bar_width=None),
162            "•",
163            DownloadColumn(),
164        ]
165        self.__progress.update(self.__task, advance=0)

Class LocalFileIO is designed to handle local file input/output operations within the smbclient-ng tool. It provides functionalities to open, read, write, and manage progress of file operations based on the expected size of the file.

Attributes: mode (str): The mode in which the file should be opened (e.g., 'rb', 'wb'). path (str): The path to the file that needs to be handled. expected_size (int, optional): The expected size of the file in bytes. This is used to display progress. debug (bool): Flag to enable debug mode which provides additional output during operations.

Methods: __init__(self, mode, path=None, expected_size=None, debug=False): Initializes the LocalFileIO instance. write(self, data): Writes data to the file and updates the progress bar if expected size is provided. read(self, size): Reads data from the file up to the specified size and updates the progress bar if expected size is provided.

LocalFileIO( mode, path=None, expected_size=None, keepRemotePath=False, debug=False)
31    def __init__(self, mode, path=None, expected_size=None, keepRemotePath=False, debug=False):
32        super(LocalFileIO, self).__init__()
33        self.mode = mode
34        # Convert remote path format to local operating system path format 
35        self.path = path.replace(ntpath.sep, os.path.sep)
36        self.dir = None
37        self.debug = False
38        self.expected_size = expected_size
39        self.keepRemotePath = keepRemotePath
40
41        # Write to local (read remote)
42        if self.mode in ["wb"]:
43            self.dir = '.' + os.path.sep
44            if keepRemotePath:
45                self.dir += os.path.dirname(self.path)
46
47            if not os.path.exists(self.dir):
48                if self.debug:
49                    print("[debug] Creating local directory '%s'" % self.dir)
50                os.makedirs(self.dir)
51
52            if self.debug:
53                print("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode))
54            
55            self.fd = open(self.dir + os.path.sep + os.path.basename(self.path), self.mode)
56
57        # Write to remote (read local)
58        elif self.mode in ["rb"]:
59            if ntpath.sep in self.path:
60                self.dir = os.path.dirname(self.path)
61
62            if self.debug:
63                print("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode))
64            self.fd = open(self.path, self.mode)
65
66            if self.expected_size is None:
67                self.expected_size = os.path.getsize(filename=self.path)
68
69        # Create progress bar
70        if self.expected_size is not None:
71            self.__progress = Progress(
72                TextColumn("[bold blue]{task.description}", justify="right"),
73                BarColumn(bar_width=None),
74                "[progress.percentage]{task.percentage:>3.1f}%",
75                "•",
76                DownloadColumn(),
77                "•",
78                TransferSpeedColumn(),
79                "•",
80                TimeRemainingColumn(),
81            )
82            self.__progress.start()
83            self.__task = self.__progress.add_task(
84                description="'%s'" % os.path.basename(self.path),
85                start=True,
86                total=self.expected_size,
87                visible=True
88            )
mode
path
dir
debug
expected_size
keepRemotePath
def write(self, data):
 90    def write(self, data):
 91        """
 92        Writes data to the file.
 93
 94        This method writes the specified data to the file and updates the progress bar with the amount of data written if the expected size is set.
 95
 96        Args:
 97            data (bytes): The data to be written to the file.
 98
 99        Returns:
100            int: The number of bytes written.
101        """
102
103        if self.expected_size is not None:
104            self.__progress.update(self.__task, advance=len(data))
105        return self.fd.write(data)

Writes data to the file.

This method writes the specified data to the file and updates the progress bar with the amount of data written if the expected size is set.

Args: data (bytes): The data to be written to the file.

Returns: int: The number of bytes written.

def read(self, size):
107    def read(self, size):
108        """
109        Reads a specified amount of data from the file.
110
111        This method reads data from the file based on the size specified. It also updates the progress bar with the amount of data read if the expected size is set.
112
113        Args:
114            size (int): The number of bytes to read from the file.
115
116        Returns:
117            bytes: The data read from the file.
118        """
119
120        read_data = self.fd.read(size)
121        if self.expected_size is not None:
122            self.__progress.update(self.__task, advance=len(read_data))
123        return read_data

Reads a specified amount of data from the file.

This method reads data from the file based on the size specified. It also updates the progress bar with the amount of data read if the expected size is set.

Args: size (int): The number of bytes to read from the file.

Returns: bytes: The data read from the file.

def close(self, remove=False):
125    def close(self, remove=False):
126        """
127        Closes the file descriptor and optionally removes the file.
128
129        This method ensures that the file descriptor is properly closed and the file is removed if specified.
130        It also stops the progress bar if it was initiated and cleans up the object by deleting it.
131
132        Args:
133            remove (bool): If True, the file at the path will be removed after closing the file descriptor.
134        """
135
136        self.fd.close()
137
138        if remove:
139            os.remove(path=self.path)
140
141        if self.expected_size is not None:
142            self.__progress.stop()
143        
144        del self

Closes the file descriptor and optionally removes the file.

This method ensures that the file descriptor is properly closed and the file is removed if specified. It also stops the progress bar if it was initiated and cleans up the object by deleting it.

Args: remove (bool): If True, the file at the path will be removed after closing the file descriptor.

def set_error(self, message):
146    def set_error(self, message):
147        """
148        Sets an error message in the progress bar's description and modifies the progress bar to show only essential columns.
149
150        This method is used to communicate error states or important messages directly in the progress bar interface.
151        It updates the task description with the provided message and simplifies the progress bar to show only the text
152        and download columns, removing other elements like speed and time remaining which may not be relevant in an error state.
153
154        Args:
155            message (str): The error or status message to display in the progress bar.
156        """
157
158        self.__progress.tasks[0].description = message
159        self.__progress.columns = [
160            TextColumn("[bold blue]{task.description}", justify="right"),
161            BarColumn(bar_width=None),
162            "•",
163            DownloadColumn(),
164        ]
165        self.__progress.update(self.__task, advance=0)

Sets an error message in the progress bar's description and modifies the progress bar to show only essential columns.

This method is used to communicate error states or important messages directly in the progress bar interface. It updates the task description with the provided message and simplifies the progress bar to show only the text and download columns, removing other elements like speed and time remaining which may not be relevant in an error state.

Args: message (str): The error or status message to display in the progress bar.