summaryrefslogtreecommitdiffstats
path: root/usr.bin/fetch
diff options
context:
space:
mode:
authorfenner <fenner@FreeBSD.org>1997-10-06 01:09:56 +0000
committerfenner <fenner@FreeBSD.org>1997-10-06 01:09:56 +0000
commit59cc2d40331a440c5510374986d6f949a64a1dab (patch)
tree99f0154a5f4fc9a766438280546d14f969a814cf /usr.bin/fetch
parentfd0c3e573362b165370b9745d874c7960cc2996f (diff)
downloadFreeBSD-src-59cc2d40331a440c5510374986d6f949a64a1dab.zip
FreeBSD-src-59cc2d40331a440c5510374986d6f949a64a1dab.tar.gz
Use the RFC1738 interpretation of ftp: URL's, i.e. CWD to each
slash-seperated element of the URL and then RETR the last element. PR: bin/4670 Reviewed by: wollman
Diffstat (limited to 'usr.bin/fetch')
-rw-r--r--usr.bin/fetch/ftp.c78
1 files changed, 68 insertions, 10 deletions
diff --git a/usr.bin/fetch/ftp.c b/usr.bin/fetch/ftp.c
index 457e43d..0972505 100644
--- a/usr.bin/fetch/ftp.c
+++ b/usr.bin/fetch/ftp.c
@@ -26,7 +26,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ftp.c,v 1.6 1997/03/11 15:13:28 jmg Exp $
+ * $Id: ftp.c,v 1.7 1997/05/31 14:45:41 ache Exp $
*/
#include <sys/types.h>
@@ -52,6 +52,10 @@ struct ftp_state {
char *ftp_user;
char *ftp_password;
char *ftp_remote_file;
+ char **ftp_remote_dirs;
+ int ftp_remote_ndirs;
+ char *ftp_remote_path;
+ char *ftp_type;
unsigned ftp_port;
};
@@ -67,7 +71,7 @@ static int
ftp_parse(struct fetch_state *fs, const char *uri)
{
const char *p, *slash, *q;
- char *hostname, *atsign, *colon;
+ char *hostname, *atsign, *colon, *path, *r, *s, **dp;
unsigned port;
struct ftp_state *ftps;
@@ -151,12 +155,41 @@ ftp_parse(struct fetch_state *fs, const char *uri)
ftps->ftp_hostname = safe_strdup(hostname);
ftps->ftp_port = port;
- p = ftps->ftp_remote_file = percent_decode(p);
- /* now p is the decoded version */
+ /* Save the full path for error messages. */
+ ftps->ftp_remote_path = percent_decode(p);
+
+ /* Build a list of directory components plus the filename. */
+ ftps->ftp_remote_ndirs = 0;
+ q = p;
+ while ((q = strchr(q, '/')) != 0) {
+ q++;
+ ftps->ftp_remote_ndirs++;
+ }
+ path = safe_strdup(p);
+ if (ftps->ftp_remote_ndirs != 0) {
+ ftps->ftp_remote_dirs = safe_malloc(ftps->ftp_remote_ndirs *
+ sizeof(char *));
+ r = s = path = safe_strdup(p);
+ dp = ftps->ftp_remote_dirs;
+ while ((s = strchr(s, '/')) != 0) {
+ *s++ = '\0';
+ *dp++ = percent_decode(r);
+ r = s;
+ }
+ } else {
+ ftps->ftp_remote_dirs = 0;
+ r = path;
+ }
+ if ((s = strchr(r, ';')) != 0 && strncmp(s, ";type=", 6) == 0) {
+ *s = '\0';
+ ftps->ftp_type = percent_decode(s+6);
+ } else
+ ftps->ftp_type = 0;
+ ftps->ftp_remote_file = percent_decode(r);
+ free(path);
if (fs->fs_outputfile == 0) {
- slash = strrchr(p, '/');
- fs->fs_outputfile = slash ? slash + 1 : p;
+ fs->fs_outputfile = ftps->ftp_remote_file;
}
if (ftps->ftp_password == 0)
@@ -271,12 +304,21 @@ static int
ftp_close(struct fetch_state *fs)
{
struct ftp_state *ftps = fs->fs_proto;
+ int i;
+ char **dp;
if (ftps->ftp_user)
free(ftps->ftp_user);
free(ftps->ftp_hostname);
free(ftps->ftp_password);
free(ftps->ftp_remote_file);
+ for (i = 0, dp = ftps->ftp_remote_dirs; i < ftps->ftp_remote_ndirs; i++, dp++)
+ free(*dp);
+ if (ftps->ftp_remote_dirs)
+ free(ftps->ftp_remote_dirs);
+ free(ftps->ftp_remote_path);
+ if (ftps->ftp_type)
+ free(ftps->ftp_type);
free(ftps);
fs->fs_proto = 0;
fs->fs_outputfile = 0;
@@ -288,7 +330,8 @@ ftp_retrieve(struct fetch_state *fs)
{
struct ftp_state *ftps = fs->fs_proto;
FILE *ftp, *remote, *local;
- int status;
+ char **dp;
+ int i, status;
off_t size;
off_t seekloc, wehave;
time_t modtime;
@@ -304,13 +347,28 @@ ftp_retrieve(struct fetch_state *fs)
status ? ftpErrString(status) : hstrerror(h_errno));
return EX_IOERR;
}
- ftpBinary(ftp);
+ if (ftps->ftp_type && strcasecmp(ftps->ftp_type, "i") != 0) {
+ if (strcasecmp(ftps->ftp_type, "a") == 0)
+ ftpAscii(ftp);
+ else {
+ warnx("unknown or unsupported type %s", ftps->ftp_type);
+ return EX_USAGE;
+ }
+ } else
+ ftpBinary(ftp);
ftpPassive(ftp, fs->fs_passive_mode);
+ for (i = 0, dp = ftps->ftp_remote_dirs; i < ftps->ftp_remote_ndirs; i++, dp++) {
+ if ((status = ftpChdir(ftp, *dp)) != 0) {
+ warnx("%s: %s: %s", ftps->ftp_hostname,
+ *dp, ftpErrString(status));
+ return EX_IOERR;
+ }
+ }
size = ftpGetSize(ftp, ftps->ftp_remote_file);
modtime = ftpGetModtime(ftp, ftps->ftp_remote_file);
if (modtime <= 0) { /* xxx */
warnx("%s: cannot get remote modification time",
- ftps->ftp_remote_file);
+ ftps->ftp_remote_path);
modtime = -1;
}
fs->fs_modtime = modtime;
@@ -346,7 +404,7 @@ ftp_retrieve(struct fetch_state *fs)
if (remote == 0) {
if (ftpErrno(ftp)) {
warnx("ftp://%s/%s: FTP error:",
- ftps->ftp_hostname, ftps->ftp_remote_file);
+ ftps->ftp_hostname, ftps->ftp_remote_path);
warnx("%s", ftpErrString(ftpErrno(ftp)));
fclose(ftp);
return EX_IOERR;
OpenPOWER on IntegriCloud