Deleted Added
full compact
fetch.c (63235) fetch.c (63345)
1/*-
2 * Copyright (c) 2000 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
1/*-
2 * Copyright (c) 2000 Dag-Erling Co�dan Sm�rgrav
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD: head/usr.bin/fetch/fetch.c 63235 2000-07-16 00:47:00Z des $
28 * $FreeBSD: head/usr.bin/fetch/fetch.c 63345 2000-07-17 21:49:01Z des $
29 */
30
31#include <sys/param.h>
32#include <sys/stat.h>
33#include <sys/socket.h>
34
35#include <ctype.h>
36#include <err.h>

--- 154 unchanged lines hidden (view full) ---

191 /* parse URL */
192 if ((url = fetchParseURL(URL)) == NULL) {
193 warnx("%s: parse error", URL);
194 goto failure;
195 }
196
197 timeout = 0;
198 *flags = 0;
29 */
30
31#include <sys/param.h>
32#include <sys/stat.h>
33#include <sys/socket.h>
34
35#include <ctype.h>
36#include <err.h>

--- 154 unchanged lines hidden (view full) ---

191 /* parse URL */
192 if ((url = fetchParseURL(URL)) == NULL) {
193 warnx("%s: parse error", URL);
194 goto failure;
195 }
196
197 timeout = 0;
198 *flags = 0;
199 count = 0;
199
200 /* common flags */
201 if (v_level > 2)
202 strcat(flags, "v");
203 switch (family) {
204 case PF_INET:
205 strcat(flags, "4");
206 break;

--- 20 unchanged lines hidden (view full) ---

227 if (A_flag)
228 strcat(flags, "A");
229 timeout = T_secs ? T_secs : http_timeout;
230 }
231
232 /* set the protocol timeout. */
233 fetchTimeout = timeout;
234
200
201 /* common flags */
202 if (v_level > 2)
203 strcat(flags, "v");
204 switch (family) {
205 case PF_INET:
206 strcat(flags, "4");
207 break;

--- 20 unchanged lines hidden (view full) ---

228 if (A_flag)
229 strcat(flags, "A");
230 timeout = T_secs ? T_secs : http_timeout;
231 }
232
233 /* set the protocol timeout. */
234 fetchTimeout = timeout;
235
235 /* stat remote file */
236 if (fetchStat(url, &us, flags) == -1)
237 goto failure;
238
239 /* just print size */
240 if (s_flag) {
236 /* just print size */
237 if (s_flag) {
238 if (fetchStat(url, &us, flags) == -1)
239 goto failure;
241 if (us.size == -1)
242 printf("Unknown\n");
243 else
244 printf("%lld\n", us.size);
245 goto success;
246 }
247
240 if (us.size == -1)
241 printf("Unknown\n");
242 else
243 printf("%lld\n", us.size);
244 goto success;
245 }
246
248 /* check that size is as expected */
249 if (S_size && us.size != -1 && us.size != S_size) {
250 warnx("%s: size mismatch: expected %lld, actual %lld",
251 path, S_size, us.size);
247 /*
248 * If the -r flag was specified, we have to compare the local and
249 * remote files, so we should really do a fetchStat() first, but I
250 * know of at least one HTTP server that only sends the content
251 * size in response to GET requests, and leaves it out of replies
252 * to HEAD requests. Also, in the (frequent) case that the local
253 * and remote files match but the local file is truncated, we have
254 * sufficient information *before* the compare to issue a correct
255 * request. Therefore, we always issue a GET request as if we were
256 * sure the local file was a truncated copy of the remote file; we
257 * can drop the connection later if we change our minds.
258 */
259 if (r_flag && !o_stdout && stat(path, &sb) != -1)
260 url->offset = sb.st_size;
261
262 /* start the transfer */
263 if ((f = fetchXGet(url, &us, flags)) == NULL) {
264 warnx("%s: %s", path, fetchLastErrString);
252 goto failure;
253 }
265 goto failure;
266 }
267 if (sigint)
268 goto signal;
254
269
270 /* check that size is as expected */
271 if (S_size) {
272 if (us.size == -1) {
273 warnx("%s: size unknown", path);
274 goto failure;
275 } else if (us.size != S_size) {
276 warnx("%s: size mismatch: expected %lld, actual %lld",
277 path, S_size, us.size);
278 goto failure;
279 }
280 }
281
255 /* symlink instead of copy */
256 if (l_flag && strcmp(url->scheme, "file") == 0 && !o_stdout) {
257 if (symlink(url->doc, path) == -1) {
258 warn("%s: symlink()", path);
259 goto failure;
260 }
261 goto success;
262 }
263
282 /* symlink instead of copy */
283 if (l_flag && strcmp(url->scheme, "file") == 0 && !o_stdout) {
284 if (symlink(url->doc, path) == -1) {
285 warn("%s: symlink()", path);
286 goto failure;
287 }
288 goto success;
289 }
290
291 /* open output file */
264 if (o_stdout) {
265 /* output to stdout */
266 of = stdout;
292 if (o_stdout) {
293 /* output to stdout */
294 of = stdout;
267 } else if (r_flag && us.size != -1 && stat(path, &sb) != -1
268 && (F_flag || (us.mtime && sb.st_mtime == us.mtime))) {
269 /* output to file, restart aborted transfer */
295 } else if (url->offset) {
296 /* resume mode, local file exists */
297 if (!F_flag && us.mtime && sb.st_mtime != us.mtime) {
298 /* no match! have to refetch */
299 fclose(f);
300 url->offset = 0;
301 if ((f = fetchXGet(url, &us, flags)) == NULL) {
302 warnx("%s: %s", path, fetchLastErrString);
303 goto failure;
304 }
305 if (sigint)
306 goto signal;
307 } else {
308 us.size += url->offset;
309 }
270 if (us.size == sb.st_size)
310 if (us.size == sb.st_size)
311 /* nothing to do */
271 goto success;
312 goto success;
272 else if (sb.st_size > us.size && truncate(path, us.size) == -1) {
273 warn("%s: truncate()", path);
313 if (sb.st_size > us.size) {
314 /* local file too long! */
315 warnx("%s: local file (%lld bytes) is longer "
316 "than remote file (%lld bytes)",
317 path, sb.st_size, us.size);
274 goto failure;
275 }
318 goto failure;
319 }
320 /* we got through, open local file in append mode */
321 /*
322 * XXX there's a race condition here - the file we open is not
323 * necessarily the same as the one we stat()'ed earlier...
324 */
276 if ((of = fopen(path, "a")) == NULL) {
277 warn("%s: open()", path);
278 goto failure;
279 }
325 if ((of = fopen(path, "a")) == NULL) {
326 warn("%s: open()", path);
327 goto failure;
328 }
280 url->offset = sb.st_size;
281 } else if (m_flag && us.size != -1 && stat(path, &sb) != -1) {
282 /* output to file, mirror mode */
329 }
330 if (m_flag && stat(path, &sb) != -1) {
331 /* mirror mode, local file exists */
283 if (sb.st_size == us.size && sb.st_mtime == us.mtime)
332 if (sb.st_size == us.size && sb.st_mtime == us.mtime)
284 return 0;
333 goto success;
334 }
335 if (!of) {
336 /*
337 * We don't yet have an output file; either this is a vanilla
338 * run with no special flags, or the local and remote files
339 * didn't match.
340 */
285 if ((of = fopen(path, "w")) == NULL) {
286 warn("%s: open()", path);
287 goto failure;
288 }
341 if ((of = fopen(path, "w")) == NULL) {
342 warn("%s: open()", path);
343 goto failure;
344 }
289 } else {
290 /* output to file, all other cases */
291 if ((of = fopen(path, "w")) == NULL) {
292 warn("%s: open()", path);
293 goto failure;
294 }
295 }
296 count = url->offset;
297
345 }
346 count = url->offset;
347
298 /* start the transfer */
299 if ((f = fetchGet(url, flags)) == NULL) {
300 warnx("%s", fetchLastErrString);
301 if (!R_flag && !r_flag && !o_stdout)
302 unlink(path);
303 goto failure;
304 }
305
306 /* start the counter */
307 stat_start(&xs, path, us.size, count);
308
309 sigint = sigalrm = 0;
310
311 /* suck in the data */
312 for (n = 0; !sigint && !sigalrm; ++n) {
313 if (us.size != -1 && us.size - count < B_size)

--- 22 unchanged lines hidden (view full) ---

336 tv[0].tv_sec = (long)(us.atime ? us.atime : us.mtime);
337 tv[1].tv_sec = (long)us.mtime;
338 tv[0].tv_usec = tv[1].tv_usec = 0;
339 if (utimes(path, tv))
340 warn("%s: utimes()", path);
341 }
342
343 /* timed out or interrupted? */
348 /* start the counter */
349 stat_start(&xs, path, us.size, count);
350
351 sigint = sigalrm = 0;
352
353 /* suck in the data */
354 for (n = 0; !sigint && !sigalrm; ++n) {
355 if (us.size != -1 && us.size - count < B_size)

--- 22 unchanged lines hidden (view full) ---

378 tv[0].tv_sec = (long)(us.atime ? us.atime : us.mtime);
379 tv[1].tv_sec = (long)us.mtime;
380 tv[0].tv_usec = tv[1].tv_usec = 0;
381 if (utimes(path, tv))
382 warn("%s: utimes()", path);
383 }
384
385 /* timed out or interrupted? */
386 signal:
344 if (sigalrm)
345 warnx("transfer timed out");
346 if (sigint)
347 warnx("transfer interrupted");
348
349 if (!sigalrm && !sigint) {
350 /* check the status of our files */
351 if (ferror(f))

--- 115 unchanged lines hidden (view full) ---

467 l_flag = 1;
468 break;
469 case 'o':
470 o_flag = 1;
471 o_filename = optarg;
472 break;
473 case 'M':
474 case 'm':
387 if (sigalrm)
388 warnx("transfer timed out");
389 if (sigint)
390 warnx("transfer interrupted");
391
392 if (!sigalrm && !sigint) {
393 /* check the status of our files */
394 if (ferror(f))

--- 115 unchanged lines hidden (view full) ---

510 l_flag = 1;
511 break;
512 case 'o':
513 o_flag = 1;
514 o_filename = optarg;
515 break;
516 case 'M':
517 case 'm':
518 if (r_flag)
519 errx(1, "the -m and -r flags are mutually exclusive");
475 m_flag = 1;
476 break;
477 case 'n':
478 n_flag = 1;
479 break;
480 case 'P':
481 case 'p':
482 p_flag = 1;
483 break;
484 case 'q':
485 v_level = 0;
486 break;
487 case 'R':
488 R_flag = 1;
489 break;
490 case 'r':
520 m_flag = 1;
521 break;
522 case 'n':
523 n_flag = 1;
524 break;
525 case 'P':
526 case 'p':
527 p_flag = 1;
528 break;
529 case 'q':
530 v_level = 0;
531 break;
532 case 'R':
533 R_flag = 1;
534 break;
535 case 'r':
536 if (m_flag)
537 errx(1, "the -m and -r flags are mutually exclusive");
491 r_flag = 1;
492 break;
493 case 'S':
494 if (parseoff(optarg, &S_size) == -1)
495 errx(1, "invalid size");
496 break;
497 case 's':
498 s_flag = 1;

--- 30 unchanged lines hidden (view full) ---

529 /* XXX this is a hack. */
530 if (strcspn(h_hostname, "@:/") != strlen(h_hostname))
531 errx(1, "invalid hostname");
532 if (asprintf(argv, "ftp://%s/%s/%s", h_hostname,
533 c_dirname ? c_dirname : "", f_filename) == -1)
534 errx(1, strerror(ENOMEM));
535 argc++;
536 }
538 r_flag = 1;
539 break;
540 case 'S':
541 if (parseoff(optarg, &S_size) == -1)
542 errx(1, "invalid size");
543 break;
544 case 's':
545 s_flag = 1;

--- 30 unchanged lines hidden (view full) ---

576 /* XXX this is a hack. */
577 if (strcspn(h_hostname, "@:/") != strlen(h_hostname))
578 errx(1, "invalid hostname");
579 if (asprintf(argv, "ftp://%s/%s/%s", h_hostname,
580 c_dirname ? c_dirname : "", f_filename) == -1)
581 errx(1, strerror(ENOMEM));
582 argc++;
583 }
537
584
538 if (!argc) {
539 usage();
540 exit(EX_USAGE);
541 }
542
543 /* allocate buffer */
544 if (B_size < MINBUFSIZE)
545 B_size = MINBUFSIZE;

--- 13 unchanged lines hidden (view full) ---

559 http_timeout = 0;
560 }
561 }
562
563 /* signal handling */
564 sa.sa_flags = 0;
565 sa.sa_handler = sig_handler;
566 sigemptyset(&sa.sa_mask);
585 if (!argc) {
586 usage();
587 exit(EX_USAGE);
588 }
589
590 /* allocate buffer */
591 if (B_size < MINBUFSIZE)
592 B_size = MINBUFSIZE;

--- 13 unchanged lines hidden (view full) ---

606 http_timeout = 0;
607 }
608 }
609
610 /* signal handling */
611 sa.sa_flags = 0;
612 sa.sa_handler = sig_handler;
613 sigemptyset(&sa.sa_mask);
567 (void)sigaction(SIGALRM, &sa, NULL);
568 (void)sigaction(SIGINT, &sa, NULL);
614 sigaction(SIGALRM, &sa, NULL);
615 sa.sa_flags = SA_RESETHAND;
616 sigaction(SIGINT, &sa, NULL);
617 fetchRestartCalls = 0;
569
570 /* output file */
571 if (o_flag) {
572 if (strcmp(o_filename, "-") == 0) {
573 o_stdout = 1;
574 } else if (stat(o_filename, &sb) == -1) {
575 if (errno == ENOENT) {
576 if (argc > 1)

--- 32 unchanged lines hidden (view full) ---

609 } else {
610 e = fetch(*argv, o_filename);
611 }
612 } else {
613 e = fetch(*argv, p);
614 }
615
616 if (sigint)
618
619 /* output file */
620 if (o_flag) {
621 if (strcmp(o_filename, "-") == 0) {
622 o_stdout = 1;
623 } else if (stat(o_filename, &sb) == -1) {
624 if (errno == ENOENT) {
625 if (argc > 1)

--- 32 unchanged lines hidden (view full) ---

658 } else {
659 e = fetch(*argv, o_filename);
660 }
661 } else {
662 e = fetch(*argv, p);
663 }
664
665 if (sigint)
617 exit(1);
666 kill(getpid(), SIGINT);
618
619 if (e == 0 && once_flag)
620 exit(0);
621
622 if (e) {
623 r = 1;
624 if ((fetchLastErrCode
625 && fetchLastErrCode != FETCH_UNAVAIL

--- 20 unchanged lines hidden ---
667
668 if (e == 0 && once_flag)
669 exit(0);
670
671 if (e) {
672 r = 1;
673 if ((fetchLastErrCode
674 && fetchLastErrCode != FETCH_UNAVAIL

--- 20 unchanged lines hidden ---