]> pd.if.org Git - zpackage/commitdiff
add options for fetchurl
authorNathan Wagner <nw@hydaspes.if.org>
Sat, 16 Feb 2019 15:52:11 +0000 (15:52 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Sat, 16 Feb 2019 15:52:11 +0000 (15:52 +0000)
crypto/rfc3986.re
doc/zpm-fetchurl.8
src/fetchurl.c

index 463486f6968549138fd98c5a5b2476b1dd4434dc..feaf49ac0340942c92700db180b867c49ce4d61b 100644 (file)
@@ -205,7 +205,6 @@ int tls_parse_uri(char *s, struct tls_uri *uri) {
        percent_decode(uri->host);
        percent_decode(uri->path);
        percent_decode(uri->query);
-
        
        if (uri->path == NULL || uri->path[0] == 0) {
                free(uri->path);
@@ -215,10 +214,21 @@ int tls_parse_uri(char *s, struct tls_uri *uri) {
        return rv;
 }
 
+#define MARK fprintf(stderr, "%s %s:%d\n", __FILE__, __func__, __LINE__)
 void tls_free_uri(struct tls_uri *uri) {
+       if (!uri) return;
+
        free(uri->host);
+       uri->host = 0;
        free(uri->path);
+       uri->path = 0;
        free(uri->query);
+       uri->query = 0;
        free(uri->port);
+       uri->port = 0;
        free(uri->scheme);
+       uri->scheme = 0;
+       free(uri->fragment);
+       uri->fragment = 0;
+       
 }
index 4a269b394f7aeaf042695d8c14629c4cc95e0092..8f9385990083b276214df5642fe636be0c6ea68b 100644 (file)
@@ -1,10 +1,10 @@
-.TH zpm-fetchurl 8 2019-02-15 "ZPM 0.4"
+.TH zpm-fetchurl 8 2019-02-16 "ZPM 0.4"
 .SH NAME
 zpm-fetchurl \- download files
 .SH SYNOPSIS
 .B zpm fetchurl
 [
-.B -ISkKr
+.B -ISkKrOn
 ]
 [
 .BI -o file
@@ -51,6 +51,12 @@ Only download if remote is newer than the file given by path
 Write the output to the file given by \fIpath\fR.  Output is
 written to stdout by default.
 .TP
+.B \-O
+Calculate the output file name from the url.
+.TP
+.B \-n
+Only if newer.  Like \-z, except use the output file name, if any.
+.TP
 .B \-f
 Fail silently on errors.
 .TP
index 9d526961f32afbd9cee6f999605be2f96e9670ee..395ce9573f5f444c61c1c2a66860e639864d12eb 100644 (file)
@@ -539,6 +539,22 @@ char *pathlast(char *path) {
        return strndup(last, len);
 }
 
+static time_t file_mtime(char *path) {
+       struct stat st;
+       int rv;
+
+       rv = stat(path, &st);
+       if (rv == -1) {
+               if (errno == ENOENT) {
+                       return 0;
+               } 
+               perror("stat failed:");
+               return -1;
+       }
+
+       return st.st_mtime;
+}
+
 int main(int ac, char *av[]) {
        int sockfd, port = -1, rv;
        ssize_t ret;
@@ -553,7 +569,7 @@ int main(int ac, char *av[]) {
        struct tls_uri uri = { 0 };
        char *outfile = 0;
        int raw = 0, head = 0;
-       int out = 1;
+       int out = 1; /* output file descriptor */
        int use_tls = 0;
        struct io io = { {0}, 0, -1, 0, 0, 0, 0, 0 };
        struct TLSContext *clientssl = 0;
@@ -567,11 +583,11 @@ int main(int ac, char *av[]) {
        size_t header_len;
        char *url = 0;
        int redirs = 0, redirlimit = 50, printstatus = 0;
-       int verifypolicy = 1, calcoutfile = 0;
+       int verifypolicy = 1, calcoutfile = 0, ifnewer = 0;
 
        ltc_mp = tfm_desc;
 
-       while ((option = getopt(ac, av, "o:OrIfz:#R:SkK")) != -1) {
+       while ((option = getopt(ac, av, "o:OrIfz:n#R:SkK")) != -1) {
                switch (option) {
                        case 'o': outfile = optarg; break;
                        case 'O': calcoutfile = 1; break;
@@ -582,6 +598,7 @@ int main(int ac, char *av[]) {
                        case 'r': raw = 1; break;
                        case 'f': failsilent = 1; break;
                        case 'z': lmfile = optarg; break;
+                       case 'n': ifnewer = 1; break;
                        case 'R': redirlimit = strtol(optarg, 0, 10); break;
                        case '#': progressbar = 1; break;
                        default:
@@ -595,29 +612,13 @@ int main(int ac, char *av[]) {
                exit(EXIT_FAILURE);
        }
 
-       io.last_modified = 0;
-       if (lmfile) {
-               struct stat st;
-               int rv;
-               struct tm *mtime;
-               time_t ts;
-
-               rv = stat(lmfile, &st);
-               if (rv == -1) {
-                       perror("stat failed:");
-                       exit(EXIT_FAILURE);
-               }
-               ts = st.st_mtime;
-               io.last_modified = ts;
-               mtime = gmtime(&ts);
-               strftime(lmtime, sizeof lmtime, "%a, %d %b %Y %H:%M:%S GMT", mtime);
-       }
-
        url = strdup(av[optind]);
        if (!url) {
                exit(EXIT_FAILURE);
        }
 
+       io.last_modified = 0;
+
        if (calcoutfile && !outfile) {
                tls_parse_uri(url, &uri);
                outfile = pathlast(uri.path);
@@ -631,11 +632,24 @@ int main(int ac, char *av[]) {
                }
        }
 
-       if (outfile) {
-               out = open(outfile, O_WRONLY|O_CREAT, 0600);
-               if (out == -1) {
-                       perror("can't open output file:");
+       if (ifnewer && outfile && !lmfile) {
+               lmfile = outfile;
+       }
+
+       if (lmfile) {
+               struct tm *mtime;
+               time_t ts;
+
+               ts = file_mtime(lmfile);
+
+               if (ts == -1) {
                        exit(EXIT_FAILURE);
+               } else if (ts != 0) {
+                       io.last_modified = ts;
+                       mtime = gmtime(&ts);
+                       strftime(lmtime, sizeof lmtime, "%a, %d %b %Y %H:%M:%S GMT", mtime);
+               } else {
+                       lmfile = 0;
                }
        }
 
@@ -648,13 +662,13 @@ int main(int ac, char *av[]) {
                tls_free_uri(&uri);
                io.response.len = 0;
                request.len = 0;
+               eoh = 0;
 
                tls_parse_uri(url, &uri);
                host = uri.host;
                port = atoi(uri.port);
                req_file = uri.path;
 
-
                /* construct request */
                if (head) {
                        tls_buffer_append(&request, "HEAD ", 5);
@@ -762,12 +776,15 @@ int main(int ac, char *av[]) {
                parse_header(&io);
 
                switch (io.status_code) {
+                       case 304:
+                               break;
                        case 301:
                        case 302:
                        case 303:
                        case 307:
                                free(url);
                                url = strdup(io.redirect);
+                               close(io.socket);
                                continue;
                                break;
                }
@@ -790,6 +807,14 @@ int main(int ac, char *av[]) {
                        }
                }
 
+               if (outfile) {
+                       out = open(outfile, O_WRONLY|O_CREAT, 0600);
+                       if (out == -1) {
+                               perror("can't open output file:");
+                               exit(EXIT_FAILURE);
+                       }
+               }
+
                do {
                        write(out, io.response.buffer, io.response.len);
                        ret = io.response.len;
@@ -817,7 +842,12 @@ int main(int ac, char *av[]) {
                if (ret < 0) {
                        fprintf(stderr, "%s read error %zd\n", uri.scheme, ret);
                }
-               /* futimens(out, ...) */
+               struct timespec ts[2];
+               ts[0].tv_sec = 0; ts[0].tv_nsec = UTIME_OMIT;
+               ts[1].tv_sec = io.last_modified;
+               ts[1].tv_nsec = 0;
+
+               futimens(out, ts);
                close(out);
                tls_buffer_free(&io.response);
                break;
@@ -834,5 +864,5 @@ int main(int ac, char *av[]) {
                putc('\n',stderr);
        }
 
-       return io.status_code == 200 ? 0 : EXIT_FAILURE;
+       return io.status_code < 400 ? 0 : EXIT_FAILURE;
 }