summaryrefslogtreecommitdiffstats
path: root/lib/libfetch
diff options
context:
space:
mode:
authorwes <wes@FreeBSD.org>2000-06-20 05:32:41 +0000
committerwes <wes@FreeBSD.org>2000-06-20 05:32:41 +0000
commit425601774ed32ba1416ec8997c1b49ba1b2b0c94 (patch)
treef8c61ac2616f7eb575587a034e009bf1eb93b65f /lib/libfetch
parente3e72a583b17917255252eaad0aded3476d3652b (diff)
downloadFreeBSD-src-425601774ed32ba1416ec8997c1b49ba1b2b0c94.zip
FreeBSD-src-425601774ed32ba1416ec8997c1b49ba1b2b0c94.tar.gz
Add implementation of fetchListFTP.
Reviewed by: silence
Diffstat (limited to 'lib/libfetch')
-rw-r--r--lib/libfetch/ftp.c148
1 files changed, 143 insertions, 5 deletions
diff --git a/lib/libfetch/ftp.c b/lib/libfetch/ftp.c
index a8a4146..833a3f6 100644
--- a/lib/libfetch/ftp.c
+++ b/lib/libfetch/ftp.c
@@ -82,6 +82,7 @@
#define FTP_OK 200
#define FTP_FILE_STATUS 213
#define FTP_SERVICE_READY 220
+#define FTP_SUCCESSFUL 226
#define FTP_PASSIVE_MODE 227
#define FTP_LPASSIVE_MODE 228
#define FTP_EPASSIVE_MODE 229
@@ -90,6 +91,7 @@
#define FTP_NEED_PASSWORD 331
#define FTP_NEED_ACCOUNT 332
#define FTP_FILE_OK 350
+#define FTP_NO_DATA_CONNECTION 425
#define FTP_SYNTAX_ERROR 500
static char ENDL[2] = "\r\n";
@@ -362,9 +364,15 @@ _ftp_transfer(int cd, char *oper, char *file,
goto sysouch;
/* make the server initiate the transfer */
- if (verbose)
- _fetch_info("initiating transfer");
- e = _ftp_cmd(cd, "%s %s", oper, s);
+ if (s && *s == '\0') {
+ if (verbose)
+ _fetch_info("initiating %s transfer", oper);
+ e = _ftp_cmd(cd, oper);
+ } else {
+ if (verbose)
+ _fetch_info("initiating %s \"%s\" transfer", oper, s);
+ e = _ftp_cmd(cd, "%s %s", oper, s);
+ }
if (e != FTP_OPEN_DATA_CONNECTION)
goto ouch;
@@ -792,6 +800,136 @@ extern void warnx(char *, ...);
struct url_ent *
fetchListFTP(struct url *url, char *flags)
{
- warnx("fetchListFTP(): not implemented");
- return NULL;
+ int cd, n, e, status;
+ int size, len;
+ struct tm tm;
+ time_t t, now;
+ off_t s;
+ FILE * df;
+ char * filename;
+ struct url_stat thistat;
+ struct url_ent * answer = NULL;
+ size_t lastbuf = 0, thisbuf = 1024;
+ char * bp, * cp, * buffer = NULL, * ln;
+
+ int verbose = (flags && strchr(flags, 'v'));
+
+ /* Connect to server. */
+ if ((cd = _ftp_cached_connect(url, flags)) == NULL)
+ return NULL;
+
+ /* Initiate the transfer. */
+ df = _ftp_transfer(cd, "NLST", url->doc, "r", (off_t) 0, flags);
+ if (df == NULL)
+ return NULL;
+
+ /* Get initial buffer for filenames. */
+ if ((buffer = malloc(thisbuf)) == NULL)
+ return NULL;
+
+ /*
+ * Read the list of filenames in this directory from the ftp connection.
+ * Once the list is complete, scan the list and STAT each file, adding
+ * them to the list.
+ */
+ while (1) {
+ n = fread(buffer + lastbuf, 1, thisbuf - lastbuf, df);
+ if (n < (thisbuf - lastbuf))
+ break;
+
+ /*
+ * That didn't get it all, so expand the buffer and read
+ * some more.
+ */
+ lastbuf = thisbuf;
+ thisbuf *= 2;
+ if ((buffer = realloc(buffer, thisbuf)) == NULL)
+ return NULL;
+ }
+
+ /* Expect server reply, punt if nothing happened. */
+ if (((e = _ftp_chkerr(cd)) != FTP_SUCCESSFUL) || (n < 0))
+ return NULL;
+
+ /*
+ * We have all the filenames in the buffer. The end of the buffer is at
+ * buffer + lastbuf + n, so we'll point lastbuf at it for convenience.
+ * Parse and stat each filename so we can fill in the URL entries.
+ */
+ lastbuf += n;
+ buffer[lastbuf++] = '\0';
+ now = time(0);
+
+ for (n = 0, bp = buffer; (cp = strsep(&bp, "\r\n")) != NULL; n++) {
+ if (*cp == '\0')
+ continue;
+
+ /* Copy the "doc" member so we can modify it. */
+
+ filename = malloc(MAXPATHLEN + 1);
+ strlcpy(filename, url->doc, MAXPATHLEN);
+ strlcat(filename, cp, MAXPATHLEN);
+
+ t = now;
+ s = (off_t) 0;
+
+ /* Get file modification time from the server. */
+
+ status = _ftp_cmd(cd, "MDTM %s", filename);
+
+ if (status == FTP_FILE_STATUS) {
+ /* MDTM succeeded, get file time */
+
+ for (ln = last_reply + 4; *ln && isspace(*ln); ln++)
+ /* nothing */ ;
+
+ switch ((e = strspn(ln, "0123456789"))) {
+ case 14:
+ break;
+ case 15:
+ ln++;
+ ln[0] = '2';
+ ln[1] = '0';
+ break;
+ default:
+ goto ouch;
+ }
+ if (sscanf(ln, "%04d%02d%02d%02d%02d%02d",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) {
+ tm.tm_mon--;
+ tm.tm_year -= 1900;
+ tm.tm_isdst = -1;
+ t = timegm(&tm);
+ if (t == (time_t)-1)
+ t = now;
+ }
+
+ ouch:
+ /* If MDTM succeeded it is a file, so get the size too. */
+ if ((e = _ftp_cmd(cd, "SIZE %s", filename)) == FTP_FILE_STATUS) {
+ for (ln = last_reply + 4; *ln && isspace(*ln); ln++)
+ /* nothing */ ;
+ sscanf(ln, "%qu", &s);
+ }
+ }
+
+ thistat.mtime = thistat.atime = t;
+ thistat.size = s;
+
+ if (verbose) {
+ printf("%2d (%3d): %qu %s %s",
+ n, status,
+ thistat.size, filename, ctime(&thistat.mtime));
+ }
+
+ _fetch_add_entry(&answer, &size, &len, filename, &thistat);
+
+ free(filename);
+ }
+
+ fclose(df);
+ free(buffer);
+
+ return answer;
}
OpenPOWER on IntegriCloud