Subject: bin/28413: pkg_add can't handle simple ftp URLs
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <kre@munnari.OZ.AU>
List: netbsd-bugs
Date: 11/24/2004 18:30:00
>Number: 28413
>Category: bin
>Synopsis: pkg_add can't handle simple ftp URLs
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Nov 24 18:30:00 +0000 2004
>Originator: Robert Elz
>Release: NetBSD 2.0B (-- irrelevant, old bug, still in -current)
>Organization:
Prince of Songkla University
>Environment:
System: NetBSD delta.noi.kre.to 2.0B NetBSD 2.0B (DELTA) #0: Fri Apr 16 23:25:38 ICT 2004 kre@lilac.noi.kre.to:/usr/obj/current/sys/arch/i386/compile/DELTA i386
Architecture: i386
Machine: i386
>Description:
pkg_add cannot handle fetching a FTP URL of the form
ftp://host/file.tgz
That is, where the file is present in the ftp login
directory on the server host.
Aside: I have entered this PR in the bin category, as
pkg_add libes in /usr/src/usr.sbin/pkg_install/*
but it could also be in pkg I guess, given that it
also lives in pkgsrc/pkgtools/pkg_install. I don't
think it is possible to have a PR in 2 categories is it?
(I'm not wasting time here testing it).
The bug probably affects all of the pkg_* commands that
can take a ftp:// type URL (as they all share common code).
>How-To-Repeat:
Just do
pkg_add ftp://hostname/anything.tgz
"hostname" must be a valid name of a host with anon FTP
enabled, but that's all that's needed to demonstrate the
problem, "anything.tgz" doesn't need to be a pkg name,
and what's more, doesn't need to exist.
If you're prepared to wait long enough (I think it is 10
minutes) I believe this is supposed to correct itself,
and the pkg_add will abort (ie: it won't work, but it
shou;dn't hang forever either) but I've never had the
patience to wait that long to be sure that works.
>Fix:
No fix, but I can explain the problem.
First, the base cause is the absurd attempt to optimise FTP
connections. Even at its worst, pkg_add isn't going to need
to make more than 15-20 fetches to get all of the bits needed
to install a package (and if there are a few worse cases,
that I've never seen, who cares anyway). Simply using one
ftp command at a time, for each file required, giving ftp the
URL of the file, and waiting for FTP to finish fetching it
would be the obvious, simple, and clean way to handle this,
and if that means a few extra secods of waiting for the RTTs
needed to connect to the server several times, then so what?
But that's not what is done - instead an attempt is made to
open one connection, and then use it over and over again to
get all the files that are required (dependencies and all
that).
To do that, pkg_add runs ftp with a URL that is of the
directory containing the file (ie: the URL minus the
last component), expecting the ftp process to use the
FTP CWD command to enter the directory it assumes will
be in the URL. It then waits for a "success" reply to
the CWD command it is expecting will be issued using this
piece of code ...
if ((expect(ftpio.answer, "\n(221|250|221|550).*\n", &rc) != 0)
|| rc != 250) {
warnx("expect1 failed, rc=%d", rc);
return -1;
}
That's from pkg_install/lib/ftpio.c in ftp_start().
Why 2 different 221's are needed I'm not going to guess at,
but that's not the cause of the problem, the problem is
in expecting to get a "250" response to the opening
sequence. That's what happens when a CWD is issued,
but without one of those, there is no 250, and the expect()
call just sits and waits (until it times out).
Possible fixes...
Force the URL to have a trailing "./" appended to it.
That will ensure that a CWD command is always issued
and so a 250 response can be expected. Of course,
it also assumes a unix filename compatible server is
being used (but is there anything else any more?)
Just wait for the FTP login response, instead of (one of the)
CWD command response, 230 would probably work.
This is OK, because there can be many 250 responses,
pkg_add sends a "prompt off" command after the login
sequence, so it can synchronise itself with the server.
It does assume that all servers correctly reply 230
to a successful login.
Get rid of the "just one ftp" nonsense, and simplify everything.
(major change). This one is certainly safe (and would
mean that ftp debug mode is no longer needed, allow the
possibility of using different ftp commands, and probably
lots of other wins).
And perhaps others.
ps: there's no need to fix this before 2.0, though the bug
is certainly present in its RCn versions (that's where I
noticed it first). Fetching packages directly from the
ftp login directory seems to be something perverse enough
that I'm the only one to have ever done it (ugh - attempted it,
since it failed.)