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, logger=None): 31 super(LocalFileIO, self).__init__() 32 self.logger = logger 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 self.logger.debug("[debug] Creating local directory '%s'" % self.dir) 49 os.makedirs(self.dir) 50 51 self.logger.debug("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode)) 52 53 try: 54 self.fd = open(self.dir + os.path.sep + os.path.basename(self.path), self.mode) 55 except PermissionError as err: 56 self.fd = None 57 58 # Write to remote (read local) 59 elif self.mode in ["rb"]: 60 if ntpath.sep in self.path: 61 self.dir = os.path.dirname(self.path) 62 63 self.logger.debug("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode)) 64 65 try: 66 self.fd = open(self.path, self.mode) 67 except PermissionError as err: 68 self.fd = None 69 70 if self.fd is not None: 71 if self.expected_size is None: 72 self.expected_size = os.path.getsize(filename=self.path) 73 74 # Create progress bar 75 if self.expected_size is not None: 76 self.__progress = Progress( 77 TextColumn("[bold blue]{task.description}", justify="right"), 78 BarColumn(bar_width=None), 79 "[progress.percentage]{task.percentage:>3.1f}%", 80 "•", 81 DownloadColumn(), 82 "•", 83 TransferSpeedColumn(), 84 "•", 85 TimeRemainingColumn(), 86 ) 87 self.__progress.start() 88 self.__task = self.__progress.add_task( 89 description="'%s'" % os.path.basename(self.path), 90 start=True, 91 total=self.expected_size, 92 visible=True 93 ) 94 95 def write(self, data): 96 """ 97 Writes data to the file. 98 99 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. 100 101 Args: 102 data (bytes): The data to be written to the file. 103 104 Returns: 105 int: The number of bytes written. 106 """ 107 108 if self.fd is not None: 109 if self.expected_size is not None: 110 self.__progress.update(self.__task, advance=len(data)) 111 return self.fd.write(data) 112 else: 113 return 0 114 115 def read(self, size): 116 """ 117 Reads a specified amount of data from the file. 118 119 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. 120 121 Args: 122 size (int): The number of bytes to read from the file. 123 124 Returns: 125 bytes: The data read from the file. 126 """ 127 128 if self.fd is not None: 129 read_data = self.fd.read(size) 130 if self.expected_size is not None: 131 self.__progress.update(self.__task, advance=len(read_data)) 132 return read_data 133 else: 134 return b"" 135 136 def close(self, remove=False): 137 """ 138 Closes the file descriptor and optionally removes the file. 139 140 This method ensures that the file descriptor is properly closed and the file is removed if specified. 141 It also stops the progress bar if it was initiated and cleans up the object by deleting it. 142 143 Args: 144 remove (bool): If True, the file at the path will be removed after closing the file descriptor. 145 """ 146 147 if self.fd is not None: 148 self.fd.close() 149 150 if remove: 151 try: 152 os.remove(path=self.path) 153 except (PermissionError, FileNotFoundError) as err: 154 pass 155 156 if self.expected_size is not None: 157 self.__progress.stop() 158 159 del self 160 161 def set_error(self, message): 162 """ 163 Sets an error message in the progress bar's description and modifies the progress bar to show only essential columns. 164 165 This method is used to communicate error states or important messages directly in the progress bar interface. 166 It updates the task description with the provided message and simplifies the progress bar to show only the text 167 and download columns, removing other elements like speed and time remaining which may not be relevant in an error state. 168 169 Args: 170 message (str): The error or status message to display in the progress bar. 171 """ 172 173 self.__progress.tasks[0].description = message 174 self.__progress.columns = [ 175 TextColumn("[bold blue]{task.description}", justify="right"), 176 BarColumn(bar_width=None), 177 "•", 178 DownloadColumn(), 179 ] 180 self.__progress.update(self.__task, advance=0)
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, logger=None): 32 super(LocalFileIO, self).__init__() 33 self.logger = logger 34 self.mode = mode 35 # Convert remote path format to local operating system path format 36 self.path = path.replace(ntpath.sep, os.path.sep) 37 self.dir = None 38 self.debug = False 39 self.expected_size = expected_size 40 self.keepRemotePath = keepRemotePath 41 42 # Write to local (read remote) 43 if self.mode in ["wb"]: 44 self.dir = '.' + os.path.sep 45 if keepRemotePath: 46 self.dir += os.path.dirname(self.path) 47 48 if not os.path.exists(self.dir): 49 self.logger.debug("[debug] Creating local directory '%s'" % self.dir) 50 os.makedirs(self.dir) 51 52 self.logger.debug("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode)) 53 54 try: 55 self.fd = open(self.dir + os.path.sep + os.path.basename(self.path), self.mode) 56 except PermissionError as err: 57 self.fd = None 58 59 # Write to remote (read local) 60 elif self.mode in ["rb"]: 61 if ntpath.sep in self.path: 62 self.dir = os.path.dirname(self.path) 63 64 self.logger.debug("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode)) 65 66 try: 67 self.fd = open(self.path, self.mode) 68 except PermissionError as err: 69 self.fd = None 70 71 if self.fd is not None: 72 if self.expected_size is None: 73 self.expected_size = os.path.getsize(filename=self.path) 74 75 # Create progress bar 76 if self.expected_size is not None: 77 self.__progress = Progress( 78 TextColumn("[bold blue]{task.description}", justify="right"), 79 BarColumn(bar_width=None), 80 "[progress.percentage]{task.percentage:>3.1f}%", 81 "•", 82 DownloadColumn(), 83 "•", 84 TransferSpeedColumn(), 85 "•", 86 TimeRemainingColumn(), 87 ) 88 self.__progress.start() 89 self.__task = self.__progress.add_task( 90 description="'%s'" % os.path.basename(self.path), 91 start=True, 92 total=self.expected_size, 93 visible=True 94 ) 95 96 def write(self, data): 97 """ 98 Writes data to the file. 99 100 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. 101 102 Args: 103 data (bytes): The data to be written to the file. 104 105 Returns: 106 int: The number of bytes written. 107 """ 108 109 if self.fd is not None: 110 if self.expected_size is not None: 111 self.__progress.update(self.__task, advance=len(data)) 112 return self.fd.write(data) 113 else: 114 return 0 115 116 def read(self, size): 117 """ 118 Reads a specified amount of data from the file. 119 120 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. 121 122 Args: 123 size (int): The number of bytes to read from the file. 124 125 Returns: 126 bytes: The data read from the file. 127 """ 128 129 if self.fd is not None: 130 read_data = self.fd.read(size) 131 if self.expected_size is not None: 132 self.__progress.update(self.__task, advance=len(read_data)) 133 return read_data 134 else: 135 return b"" 136 137 def close(self, remove=False): 138 """ 139 Closes the file descriptor and optionally removes the file. 140 141 This method ensures that the file descriptor is properly closed and the file is removed if specified. 142 It also stops the progress bar if it was initiated and cleans up the object by deleting it. 143 144 Args: 145 remove (bool): If True, the file at the path will be removed after closing the file descriptor. 146 """ 147 148 if self.fd is not None: 149 self.fd.close() 150 151 if remove: 152 try: 153 os.remove(path=self.path) 154 except (PermissionError, FileNotFoundError) as err: 155 pass 156 157 if self.expected_size is not None: 158 self.__progress.stop() 159 160 del self 161 162 def set_error(self, message): 163 """ 164 Sets an error message in the progress bar's description and modifies the progress bar to show only essential columns. 165 166 This method is used to communicate error states or important messages directly in the progress bar interface. 167 It updates the task description with the provided message and simplifies the progress bar to show only the text 168 and download columns, removing other elements like speed and time remaining which may not be relevant in an error state. 169 170 Args: 171 message (str): The error or status message to display in the progress bar. 172 """ 173 174 self.__progress.tasks[0].description = message 175 self.__progress.columns = [ 176 TextColumn("[bold blue]{task.description}", justify="right"), 177 BarColumn(bar_width=None), 178 "•", 179 DownloadColumn(), 180 ] 181 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.
31 def __init__(self, mode, path=None, expected_size=None, keepRemotePath=False, logger=None): 32 super(LocalFileIO, self).__init__() 33 self.logger = logger 34 self.mode = mode 35 # Convert remote path format to local operating system path format 36 self.path = path.replace(ntpath.sep, os.path.sep) 37 self.dir = None 38 self.debug = False 39 self.expected_size = expected_size 40 self.keepRemotePath = keepRemotePath 41 42 # Write to local (read remote) 43 if self.mode in ["wb"]: 44 self.dir = '.' + os.path.sep 45 if keepRemotePath: 46 self.dir += os.path.dirname(self.path) 47 48 if not os.path.exists(self.dir): 49 self.logger.debug("[debug] Creating local directory '%s'" % self.dir) 50 os.makedirs(self.dir) 51 52 self.logger.debug("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode)) 53 54 try: 55 self.fd = open(self.dir + os.path.sep + os.path.basename(self.path), self.mode) 56 except PermissionError as err: 57 self.fd = None 58 59 # Write to remote (read local) 60 elif self.mode in ["rb"]: 61 if ntpath.sep in self.path: 62 self.dir = os.path.dirname(self.path) 63 64 self.logger.debug("[debug] Openning local '%s' with mode '%s'" % (self.path, self.mode)) 65 66 try: 67 self.fd = open(self.path, self.mode) 68 except PermissionError as err: 69 self.fd = None 70 71 if self.fd is not None: 72 if self.expected_size is None: 73 self.expected_size = os.path.getsize(filename=self.path) 74 75 # Create progress bar 76 if self.expected_size is not None: 77 self.__progress = Progress( 78 TextColumn("[bold blue]{task.description}", justify="right"), 79 BarColumn(bar_width=None), 80 "[progress.percentage]{task.percentage:>3.1f}%", 81 "•", 82 DownloadColumn(), 83 "•", 84 TransferSpeedColumn(), 85 "•", 86 TimeRemainingColumn(), 87 ) 88 self.__progress.start() 89 self.__task = self.__progress.add_task( 90 description="'%s'" % os.path.basename(self.path), 91 start=True, 92 total=self.expected_size, 93 visible=True 94 )
96 def write(self, data): 97 """ 98 Writes data to the file. 99 100 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. 101 102 Args: 103 data (bytes): The data to be written to the file. 104 105 Returns: 106 int: The number of bytes written. 107 """ 108 109 if self.fd is not None: 110 if self.expected_size is not None: 111 self.__progress.update(self.__task, advance=len(data)) 112 return self.fd.write(data) 113 else: 114 return 0
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.
116 def read(self, size): 117 """ 118 Reads a specified amount of data from the file. 119 120 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. 121 122 Args: 123 size (int): The number of bytes to read from the file. 124 125 Returns: 126 bytes: The data read from the file. 127 """ 128 129 if self.fd is not None: 130 read_data = self.fd.read(size) 131 if self.expected_size is not None: 132 self.__progress.update(self.__task, advance=len(read_data)) 133 return read_data 134 else: 135 return b""
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.
137 def close(self, remove=False): 138 """ 139 Closes the file descriptor and optionally removes the file. 140 141 This method ensures that the file descriptor is properly closed and the file is removed if specified. 142 It also stops the progress bar if it was initiated and cleans up the object by deleting it. 143 144 Args: 145 remove (bool): If True, the file at the path will be removed after closing the file descriptor. 146 """ 147 148 if self.fd is not None: 149 self.fd.close() 150 151 if remove: 152 try: 153 os.remove(path=self.path) 154 except (PermissionError, FileNotFoundError) as err: 155 pass 156 157 if self.expected_size is not None: 158 self.__progress.stop() 159 160 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.
162 def set_error(self, message): 163 """ 164 Sets an error message in the progress bar's description and modifies the progress bar to show only essential columns. 165 166 This method is used to communicate error states or important messages directly in the progress bar interface. 167 It updates the task description with the provided message and simplifies the progress bar to show only the text 168 and download columns, removing other elements like speed and time remaining which may not be relevant in an error state. 169 170 Args: 171 message (str): The error or status message to display in the progress bar. 172 """ 173 174 self.__progress.tasks[0].description = message 175 self.__progress.columns = [ 176 TextColumn("[bold blue]{task.description}", justify="right"), 177 BarColumn(bar_width=None), 178 "•", 179 DownloadColumn(), 180 ] 181 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.