Index: usr.bin/fetch/fetch.1 =================================================================== --- usr.bin/fetch/fetch.1 (revision 185869) +++ usr.bin/fetch/fetch.1 (working copy) @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 11, 2003 +.Dd December 10, 2008 .Dt FETCH 1 .Os .Sh NAME @@ -43,6 +43,7 @@ .Op Fl T Ar seconds .Op Fl N Ar file .Op Fl o Ar file +.Op Fl i Ar file .Op Fl w Ar seconds .Op Fl h Ar host .Op Fl c Ar dir @@ -110,6 +111,11 @@ .Ar host . This option is deprecated and is provided for backward compatibility only. +.It Fl i Ar file +The file should only be retrieved if it is newer than +.Ar file +on the local host. +(HTTP only) .It Fl l If the target is a file-scheme URL, make a symbolic link to the target rather than trying to copy it. Index: usr.bin/fetch/fetch.c =================================================================== --- usr.bin/fetch/fetch.c (revision 185869) +++ usr.bin/fetch/fetch.c (working copy) @@ -60,6 +60,8 @@ int F_flag; /* -F: restart without checking mtime */ char *f_filename; /* -f: file to fetch */ char *h_hostname; /* -h: host to fetch from */ +int i_flag; /* -i: specify input file for mtime comparison */ +char *i_filename; /* name of input file */ int l_flag; /* -l: link rather than copy file: URLs */ int m_flag; /* -[Mm]: mirror mode */ char *N_filename; /* -N: netrc file name */ @@ -381,6 +383,14 @@ if (A_flag) strcat(flags, "A"); timeout = T_secs ? T_secs : http_timeout; + if (i_flag) { + if (stat(i_filename, &sb)) { + warnx("Could not stat: %s", i_filename); + goto failure; + } + url->ims_time = sb.st_mtime; + strcat(flags, "i"); + } } /* set the protocol timeout. */ @@ -713,7 +723,7 @@ fprintf(stderr, "%s\n%s\n%s\n", "usage: fetch [-146AFMPRUadlmnpqrsv] [-N netrc] [-o outputfile]", " [-S bytes] [-B bytes] [-T seconds] [-w seconds]", - " [-h host -f file [-c dir] | URL ...]"); + " [-h host -i imsfile -f file [-c dir] | URL ...]"); } @@ -730,7 +740,7 @@ int c, e, r; while ((c = getopt(argc, argv, - "146AaB:bc:dFf:Hh:lMmN:nPpo:qRrS:sT:tUvw:")) != -1) + "146AaB:bc:dFf:Hh:i:lMmN:nPpo:qRrS:sT:tUvw:")) != -1) switch (c) { case '1': once_flag = 1; @@ -775,6 +785,10 @@ case 'h': h_hostname = optarg; break; + case 'i': + i_flag = 1; + i_filename = optarg; + break; case 'l': l_flag = 1; break; Index: lib/libfetch/fetch.h =================================================================== --- lib/libfetch/fetch.h (revision 185869) +++ lib/libfetch/fetch.h (working copy) @@ -46,6 +46,7 @@ char *doc; off_t offset; size_t length; + time_t ims_time; }; struct url_stat { Index: lib/libfetch/http.c =================================================================== --- lib/libfetch/http.c (revision 185869) +++ lib/libfetch/http.c (working copy) @@ -63,6 +63,7 @@ #include #include +#include #include #include @@ -797,21 +798,24 @@ http_request(struct url *URL, const char *op, struct url_stat *us, struct url *purl, const char *flags) { + char timebuf[80]; + char hbuf[MAXHOSTNAMELEN + 7], *host; conn_t *conn; struct url *url, *new; - int chunked, direct, need_auth, noredirect, verbose; + int chunked, direct, ims, need_auth, noredirect, verbose; int e, i, n, val; off_t offset, clength, length, size; time_t mtime; const char *p; FILE *f; hdr_t h; - char hbuf[MAXHOSTNAMELEN + 7], *host; + struct tm *timestruct; direct = CHECK_FLAG('d'); noredirect = CHECK_FLAG('A'); verbose = CHECK_FLAG('v'); - + ims = CHECK_FLAG('i'); + if (direct && purl) { fetchFreeURL(purl); purl = NULL; @@ -879,6 +883,14 @@ op, url->doc); } + if (ims && url->ims_time) { + timestruct = gmtime((time_t *)&url->ims_time); + (void)strftime(timebuf, 80, "%a, %d %b %Y %T GMT", + timestruct); + if (verbose) + fetch_info("If-Modified-Since: %s", timebuf); + http_cmd(conn, "If-Modified-Since: %s", timebuf); + } /* virtual host */ http_cmd(conn, "Host: %s", host); Index: lib/libfetch/fetch.3 =================================================================== --- lib/libfetch/fetch.3 (revision 185869) +++ lib/libfetch/fetch.3 (working copy) @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 18, 2007 +.Dd December 10, 2008 .Dt FETCH 3 .Os .Sh NAME @@ -165,9 +165,16 @@ char *doc; off_t offset; size_t length; + time_t ims_time; }; .Ed .Pp +The +.Vt ims_time +field stores the time value for +.Li If-Modified-Since +HTTP requests. +.Pp The pointer returned by .Fn fetchMakeURL or @@ -353,6 +360,22 @@ .Fn fetchPutHTTP will use a direct connection even if a proxy server is defined. .Pp +If the +.Ql i +(if-modified-since) flag is specified, and +the +.Fa ims_time +field is set in +.Vt struct url , +then +.Fn fetchXGetHTTP +and +.Fn fetchGetHTTP +will send a conditional +.Li If-Modified-Since +HTTP header to only fetch the content if it is newer than +.Fa ims_time . +.Pp Since there seems to be no good way of implementing the HTTP PUT method in a manner consistent with the rest of the .Nm fetch