Add implementation of fetchListFTP.
Reviewed by: silence
This commit is contained in:
parent
a79b71281c
commit
bda4ef1aa0
@ -82,6 +82,7 @@
|
|||||||
#define FTP_OK 200
|
#define FTP_OK 200
|
||||||
#define FTP_FILE_STATUS 213
|
#define FTP_FILE_STATUS 213
|
||||||
#define FTP_SERVICE_READY 220
|
#define FTP_SERVICE_READY 220
|
||||||
|
#define FTP_SUCCESSFUL 226
|
||||||
#define FTP_PASSIVE_MODE 227
|
#define FTP_PASSIVE_MODE 227
|
||||||
#define FTP_LPASSIVE_MODE 228
|
#define FTP_LPASSIVE_MODE 228
|
||||||
#define FTP_EPASSIVE_MODE 229
|
#define FTP_EPASSIVE_MODE 229
|
||||||
@ -90,6 +91,7 @@
|
|||||||
#define FTP_NEED_PASSWORD 331
|
#define FTP_NEED_PASSWORD 331
|
||||||
#define FTP_NEED_ACCOUNT 332
|
#define FTP_NEED_ACCOUNT 332
|
||||||
#define FTP_FILE_OK 350
|
#define FTP_FILE_OK 350
|
||||||
|
#define FTP_NO_DATA_CONNECTION 425
|
||||||
#define FTP_SYNTAX_ERROR 500
|
#define FTP_SYNTAX_ERROR 500
|
||||||
|
|
||||||
static char ENDL[2] = "\r\n";
|
static char ENDL[2] = "\r\n";
|
||||||
@ -362,9 +364,15 @@ _ftp_transfer(int cd, char *oper, char *file,
|
|||||||
goto sysouch;
|
goto sysouch;
|
||||||
|
|
||||||
/* make the server initiate the transfer */
|
/* make the server initiate the transfer */
|
||||||
if (verbose)
|
if (s && *s == '\0') {
|
||||||
_fetch_info("initiating transfer");
|
if (verbose)
|
||||||
e = _ftp_cmd(cd, "%s %s", oper, s);
|
_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)
|
if (e != FTP_OPEN_DATA_CONNECTION)
|
||||||
goto ouch;
|
goto ouch;
|
||||||
|
|
||||||
@ -792,6 +800,136 @@ extern void warnx(char *, ...);
|
|||||||
struct url_ent *
|
struct url_ent *
|
||||||
fetchListFTP(struct url *url, char *flags)
|
fetchListFTP(struct url *url, char *flags)
|
||||||
{
|
{
|
||||||
warnx("fetchListFTP(): not implemented");
|
int cd, n, e, status;
|
||||||
return NULL;
|
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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user