updater.c (156230) | updater.c (156701) |
---|---|
1/*- 2 * Copyright (c) 2003-2006, Maxime Henrion <mux@FreeBSD.org> 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 --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 2003-2006, Maxime Henrion <mux@FreeBSD.org> 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 --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: vendor/csup/dist/contrib/csup/updater.c 156230 2006-03-03 04:11:29Z mux $ | 26 * $FreeBSD: vendor/csup/dist/contrib/csup/updater.c 156701 2006-03-14 03:51:13Z mux $ |
27 */ 28 29#include <sys/types.h> 30#include <sys/stat.h> 31 32#include <assert.h> 33#include <errno.h> 34#include <fcntl.h> --- 14 unchanged lines hidden (view full) --- 49#include "proto.h" 50#include "status.h" 51#include "stream.h" 52 53/* Internal error codes. */ 54#define UPDATER_ERR_PROTO (-1) /* Protocol error. */ 55#define UPDATER_ERR_MSG (-2) /* Error is in updater->errmsg. */ 56#define UPDATER_ERR_READ (-3) /* Error reading from server. */ | 27 */ 28 29#include <sys/types.h> 30#include <sys/stat.h> 31 32#include <assert.h> 33#include <errno.h> 34#include <fcntl.h> --- 14 unchanged lines hidden (view full) --- 49#include "proto.h" 50#include "status.h" 51#include "stream.h" 52 53/* Internal error codes. */ 54#define UPDATER_ERR_PROTO (-1) /* Protocol error. */ 55#define UPDATER_ERR_MSG (-2) /* Error is in updater->errmsg. */ 56#define UPDATER_ERR_READ (-3) /* Error reading from server. */ |
57#define UPDATER_ERR_DELETELIM (-4) /* File deletion limit exceeded. */ |
|
57 58/* Everything needed to update a file. */ 59struct file_update { 60 struct statusrec srbuf; 61 char *destpath; | 58 59/* Everything needed to update a file. */ 60struct file_update { 61 struct statusrec srbuf; 62 char *destpath; |
63 char *temppath; |
|
62 char *coname; /* Points somewhere in destpath. */ 63 char *wantmd5; 64 struct coll *coll; 65 struct status *st; 66 /* Those are only used for diff updating. */ 67 char *author; 68 struct stream *orig; 69 struct stream *to; 70 int expand; 71}; 72 73struct updater { 74 struct config *config; 75 struct stream *rd; 76 char *errmsg; | 64 char *coname; /* Points somewhere in destpath. */ 65 char *wantmd5; 66 struct coll *coll; 67 struct status *st; 68 /* Those are only used for diff updating. */ 69 char *author; 70 struct stream *orig; 71 struct stream *to; 72 int expand; 73}; 74 75struct updater { 76 struct config *config; 77 struct stream *rd; 78 char *errmsg; |
79 int deletecount; |
|
77}; 78 79static struct file_update *fup_new(struct coll *, struct status *); 80static int fup_prepare(struct file_update *, char *); 81static void fup_cleanup(struct file_update *); 82static void fup_free(struct file_update *); 83 84static void updater_prunedirs(char *, char *); 85static int updater_batch(struct updater *, int); 86static int updater_docoll(struct updater *, struct file_update *, int); | 80}; 81 82static struct file_update *fup_new(struct coll *, struct status *); 83static int fup_prepare(struct file_update *, char *); 84static void fup_cleanup(struct file_update *); 85static void fup_free(struct file_update *); 86 87static void updater_prunedirs(char *, char *); 88static int updater_batch(struct updater *, int); 89static int updater_docoll(struct updater *, struct file_update *, int); |
87static void updater_delete(struct file_update *); | 90static int updater_delete(struct updater *, struct file_update *); 91static void updater_deletefile(const char *); |
88static int updater_checkout(struct updater *, struct file_update *, int); 89static int updater_setattrs(struct updater *, struct file_update *, 90 char *, char *, char *, char *, char *, struct fattr *); | 92static int updater_checkout(struct updater *, struct file_update *, int); 93static int updater_setattrs(struct updater *, struct file_update *, 94 char *, char *, char *, char *, char *, struct fattr *); |
91static void updater_checkmd5(struct updater *, struct file_update *, 92 const char *, int); | |
93static int updater_updatefile(struct updater *, struct file_update *fup, | 95static int updater_updatefile(struct updater *, struct file_update *fup, |
94 const char *, const char *); | 96 const char *, int); |
95static int updater_diff(struct updater *, struct file_update *); 96static int updater_diff_batch(struct updater *, struct file_update *); 97static int updater_diff_apply(struct updater *, struct file_update *, 98 char *); 99 100static struct file_update * 101fup_new(struct coll *coll, struct status *st) 102{ --- 26 unchanged lines hidden (view full) --- 129 struct statusrec *sr; 130 131 sr = &fup->srbuf; 132 133 if (fup->destpath != NULL) { 134 free(fup->destpath); 135 fup->destpath = NULL; 136 } | 97static int updater_diff(struct updater *, struct file_update *); 98static int updater_diff_batch(struct updater *, struct file_update *); 99static int updater_diff_apply(struct updater *, struct file_update *, 100 char *); 101 102static struct file_update * 103fup_new(struct coll *coll, struct status *st) 104{ --- 26 unchanged lines hidden (view full) --- 131 struct statusrec *sr; 132 133 sr = &fup->srbuf; 134 135 if (fup->destpath != NULL) { 136 free(fup->destpath); 137 fup->destpath = NULL; 138 } |
139 if (fup->temppath != NULL) { 140 free(fup->temppath); 141 fup->temppath = NULL; 142 } |
|
137 fup->coname = NULL; 138 if (fup->author != NULL) { 139 free(fup->author); 140 fup->author = NULL; 141 } 142 fup->expand = 0; 143 if (fup->wantmd5 != NULL) { 144 free(fup->wantmd5); --- 38 unchanged lines hidden (view full) --- 183 int error; 184 185 args = arg; 186 187 up = &upbuf; 188 up->config = args->config; 189 up->rd = args->rd; 190 up->errmsg = NULL; | 143 fup->coname = NULL; 144 if (fup->author != NULL) { 145 free(fup->author); 146 fup->author = NULL; 147 } 148 fup->expand = 0; 149 if (fup->wantmd5 != NULL) { 150 free(fup->wantmd5); --- 38 unchanged lines hidden (view full) --- 189 int error; 190 191 args = arg; 192 193 up = &upbuf; 194 up->config = args->config; 195 up->rd = args->rd; 196 up->errmsg = NULL; |
197 up->deletecount = 0; |
|
191 192 error = updater_batch(up, 0); 193 194 /* 195 * Make sure to close the fixups even in case of an error, 196 * so that the lister thread doesn't block indefinitely. 197 */ 198 fixups_close(up->config->fixups); --- 14 unchanged lines hidden (view full) --- 213 xasprintf(&args->errmsg, "Updater failed: " 214 "Premature EOF from server"); 215 } else { 216 xasprintf(&args->errmsg, "Updater failed: " 217 "Network read failure: %s", strerror(errno)); 218 } 219 args->status = STATUS_TRANSIENTFAILURE; 220 break; | 198 199 error = updater_batch(up, 0); 200 201 /* 202 * Make sure to close the fixups even in case of an error, 203 * so that the lister thread doesn't block indefinitely. 204 */ 205 fixups_close(up->config->fixups); --- 14 unchanged lines hidden (view full) --- 220 xasprintf(&args->errmsg, "Updater failed: " 221 "Premature EOF from server"); 222 } else { 223 xasprintf(&args->errmsg, "Updater failed: " 224 "Network read failure: %s", strerror(errno)); 225 } 226 args->status = STATUS_TRANSIENTFAILURE; 227 break; |
228 case UPDATER_ERR_DELETELIM: 229 xasprintf(&args->errmsg, "Updater failed: " 230 "File deletion limit exceeded"); 231 args->status = STATUS_FAILURE; 232 break; |
|
221 default: 222 assert(error == 0); 223 args->status = STATUS_SUCCESS; 224 }; 225 return (NULL); 226} 227 228static int --- 27 unchanged lines hidden (view full) --- 256 if (!isfixups) 257 lprintf(1, "Updating collection %s/%s\n", coll->co_name, 258 coll->co_release); 259 260 if (coll->co_options & CO_COMPRESS) 261 stream_filter_start(rd, STREAM_FILTER_ZLIB, NULL); 262 263 st = status_open(coll, coll->co_scantime, &errmsg); | 233 default: 234 assert(error == 0); 235 args->status = STATUS_SUCCESS; 236 }; 237 return (NULL); 238} 239 240static int --- 27 unchanged lines hidden (view full) --- 268 if (!isfixups) 269 lprintf(1, "Updating collection %s/%s\n", coll->co_name, 270 coll->co_release); 271 272 if (coll->co_options & CO_COMPRESS) 273 stream_filter_start(rd, STREAM_FILTER_ZLIB, NULL); 274 275 st = status_open(coll, coll->co_scantime, &errmsg); |
264 fup = fup_new(coll, st); | |
265 if (st == NULL) { | 276 if (st == NULL) { |
266 fup_free(fup); | |
267 up->errmsg = errmsg; 268 return (UPDATER_ERR_MSG); 269 } | 277 up->errmsg = errmsg; 278 return (UPDATER_ERR_MSG); 279 } |
280 fup = fup_new(coll, st); |
|
270 error = updater_docoll(up, fup, isfixups); 271 status_close(st, &errmsg); 272 fup_free(fup); 273 if (errmsg != NULL) { 274 /* Discard previous error. */ 275 if (up->errmsg != NULL) 276 free(up->errmsg); 277 up->errmsg = errmsg; --- 77 unchanged lines hidden (view full) --- 355 return (UPDATER_ERR_PROTO); 356 357 error = fup_prepare(fup, name); 358 if (error) 359 return (UPDATER_ERR_PROTO); 360 /* Theoritically, the file does not exist on the client. 361 Just to make sure, we'll delete it here, if it 362 exists. */ | 281 error = updater_docoll(up, fup, isfixups); 282 status_close(st, &errmsg); 283 fup_free(fup); 284 if (errmsg != NULL) { 285 /* Discard previous error. */ 286 if (up->errmsg != NULL) 287 free(up->errmsg); 288 up->errmsg = errmsg; --- 77 unchanged lines hidden (view full) --- 366 return (UPDATER_ERR_PROTO); 367 368 error = fup_prepare(fup, name); 369 if (error) 370 return (UPDATER_ERR_PROTO); 371 /* Theoritically, the file does not exist on the client. 372 Just to make sure, we'll delete it here, if it 373 exists. */ |
363 if (access(fup->destpath, F_OK) == 0) 364 updater_delete(fup); | 374 if (access(fup->destpath, F_OK) == 0) { 375 error = updater_delete(up, fup); 376 if (error) 377 return (error); 378 } |
365 366 sr = &srbuf; 367 sr->sr_type = SR_CHECKOUTDEAD; 368 sr->sr_file = name; 369 sr->sr_tag = tag; 370 sr->sr_date = date; 371 sr->sr_serverattr = fattr_decode(attr); 372 if (sr->sr_serverattr == NULL) --- 32 unchanged lines hidden (view full) --- 405 fup->expand = keyword_decode_expand(expand); 406 if (fup->expand == -1) 407 return (UPDATER_ERR_PROTO); 408 error = fup_prepare(fup, name); 409 if (error) 410 return (UPDATER_ERR_PROTO); 411 412 fup->wantmd5 = xstrdup(wantmd5); | 379 380 sr = &srbuf; 381 sr->sr_type = SR_CHECKOUTDEAD; 382 sr->sr_file = name; 383 sr->sr_tag = tag; 384 sr->sr_date = date; 385 sr->sr_serverattr = fattr_decode(attr); 386 if (sr->sr_serverattr == NULL) --- 32 unchanged lines hidden (view full) --- 419 fup->expand = keyword_decode_expand(expand); 420 if (fup->expand == -1) 421 return (UPDATER_ERR_PROTO); 422 error = fup_prepare(fup, name); 423 if (error) 424 return (UPDATER_ERR_PROTO); 425 426 fup->wantmd5 = xstrdup(wantmd5); |
427 fup->temppath = tempname(fup->destpath); |
|
413 error = updater_diff(up, fup); 414 if (error) 415 return (error); 416 break; 417 case 'u': 418 /* Update dead checked-out file. */ 419 name = proto_get_ascii(&line); 420 tag = proto_get_ascii(&line); 421 date = proto_get_ascii(&line); 422 attr = proto_get_ascii(&line); 423 if (attr == NULL || line != NULL) 424 return (UPDATER_ERR_PROTO); 425 426 error = fup_prepare(fup, name); 427 if (error) 428 return (UPDATER_ERR_PROTO); | 428 error = updater_diff(up, fup); 429 if (error) 430 return (error); 431 break; 432 case 'u': 433 /* Update dead checked-out file. */ 434 name = proto_get_ascii(&line); 435 tag = proto_get_ascii(&line); 436 date = proto_get_ascii(&line); 437 attr = proto_get_ascii(&line); 438 if (attr == NULL || line != NULL) 439 return (UPDATER_ERR_PROTO); 440 441 error = fup_prepare(fup, name); 442 if (error) 443 return (UPDATER_ERR_PROTO); |
429 updater_delete(fup); | 444 error = updater_delete(up, fup); 445 if (error) 446 return (error); |
430 sr = &srbuf; 431 sr->sr_type = SR_CHECKOUTDEAD; 432 sr->sr_file = name; 433 sr->sr_tag = tag; 434 sr->sr_date = date; 435 sr->sr_serverattr = fattr_decode(attr); 436 if (sr->sr_serverattr == NULL) 437 return (UPDATER_ERR_PROTO); --- 35 unchanged lines hidden (view full) --- 473 tmp = fattr_forcheckout(sr->sr_serverattr, 474 coll->co_umask); 475 fattr_override(sr->sr_clientattr, tmp, FA_MASK); 476 fattr_free(tmp); 477 fattr_mergedefault(sr->sr_clientattr); 478 error = fup_prepare(fup, name); 479 if (error) 480 return (UPDATER_ERR_PROTO); | 447 sr = &srbuf; 448 sr->sr_type = SR_CHECKOUTDEAD; 449 sr->sr_file = name; 450 sr->sr_tag = tag; 451 sr->sr_date = date; 452 sr->sr_serverattr = fattr_decode(attr); 453 if (sr->sr_serverattr == NULL) 454 return (UPDATER_ERR_PROTO); --- 35 unchanged lines hidden (view full) --- 490 tmp = fattr_forcheckout(sr->sr_serverattr, 491 coll->co_umask); 492 fattr_override(sr->sr_clientattr, tmp, FA_MASK); 493 fattr_free(tmp); 494 fattr_mergedefault(sr->sr_clientattr); 495 error = fup_prepare(fup, name); 496 if (error) 497 return (UPDATER_ERR_PROTO); |
498 fup->temppath = tempname(fup->destpath); |
|
481 if (*cmd == 'Y') 482 error = updater_checkout(up, fup, 1); 483 else 484 error = updater_checkout(up, fup, 0); 485 if (error) 486 return (error); 487 break; 488 case 'D': 489 /* Delete file. */ 490 name = proto_get_ascii(&line); 491 if (name == NULL || line != NULL) 492 return (UPDATER_ERR_PROTO); 493 error = fup_prepare(fup, name); 494 if (error) 495 return (UPDATER_ERR_PROTO); | 499 if (*cmd == 'Y') 500 error = updater_checkout(up, fup, 1); 501 else 502 error = updater_checkout(up, fup, 0); 503 if (error) 504 return (error); 505 break; 506 case 'D': 507 /* Delete file. */ 508 name = proto_get_ascii(&line); 509 if (name == NULL || line != NULL) 510 return (UPDATER_ERR_PROTO); 511 error = fup_prepare(fup, name); 512 if (error) 513 return (UPDATER_ERR_PROTO); |
496 updater_delete(fup); | 514 error = updater_delete(up, fup); 515 if (error) 516 return (error); |
497 error = status_delete(fup->st, name, 0); 498 if (error) { 499 up->errmsg = status_errmsg(fup->st); 500 return (UPDATER_ERR_MSG); 501 } 502 break; 503 case '!': 504 /* Warning from server. */ --- 8 unchanged lines hidden (view full) --- 513 fup_cleanup(fup); 514 } 515 if (line == NULL) 516 return (UPDATER_ERR_READ); 517 return (0); 518} 519 520/* Delete file. */ | 517 error = status_delete(fup->st, name, 0); 518 if (error) { 519 up->errmsg = status_errmsg(fup->st); 520 return (UPDATER_ERR_MSG); 521 } 522 break; 523 case '!': 524 /* Warning from server. */ --- 8 unchanged lines hidden (view full) --- 533 fup_cleanup(fup); 534 } 535 if (line == NULL) 536 return (UPDATER_ERR_READ); 537 return (0); 538} 539 540/* Delete file. */ |
521static void 522updater_delete(struct file_update *fup) | 541static int 542updater_delete(struct updater *up, struct file_update *fup) |
523{ | 543{ |
544 struct config *config; |
|
524 struct coll *coll; | 545 struct coll *coll; |
525 int error; | |
526 | 546 |
527 /* XXX - delete limit handling */ | 547 config = up->config; |
528 coll = fup->coll; 529 if (coll->co_options & CO_DELETE) { 530 lprintf(1, " Delete %s\n", fup->coname); | 548 coll = fup->coll; 549 if (coll->co_options & CO_DELETE) { 550 lprintf(1, " Delete %s\n", fup->coname); |
531 error = fattr_delete(fup->destpath); 532 if (error) { 533 lprintf(-1, "Cannot delete \"%s\": %s\n", 534 fup->destpath, strerror(errno)); 535 return; 536 } | 551 if (config->deletelim >= 0 && 552 up->deletecount >= config->deletelim) 553 return (UPDATER_ERR_DELETELIM); 554 up->deletecount++; 555 updater_deletefile(fup->destpath); |
537 if (coll->co_options & CO_CHECKOUTMODE) 538 updater_prunedirs(coll->co_prefix, fup->destpath); 539 } else { 540 lprintf(1," NoDelete %s\n", fup->coname); 541 } | 556 if (coll->co_options & CO_CHECKOUTMODE) 557 updater_prunedirs(coll->co_prefix, fup->destpath); 558 } else { 559 lprintf(1," NoDelete %s\n", fup->coname); 560 } |
561 return (0); |
|
542} 543 | 562} 563 |
564static void 565updater_deletefile(const char *path) 566{ 567 int error; 568 569 error = fattr_delete(path); 570 if (error && errno != ENOENT) { 571 lprintf(-1, "Cannot delete \"%s\": %s\n", 572 path, strerror(errno)); 573 } 574} 575 |
|
544static int 545updater_setattrs(struct updater *up, struct file_update *fup, char *name, 546 char *tag, char *date, char *revnum, char *revdate, struct fattr *rcsattr) 547{ 548 struct statusrec sr; 549 struct status *st; 550 struct coll *coll; 551 struct fattr *fileattr, *fa; --- 56 unchanged lines hidden (view full) --- 608 fattr_free(fileattr); 609 if (error) { 610 up->errmsg = status_errmsg(st); 611 return (UPDATER_ERR_MSG); 612 } 613 return (0); 614} 615 | 576static int 577updater_setattrs(struct updater *up, struct file_update *fup, char *name, 578 char *tag, char *date, char *revnum, char *revdate, struct fattr *rcsattr) 579{ 580 struct statusrec sr; 581 struct status *st; 582 struct coll *coll; 583 struct fattr *fileattr, *fa; --- 56 unchanged lines hidden (view full) --- 640 fattr_free(fileattr); 641 if (error) { 642 up->errmsg = status_errmsg(st); 643 return (UPDATER_ERR_MSG); 644 } 645 return (0); 646} 647 |
616/* 617 * Check that the file we created/updated has a correct MD5 checksum. 618 * If it doesn't and that this is not a fixup update, add a fixup 619 * request to checkout the whole file. If it's already a fixup update, 620 * we just fail. 621 */ 622static void 623updater_checkmd5(struct updater *up, struct file_update *fup, const char *md5, 624 int isfixup) 625{ 626 struct statusrec *sr; 627 628 sr = &fup->srbuf; 629 if (strcmp(fup->wantmd5, md5) == 0) 630 return; 631 if (isfixup) { 632 lprintf(-1, "%s: Checksum mismatch -- file not updated\n", 633 fup->destpath); 634 return; 635 } 636 lprintf(-1, "%s: Checksum mismatch -- will transfer entire file\n", 637 fup->destpath); 638 fixups_put(up->config->fixups, fup->coll, sr->sr_file); 639} 640 | |
641static int | 648static int |
642updater_updatefile(struct updater *up, struct file_update *fup, const char *to, 643 const char *from) | 649updater_updatefile(struct updater *up, struct file_update *fup, 650 const char *md5, int isfixup) |
644{ 645 struct coll *coll; 646 struct status *st; 647 struct statusrec *sr; 648 struct fattr *fileattr; 649 int error, rv; 650 651 coll = fup->coll; 652 sr = &fup->srbuf; 653 st = fup->st; 654 | 651{ 652 struct coll *coll; 653 struct status *st; 654 struct statusrec *sr; 655 struct fattr *fileattr; 656 int error, rv; 657 658 coll = fup->coll; 659 sr = &fup->srbuf; 660 st = fup->st; 661 |
662 if (strcmp(fup->wantmd5, md5) != 0) { 663 if (isfixup) { 664 lprintf(-1, "%s: Checksum mismatch -- " 665 "file not updated\n", fup->destpath); 666 } else { 667 lprintf(-1, "%s: Checksum mismatch -- " 668 "will transfer entire file\n", fup->destpath); 669 fixups_put(up->config->fixups, fup->coll, sr->sr_file); 670 } 671 if (coll->co_options & CO_KEEPBADFILES) 672 lprintf(-1, "Bad version saved in %s\n", fup->temppath); 673 else 674 updater_deletefile(fup->temppath); 675 return (0); 676 } 677 |
|
655 fattr_umask(sr->sr_clientattr, coll->co_umask); | 678 fattr_umask(sr->sr_clientattr, coll->co_umask); |
656 rv = fattr_install(sr->sr_clientattr, to, from); | 679 rv = fattr_install(sr->sr_clientattr, fup->destpath, fup->temppath); |
657 if (rv == -1) { | 680 if (rv == -1) { |
658 if (from == NULL) 659 xasprintf(&up->errmsg, "Cannot install \"%s\": %s", 660 to, strerror(errno)); 661 else 662 xasprintf(&up->errmsg, 663 "Cannot install \"%s\" to \"%s\": %s", 664 from, to, strerror(errno)); | 681 xasprintf(&up->errmsg, "Cannot install \"%s\" to \"%s\": %s", 682 fup->temppath, fup->destpath, strerror(errno)); |
665 return (UPDATER_ERR_MSG); 666 } 667 668 /* XXX Executes */ 669 /* 670 * We weren't necessarily able to set all the file attributes to the 671 * desired values, and any executes may have altered the attributes. 672 * To make sure we record the actual attribute values, we fetch 673 * them from the file. 674 * 675 * However, we preserve the link count as received from the 676 * server. This is important for preserving hard links in mirror 677 * mode. 678 */ | 683 return (UPDATER_ERR_MSG); 684 } 685 686 /* XXX Executes */ 687 /* 688 * We weren't necessarily able to set all the file attributes to the 689 * desired values, and any executes may have altered the attributes. 690 * To make sure we record the actual attribute values, we fetch 691 * them from the file. 692 * 693 * However, we preserve the link count as received from the 694 * server. This is important for preserving hard links in mirror 695 * mode. 696 */ |
679 fileattr = fattr_frompath(to, FATTR_NOFOLLOW); | 697 fileattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW); |
680 if (fileattr == NULL) { | 698 if (fileattr == NULL) { |
681 xasprintf(&up->errmsg, "Cannot stat \"%s\": %s", to, | 699 xasprintf(&up->errmsg, "Cannot stat \"%s\": %s", fup->destpath, |
682 strerror(errno)); 683 return (UPDATER_ERR_MSG); 684 } 685 fattr_override(fileattr, sr->sr_clientattr, FA_LINKCOUNT); 686 fattr_free(sr->sr_clientattr); 687 sr->sr_clientattr = fileattr; 688 689 /* --- 20 unchanged lines hidden (view full) --- 710static int 711updater_diff(struct updater *up, struct file_update *fup) 712{ 713 char md5[MD5_DIGEST_SIZE]; 714 struct coll *coll; 715 struct statusrec *sr; 716 struct fattr *fa, *tmp; 717 char *author, *path, *revnum, *revdate; | 700 strerror(errno)); 701 return (UPDATER_ERR_MSG); 702 } 703 fattr_override(fileattr, sr->sr_clientattr, FA_LINKCOUNT); 704 fattr_free(sr->sr_clientattr); 705 sr->sr_clientattr = fileattr; 706 707 /* --- 20 unchanged lines hidden (view full) --- 728static int 729updater_diff(struct updater *up, struct file_update *fup) 730{ 731 char md5[MD5_DIGEST_SIZE]; 732 struct coll *coll; 733 struct statusrec *sr; 734 struct fattr *fa, *tmp; 735 char *author, *path, *revnum, *revdate; |
718 char *line, *cmd, *temppath; | 736 char *line, *cmd; |
719 int error; 720 | 737 int error; 738 |
721 temppath = NULL; | |
722 coll = fup->coll; 723 sr = &fup->srbuf; 724 path = fup->destpath; 725 726 lprintf(1, " Edit %s\n", fup->coname); 727 while ((line = stream_getln(up->rd, NULL)) != NULL) { 728 if (strcmp(line, ".") == 0) 729 break; 730 cmd = proto_get_ascii(&line); | 739 coll = fup->coll; 740 sr = &fup->srbuf; 741 path = fup->destpath; 742 743 lprintf(1, " Edit %s\n", fup->coname); 744 while ((line = stream_getln(up->rd, NULL)) != NULL) { 745 if (strcmp(line, ".") == 0) 746 break; 747 cmd = proto_get_ascii(&line); |
731 if (cmd == NULL || strcmp(cmd, "D") != 0) { 732 error = UPDATER_ERR_PROTO; 733 goto bad; 734 } | 748 if (cmd == NULL || strcmp(cmd, "D") != 0) 749 return (UPDATER_ERR_PROTO); |
735 revnum = proto_get_ascii(&line); 736 proto_get_ascii(&line); /* XXX - diffbase */ 737 revdate = proto_get_ascii(&line); 738 author = proto_get_ascii(&line); | 750 revnum = proto_get_ascii(&line); 751 proto_get_ascii(&line); /* XXX - diffbase */ 752 revdate = proto_get_ascii(&line); 753 author = proto_get_ascii(&line); |
739 if (author == NULL || line != NULL) { 740 error = UPDATER_ERR_PROTO; 741 goto bad; 742 } | 754 if (author == NULL || line != NULL) 755 return (UPDATER_ERR_PROTO); |
743 if (sr->sr_revnum != NULL) 744 free(sr->sr_revnum); 745 if (sr->sr_revdate != NULL) 746 free(sr->sr_revdate); 747 if (fup->author != NULL) 748 free(fup->author); 749 sr->sr_revnum = xstrdup(revnum); 750 sr->sr_revdate = xstrdup(revdate); 751 fup->author = xstrdup(author); 752 if (fup->orig == NULL) { 753 /* First patch, the "origin" file is the one we have. */ 754 fup->orig = stream_open_file(path, O_RDONLY); 755 if (fup->orig == NULL) { 756 xasprintf(&up->errmsg, "%s: Cannot open: %s", 757 path, strerror(errno)); | 756 if (sr->sr_revnum != NULL) 757 free(sr->sr_revnum); 758 if (sr->sr_revdate != NULL) 759 free(sr->sr_revdate); 760 if (fup->author != NULL) 761 free(fup->author); 762 sr->sr_revnum = xstrdup(revnum); 763 sr->sr_revdate = xstrdup(revdate); 764 fup->author = xstrdup(author); 765 if (fup->orig == NULL) { 766 /* First patch, the "origin" file is the one we have. */ 767 fup->orig = stream_open_file(path, O_RDONLY); 768 if (fup->orig == NULL) { 769 xasprintf(&up->errmsg, "%s: Cannot open: %s", 770 path, strerror(errno)); |
758 error = UPDATER_ERR_MSG; 759 goto bad; | 771 return (UPDATER_ERR_MSG); |
760 } 761 } else { 762 /* Subsequent patches. */ 763 stream_close(fup->orig); 764 fup->orig = fup->to; 765 stream_rewind(fup->orig); | 772 } 773 } else { 774 /* Subsequent patches. */ 775 stream_close(fup->orig); 776 fup->orig = fup->to; 777 stream_rewind(fup->orig); |
766 unlink(temppath); 767 free(temppath); | 778 unlink(fup->temppath); 779 free(fup->temppath); 780 fup->temppath = tempname(path); |
768 } | 781 } |
769 temppath = tempname(path); 770 fup->to = stream_open_file(temppath, 771 O_RDWR | O_CREAT | O_EXCL, 0600); | 782 fup->to = stream_open_file(fup->temppath, 783 O_RDWR | O_CREAT | O_TRUNC, 0600); |
772 if (fup->to == NULL) { 773 xasprintf(&up->errmsg, "%s: Cannot open: %s", | 784 if (fup->to == NULL) { 785 xasprintf(&up->errmsg, "%s: Cannot open: %s", |
774 temppath, strerror(errno)); 775 error = UPDATER_ERR_MSG; 776 goto bad; | 786 fup->temppath, strerror(errno)); 787 return (UPDATER_ERR_MSG); |
777 } 778 lprintf(2, " Add delta %s %s %s\n", sr->sr_revnum, 779 sr->sr_revdate, fup->author); 780 error = updater_diff_batch(up, fup); 781 if (error) | 788 } 789 lprintf(2, " Add delta %s %s %s\n", sr->sr_revnum, 790 sr->sr_revdate, fup->author); 791 error = updater_diff_batch(up, fup); 792 if (error) |
782 goto bad; | 793 return (error); |
783 } | 794 } |
784 if (line == NULL) { 785 error = UPDATER_ERR_READ; 786 goto bad; 787 } | 795 if (line == NULL) 796 return (UPDATER_ERR_READ); |
788 789 fa = fattr_frompath(path, FATTR_FOLLOW); 790 tmp = fattr_forcheckout(sr->sr_serverattr, coll->co_umask); 791 fattr_override(fa, tmp, FA_MASK); 792 fattr_free(tmp); 793 fattr_maskout(fa, FA_MODTIME); 794 sr->sr_clientattr = fa; 795 | 797 798 fa = fattr_frompath(path, FATTR_FOLLOW); 799 tmp = fattr_forcheckout(sr->sr_serverattr, coll->co_umask); 800 fattr_override(fa, tmp, FA_MASK); 801 fattr_free(tmp); 802 fattr_maskout(fa, FA_MODTIME); 803 sr->sr_clientattr = fa; 804 |
796 error = updater_updatefile(up, fup, path, temppath); 797 if (error) 798 goto bad; 799 800 if (MD5_File(path, md5) == -1) { | 805 if (MD5_File(fup->temppath, md5) == -1) { |
801 xasprintf(&up->errmsg, 802 "Cannot calculate checksum for \"%s\": %s", 803 path, strerror(errno)); | 806 xasprintf(&up->errmsg, 807 "Cannot calculate checksum for \"%s\": %s", 808 path, strerror(errno)); |
804 error = UPDATER_ERR_MSG; 805 goto bad; | 809 return (UPDATER_ERR_MSG); |
806 } | 810 } |
807 updater_checkmd5(up, fup, md5, 0); 808 free(temppath); 809 return (0); 810bad: 811 assert(error); 812 if (temppath != NULL) 813 free(temppath); | 811 error = updater_updatefile(up, fup, md5, 0); |
814 return (error); 815} 816 817static int 818updater_diff_batch(struct updater *up, struct file_update *fup) 819{ 820 struct stream *rd; 821 char *cmd, *line, *state, *tok; --- 107 unchanged lines hidden (view full) --- 929 error = mkdirhier(path, coll->co_umask); 930 if (error) { 931 xasprintf(&up->errmsg, 932 "Cannot create directories leading to \"%s\": %s", 933 path, strerror(errno)); 934 return (UPDATER_ERR_MSG); 935 } 936 | 812 return (error); 813} 814 815static int 816updater_diff_batch(struct updater *up, struct file_update *fup) 817{ 818 struct stream *rd; 819 char *cmd, *line, *state, *tok; --- 107 unchanged lines hidden (view full) --- 927 error = mkdirhier(path, coll->co_umask); 928 if (error) { 929 xasprintf(&up->errmsg, 930 "Cannot create directories leading to \"%s\": %s", 931 path, strerror(errno)); 932 return (UPDATER_ERR_MSG); 933 } 934 |
937 to = stream_open_file(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); | 935 to = stream_open_file(fup->temppath, 936 O_WRONLY | O_CREAT | O_TRUNC, 0600); |
938 if (to == NULL) { 939 xasprintf(&up->errmsg, "%s: Cannot create: %s", | 937 if (to == NULL) { 938 xasprintf(&up->errmsg, "%s: Cannot create: %s", |
940 path, strerror(errno)); | 939 fup->temppath, strerror(errno)); |
941 return (UPDATER_ERR_MSG); 942 } 943 stream_filter_start(to, STREAM_FILTER_MD5, md5); 944 line = stream_getln(up->rd, &size); 945 first = 1; 946 while (line != NULL) { 947 if (line[size - 1] == '\n') 948 size--; --- 26 unchanged lines hidden (view full) --- 975 /* Get the checksum line. */ 976 line = stream_getln(up->rd, NULL); 977 if (line == NULL) 978 return (UPDATER_ERR_READ); 979 cmd = proto_get_ascii(&line); 980 fup->wantmd5 = proto_get_ascii(&line); 981 if (fup->wantmd5 == NULL || line != NULL || strcmp(cmd, "5") != 0) 982 return (UPDATER_ERR_PROTO); | 940 return (UPDATER_ERR_MSG); 941 } 942 stream_filter_start(to, STREAM_FILTER_MD5, md5); 943 line = stream_getln(up->rd, &size); 944 first = 1; 945 while (line != NULL) { 946 if (line[size - 1] == '\n') 947 size--; --- 26 unchanged lines hidden (view full) --- 974 /* Get the checksum line. */ 975 line = stream_getln(up->rd, NULL); 976 if (line == NULL) 977 return (UPDATER_ERR_READ); 978 cmd = proto_get_ascii(&line); 979 fup->wantmd5 = proto_get_ascii(&line); 980 if (fup->wantmd5 == NULL || line != NULL || strcmp(cmd, "5") != 0) 981 return (UPDATER_ERR_PROTO); |
983 updater_checkmd5(up, fup, md5, isfixup); | 982 error = updater_updatefile(up, fup, md5, isfixup); |
984 fup->wantmd5 = NULL; /* So that it doesn't get freed. */ | 983 fup->wantmd5 = NULL; /* So that it doesn't get freed. */ |
985 error = updater_updatefile(up, fup, path, NULL); | |
986 if (error) 987 return (error); 988 return (0); 989bad: | 984 if (error) 985 return (error); 986 return (0); 987bad: |
990 xasprintf(&up->errmsg, "%s: Cannot write: %s", path, strerror(errno)); | 988 xasprintf(&up->errmsg, "%s: Cannot write: %s", fup->temppath, 989 strerror(errno)); |
991 return (UPDATER_ERR_MSG); 992} 993 994/* 995 * Remove all empty directories below file. 996 * This function will trash the path passed to it. 997 */ 998static void --- 14 unchanged lines hidden --- | 990 return (UPDATER_ERR_MSG); 991} 992 993/* 994 * Remove all empty directories below file. 995 * This function will trash the path passed to it. 996 */ 997static void --- 14 unchanged lines hidden --- |