Opened 6 years ago

Closed 6 years ago

#71 closed defect (worksforme)

receiving TemporaryError: 450 2 J-a: No such file or directory in listdir(path)

Reported by: ftputiluser Owned by: schwa
Priority: minor Milestone:
Component: Library Version: 2.7.1
Keywords: listdir, TemporaryError, hidden directory items Cc: miro.radenovic@…

Description

First of all i want to thank you for your work. I'm incurring in a weird problem using listdir() with a specific ftp server and i'm not sure if the problem is related to ftputil or to the ftp server. i will try to explain the problem and eventually if is not related your library, please excuse me.

i have created a program that uses internally ftputil to upload virtual machine' s backups to several ftp servers. Even if all ftp server are configured at the same (i have no control on the ftp server as they belongs to the hosting company) when i want to list directories into a particular ftp server I receive:

TemporaryError: 450   2 J-a: No such file or directory

the strange behavior is that if i re run the same command again, everything works as it should. using pdb i have summarize the problem:

(Pdb) l
 64             try:
 65                 self._ftplib.listdir(remoteFolder)
 66             except Exception:
 67                 self._ftplib.makedirs(remoteFolder)
 68
 69  ->     def listdir(self,path):
 70             return self._ftplib.listdir(path)
 71
 72         def rmtree(self, path):
 73             self._ftplib.rmtree(path)
 74
(Pdb) n
> c:\tools\backupscripts\vmexplorerbackup\ftphostfactory.py(70)listdir()
-> return self._ftplib.listdir(path)
(Pdb) self._ftplib.listdir(path)
*** TemporaryError: 450   2 J-a: No such file or directory
Debugging info: ftputil 2.7.1, Python 2.6.6 (win32)
(Pdb) self._ftplib.listdir(path)
[]
(Pdb) self._ftplib.listdir(path)
[]
(Pdb) self._ftplib.listdir(path)
[]
(Pdb)

as you can see, executing for the first time the instrucion

self._ftplib.listdir(path)

I receive the TemporaryError? 450. if I rerun the same instruction again

self._ftplib.listdir(path)

it returns [] which is the correct result. i have solved the problem by changing my code into this ugly fix:

 def listdir(self,path):
        try:
            return self._ftplib.listdir(path)
        except ftputil.ftp_error.TemporaryError:
            return self._ftplib.listdir(path)

and now everything works, but i was wondering if this could be a bug or there is something wrong with the ftp server.

i have always connected using filezilla to the server with no problems, and if this can helps you, this is the filezilla's

Risposta:	220 ProFTPD 1.3.4b Server (Hetzner Backup) [::ffff:78.47.17.107]
Comando:	USER u59969
Risposta:	331 Password required for u59969
Comando:	PASS ****************
Risposta:	230 User u59969 logged in
Comando:	SYST
Risposta:	215 UNIX Type: L8
Comando:	FEAT
Risposta:	211-Features:
Risposta:	 MDTM
Risposta:	 MFMT
Risposta:	 TVFS
Risposta:	 AUTH TLS
Risposta:	 MFF modify;UNIX.group;UNIX.mode;
Risposta:	 MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.mode*;UNIX.owner*;
Risposta:	 PBSZ
Risposta:	 PROT
Risposta:	 REST STREAM
Risposta:	 SIZE
Risposta:	211 End
Stato:	Connesso
Stato:	Lettura elenco cartelle...
Comando:	PWD
Risposta:	257 "/" is the current directory
Comando:	TYPE I
Risposta:	200 Type set to I
Comando:	PASV
Risposta:	227 Entering Passive Mode (78,47,17,107,207,127).
Comando:	MLSD
Risposta:	150 Opening BINARY mode data connection for MLSD
Risposta:	226 Transfer complete
Stato:	Contenuto cartella letto con successo
Stato:	Lettura elenco cartelle...
Comando:	CWD /VirtualMachinesBackUps
Risposta:	250 CWD command successful
Comando:	PWD
Risposta:	257 "/VirtualMachinesBackUps" is the current directory
Comando:	PASV
Risposta:	227 Entering Passive Mode (78,47,17,107,239,181).
Comando:	MLSD
Risposta:	150 Opening BINARY mode data connection for MLSD
Risposta:	226 Transfer complete

Change History (12)

comment:1 Changed 6 years ago by schwa

Keywords: listdir added
Status: newassigned

Hi Miro, thanks a lot for the investigation! :)

The "-a" looks as if it might be something to do with the recently-added support for getting data on "hidden" files (ticket #23).

Here are some tests that might help shed some light on the issue:

  • Do you get a corresponding result if you don't use ftputil, but instead list the directory with ftplib.FTP like this?
    import ftplib
    ftp = ftplib.FTP(server, username, password)
    try:
        ftp.dir(the_path)
    except ftplib.error_temp:
        print "=== again ==="
        ftp.dir(the_path)
    
  • When running the above ftplib code, you can switch on debugging with the set_debuglevel method:
    import ftplib
    ftp = ftplib.FTP(server, username, password)
    ftp.set_debuglevel(2)
    try:
        ftp.dir(the_path)
    except ftplib.error_temp:
        print "=== again ==="
        ftp.dir(the_path)
    
  • Since ftputil uses ftplib internally, you can similarly write:
    import ftputil
    import ftputil.ftp_error
    
    ftp_host = ftputil.FTPHost(server, username, password)
    ftp_host._session.set_debuglevel(2)
    try:
        ftp_host.listdir(the_path)
    except ftputil.ftp_error.TemporaryError:
        print "=== again ==="
        ftp_host.listdir(the_path)
    
  • You can switch off the usage of the -a option by setting an attribute:
    import ftputil
    import ftputil.ftp_error
    
    ftp_host = ftputil.FTPHost(server, username, password)
    print "=== _accepts_list_a_option:", ftp_host._accepts_list_a_option
    ftp_host._accepts_list_a_option = False
    # You can additionally use the debug level setting (see above).
    try:
        ftp_host.listdir(the_path)
    except ftputil.ftp_error.TemporaryError:
        print "=== again ==="
        ftp_host.listdir(the_path)
    

What results do you get?

comment:2 Changed 6 years ago by ftputiluser

using ftplib only it works well without errors, but when i switch yo ftputil, the problem persists. Please note that in the remote server, under the path "/VirtualMachinesBackUps?", now there is a folder named "Toki". here are my results: for

ftp = ftplib.FTP(server, username, password)
try:
    ftp.dir(the_path)
except ftplib.error_temp:
    print "=== again ==="
    ftp.dir(the_path

i received

drwxr-xr-x   4 u27738   u27738          4 Jan 23 16:46 Toki

for

ftp = ftplib.FTP(server, username, password)
ftp.set_debuglevel(2)
try:
    ftp.dir(the_path)
except ftplib.error_temp:
    print "=== again ==="
    ftp.dir(the_path)

i received

*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,216,112).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,216,112).'
*cmd* 'LIST /VirtualMachinesBackUps'
*put* 'LIST /VirtualMachinesBackUps\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
drwxr-xr-x   4 u27738   u27738          4 Jan 23 16:46 Toki
*get* '226 Transfer complete\r\n'
*resp* '226 Transfer complete'

as you can see with ftplib everything is ok. now, let's swith to ftputil.

ftp_host = ftputil.FTPHost(server, username, password)
ftp_host._session.set_debuglevel(2)
try:
    ftp_host.listdir(the_path)
except ftputil.ftp_error.TemporaryError:
    print "=== again ==="
    ftp_host.listdir(the_path)

i received

*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,235,41).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,235,41).'
*cmd* u'LIST -a'
*put* u'LIST -a\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
*get* '450   3 J-a: No such file or directory\r\n'
*resp* '450   3 J-a: No such file or directory'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
=== again ===
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,204,103).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,204,103).'
*cmd* u'LIST -a'
*put* u'LIST -a\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
*get* '226 Transfer complete\r\n'
*resp* '226 Transfer complete'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'CWD /VirtualMachinesBackUps'
*put* 'CWD /VirtualMachinesBackUps\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,235,254).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,235,254).'
*cmd* u'LIST -a'
*put* u'LIST -a\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
*get* '226 Transfer complete\r\n'
*resp* '226 Transfer complete'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'

ftp_host = ftputil.FTPHost(server, username, password)
print "=== _accepts_list_a_option:", ftp_host._accepts_list_a_option
ftp_host._accepts_list_a_option = False
# You can additionally use the debug level setting (see above).
try:
    ftp_host.listdir(the_path)
except ftputil.ftp_error.TemporaryError:
    print "=== again ==="
    ftp_host.listdir(the_path)

returns

=== _accepts_list_a_option: True

Please let me know if I can be more helpful to you and to your project.

comment:3 in reply to:  2 ; Changed 6 years ago by schwa

Keywords: hidden directory items added

Thanks for your feedback.

Replying to ftputiluser:

using ftplib only it works well without errors, but when i switch yo ftputil, the problem persists.

Please note that in the remote server, under the path "/VirtualMachinesBackUps?", now there is a folder named "Toki". here are my results:

for

ftp = ftplib.FTP(server, username, password)
ftp.set_debuglevel(2)
try:
    ftp.dir(the_path)
except ftplib.error_temp:
    print "=== again ==="
    ftp.dir(the_path)

i received

*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,216,112).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,216,112).'
*cmd* 'LIST /VirtualMachinesBackUps'
*put* 'LIST /VirtualMachinesBackUps\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
drwxr-xr-x   4 u27738   u27738          4 Jan 23 16:46 Toki
*get* '226 Transfer complete\r\n'
*resp* '226 Transfer complete'

as you can see with ftplib everything is ok.

Yes, this looks ok.

now, let's swith to ftputil.

ftp_host = ftputil.FTPHost(server, username, password)
ftp_host._session.set_debuglevel(2)
try:
    ftp_host.listdir(the_path)
except ftputil.ftp_error.TemporaryError:
    print "=== again ==="
    ftp_host.listdir(the_path)

i received

*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'

It's normal that ftputil checks the "intermediate" directories, but it shouldn't run CWD / twice. I don't think it's related to your problem, but I should still check this behavior.

*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,235,41).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,235,41).'
*cmd* u'LIST -a'
*put* u'LIST -a\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
*get* '450   3 J-a: No such file or directory\r\n'
*resp* '450   3 J-a: No such file or directory'

It seems the server is quite confused by the -a option in LIST -a. I can imagine that it might try to list information on a directory/file "-a", but I don't understand at all why it inserts the "J" in front. Moreover, I would expect an error message "No such file or directory" to be accompanied by a permanent error (status code 5xx), not a temporary error (status code 4xx).

...
=== again ===
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,204,103).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,204,103).'
*cmd* u'LIST -a'
*put* u'LIST -a\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
*get* '226 Transfer complete\r\n'
...

And it's really weird that it works the second time.

You didn't ask, but just a remark. You don't see the output with the VirtualMachineBackUps entry because this is collected and parsed by ftputil. (Maybe this is obvious to you, anyway. ;-) )

...
*cmd* u'LIST -a'
*put* u'LIST -a\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
*get* '226 Transfer complete\r\n'
*resp* '226 Transfer complete'
...

Nothing suspicious in the second attempt. That's what I (or we) would have expected for the first attempt, too.


ftp_host = ftputil.FTPHost(server, username, password)
print "=== _accepts_list_a_option:", ftp_host._accepts_list_a_option
ftp_host._accepts_list_a_option = False
# You can additionally use the debug level setting (see above).
try:
    ftp_host.listdir(the_path)
except ftputil.ftp_error.TemporaryError:
    print "=== again ==="
    ftp_host.listdir(the_path)

returns

=== _accepts_list_a_option: True

Sorry, I didn't write clearly what I had in mind. What I meant is: Can you please repeat your original code, but setting ftp_host._accepts_list_a_option = False immediately after setting up the connection with the FTPHost constructor? That way, ftputil shouldn't use the -a option, and I'm curious whether your problem goes away then. That is, do you get the expected directory contents on the first attempt, without the exception?

Please let me know if I can be more helpful to you and to your project.

See the previous question. :) Please tell me if you now get the expected listing without the exception on the first listdir attempt. Setting the attribute _accepts_list_a_option to False should make ftputil omit the -a option when asking for the directory contents, and you should get the same behavior as with ftplib.

Can you possibly tell me the name and/or version of the FTP server? You should be able to see something when you log into the server with an FTP command line client.

comment:4 Changed 6 years ago by schwa

It might also be interesting to repeat the first code snippet using only ftplib, but prepend the directory name you're using with "-a " ("-a" and a space). What output do you get then, again with the debug level set to 2?

comment:5 Changed 6 years ago by ftputiluser

hello back schwa,

 Can you please repeat your original code, but setting ftp_host._accepts_list_a_option = False immediately after setting up the connection with the FTPHost constructor?

I have tried what you have suggested me and it works correctly if I set ftp_host._accepts_list_a_option to False. At the first attempt it does what it should and no exception is raised :))

Can you possibly tell me the name and/or version of the FTP server? You should be able to see something when you log into the server with an FTP command line client.

Sure! using filezilla, the server's welcome message says: 220 ProFTPD 1.3.4b Server (Hetzner Backup)

comment:6 in reply to:  4 ; Changed 6 years ago by ftputiluser

ops.... I almost forgot to reply to the last question:

Replying to schwa:

It might also be interesting to repeat the first code snippet using only ftplib, but prepend the directory name you're using with "-a " ("-a" and a space). What output do you get then, again with the debug level set to 2?

ftp = ftplib.FTP(server, username, password)
try:
    ftp.dir("-a " +the_path)
except ftplib.error_temp:
    print "=== again ==="
    ftp.dir(the_path)

returns to me:

drwxr-xr-x   3 u27738   u27738          3 Jan 23 16:24 .
drwxr-xr-x   4 u27738   u27738          6 Jan 23 14:39 ..
drwxr-xr-x   3 u27738   u27738          3 Jan 28 22:35 Toki

comment:7 in reply to:  5 Changed 6 years ago by schwa

Replying to ftputiluser:

hello back schwa,

My name is Stefan Schwarzer; schwa just happens to be my user id on this Trac instance. :-)

Can you please repeat your original code, but setting ftp_host._accepts_list_a_option = False immediately after setting up the connection with the FTPHost constructor?

I have tried what you have suggested me and it works correctly if I set ftp_host._accepts_list_a_option to False. At the first attempt it does what it should and no exception is raised :))

You'll possibly lose "hidden" directory entries though. So we're not (completely) there yet. :)

Can you possibly tell me the name and/or version of the FTP server? You should be able to see something when you log into the server with an FTP command line client.

Sure! using filezilla, the server's welcome message says: 220 ProFTPD 1.3.4b Server (Hetzner Backup)

After the weird observations I had thought this might be some obscure self-hacked FTP server. Seems it isn't.

comment:8 in reply to:  6 Changed 6 years ago by schwa

Replying to ftputiluser:

Replying to schwa:

It might also be interesting to repeat the first code snippet using only ftplib, but prepend the directory name you're using with "-a " ("-a" and a space). What output do you get then, again with the debug level set to 2?

ftp = ftplib.FTP(server, username, password)
try:
    ftp.dir("-a " +the_path)
except ftplib.error_temp:
    print "=== again ==="
    ftp.dir(the_path)

returns to me:

drwxr-xr-x   3 u27738   u27738          3 Jan 23 16:24 .
drwxr-xr-x   4 u27738   u27738          6 Jan 23 14:39 ..
drwxr-xr-x   3 u27738   u27738          3 Jan 28 22:35 Toki

I had expected the same kind of exception, but now I have an idea. Could it be that you used "-a /VirtualMachinesBackUps?"? Maybe it matters whether you use a directory name after the option.

Could you please try changing into VirtualMachinesBackUps and using ftp.dir("-a"). Also try ftp.dir("-a .") (including the dot). What results do you get in both cases? Please don't forget to post the ftplib debugging output with the debug level set to 2, too (read this aloud ;-) ).

comment:9 Changed 6 years ago by ftputiluser

I'm back! sorry for the late reply, but is was a reaaaally busy week :(

here are your outputs.. first test:

print('##############')
print('# first test')
print('##############')


ftp = ftplib.FTP(server, username, password)
ftp.set_debuglevel(2)
#import pdb; pdb.set_trace()
try:
    ftp.cwd('/VirtualMachinesBackUps')
    ftp.dir("-a")
except ftplib.error_temp:
    print "=== again ==="
    ftp.dir("-a")

outputs:

##############
# first test
##############
*cmd* 'CWD /VirtualMachinesBackUps'
*put* 'CWD /VirtualMachinesBackUps\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,238,59).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,238,59).'
*cmd* 'LIST -a'
*put* 'LIST -a\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
drwxr-xr-x   3 u27738   u27738          3 Jan 23 16:24 .
drwxr-xr-x   4 u27738   u27738          6 Jan 23 14:39 ..
drwxr-xr-x   4 u27738   u27738          4 Jan 28 22:46 Toki
*get* '226 Transfer complete\r\n'

and second test...

print('##############')
print('# second test')
print('##############')



ftp = ftplib.FTP(server, username, password)
ftp.set_debuglevel(2)
#import pdb; pdb.set_trace()
try:
    ftp.cwd('/VirtualMachinesBackUps')
    ftp.dir("-a .")
except ftplib.error_temp:
    print "=== again ==="
    ftp.dir("-a .")

outputs..

##############
# second test
##############
*cmd* 'CWD /VirtualMachinesBackUps'
*put* 'CWD /VirtualMachinesBackUps\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,200,16).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,200,16).'
*cmd* 'LIST -a .'
*put* 'LIST -a .\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
drwxr-xr-x   3 u27738   u27738          3 Jan 23 16:24 .
drwxr-xr-x   4 u27738   u27738          6 Jan 23 14:39 ..
drwxr-xr-x   4 u27738   u27738          4 Jan 28 22:46 Toki
*get* '226 Transfer complete\r\n'
*resp* '226 Transfer complete'

and just to make sure that the problem is still present (and that nothing has changed in the remote ftp server), here is my third test that reproduces again the bug

print('##############')
print('# third test')
print('##############')


ftp_host = ftputil.FTPHost(server, username, password)
ftp_host._session.set_debuglevel(2)
try:
    ftp_host.listdir(the_path)
except ftputil.ftp_error.TemporaryError:
    print "=== again ==="
    ftp_host.listdir(the_path)

outputs:

##############
# third test
##############
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,206,199).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,206,199).'
*cmd* u'LIST -a'
*put* u'LIST -a\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
*get* '450   3 J-a: No such file or directory\r\n'
*resp* '450   3 J-a: No such file or directory'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
=== again ===
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,225,73).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,225,73).'
*cmd* u'LIST -a'
*put* u'LIST -a\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
*get* '226 Transfer complete\r\n'
*resp* '226 Transfer complete'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'CWD /VirtualMachinesBackUps'
*put* 'CWD /VirtualMachinesBackUps\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A\r\n'
*resp* '200 Type set to A'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (188,40,2,180,252,12).\r\n'
*resp* '227 Entering Passive Mode (188,40,2,180,252,12).'
*cmd* u'LIST -a'
*put* u'LIST -a\r\n'
*get* '150 Opening ASCII mode data connection for file list\r\n'
*resp* '150 Opening ASCII mode data connection for file list'
*get* '226 Transfer complete\r\n'
*resp* '226 Transfer complete'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'

I'm waiting for more orders! :)

comment:10 in reply to:  3 Changed 6 years ago by schwa

Replying to schwa:

Replying to ftputiluser:

i received

*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 CWD command successful\r\n'
*resp* '250 CWD command successful'

It's normal that ftputil checks the "intermediate" directories, but it shouldn't run CWD / twice. I don't think it's related to your problem, but I should still check this behavior.

I ran this test code in the debugger:

ftp_host = ftputil.FTPHost("localhost", "ftptest", local_password)
ftp_host._session.set_debuglevel(2)
import pdb; pdb.set_trace()
ftp_host.listdir("/rootdir2")

and saw that the first CWD / is from a call to _check_inaccessible_login_directory in ftputil.__init__._robust_ftp_command and the second CWD / from the call to chdir in the same function invocation, but a bit further down. I introduced the check for a potentially inaccessible login directory as a workaround several years ago. So the two consecutive CWD / seem to be ok.

comment:11 in reply to:  9 Changed 6 years ago by schwa

Hi Miro,

Sorry for the long delay. I hope you still have the test environment available.

Replying to ftputiluser:

and just to make sure that the problem is still present (and that nothing has changed in the remote ftp server), here is my third test that reproduces again the bug ...

Can you please run the following code which is, it seems, what ftputil does to "cause" the error:

ftp = ftplib.FTP(host, user, password)
ftp.set_debuglevel(2)
ftp.cwd("/")
ftp.cwd("/")
ftp.dir("-a")

For my local FTP server this gives the output:

*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 OK. Current directory is /\r\n'
*resp* '250 OK. Current directory is /'
*cmd* 'CWD /'
*put* 'CWD /\r\n'
*get* '250 OK. Current directory is /\r\n'
*resp* '250 OK. Current directory is /'
*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 TYPE is now ASCII\r\n'
*resp* '200 TYPE is now ASCII'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (127,0,0,1,217,60)\r\n'
*resp* '227 Entering Passive Mode (127,0,0,1,217,60)'
*cmd* 'LIST -a'
*put* 'LIST -a\r\n'
*get* '150 Accepted data connection\r\n'
*resp* '150 Accepted data connection'
drwxr-xr-x    8 1004       ftptest          4096 Mar 29 20:08 .
drwxr-xr-x    8 1004       ftptest          4096 Mar 29 20:08 ..
drwxr-xr-x    2 0          0                4096 May 31  2012 .hidden
...
*get* '226-Options: -a -l \r\n'
*get* '226 12 matches total\r\n'
*resp* '226-Options: -a -l \n226 12 matches total'

If the above code results in the error message we saw earlier, you might try removing one or both of the cwd calls at the start of the script and check if the error goes away.

Please let me know what you find. :-)

comment:12 Changed 6 years ago by schwa

Resolution: worksforme
Status: assignedclosed

Since the ticket submitter didn't react to my last comment, I can't debug the problem any further.

Therefore, I close the ticket for now. Please re-open it if there's new information.

Note: See TracTickets for help on using tickets.