Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy a file using pysmb from windows to linux #213

Closed
prathishpkr opened this issue Aug 8, 2023 · 8 comments
Closed

Copy a file using pysmb from windows to linux #213

prathishpkr opened this issue Aug 8, 2023 · 8 comments

Comments

@prathishpkr
Copy link

Copy a file using smb from windows to remote linux and linux to remote windows, is that possible using retrieveFile() or storeFile().

import smbclient
from smb.SMBConnection import SMBConnection

def Copy_data_linux_to_windows(source_file, destination_file, username, password, server_ip, share_name):
try:
conn = SMBConnection(username, password, '', '')

    conn = connect(server_ip, 445)

    #with smbclient.open_file(source_path, mode ="rb", username=username, password=password, remote_host=remote_host, port=port) as f:
    with open(source_file, "rb") as local_file:
            
            with conn.retrieveFile(share_name, destination_file, overwrite=True) as remote_file:
                 
                 remote_file.write(local_file.read())

    print("File Copied successfully from Linux to Win")

except Exception as e:
    print("Error occurred while copying file from Linux to Windows: {e}")

finally:
     conn.close()            

if name == "main":
source_file = "/tmp/Copy_dir/Python_Test.zip"
destination_file = r"W:\Python_Test.zip"
#destination_path ="C:\SMB\Python_Test.zip"
username = "uname"
password = ""paswrd
server_ip ="ipaddress"
share_name = "share_name"

print("Copying file from Linux to windows")
Copy_data_linux_to_windows(source_file, destination_file, server_ip, username, password, share_name)
@miketeo
Copy link
Owner

miketeo commented Aug 8, 2023

@prathishpkr Yes, pysmb can be used to copy file between Windows and Linux Samba service.
However, there are issues with your code snippet. Please refer to https://pysmb.readthedocs.io/en/latest/api/smb_SMBConnection.html for an example on how the perform the copy operation.

@prathishpkr
Copy link
Author

prathishpkr commented Aug 9, 2023

@miketeo, i have tried to upload the file from local to Samba server using storeFile method, there am getting the below issues

NFO:SMB.SMBConnection:Authentication with remote machine "IP address" for user "osboxes" will be using NTLM v2 authentication (with extended security)
Traceback (most recent call last):
File "w:/FIM_C_src/FIM-C-master/FIM-C-master/fim/Loc_SMB.py", line 50, in
transfer_file()
File "w:/FIM_C_src/FIM-C-master/FIM-C-master/fim/Loc_SMB.py", line 36, in transfer_file
conn.connect(server_ip, 445)
File "C:\Python38-32\lib\site-packages\smb\SMBConnection.py", line 129, in connect
self._pollForNetBIOSPacket(timeout)
File "C:\Python38-32\lib\site-packages\smb\SMBConnection.py", line 649, in _pollForNetBIOSPacket
self.feedData(data)
File "C:\Python38-32\lib\site-packages\nmb\base.py", line 54, in feedData
self._processNMBSessionPacket(self.data_nmb)
File "C:\Python38-32\lib\site-packages\nmb\base.py", line 75, in _processNMBSessionPacket
self.onNMBSessionMessage(packet.flags, packet.data)
File "C:\Python38-32\lib\site-packages\smb\base.py", line 128, in onNMBSessionMessage
i = self.smb_message.decode(data)
File "C:\Python38-32\lib\site-packages\smb\smb_structs.py", line 228, in decode
self._decodePayload()
File "C:\Python38-32\lib\site-packages\smb\smb_structs.py", line 255, in _decodePayload
self.payload.decode(self)
File "C:\Python38-32\lib\site-packages\smb\smb_structs.py", line 361, in decode
raise ProtocolError('Server does not support any of the pysmb dialects. Please email pysmb to add in support for your OS',
smb.smb_structs.ProtocolError: Server does not support any of the pysmb dialects. Please email pysmb to add in support for your OS
==================== SMB Message ====================
Command: 0x72 (SMB_COM_NEGOTIATE)
Status: NTSTATUS=0x00000000
Flags: 0x88
Flags2: 0xC003
PID: 26092
UID: 0
MID: 1
TID: 0
Security: 0x0000000000000000
Parameters: 2 bytes
b'ffff'
Data: 0 bytes
b''
==================== SMB Data Packet (hex) ====================
b'ff534d4272000000008803c00000000000000000000000000000ec650000010001ffff0000',

@miketeo
Copy link
Owner

miketeo commented Aug 9, 2023

@prathishpkr try to modify the smb.conf on the Samba service, and restart your Samba service.

client min protocol = SMB2
client max protocol = SMB3

More information at https://www.cyberciti.biz/faq/how-to-configure-samba-to-use-smbv2-and-disable-smbv1-on-linux-or-unix/

@prathishpkr
Copy link
Author

prathishpkr commented Aug 30, 2023

@miketeo, could you please assist me for test file for this below code, do we want to define the function 2 times for connection for SMB2 and SMB, cause below code am not able to upload the files and also large amount of data will support to transfer storefile ?

class SMBNetworkShare():
SMBDetails(hardcoded) -> declared as Glo variable.

def __init__(self, smbServerAddress, smbport, conn, smbUser, smbPassword, smbShareName, smbClientName, smbDestFolder, smbSourceFolder, smbretSourceFolder, smbretDestFolder) -> None:
    self.smbServerAddress = smbServerAddress
    self.smbShareName = smbShareName
    self.smbClientName = smbClientName
    self.smbUser = smbUser
    self.smbport = smbport
    self.password = smbPassword
    self.conn = conn
    self.smbDestFolder = smbDestFolder
    self.smbSourceFolder = smbSourceFolder
    # self.smbretSourceFolder = smbretSourceFolder
    # self.smbretDestFolder = smbDestFolder
    # self.directory_was_online = True

# SMB Connect to Samba server

def __open_connection(self) -> None:
    logger = logging.getLogger("SMBNetworkShare")
    try:
        self.conn = SMBConnection(self.smbServerAddress, self.smbport, self.smbUser,
                                  self.smbPassword, self.smbClientName, use_ntlm_v2=True, is_direct_tcp=True)
        self.conn.connect(self.smbServerAddress, 445)
    except Exception as ex:
        logger.error('Failed to connect smb server "(' +
                     self.smbServerAddress + '":' + str(ex))

def local_dir_list(self, dir: str):  # Local dir
    list_dir = []
    try:
        # SMB_FILE_ATTRIBUTE_ARCHIVE | SMB_FILE_ATTRIBUTE_INCL_NORMAL)
        local_dir = os.listdir(dir)
        for file_list in local_dir:
            file_list.append(list_dir)
    except Exception as e:
        logging.error("Error occurred while listing files", str(e))

# -> None: #smb_shareName(target_dir)
def copy_to(self, SMBConnection, source_dir: str, target_dir: str, max_attempts=3):
    logger = logging.getLogger(SMBConnection)
    # self.conn.connect()

    try:
        source_file_size = os.path.getsize(self.smbSourceFolder)

        for attempt in range(1, max_attempts + 1):

            try:

                fileList = self.local_dir_list(source_dir)
                for filename in fileList:
                    logger.info("File Copying " + filename)
                # smbDestFolder, filename)
                destPath = os.path.join(
                    self.smbDestFolder, target_dir, filename)
                # (smbSourceFolder, filename)
                srcPath = os.path.join(source_dir, filename)

                with open(srcPath, 'rb') as f:
                    # (smbShareName, destPath, f)
                    self.conn.storeFile(
                        f, self.smbShareName, destPath, overwrite=True)
                    # ********for checking successfully******
                    logger.info(f"File Uploaded ")

                    destination_file_info = self.conn.query_info(
                        self.smbDestFolder)  # get_attributes(self.smbDestFolder)
                    destination_file_size = destination_file_info.standard_infromation.endoffile

                    if source_file_size != destination_file_size:
                        logger.warning(
                            f" File {attempt} + filename + Uploaded Successfully, but filesize does not match !!!")

                        if attempt < max_attempts:
                            logger.warning(
                                f"Retrying to upload again after sleep time")
                            time.sleep(5)  # wait for 5ms to retry!!!
                        else:
                            logger.info(
                                f"Filesize are same and uploaded successfully")
                    else:
                        # Successfully done
                        return True

            except Exception as ex:
                logger.warning(
                    f"Attempt {attempt} failed: + filename + :  + {str(ex)}")

                if attempt < max_attempts:
                    logger.warning(f"Retrying after sleep time")
                    time.sleep(5)  # wait for 5ms to retry!!!
                else:
                    logger.error(
                        f'Maximum attempts reached, Failed to upload')

    finally:
        self.conn.disconnect()
        if conn == True:
            conn.close()

@miketeo
Copy link
Owner

miketeo commented Aug 30, 2023

Can you correct the formatting for your code?

@prathishpkr
Copy link
Author

@miketeo could you please check above format now, please check and let know.

@miketeo
Copy link
Owner

miketeo commented Aug 31, 2023

self.conn = SMBConnection(self.smbServerAddress, self.smbport, self.smbUser, self.smbPassword, self.smbClientName, use_ntlm_v2=True, is_direct_tcp=True)

The parameters to the SMBConnection are incorrect. The order should be userID, password, client_machine_name, server_name, use_ntlm_v2. The server_name must be the remote Samba name, e.g. MYSERVER, or SAMBA. You need to check your Samba configuration or try to use your Windows explorer to browse for the exact name.

It's probably safe to drop support SMB and focus on supporting SMB2 in your app.
If your app fails to connect using port 445, try port 139. Sometimes, one of the ports is blocked by firewall.

@prathishpkr
Copy link
Author

@miketeo Could you please assist me, have try to find the document of to get the list of files presents in subdirectory/subfolder and the filesize checked for destination location (remote location ), is that support os.walk() which is support for localfile to fetch the list of files details(it should retrieve the files of all file format, including subdirectory/subfolder inside files) and for filesize can we retrieve the information if use the below method

destination_file_info = self.conn.query_info(self.smbDestFolder) # get_attributes(self.smbDestFolder)
destination_file_size = destination_file_info.standard_infromation.endoffile.

could you please share the documents, if we use above method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants