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

I/O Error in curlftpfs (works with ftpiiu from HBL) #62

Open
eku opened this issue Jul 22, 2024 · 9 comments · Fixed by #66
Open

I/O Error in curlftpfs (works with ftpiiu from HBL) #62

eku opened this issue Jul 22, 2024 · 9 comments · Fixed by #66

Comments

@eku
Copy link

eku commented Jul 22, 2024

I have always used curlftps to access the memory of my WiiIU transparently in the file system of my Linux computer.
This works wonderfully with the ftpiiu_everwhere started via the HBL in the Tiramisu environment.

$ LANG=c ls /media/ftp/aticatac
sd         storage_mlc          storage_odd_content2  storage_odd_updates  storage_usb
slccmpt01  storage_odd_content  storage_odd_tickets   storage_slc          usb

In Aroma I immediately get an I/O error.

$ LANG=c ls /media/ftp/aticatac
ls: reading directory '/media/ftp/aticatac': Input/output error

What information do you need for the analysis? The recording of the network traffic or a strace from the ls command or logs from the WiiU?

@Maschell
Copy link
Collaborator

What happens if you directly try to access the /fs/ of the ftp server?

@eku
Copy link
Author

eku commented Jul 22, 2024

# lftp -c "open 192.168.55.82;ls"
d--------- 0 WiiU WiiU 0 Jan  1 1970 slccmpt01
d--------- 0 WiiU WiiU 0 Jan  1 1970 storage_odd_tickets
d--------- 0 WiiU WiiU 0 Jan  1 1970 storage_odd_updates
d--------- 0 WiiU WiiU 0 Jan  1 1970 storage_odd_content
d--------- 0 WiiU WiiU 0 Jan  1 1970 storage_odd_content2
d--------- 0 WiiU WiiU 0 Jan  1 1970 storage_slc
d--------- 0 WiiU WiiU 0 Jan  1 1970 storage_mlc
d--------- 0 WiiU WiiU 0 Jan  1 1970 storage_usb
d--------- 0 WiiU WiiU 0 Jan  1 1970 fs

# lftp -c "open 192.168.55.82;ls fs/vol"
d--------- 0 WiiU WiiU 0 Jan  1 1970 external01
d--------- 0 WiiU WiiU 0 Jan  1 1970 content
d--------- 0 WiiU WiiU 0 Jan  1 1970 save

BTW it worked before your Rewrite the plugin to be based on ftpd instead of ftpii.

On my 3DS I use ftpd and it works with curlftps except for issue 180.

@eku
Copy link
Author

eku commented Jul 24, 2024

tcpdump from ls /media/ftp/aticatac:

220 Hello!
USER anonymous
230 OK
PWD
257 "/"
PASV
227 Entering Passive Mode (192,168,55,82,10,181).
TYPE A
200 OK
LIST -a
550 No such device
PASV
227 Entering Passive Mode (192,168,55,82,10,182).
LIST -a
550 No such device

which leads to I/O error at shell level.

Before fa4440b the error is the same.

With Tiramisu and ftpiiu_everwhere this looks as following

220 ftpii
USER anonymous
331 User name okay, need password.
PASS [email protected]
230 User logged in, proceed.
PWD
257 "/" is current directory.
PASV
227 Entering Passive Mode (192,168,55,82,4,0).
TYPE A
200 Type set to A.
LIST -a
150 Transferring data.
226 Closing data connection, transfer successful.
PASV
227 Entering Passive Mode (192,168,55,82,4,1).
LIST -a
150 Transferring data.
226 Closing data connection, transfer successful.

I hope this is of any help.

@eku
Copy link
Author

eku commented Sep 20, 2024

Might also be related mtheall/ftpd#183

@UnasZole
Copy link

The issue is probably related to the usage of "LIST -a" by some clients.

Related part of the code :

// work around broken clients that think LIST -a/-l is valid
if (workaround_)
{
if (args_[0] == '-' && (args_[1] == 'a' || args_[1] == 'l'))
{
char const *args = &args_[2];
if (*args == '\0' || *args == ' ')
{
if (*args == ' ')
++args;
xferDir (args, mode_, false);
return;
}
}
}
sendResponse ("550 %s\r\n", std::strerror (errno));
setState (State::COMMAND, true, true);
return;

This workaround seems rather fragile, as it counts characters one by one and therefore any additional space (or possibly any windows-style line ending) would break it.
I'm not sure that's exactly what's happening here as I couldn't see such spaces in my logs, but imagine there is just an additional space or CR after the -a (e.g. LIST -a ) : then the ending space will be forwarded to the recursive call, and you end up with std::strlen (args_) > 0 true, which then tries to build a path with the whitespace appended. And there is no special logic to handle whitespaces in

std::string buildPath (std::string_view const cwd_, std::string_view const args_)
.

Maybe just trimming the string before the recursive call would help.

@UnasZole
Copy link

UnasZole commented Nov 11, 2024

Note that the initial argument string is effectively left-trimmed before it's sent to processing : all initial spaces are skipped at

while (*args && !std::isspace (*args))
++args;

A similar logic should probably be used before the recursive call.
ie replace

if (*args == ' ')
++args;

by the same two lines as above.

@eku
Copy link
Author

eku commented Nov 21, 2024

I'm not sure that's exactly what's happening here as I couldn't see such spaces in my logs

Same here.

Having a look at the code of ftpiiu_everywhere which works, I see that it sets the path to . if none provided.

I wonder which of the functions returns the ENODEV as errno. You would have to include some code for the analysis.

@eku
Copy link
Author

eku commented Nov 22, 2024

auto const path = buildResolvedPath (m_cwd, args_);
if (path.empty ())
{
// work around broken clients that think LIST -a/-l is valid
if (workaround_)
{
if (args_[0] == '-' && (args_[1] == 'a' || args_[1] == 'l'))
{
char const *args = &args_[2];
if (*args == '\0' || *args == ' ')
{
if (*args == ' ')
++args;
xferDir (args, mode_, false);
return;
}
}
}
sendResponse ("550 %s\r\n", std::strerror (errno));
setState (State::COMMAND, true, true);
return;
}
struct stat st;
if (IOAbstraction::stat (path.c_str (), &st) != 0)
{
sendResponse ("550 %s\r\n", std::strerror (errno));

The result of buildResolvedPath is never empty, because the funtion concatenates the cwd with arg, which results in case of LIST -a in being /-a. So the special handling of additional options is skipped and IOAbstraction::stat will fail with ENODEV.

@Maschell
Copy link
Collaborator

Then looking into this and fixing it.

This fix will be included in the upcoming ftpiiu plugin version v0.4.4. I'll close this issue once it has been released.

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

Successfully merging a pull request may close this issue.

3 participants