]> pd.if.org Git - zpackage/blobdiff - src/fetchurl.c
add options for fetchurl
[zpackage] / src / fetchurl.c
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;
 }