updater.c revision 190406
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 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 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: head/contrib/csup/updater.c 190406 2009-03-25 07:01:45Z lulf $ 27 */ 28 29#include <sys/types.h> 30#include <sys/stat.h> 31 32#include <assert.h> 33#include <err.h> 34#include <errno.h> 35#include <fcntl.h> 36#include <stddef.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40#include <unistd.h> 41 42#include "config.h" 43#include "diff.h" 44#include "fattr.h" 45#include "fixups.h" 46#include "keyword.h" 47#include "updater.h" 48#include "misc.h" 49#include "mux.h" 50#include "proto.h" 51#include "rcsfile.h" 52#include "status.h" 53#include "stream.h" 54 55/* Internal error codes. */ 56#define UPDATER_ERR_PROTO (-1) /* Protocol error. */ 57#define UPDATER_ERR_MSG (-2) /* Error is in updater->errmsg. */ 58#define UPDATER_ERR_READ (-3) /* Error reading from server. */ 59#define UPDATER_ERR_DELETELIM (-4) /* File deletion limit exceeded. */ 60 61#define BUFSIZE 4096 62 63/* Everything needed to update a file. */ 64struct file_update { 65 struct statusrec srbuf; 66 char *destpath; 67 char *temppath; 68 char *origpath; 69 char *coname; /* Points somewhere in destpath. */ 70 char *wantmd5; 71 struct coll *coll; 72 struct status *st; 73 /* Those are only used for diff updating. */ 74 char *author; 75 struct stream *orig; 76 struct stream *to; 77 int attic; 78 int expand; 79}; 80 81struct updater { 82 struct config *config; 83 struct stream *rd; 84 char *errmsg; 85 int deletecount; 86}; 87 88static struct file_update *fup_new(struct coll *, struct status *); 89static int fup_prepare(struct file_update *, char *, int); 90static void fup_cleanup(struct file_update *); 91static void fup_free(struct file_update *); 92 93static void updater_prunedirs(char *, char *); 94static int updater_batch(struct updater *, int); 95static int updater_docoll(struct updater *, struct file_update *, int); 96static int updater_delete(struct updater *, struct file_update *); 97static void updater_deletefile(const char *); 98static int updater_checkout(struct updater *, struct file_update *, int); 99static int updater_addfile(struct updater *, struct file_update *, 100 char *, int); 101int updater_addelta(struct rcsfile *, struct stream *, char *); 102static int updater_setattrs(struct updater *, struct file_update *, 103 char *, char *, char *, char *, char *, struct fattr *); 104static int updater_setdirattrs(struct updater *, struct coll *, 105 struct file_update *, char *, char *); 106static int updater_updatefile(struct updater *, struct file_update *fup, 107 const char *, int); 108static int updater_updatenode(struct updater *, struct coll *, 109 struct file_update *, char *, char *); 110static int updater_diff(struct updater *, struct file_update *); 111static int updater_diff_batch(struct updater *, struct file_update *); 112static int updater_diff_apply(struct updater *, struct file_update *, 113 char *); 114static int updater_rcsedit(struct updater *, struct file_update *, char *, 115 char *); 116int updater_append_file(struct updater *, struct file_update *, 117 off_t); 118static int updater_rsync(struct updater *, struct file_update *, size_t); 119static int updater_read_checkout(struct stream *, struct stream *); 120 121static struct file_update * 122fup_new(struct coll *coll, struct status *st) 123{ 124 struct file_update *fup; 125 126 fup = xmalloc(sizeof(struct file_update)); 127 memset(fup, 0, sizeof(*fup)); 128 fup->coll = coll; 129 fup->st = st; 130 return (fup); 131} 132 133static int 134fup_prepare(struct file_update *fup, char *name, int attic) 135{ 136 struct coll *coll; 137 138 coll = fup->coll; 139 fup->attic = 0; 140 fup->origpath = NULL; 141 142 if (coll->co_options & CO_CHECKOUTMODE) 143 fup->destpath = checkoutpath(coll->co_prefix, name); 144 else { 145 fup->destpath = cvspath(coll->co_prefix, name, attic); 146 fup->origpath = atticpath(coll->co_prefix, name); 147 /* If they're equal, we don't need special care. */ 148 if (fup->origpath != NULL && 149 strcmp(fup->origpath, fup->destpath) == 0) { 150 free(fup->origpath); 151 fup->origpath = NULL; 152 } 153 fup->attic = attic; 154 } 155 if (fup->destpath == NULL) 156 return (-1); 157 fup->coname = fup->destpath + coll->co_prefixlen + 1; 158 return (0); 159} 160 161/* Called after each file update to reinit the structure. */ 162static void 163fup_cleanup(struct file_update *fup) 164{ 165 struct statusrec *sr; 166 167 sr = &fup->srbuf; 168 169 if (fup->destpath != NULL) { 170 free(fup->destpath); 171 fup->destpath = NULL; 172 } 173 if (fup->temppath != NULL) { 174 free(fup->temppath); 175 fup->temppath = NULL; 176 } 177 if (fup->origpath != NULL) { 178 free(fup->origpath); 179 fup->origpath = NULL; 180 } 181 fup->coname = NULL; 182 if (fup->author != NULL) { 183 free(fup->author); 184 fup->author = NULL; 185 } 186 fup->expand = 0; 187 if (fup->wantmd5 != NULL) { 188 free(fup->wantmd5); 189 fup->wantmd5 = NULL; 190 } 191 if (fup->orig != NULL) { 192 stream_close(fup->orig); 193 fup->orig = NULL; 194 } 195 if (fup->to != NULL) { 196 stream_close(fup->to); 197 fup->to = NULL; 198 } 199 if (sr->sr_file != NULL) 200 free(sr->sr_file); 201 if (sr->sr_tag != NULL) 202 free(sr->sr_tag); 203 if (sr->sr_date != NULL) 204 free(sr->sr_date); 205 if (sr->sr_revnum != NULL) 206 free(sr->sr_revnum); 207 if (sr->sr_revdate != NULL) 208 free(sr->sr_revdate); 209 fattr_free(sr->sr_clientattr); 210 fattr_free(sr->sr_serverattr); 211 memset(sr, 0, sizeof(*sr)); 212} 213 214static void 215fup_free(struct file_update *fup) 216{ 217 218 fup_cleanup(fup); 219 free(fup); 220} 221 222void * 223updater(void *arg) 224{ 225 struct thread_args *args; 226 struct updater upbuf, *up; 227 int error; 228 229 args = arg; 230 231 up = &upbuf; 232 up->config = args->config; 233 up->rd = args->rd; 234 up->errmsg = NULL; 235 up->deletecount = 0; 236 237 error = updater_batch(up, 0); 238 239 /* 240 * Make sure to close the fixups even in case of an error, 241 * so that the lister thread doesn't block indefinitely. 242 */ 243 fixups_close(up->config->fixups); 244 if (!error) 245 error = updater_batch(up, 1); 246 switch (error) { 247 case UPDATER_ERR_PROTO: 248 xasprintf(&args->errmsg, "Updater failed: Protocol error"); 249 args->status = STATUS_FAILURE; 250 break; 251 case UPDATER_ERR_MSG: 252 xasprintf(&args->errmsg, "Updater failed: %s", up->errmsg); 253 free(up->errmsg); 254 args->status = STATUS_FAILURE; 255 break; 256 case UPDATER_ERR_READ: 257 if (stream_eof(up->rd)) { 258 xasprintf(&args->errmsg, "Updater failed: " 259 "Premature EOF from server"); 260 } else { 261 xasprintf(&args->errmsg, "Updater failed: " 262 "Network read failure: %s", strerror(errno)); 263 } 264 args->status = STATUS_TRANSIENTFAILURE; 265 break; 266 case UPDATER_ERR_DELETELIM: 267 xasprintf(&args->errmsg, "Updater failed: " 268 "File deletion limit exceeded"); 269 args->status = STATUS_FAILURE; 270 break; 271 default: 272 assert(error == 0); 273 args->status = STATUS_SUCCESS; 274 }; 275 return (NULL); 276} 277 278static int 279updater_batch(struct updater *up, int isfixups) 280{ 281 struct stream *rd; 282 struct coll *coll; 283 struct status *st; 284 struct file_update *fup; 285 char *line, *cmd, *errmsg, *collname, *release; 286 int error; 287 288 rd = up->rd; 289 STAILQ_FOREACH(coll, &up->config->colls, co_next) { 290 if (coll->co_options & CO_SKIP) 291 continue; 292 umask(coll->co_umask); 293 line = stream_getln(rd, NULL); 294 if (line == NULL) 295 return (UPDATER_ERR_READ); 296 cmd = proto_get_ascii(&line); 297 collname = proto_get_ascii(&line); 298 release = proto_get_ascii(&line); 299 if (release == NULL || line != NULL) 300 return (UPDATER_ERR_PROTO); 301 if (strcmp(cmd, "COLL") != 0 || 302 strcmp(collname, coll->co_name) != 0 || 303 strcmp(release, coll->co_release) != 0) 304 return (UPDATER_ERR_PROTO); 305 306 if (!isfixups) 307 lprintf(1, "Updating collection %s/%s\n", coll->co_name, 308 coll->co_release); 309 310 if (coll->co_options & CO_COMPRESS) 311 stream_filter_start(rd, STREAM_FILTER_ZLIB, NULL); 312 313 st = status_open(coll, coll->co_scantime, &errmsg); 314 if (st == NULL) { 315 up->errmsg = errmsg; 316 return (UPDATER_ERR_MSG); 317 } 318 fup = fup_new(coll, st); 319 error = updater_docoll(up, fup, isfixups); 320 status_close(st, &errmsg); 321 fup_free(fup); 322 if (errmsg != NULL) { 323 /* Discard previous error. */ 324 if (up->errmsg != NULL) 325 free(up->errmsg); 326 up->errmsg = errmsg; 327 return (UPDATER_ERR_MSG); 328 } 329 if (error) 330 return (error); 331 332 if (coll->co_options & CO_COMPRESS) 333 stream_filter_stop(rd); 334 } 335 line = stream_getln(rd, NULL); 336 if (line == NULL) 337 return (UPDATER_ERR_READ); 338 if (strcmp(line, ".") != 0) 339 return (UPDATER_ERR_PROTO); 340 return (0); 341} 342 343static int 344updater_docoll(struct updater *up, struct file_update *fup, int isfixups) 345{ 346 struct stream *rd; 347 struct coll *coll; 348 struct statusrec srbuf, *sr; 349 struct fattr *rcsattr, *tmp; 350 char *attr, *cmd, *blocksize, *line, *msg; 351 char *name, *tag, *date, *revdate; 352 char *expand, *wantmd5, *revnum; 353 char *optstr, *rcsopt, *pos; 354 time_t t; 355 off_t position; 356 int attic, error, needfixupmsg; 357 358 error = 0; 359 rd = up->rd; 360 coll = fup->coll; 361 needfixupmsg = isfixups; 362 while ((line = stream_getln(rd, NULL)) != NULL) { 363 if (strcmp(line, ".") == 0) 364 break; 365 memset(&srbuf, 0, sizeof(srbuf)); 366 if (needfixupmsg) { 367 lprintf(1, "Applying fixups for collection %s/%s\n", 368 coll->co_name, coll->co_release); 369 needfixupmsg = 0; 370 } 371 cmd = proto_get_ascii(&line); 372 if (cmd == NULL || strlen(cmd) != 1) 373 return (UPDATER_ERR_PROTO); 374 switch (cmd[0]) { 375 case 'T': 376 /* Update recorded information for checked-out file. */ 377 name = proto_get_ascii(&line); 378 tag = proto_get_ascii(&line); 379 date = proto_get_ascii(&line); 380 revnum = proto_get_ascii(&line); 381 revdate = proto_get_ascii(&line); 382 attr = proto_get_ascii(&line); 383 if (attr == NULL || line != NULL) 384 return (UPDATER_ERR_PROTO); 385 386 rcsattr = fattr_decode(attr); 387 if (rcsattr == NULL) 388 return (UPDATER_ERR_PROTO); 389 390 error = fup_prepare(fup, name, 0); 391 if (error) 392 return (UPDATER_ERR_PROTO); 393 error = updater_setattrs(up, fup, name, tag, date, 394 revnum, revdate, rcsattr); 395 fattr_free(rcsattr); 396 if (error) 397 return (error); 398 break; 399 case 'c': 400 /* Checkout dead file. */ 401 name = proto_get_ascii(&line); 402 tag = proto_get_ascii(&line); 403 date = proto_get_ascii(&line); 404 attr = proto_get_ascii(&line); 405 if (attr == NULL || line != NULL) 406 return (UPDATER_ERR_PROTO); 407 408 error = fup_prepare(fup, name, 0); 409 if (error) 410 return (UPDATER_ERR_PROTO); 411 /* Theoritically, the file does not exist on the client. 412 Just to make sure, we'll delete it here, if it 413 exists. */ 414 if (access(fup->destpath, F_OK) == 0) { 415 error = updater_delete(up, fup); 416 if (error) 417 return (error); 418 } 419 420 sr = &srbuf; 421 sr->sr_type = SR_CHECKOUTDEAD; 422 sr->sr_file = name; 423 sr->sr_tag = tag; 424 sr->sr_date = date; 425 sr->sr_serverattr = fattr_decode(attr); 426 if (sr->sr_serverattr == NULL) 427 return (UPDATER_ERR_PROTO); 428 429 error = status_put(fup->st, sr); 430 fattr_free(sr->sr_serverattr); 431 if (error) { 432 up->errmsg = status_errmsg(fup->st); 433 return (UPDATER_ERR_MSG); 434 } 435 break; 436 case 'U': 437 /* Update live checked-out file. */ 438 name = proto_get_ascii(&line); 439 tag = proto_get_ascii(&line); 440 date = proto_get_ascii(&line); 441 proto_get_ascii(&line); /* XXX - oldRevNum */ 442 proto_get_ascii(&line); /* XXX - fromAttic */ 443 proto_get_ascii(&line); /* XXX - logLines */ 444 expand = proto_get_ascii(&line); 445 attr = proto_get_ascii(&line); 446 wantmd5 = proto_get_ascii(&line); 447 if (wantmd5 == NULL || line != NULL) 448 return (UPDATER_ERR_PROTO); 449 450 sr = &fup->srbuf; 451 sr->sr_type = SR_CHECKOUTLIVE; 452 sr->sr_file = xstrdup(name); 453 sr->sr_date = xstrdup(date); 454 sr->sr_tag = xstrdup(tag); 455 sr->sr_serverattr = fattr_decode(attr); 456 if (sr->sr_serverattr == NULL) 457 return (UPDATER_ERR_PROTO); 458 459 fup->expand = keyword_decode_expand(expand); 460 if (fup->expand == -1) 461 return (UPDATER_ERR_PROTO); 462 error = fup_prepare(fup, name, 0); 463 if (error) 464 return (UPDATER_ERR_PROTO); 465 466 fup->wantmd5 = xstrdup(wantmd5); 467 fup->temppath = tempname(fup->destpath); 468 error = updater_diff(up, fup); 469 if (error) 470 return (error); 471 break; 472 case 'u': 473 /* Update dead checked-out file. */ 474 name = proto_get_ascii(&line); 475 tag = proto_get_ascii(&line); 476 date = proto_get_ascii(&line); 477 attr = proto_get_ascii(&line); 478 if (attr == NULL || line != NULL) 479 return (UPDATER_ERR_PROTO); 480 481 error = fup_prepare(fup, name, 0); 482 if (error) 483 return (UPDATER_ERR_PROTO); 484 error = updater_delete(up, fup); 485 if (error) 486 return (error); 487 sr = &srbuf; 488 sr->sr_type = SR_CHECKOUTDEAD; 489 sr->sr_file = name; 490 sr->sr_tag = tag; 491 sr->sr_date = date; 492 sr->sr_serverattr = fattr_decode(attr); 493 if (sr->sr_serverattr == NULL) 494 return (UPDATER_ERR_PROTO); 495 error = status_put(fup->st, sr); 496 fattr_free(sr->sr_serverattr); 497 if (error) { 498 up->errmsg = status_errmsg(fup->st); 499 return (UPDATER_ERR_MSG); 500 } 501 break; 502 case 'C': 503 case 'Y': 504 /* Checkout file. */ 505 name = proto_get_ascii(&line); 506 tag = proto_get_ascii(&line); 507 date = proto_get_ascii(&line); 508 revnum = proto_get_ascii(&line); 509 revdate = proto_get_ascii(&line); 510 attr = proto_get_ascii(&line); 511 if (attr == NULL || line != NULL) 512 return (UPDATER_ERR_PROTO); 513 514 sr = &fup->srbuf; 515 sr->sr_type = SR_CHECKOUTLIVE; 516 sr->sr_file = xstrdup(name); 517 sr->sr_tag = xstrdup(tag); 518 sr->sr_date = xstrdup(date); 519 sr->sr_revnum = xstrdup(revnum); 520 sr->sr_revdate = xstrdup(revdate); 521 sr->sr_serverattr = fattr_decode(attr); 522 if (sr->sr_serverattr == NULL) 523 return (UPDATER_ERR_PROTO); 524 525 t = rcsdatetotime(revdate); 526 if (t == -1) 527 return (UPDATER_ERR_PROTO); 528 529 sr->sr_clientattr = fattr_new(FT_FILE, t); 530 tmp = fattr_forcheckout(sr->sr_serverattr, 531 coll->co_umask); 532 fattr_override(sr->sr_clientattr, tmp, FA_MASK); 533 fattr_free(tmp); 534 fattr_mergedefault(sr->sr_clientattr); 535 error = fup_prepare(fup, name, 0); 536 if (error) 537 return (UPDATER_ERR_PROTO); 538 fup->temppath = tempname(fup->destpath); 539 if (*cmd == 'Y') 540 error = updater_checkout(up, fup, 1); 541 else 542 error = updater_checkout(up, fup, 0); 543 if (error) 544 return (error); 545 break; 546 case 'D': 547 /* Delete file. */ 548 name = proto_get_ascii(&line); 549 if (name == NULL || line != NULL) 550 return (UPDATER_ERR_PROTO); 551 error = fup_prepare(fup, name, 0); 552 if (error) 553 return (UPDATER_ERR_PROTO); 554 error = updater_delete(up, fup); 555 if (error) 556 return (error); 557 error = status_delete(fup->st, name, 0); 558 if (error) { 559 up->errmsg = status_errmsg(fup->st); 560 return (UPDATER_ERR_MSG); 561 } 562 break; 563 case 'A': 564 case 'a': 565 case 'R': 566 name = proto_get_ascii(&line); 567 attr = proto_get_ascii(&line); 568 if (name == NULL || attr == NULL || line != NULL) 569 return (UPDATER_ERR_PROTO); 570 attic = (cmd[0] == 'a'); 571 error = fup_prepare(fup, name, attic); 572 if (error) 573 return (UPDATER_ERR_PROTO); 574 575 fup->temppath = tempname(fup->destpath); 576 sr = &fup->srbuf; 577 sr->sr_type = attic ? SR_FILEDEAD : SR_FILELIVE; 578 sr->sr_file = xstrdup(name); 579 sr->sr_serverattr = fattr_decode(attr); 580 if (sr->sr_serverattr == NULL) 581 return (UPDATER_ERR_PROTO); 582 if (attic) 583 lprintf(1, " Create %s -> Attic\n", name); 584 else 585 lprintf(1, " Create %s\n", name); 586 error = updater_addfile(up, fup, attr, 0); 587 if (error) 588 return (error); 589 break; 590 case 'r': 591 name = proto_get_ascii(&line); 592 attr = proto_get_ascii(&line); 593 blocksize = proto_get_ascii(&line); 594 wantmd5 = proto_get_ascii(&line); 595 if (name == NULL || attr == NULL || blocksize == NULL || 596 wantmd5 == NULL) { 597 return (UPDATER_ERR_PROTO); 598 } 599 error = fup_prepare(fup, name, 0); 600 if (error) 601 return (UPDATER_ERR_PROTO); 602 fup->wantmd5 = xstrdup(wantmd5); 603 fup->temppath = tempname(fup->destpath); 604 sr = &fup->srbuf; 605 sr->sr_file = xstrdup(name); 606 sr->sr_serverattr = fattr_decode(attr); 607 sr->sr_type = SR_FILELIVE; 608 if (sr->sr_serverattr == NULL) 609 return (UPDATER_ERR_PROTO); 610 error = updater_rsync(up, fup, strtol(blocksize, NULL, 611 10)); 612 if (error) 613 return (error); 614 break; 615 case 'I': 616 /* 617 * Create directory and add DirDown entry in status 618 * file. 619 */ 620 name = proto_get_ascii(&line); 621 if (name == NULL || line != NULL) 622 return (UPDATER_ERR_PROTO); 623 error = fup_prepare(fup, name, 0); 624 if (error) 625 return (UPDATER_ERR_PROTO); 626 sr = &fup->srbuf; 627 sr->sr_type = SR_DIRDOWN; 628 sr->sr_file = xstrdup(name); 629 sr->sr_serverattr = NULL; 630 sr->sr_clientattr = fattr_new(FT_DIRECTORY, -1); 631 fattr_mergedefault(sr->sr_clientattr); 632 633 error = mkdirhier(fup->destpath, coll->co_umask); 634 if (error) 635 return (UPDATER_ERR_PROTO); 636 if (access(fup->destpath, F_OK) != 0) { 637 lprintf(1, " Mkdir %s\n", name); 638 error = fattr_makenode(sr->sr_clientattr, 639 fup->destpath); 640 if (error) 641 return (UPDATER_ERR_PROTO); 642 } 643 error = status_put(fup->st, sr); 644 if (error) { 645 up->errmsg = status_errmsg(fup->st); 646 return (UPDATER_ERR_MSG); 647 } 648 break; 649 case 'i': 650 /* Remove DirDown entry in status file. */ 651 name = proto_get_ascii(&line); 652 if (name == NULL || line != NULL) 653 return (UPDATER_ERR_PROTO); 654 error = fup_prepare(fup, name, 0); 655 if (error) 656 return (UPDATER_ERR_PROTO); 657 error = status_delete(fup->st, name, 0); 658 if (error) { 659 up->errmsg = status_errmsg(fup->st); 660 return (UPDATER_ERR_MSG); 661 } 662 break; 663 case 'J': 664 /* 665 * Set attributes of directory and update DirUp entry in 666 * status file. 667 */ 668 name = proto_get_ascii(&line); 669 if (name == NULL) 670 return (UPDATER_ERR_PROTO); 671 attr = proto_get_ascii(&line); 672 if (attr == NULL || line != NULL) 673 return (UPDATER_ERR_PROTO); 674 error = fup_prepare(fup, name, 0); 675 if (error) 676 return (UPDATER_ERR_PROTO); 677 error = updater_setdirattrs(up, coll, fup, name, attr); 678 if (error) 679 return (error); 680 break; 681 case 'j': 682 /* 683 * Remove directory and delete its DirUp entry in status 684 * file. 685 */ 686 name = proto_get_ascii(&line); 687 if (name == NULL || line != NULL) 688 return (UPDATER_ERR_PROTO); 689 error = fup_prepare(fup, name, 0); 690 if (error) 691 return (UPDATER_ERR_PROTO); 692 lprintf(1, " Rmdir %s\n", name); 693 updater_deletefile(fup->destpath); 694 error = status_delete(fup->st, name, 0); 695 if (error) { 696 up->errmsg = status_errmsg(fup->st); 697 return (UPDATER_ERR_MSG); 698 } 699 break; 700 case 'L': 701 case 'l': 702 name = proto_get_ascii(&line); 703 if (name == NULL) 704 return (UPDATER_ERR_PROTO); 705 attr = proto_get_ascii(&line); 706 if (attr == NULL || line != NULL) 707 return (UPDATER_ERR_PROTO); 708 attic = (cmd[0] == 'l'); 709 sr = &fup->srbuf; 710 sr->sr_type = attic ? SR_FILEDEAD : SR_FILELIVE; 711 sr->sr_file = xstrdup(name); 712 sr->sr_serverattr = fattr_decode(attr); 713 sr->sr_clientattr = fattr_decode(attr); 714 if (sr->sr_serverattr == NULL || 715 sr->sr_clientattr == NULL) 716 return (UPDATER_ERR_PROTO); 717 718 /* Save space. Described in detail in updatefile. */ 719 if (!(fattr_getmask(sr->sr_clientattr) & FA_LINKCOUNT) 720 || fattr_getlinkcount(sr->sr_clientattr) <= 1) 721 fattr_maskout(sr->sr_clientattr, 722 FA_DEV | FA_INODE); 723 fattr_maskout(sr->sr_clientattr, FA_FLAGS); 724 error = status_put(fup->st, sr); 725 if (error) { 726 up->errmsg = status_errmsg(fup->st); 727 return (UPDATER_ERR_MSG); 728 } 729 break; 730 case 'N': 731 case 'n': 732 name = proto_get_ascii(&line); 733 attr = proto_get_ascii(&line); 734 if (name == NULL || attr == NULL || line != NULL) 735 return (UPDATER_ERR_PROTO); 736 attic = (cmd[0] == 'n'); 737 error = fup_prepare(fup, name, attic); 738 if (error) 739 return (UPDATER_ERR_PROTO); 740 sr = &fup->srbuf; 741 sr->sr_type = (attic ? SR_FILEDEAD : SR_FILELIVE); 742 sr->sr_file = xstrdup(name); 743 sr->sr_serverattr = fattr_decode(attr); 744 sr->sr_clientattr = fattr_new(FT_SYMLINK, -1); 745 fattr_mergedefault(sr->sr_clientattr); 746 fattr_maskout(sr->sr_clientattr, FA_FLAGS); 747 error = updater_updatenode(up, coll, fup, name, attr); 748 if (error) 749 return (error); 750 break; 751 case 'V': 752 case 'v': 753 name = proto_get_ascii(&line); 754 attr = proto_get_ascii(&line); 755 optstr = proto_get_ascii(&line); 756 wantmd5 = proto_get_ascii(&line); 757 rcsopt = NULL; /* XXX: Not supported. */ 758 if (attr == NULL || line != NULL || wantmd5 == NULL) 759 return (UPDATER_ERR_PROTO); 760 attic = (cmd[0] == 'v'); 761 error = fup_prepare(fup, name, attic); 762 if (error) 763 return (UPDATER_ERR_PROTO); 764 fup->temppath = tempname(fup->destpath); 765 fup->wantmd5 = xstrdup(wantmd5); 766 sr = &fup->srbuf; 767 sr->sr_type = attic ? SR_FILEDEAD : SR_FILELIVE; 768 sr->sr_file = xstrdup(name); 769 sr->sr_serverattr = fattr_decode(attr); 770 if (sr->sr_serverattr == NULL) 771 return (UPDATER_ERR_PROTO); 772 773 error = 0; 774 error = updater_rcsedit(up, fup, name, rcsopt); 775 if (error) 776 return (error); 777 break; 778 case 'X': 779 case 'x': 780 name = proto_get_ascii(&line); 781 attr = proto_get_ascii(&line); 782 if (name == NULL || attr == NULL || line != NULL) 783 return (UPDATER_ERR_PROTO); 784 attic = (cmd[0] == 'x'); 785 error = fup_prepare(fup, name, attic); 786 if (error) 787 return (UPDATER_ERR_PROTO); 788 789 fup->temppath = tempname(fup->destpath); 790 sr = &fup->srbuf; 791 sr->sr_type = attic ? SR_FILEDEAD : SR_FILELIVE; 792 sr->sr_file = xstrdup(name); 793 sr->sr_serverattr = fattr_decode(attr); 794 if (sr->sr_serverattr == NULL) 795 return (UPDATER_ERR_PROTO); 796 lprintf(1, " Fixup %s\n", name); 797 error = updater_addfile(up, fup, attr, 1); 798 if (error) 799 return (error); 800 break; 801 case 'Z': 802 name = proto_get_ascii(&line); 803 attr = proto_get_ascii(&line); 804 pos = proto_get_ascii(&line); 805 if (name == NULL || attr == NULL || pos == NULL || 806 line != NULL) 807 return (UPDATER_ERR_PROTO); 808 error = fup_prepare(fup, name, 0); 809 fup->temppath = tempname(fup->destpath); 810 sr = &fup->srbuf; 811 sr->sr_type = SR_FILELIVE; 812 sr->sr_file = xstrdup(name); 813 sr->sr_serverattr = fattr_decode(attr); 814 if (sr->sr_serverattr == NULL) 815 return (UPDATER_ERR_PROTO); 816 position = strtol(pos, NULL, 10); 817 lprintf(1, " Append to %s\n", name); 818 error = updater_append_file(up, fup, position); 819 if (error) 820 return (error); 821 break; 822 case '!': 823 /* Warning from server. */ 824 msg = proto_get_rest(&line); 825 if (msg == NULL) 826 return (UPDATER_ERR_PROTO); 827 lprintf(-1, "Server warning: %s\n", msg); 828 break; 829 default: 830 return (UPDATER_ERR_PROTO); 831 } 832 fup_cleanup(fup); 833 } 834 if (line == NULL) 835 return (UPDATER_ERR_READ); 836 return (0); 837} 838 839/* Delete file. */ 840static int 841updater_delete(struct updater *up, struct file_update *fup) 842{ 843 struct config *config; 844 struct coll *coll; 845 846 config = up->config; 847 coll = fup->coll; 848 if (coll->co_options & CO_DELETE) { 849 lprintf(1, " Delete %s\n", fup->coname); 850 if (config->deletelim >= 0 && 851 up->deletecount >= config->deletelim) 852 return (UPDATER_ERR_DELETELIM); 853 up->deletecount++; 854 updater_deletefile(fup->destpath); 855 if (coll->co_options & CO_CHECKOUTMODE) 856 updater_prunedirs(coll->co_prefix, fup->destpath); 857 } else { 858 lprintf(1," NoDelete %s\n", fup->coname); 859 } 860 return (0); 861} 862 863static void 864updater_deletefile(const char *path) 865{ 866 int error; 867 868 error = fattr_delete(path); 869 if (error && errno != ENOENT) { 870 lprintf(-1, "Cannot delete \"%s\": %s\n", 871 path, strerror(errno)); 872 } 873} 874 875static int 876updater_setattrs(struct updater *up, struct file_update *fup, char *name, 877 char *tag, char *date, char *revnum, char *revdate, struct fattr *rcsattr) 878{ 879 struct statusrec sr; 880 struct status *st; 881 struct coll *coll; 882 struct fattr *fileattr, *fa; 883 char *path; 884 int error, rv; 885 886 coll = fup->coll; 887 st = fup->st; 888 path = fup->destpath; 889 890 fileattr = fattr_frompath(path, FATTR_NOFOLLOW); 891 if (fileattr == NULL) { 892 /* The file has vanished. */ 893 error = status_delete(st, name, 0); 894 if (error) { 895 up->errmsg = status_errmsg(st); 896 return (UPDATER_ERR_MSG); 897 } 898 return (0); 899 } 900 fa = fattr_forcheckout(rcsattr, coll->co_umask); 901 fattr_override(fileattr, fa, FA_MASK); 902 fattr_free(fa); 903 904 rv = fattr_install(fileattr, path, NULL); 905 if (rv == -1) { 906 lprintf(1, " SetAttrs %s\n", fup->coname); 907 fattr_free(fileattr); 908 xasprintf(&up->errmsg, "Cannot set attributes for \"%s\": %s", 909 path, strerror(errno)); 910 return (UPDATER_ERR_MSG); 911 } 912 if (rv == 1) { 913 lprintf(1, " SetAttrs %s\n", fup->coname); 914 fattr_free(fileattr); 915 fileattr = fattr_frompath(path, FATTR_NOFOLLOW); 916 if (fileattr == NULL) { 917 /* We're being very unlucky. */ 918 error = status_delete(st, name, 0); 919 if (error) { 920 up->errmsg = status_errmsg(st); 921 return (UPDATER_ERR_MSG); 922 } 923 return (0); 924 } 925 } 926 927 fattr_maskout(fileattr, FA_COIGNORE); 928 929 sr.sr_type = SR_CHECKOUTLIVE; 930 sr.sr_file = name; 931 sr.sr_tag = tag; 932 sr.sr_date = date; 933 sr.sr_revnum = revnum; 934 sr.sr_revdate = revdate; 935 sr.sr_clientattr = fileattr; 936 sr.sr_serverattr = rcsattr; 937 938 error = status_put(st, &sr); 939 fattr_free(fileattr); 940 if (error) { 941 up->errmsg = status_errmsg(st); 942 return (UPDATER_ERR_MSG); 943 } 944 return (0); 945} 946 947static int 948updater_updatefile(struct updater *up, struct file_update *fup, 949 const char *md5, int isfixup) 950{ 951 struct coll *coll; 952 struct status *st; 953 struct statusrec *sr; 954 struct fattr *fileattr; 955 int error, rv; 956 957 coll = fup->coll; 958 sr = &fup->srbuf; 959 st = fup->st; 960 961 if (strcmp(fup->wantmd5, md5) != 0) { 962 if (isfixup) { 963 lprintf(-1, "%s: Checksum mismatch -- " 964 "file not updated\n", fup->destpath); 965 } else { 966 lprintf(-1, "%s: Checksum mismatch -- " 967 "will transfer entire file\n", fup->destpath); 968 fixups_put(up->config->fixups, fup->coll, sr->sr_file); 969 } 970 if (coll->co_options & CO_KEEPBADFILES) 971 lprintf(-1, "Bad version saved in %s\n", fup->temppath); 972 else 973 updater_deletefile(fup->temppath); 974 return (0); 975 } 976 977 fattr_umask(sr->sr_clientattr, coll->co_umask); 978 rv = fattr_install(sr->sr_clientattr, fup->destpath, fup->temppath); 979 if (rv == -1) { 980 xasprintf(&up->errmsg, "Cannot install \"%s\" to \"%s\": %s", 981 fup->temppath, fup->destpath, strerror(errno)); 982 return (UPDATER_ERR_MSG); 983 } 984 985 /* XXX Executes */ 986 /* 987 * We weren't necessarily able to set all the file attributes to the 988 * desired values, and any executes may have altered the attributes. 989 * To make sure we record the actual attribute values, we fetch 990 * them from the file. 991 * 992 * However, we preserve the link count as received from the 993 * server. This is important for preserving hard links in mirror 994 * mode. 995 */ 996 fileattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW); 997 if (fileattr == NULL) { 998 xasprintf(&up->errmsg, "Cannot stat \"%s\": %s", fup->destpath, 999 strerror(errno)); 1000 return (UPDATER_ERR_MSG); 1001 } 1002 fattr_override(fileattr, sr->sr_clientattr, FA_LINKCOUNT); 1003 fattr_free(sr->sr_clientattr); 1004 sr->sr_clientattr = fileattr; 1005 1006 /* 1007 * To save space, don't write out the device and inode unless 1008 * the link count is greater than 1. These attributes are used 1009 * only for detecting hard links. If the link count is 1 then we 1010 * know there aren't any hard links. 1011 */ 1012 if (!(fattr_getmask(sr->sr_clientattr) & FA_LINKCOUNT) || 1013 fattr_getlinkcount(sr->sr_clientattr) <= 1) 1014 fattr_maskout(sr->sr_clientattr, FA_DEV | FA_INODE); 1015 1016 if (coll->co_options & CO_CHECKOUTMODE) 1017 fattr_maskout(sr->sr_clientattr, FA_COIGNORE); 1018 1019 error = status_put(st, sr); 1020 if (error) { 1021 up->errmsg = status_errmsg(st); 1022 return (UPDATER_ERR_MSG); 1023 } 1024 return (0); 1025} 1026 1027/* 1028 * Update attributes of a directory. 1029 */ 1030static int 1031updater_setdirattrs(struct updater *up, struct coll *coll, 1032 struct file_update *fup, char *name, char *attr) 1033{ 1034 struct statusrec *sr; 1035 struct fattr *fa; 1036 int error, rv; 1037 1038 sr = &fup->srbuf; 1039 sr->sr_type = SR_DIRUP; 1040 sr->sr_file = xstrdup(name); 1041 sr->sr_clientattr = fattr_decode(attr); 1042 sr->sr_serverattr = fattr_decode(attr); 1043 if (sr->sr_clientattr == NULL || sr->sr_serverattr == NULL) 1044 return (UPDATER_ERR_PROTO); 1045 fattr_mergedefault(sr->sr_clientattr); 1046 fattr_umask(sr->sr_clientattr, coll->co_umask); 1047 rv = fattr_install(sr->sr_clientattr, fup->destpath, NULL); 1048 lprintf(1, " SetAttrs %s\n", name); 1049 if (rv == -1) { 1050 xasprintf(&up->errmsg, "Cannot install \"%s\" to \"%s\": %s", 1051 fup->temppath, fup->destpath, strerror(errno)); 1052 return (UPDATER_ERR_MSG); 1053 } 1054 /* 1055 * Now, make sure they were set and record what was set in the status 1056 * file. 1057 */ 1058 fa = fattr_frompath(fup->destpath, FATTR_NOFOLLOW); 1059 if (fa == NULL) { 1060 xasprintf(&up->errmsg, "Cannot open \%s\": %s", fup->destpath, 1061 strerror(errno)); 1062 return (UPDATER_ERR_MSG); 1063 } 1064 fattr_free(sr->sr_clientattr); 1065 fattr_maskout(fa, FA_FLAGS); 1066 sr->sr_clientattr = fa; 1067 error = status_put(fup->st, sr); 1068 if (error) { 1069 up->errmsg = status_errmsg(fup->st); 1070 return (UPDATER_ERR_MSG); 1071 } 1072 1073 return (0); 1074} 1075 1076static int 1077updater_diff(struct updater *up, struct file_update *fup) 1078{ 1079 char md5[MD5_DIGEST_SIZE]; 1080 struct coll *coll; 1081 struct statusrec *sr; 1082 struct fattr *fa, *tmp; 1083 char *author, *path, *revnum, *revdate; 1084 char *line, *cmd; 1085 int error; 1086 1087 coll = fup->coll; 1088 sr = &fup->srbuf; 1089 path = fup->destpath; 1090 1091 lprintf(1, " Edit %s\n", fup->coname); 1092 while ((line = stream_getln(up->rd, NULL)) != NULL) { 1093 if (strcmp(line, ".") == 0) 1094 break; 1095 cmd = proto_get_ascii(&line); 1096 if (cmd == NULL || strcmp(cmd, "D") != 0) 1097 return (UPDATER_ERR_PROTO); 1098 revnum = proto_get_ascii(&line); 1099 proto_get_ascii(&line); /* XXX - diffbase */ 1100 revdate = proto_get_ascii(&line); 1101 author = proto_get_ascii(&line); 1102 if (author == NULL || line != NULL) 1103 return (UPDATER_ERR_PROTO); 1104 if (sr->sr_revnum != NULL) 1105 free(sr->sr_revnum); 1106 if (sr->sr_revdate != NULL) 1107 free(sr->sr_revdate); 1108 if (fup->author != NULL) 1109 free(fup->author); 1110 sr->sr_revnum = xstrdup(revnum); 1111 sr->sr_revdate = xstrdup(revdate); 1112 fup->author = xstrdup(author); 1113 if (fup->orig == NULL) { 1114 /* First patch, the "origin" file is the one we have. */ 1115 fup->orig = stream_open_file(path, O_RDONLY); 1116 if (fup->orig == NULL) { 1117 xasprintf(&up->errmsg, "%s: Cannot open: %s", 1118 path, strerror(errno)); 1119 return (UPDATER_ERR_MSG); 1120 } 1121 } else { 1122 /* Subsequent patches. */ 1123 stream_close(fup->orig); 1124 fup->orig = fup->to; 1125 stream_rewind(fup->orig); 1126 unlink(fup->temppath); 1127 free(fup->temppath); 1128 fup->temppath = tempname(path); 1129 } 1130 fup->to = stream_open_file(fup->temppath, 1131 O_RDWR | O_CREAT | O_TRUNC, 0600); 1132 if (fup->to == NULL) { 1133 xasprintf(&up->errmsg, "%s: Cannot open: %s", 1134 fup->temppath, strerror(errno)); 1135 return (UPDATER_ERR_MSG); 1136 } 1137 lprintf(2, " Add delta %s %s %s\n", sr->sr_revnum, 1138 sr->sr_revdate, fup->author); 1139 error = updater_diff_batch(up, fup); 1140 if (error) 1141 return (error); 1142 } 1143 if (line == NULL) 1144 return (UPDATER_ERR_READ); 1145 1146 fa = fattr_frompath(path, FATTR_FOLLOW); 1147 tmp = fattr_forcheckout(sr->sr_serverattr, coll->co_umask); 1148 fattr_override(fa, tmp, FA_MASK); 1149 fattr_free(tmp); 1150 fattr_maskout(fa, FA_MODTIME); 1151 sr->sr_clientattr = fa; 1152 1153 if (MD5_File(fup->temppath, md5) == -1) { 1154 xasprintf(&up->errmsg, 1155 "Cannot calculate checksum for \"%s\": %s", 1156 path, strerror(errno)); 1157 return (UPDATER_ERR_MSG); 1158 } 1159 error = updater_updatefile(up, fup, md5, 0); 1160 return (error); 1161} 1162 1163/* 1164 * Edit a file and add delta. 1165 */ 1166static int 1167updater_diff_batch(struct updater *up, struct file_update *fup) 1168{ 1169 struct stream *rd; 1170 char *cmd, *line, *state, *tok; 1171 int error; 1172 1173 state = NULL; 1174 rd = up->rd; 1175 while ((line = stream_getln(rd, NULL)) != NULL) { 1176 if (strcmp(line, ".") == 0) 1177 break; 1178 cmd = proto_get_ascii(&line); 1179 if (cmd == NULL || strlen(cmd) != 1) { 1180 error = UPDATER_ERR_PROTO; 1181 goto bad; 1182 } 1183 switch (cmd[0]) { 1184 case 'L': 1185 line = stream_getln(rd, NULL); 1186 /* XXX - We're just eating the log for now. */ 1187 while (line != NULL && strcmp(line, ".") != 0 && 1188 strcmp(line, ".+") != 0) 1189 line = stream_getln(rd, NULL); 1190 if (line == NULL) { 1191 error = UPDATER_ERR_READ; 1192 goto bad; 1193 } 1194 break; 1195 case 'S': 1196 tok = proto_get_ascii(&line); 1197 if (tok == NULL || line != NULL) { 1198 error = UPDATER_ERR_PROTO; 1199 goto bad; 1200 } 1201 if (state != NULL) 1202 free(state); 1203 state = xstrdup(tok); 1204 break; 1205 case 'T': 1206 error = updater_diff_apply(up, fup, state); 1207 if (error) 1208 goto bad; 1209 break; 1210 default: 1211 error = UPDATER_ERR_PROTO; 1212 goto bad; 1213 } 1214 } 1215 if (line == NULL) { 1216 error = UPDATER_ERR_READ; 1217 goto bad; 1218 } 1219 if (state != NULL) 1220 free(state); 1221 return (0); 1222bad: 1223 if (state != NULL) 1224 free(state); 1225 return (error); 1226} 1227 1228int 1229updater_diff_apply(struct updater *up, struct file_update *fup, char *state) 1230{ 1231 struct diffinfo dibuf, *di; 1232 struct coll *coll; 1233 struct statusrec *sr; 1234 int error; 1235 1236 coll = fup->coll; 1237 sr = &fup->srbuf; 1238 di = &dibuf; 1239 1240 di->di_rcsfile = sr->sr_file; 1241 di->di_cvsroot = coll->co_cvsroot; 1242 di->di_revnum = sr->sr_revnum; 1243 di->di_revdate = sr->sr_revdate; 1244 di->di_author = fup->author; 1245 di->di_tag = sr->sr_tag; 1246 di->di_state = state; 1247 di->di_expand = fup->expand; 1248 1249 error = diff_apply(up->rd, fup->orig, fup->to, coll->co_keyword, di, 1); 1250 if (error) { 1251 /* XXX Bad error message */ 1252 xasprintf(&up->errmsg, "Bad diff from server"); 1253 return (UPDATER_ERR_MSG); 1254 } 1255 return (0); 1256} 1257 1258/* Update or create a node. */ 1259static int 1260updater_updatenode(struct updater *up, struct coll *coll, 1261 struct file_update *fup, char *name, char *attr) 1262{ 1263 struct fattr *fa, *fileattr; 1264 struct status *st; 1265 struct statusrec *sr; 1266 int error, rv; 1267 1268 sr = &fup->srbuf; 1269 st = fup->st; 1270 fa = fattr_decode(attr); 1271 1272 if (fattr_type(fa) == FT_SYMLINK) { 1273 lprintf(1, " Symlink %s -> %s\n", name, 1274 fattr_getlinktarget(fa)); 1275 } else { 1276 lprintf(1, " Mknod %s\n", name); 1277 } 1278 1279 /* Create directory. */ 1280 error = mkdirhier(fup->destpath, coll->co_umask); 1281 if (error) 1282 return (UPDATER_ERR_PROTO); 1283 1284 /* If it does not exist, create it. */ 1285 if (access(fup->destpath, F_OK) != 0) 1286 fattr_makenode(fa, fup->destpath); 1287 1288 /* 1289 * Coming from attic? I don't think this is a problem since we have 1290 * determined attic before we call this function (Look at UpdateNode in 1291 * cvsup). 1292 */ 1293 fattr_umask(fa, coll->co_umask); 1294 rv = fattr_install(fa, fup->destpath, fup->temppath); 1295 if (rv == -1) { 1296 xasprintf(&up->errmsg, "Cannot update attributes on " 1297 "\"%s\": %s", fup->destpath, strerror(errno)); 1298 return (UPDATER_ERR_MSG); 1299 } 1300 /* 1301 * XXX: Executes not implemented. Have not encountered much use for it 1302 * yet. 1303 */ 1304 /* 1305 * We weren't necessarily able to set all the file attributes to the 1306 * desired values, and any executes may have altered the attributes. 1307 * To make sure we record the actual attribute values, we fetch 1308 * them from the file. 1309 * 1310 * However, we preserve the link count as received from the 1311 * server. This is important for preserving hard links in mirror 1312 * mode. 1313 */ 1314 fileattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW); 1315 if (fileattr == NULL) { 1316 xasprintf(&up->errmsg, "Cannot stat \"%s\": %s", fup->destpath, 1317 strerror(errno)); 1318 return (UPDATER_ERR_MSG); 1319 } 1320 fattr_override(fileattr, sr->sr_clientattr, FA_LINKCOUNT); 1321 fattr_free(sr->sr_clientattr); 1322 sr->sr_clientattr = fileattr; 1323 1324 /* 1325 * To save space, don't write out the device and inode unless 1326 * the link count is greater than 1. These attributes are used 1327 * only for detecting hard links. If the link count is 1 then we 1328 * know there aren't any hard links. 1329 */ 1330 if (!(fattr_getmask(sr->sr_clientattr) & FA_LINKCOUNT) || 1331 fattr_getlinkcount(sr->sr_clientattr) <= 1) 1332 fattr_maskout(sr->sr_clientattr, FA_DEV | FA_INODE); 1333 1334 /* If it is a symlink, write only out it's path. */ 1335 if (fattr_type(fa) == FT_SYMLINK) { 1336 fattr_maskout(sr->sr_clientattr, ~(FA_FILETYPE | 1337 FA_LINKTARGET)); 1338 } 1339 fattr_maskout(sr->sr_clientattr, FA_FLAGS); 1340 error = status_put(st, sr); 1341 if (error) { 1342 up->errmsg = status_errmsg(st); 1343 return (UPDATER_ERR_MSG); 1344 } 1345 fattr_free(fa); 1346 1347 return (0); 1348} 1349 1350/* 1351 * Fetches a new file in CVS mode. 1352 */ 1353static int 1354updater_addfile(struct updater *up, struct file_update *fup, char *attr, 1355 int isfixup) 1356{ 1357 struct coll *coll; 1358 struct stream *to; 1359 struct statusrec *sr; 1360 struct fattr *fa; 1361 char buf[BUFSIZE]; 1362 char md5[MD5_DIGEST_SIZE]; 1363 ssize_t nread; 1364 off_t fsize, remains; 1365 char *cmd, *line, *path; 1366 int error; 1367 1368 coll = fup->coll; 1369 path = fup->destpath; 1370 sr = &fup->srbuf; 1371 fa = fattr_decode(attr); 1372 fsize = fattr_filesize(fa); 1373 1374 error = mkdirhier(path, coll->co_umask); 1375 if (error) 1376 return (UPDATER_ERR_PROTO); 1377 to = stream_open_file(fup->temppath, O_WRONLY | O_CREAT | O_TRUNC, 0755); 1378 if (to == NULL) { 1379 xasprintf(&up->errmsg, "%s: Cannot create: %s", 1380 fup->temppath, strerror(errno)); 1381 return (UPDATER_ERR_MSG); 1382 } 1383 stream_filter_start(to, STREAM_FILTER_MD5, md5); 1384 remains = fsize; 1385 do { 1386 nread = stream_read(up->rd, buf, (BUFSIZE > remains ? 1387 remains : BUFSIZE)); 1388 remains -= nread; 1389 stream_write(to, buf, nread); 1390 } while (remains > 0); 1391 stream_close(to); 1392 line = stream_getln(up->rd, NULL); 1393 if (line == NULL) 1394 return (UPDATER_ERR_PROTO); 1395 /* Check for EOF. */ 1396 if (!(*line == '.' || (strncmp(line, ".<", 2) != 0))) 1397 return (UPDATER_ERR_PROTO); 1398 line = stream_getln(up->rd, NULL); 1399 if (line == NULL) 1400 return (UPDATER_ERR_PROTO); 1401 1402 cmd = proto_get_ascii(&line); 1403 fup->wantmd5 = proto_get_ascii(&line); 1404 if (fup->wantmd5 == NULL || line != NULL || strcmp(cmd, "5") != 0) 1405 return (UPDATER_ERR_PROTO); 1406 1407 sr->sr_clientattr = fattr_frompath(fup->temppath, FATTR_NOFOLLOW); 1408 if (sr->sr_clientattr == NULL) 1409 return (UPDATER_ERR_PROTO); 1410 fattr_override(sr->sr_clientattr, sr->sr_serverattr, 1411 FA_MODTIME | FA_MASK); 1412 error = updater_updatefile(up, fup, md5, isfixup); 1413 fup->wantmd5 = NULL; /* So that it doesn't get freed. */ 1414 if (error) 1415 return (error); 1416 return (0); 1417} 1418 1419static int 1420updater_checkout(struct updater *up, struct file_update *fup, int isfixup) 1421{ 1422 char md5[MD5_DIGEST_SIZE]; 1423 struct statusrec *sr; 1424 struct coll *coll; 1425 struct stream *to; 1426 ssize_t nbytes; 1427 size_t size; 1428 char *cmd, *path, *line; 1429 int error, first; 1430 1431 coll = fup->coll; 1432 sr = &fup->srbuf; 1433 path = fup->destpath; 1434 1435 if (isfixup) 1436 lprintf(1, " Fixup %s\n", fup->coname); 1437 else 1438 lprintf(1, " Checkout %s\n", fup->coname); 1439 error = mkdirhier(path, coll->co_umask); 1440 if (error) { 1441 xasprintf(&up->errmsg, 1442 "Cannot create directories leading to \"%s\": %s", 1443 path, strerror(errno)); 1444 return (UPDATER_ERR_MSG); 1445 } 1446 1447 to = stream_open_file(fup->temppath, 1448 O_WRONLY | O_CREAT | O_TRUNC, 0600); 1449 if (to == NULL) { 1450 xasprintf(&up->errmsg, "%s: Cannot create: %s", 1451 fup->temppath, strerror(errno)); 1452 return (UPDATER_ERR_MSG); 1453 } 1454 stream_filter_start(to, STREAM_FILTER_MD5, md5); 1455 line = stream_getln(up->rd, &size); 1456 first = 1; 1457 while (line != NULL) { 1458 if (line[size - 1] == '\n') 1459 size--; 1460 if ((size == 1 && *line == '.') || 1461 (size == 2 && memcmp(line, ".+", 2) == 0)) 1462 break; 1463 if (size >= 2 && memcmp(line, "..", 2) == 0) { 1464 size--; 1465 line++; 1466 } 1467 if (!first) { 1468 nbytes = stream_write(to, "\n", 1); 1469 if (nbytes == -1) 1470 goto bad; 1471 } 1472 stream_write(to, line, size); 1473 line = stream_getln(up->rd, &size); 1474 first = 0; 1475 } 1476 if (line == NULL) { 1477 stream_close(to); 1478 return (UPDATER_ERR_READ); 1479 } 1480 if (size == 1 && *line == '.') { 1481 nbytes = stream_write(to, "\n", 1); 1482 if (nbytes == -1) 1483 goto bad; 1484 } 1485 stream_close(to); 1486 /* Get the checksum line. */ 1487 line = stream_getln(up->rd, NULL); 1488 if (line == NULL) 1489 return (UPDATER_ERR_READ); 1490 cmd = proto_get_ascii(&line); 1491 fup->wantmd5 = proto_get_ascii(&line); 1492 if (fup->wantmd5 == NULL || line != NULL || strcmp(cmd, "5") != 0) 1493 return (UPDATER_ERR_PROTO); 1494 error = updater_updatefile(up, fup, md5, isfixup); 1495 fup->wantmd5 = NULL; /* So that it doesn't get freed. */ 1496 if (error) 1497 return (error); 1498 return (0); 1499bad: 1500 xasprintf(&up->errmsg, "%s: Cannot write: %s", fup->temppath, 1501 strerror(errno)); 1502 return (UPDATER_ERR_MSG); 1503} 1504 1505/* 1506 * Remove all empty directories below file. 1507 * This function will trash the path passed to it. 1508 */ 1509static void 1510updater_prunedirs(char *base, char *file) 1511{ 1512 char *cp; 1513 int error; 1514 1515 while ((cp = strrchr(file, '/')) != NULL) { 1516 *cp = '\0'; 1517 if (strcmp(base, file) == 0) 1518 return; 1519 error = rmdir(file); 1520 if (error) 1521 return; 1522 } 1523} 1524 1525/* 1526 * Edit an RCS file. 1527 */ 1528static int 1529updater_rcsedit(struct updater *up, struct file_update *fup, char *name, 1530 char *rcsopt) 1531{ 1532 struct coll *coll; 1533 struct stream *dest; 1534 struct statusrec *sr; 1535 struct status *st; 1536 struct rcsfile *rf; 1537 struct fattr *oldfattr; 1538 char md5[MD5_DIGEST_SIZE]; 1539 char *branch, *cmd, *expand, *line, *path, *revnum, *tag, *temppath; 1540 int error; 1541 1542 coll = fup->coll; 1543 sr = &fup->srbuf; 1544 st = fup->st; 1545 temppath = fup->temppath; 1546 path = fup->origpath != NULL ? fup->origpath : fup->destpath; 1547 error = 0; 1548 1549 /* If the path is new, we must create the Attic dir if needed. */ 1550 if (fup->origpath != NULL) { 1551 error = mkdirhier(fup->destpath, coll->co_umask); 1552 if (error) { 1553 xasprintf(&up->errmsg, "Unable to create Attic dir for " 1554 "%s\n", fup->origpath); 1555 return (UPDATER_ERR_MSG); 1556 } 1557 } 1558 /* 1559 * XXX: we could avoid parsing overhead if we're reading ahead before we 1560 * parse the file. 1561 */ 1562 oldfattr = fattr_frompath(path, FATTR_NOFOLLOW); 1563 if (oldfattr == NULL) { 1564 xasprintf(&up->errmsg, "%s: Cannot get attributes: %s", path, 1565 strerror(errno)); 1566 return (UPDATER_ERR_MSG); 1567 } 1568 fattr_merge(sr->sr_serverattr, oldfattr); 1569 rf = NULL; 1570 1571 /* Macro for making touching an RCS file faster. */ 1572#define UPDATER_OPENRCS(rf, up, path, name, cvsroot, tag) do { \ 1573 if ((rf) == NULL) { \ 1574 lprintf(1, " Edit %s", fup->coname); \ 1575 if (fup->attic) \ 1576 lprintf(1, " -> Attic"); \ 1577 lprintf(1, "\n"); \ 1578 (rf) = rcsfile_frompath((path), (name), (cvsroot), \ 1579 (tag), 0); \ 1580 if ((rf) == NULL) { \ 1581 xasprintf(&(up)->errmsg, \ 1582 "Error reading rcsfile %s\n", (name)); \ 1583 return (UPDATER_ERR_MSG); \ 1584 } \ 1585 } \ 1586} while (0) 1587 1588 while ((line = stream_getln(up->rd, NULL)) != NULL) { 1589 if (strcmp(line, ".") == 0) 1590 break; 1591 cmd = proto_get_ascii(&line); 1592 if (cmd == NULL) { 1593 lprintf(-1, "Error editing %s\n", name); 1594 return (UPDATER_ERR_PROTO); 1595 } 1596 switch(cmd[0]) { 1597 case 'B': 1598 branch = proto_get_ascii(&line); 1599 if (branch == NULL || line != NULL) 1600 return (UPDATER_ERR_PROTO); 1601 UPDATER_OPENRCS(rf, up, path, name, 1602 coll->co_cvsroot, coll->co_tag); 1603 break; 1604 case 'b': 1605 UPDATER_OPENRCS(rf, up, path, name, 1606 coll->co_cvsroot, coll->co_tag); 1607 rcsfile_setval(rf, RCSFILE_BRANCH, NULL); 1608 break; 1609 case 'D': 1610 UPDATER_OPENRCS(rf, up, path, name, 1611 coll->co_cvsroot, coll->co_tag); 1612 error = updater_addelta(rf, up->rd, line); 1613 if (error) 1614 return (error); 1615 break; 1616 case 'd': 1617 revnum = proto_get_ascii(&line); 1618 if (revnum == NULL || line != NULL) 1619 return (UPDATER_ERR_PROTO); 1620 UPDATER_OPENRCS(rf, up, path, name, 1621 coll->co_cvsroot, coll->co_tag); 1622 rcsfile_deleterev(rf, revnum); 1623 break; 1624 case 'E': 1625 expand = proto_get_ascii(&line); 1626 if (expand == NULL || line != NULL) 1627 return (UPDATER_ERR_PROTO); 1628 UPDATER_OPENRCS(rf, up, path, name, 1629 coll->co_cvsroot, coll->co_tag); 1630 rcsfile_setval(rf, RCSFILE_EXPAND, expand); 1631 break; 1632 case 'T': 1633 tag = proto_get_ascii(&line); 1634 revnum = proto_get_ascii(&line); 1635 if (tag == NULL || revnum == NULL || 1636 line != NULL) 1637 return (UPDATER_ERR_PROTO); 1638 UPDATER_OPENRCS(rf, up, path, name, 1639 coll->co_cvsroot, coll->co_tag); 1640 rcsfile_addtag(rf, tag, revnum); 1641 break; 1642 case 't': 1643 tag = proto_get_ascii(&line); 1644 revnum = proto_get_ascii(&line); 1645 if (tag == NULL || revnum == NULL || 1646 line != NULL) 1647 return (UPDATER_ERR_PROTO); 1648 UPDATER_OPENRCS(rf, up, path, name, 1649 coll->co_cvsroot, coll->co_tag); 1650 rcsfile_deletetag(rf, tag, revnum); 1651 break; 1652 default: 1653 return (UPDATER_ERR_PROTO); 1654 } 1655 } 1656 1657 if (rf == NULL) { 1658 fattr_maskout(oldfattr, ~FA_MODTIME); 1659 if (fattr_equal(oldfattr, sr->sr_serverattr)) 1660 lprintf(1, " SetAttrs %s", fup->coname); 1661 else 1662 lprintf(1, " Touch %s", fup->coname); 1663 /* Install new attributes. */ 1664 fattr_umask(sr->sr_serverattr, coll->co_umask); 1665 fattr_install(sr->sr_serverattr, fup->destpath, NULL); 1666 if (fup->attic) 1667 lprintf(1, " -> Attic"); 1668 lprintf(1, "\n"); 1669 fattr_free(oldfattr); 1670 goto finish; 1671 } 1672 1673 /* Write and rename temp file. */ 1674 dest = stream_open_file(fup->temppath, 1675 O_RDWR | O_CREAT | O_TRUNC, 0600); 1676 if (dest == NULL) { 1677 xasprintf(&up->errmsg, "Error opening file %s for writing: %s\n", 1678 fup->temppath, strerror(errno)); 1679 return (UPDATER_ERR_MSG); 1680 } 1681 stream_filter_start(dest, STREAM_FILTER_MD5RCS, md5); 1682 error = rcsfile_write(rf, dest); 1683 stream_close(dest); 1684 rcsfile_free(rf); 1685 if (error) 1686 lprintf(-1, "Error writing %s\n", name); 1687 1688finish: 1689 sr->sr_clientattr = fattr_frompath(path, FATTR_NOFOLLOW); 1690 if (sr->sr_clientattr == NULL) { 1691 xasprintf(&up->errmsg, "%s: Cannot get attributes: %s", 1692 fup->destpath, strerror(errno)); 1693 return (UPDATER_ERR_MSG); 1694 } 1695 fattr_override(sr->sr_clientattr, sr->sr_serverattr, 1696 FA_MODTIME | FA_MASK); 1697 if (rf != NULL) { 1698 error = updater_updatefile(up, fup, md5, 0); 1699 fup->wantmd5 = NULL; /* So that it doesn't get freed. */ 1700 if (error) 1701 return (error); 1702 } else { 1703 /* Record its attributes since we touched it. */ 1704 if (!(fattr_getmask(sr->sr_clientattr) & FA_LINKCOUNT) || 1705 fattr_getlinkcount(sr->sr_clientattr) <= 1) 1706 fattr_maskout(sr->sr_clientattr, FA_DEV | FA_INODE); 1707 error = status_put(st, sr); 1708 if (error) { 1709 up->errmsg = status_errmsg(st); 1710 return (UPDATER_ERR_MSG); 1711 } 1712 } 1713 1714 /* In this case, we need to remove the old file afterwards. */ 1715 /* XXX: Can we be sure that a file not edited is moved? I don't think 1716 * this is a problem, since if a file is moved, it should be edited to 1717 * show if it's dead or not. 1718 */ 1719 if (fup->origpath != NULL) 1720 updater_deletefile(fup->origpath); 1721 return (0); 1722} 1723 1724/* 1725 * Add a delta to a RCS file. 1726 */ 1727int 1728updater_addelta(struct rcsfile *rf, struct stream *rd, char *cmdline) 1729{ 1730 struct delta *d; 1731 size_t size; 1732 char *author, *cmd, *diffbase, *line, *logline; 1733 char *revdate, *revnum, *state, *textline; 1734 1735 revnum = proto_get_ascii(&cmdline); 1736 diffbase = proto_get_ascii(&cmdline); 1737 revdate = proto_get_ascii(&cmdline); 1738 author = proto_get_ascii(&cmdline); 1739 size = 0; 1740 1741 if (revnum == NULL || revdate == NULL || author == NULL) 1742 return (UPDATER_ERR_PROTO); 1743 1744 /* First add the delta so we have it. */ 1745 d = rcsfile_addelta(rf, revnum, revdate, author, diffbase); 1746 if (d == NULL) { 1747 lprintf(-1, "Error adding delta %s\n", revnum); 1748 return (UPDATER_ERR_READ); 1749 } 1750 while ((line = stream_getln(rd, NULL)) != NULL) { 1751 if (strcmp(line, ".") == 0) 1752 break; 1753 cmd = proto_get_ascii(&line); 1754 switch (cmd[0]) { 1755 case 'L': 1756 /* Do the same as in 'C' command. */ 1757 logline = stream_getln(rd, &size); 1758 while (logline != NULL) { 1759 if (size == 2 && *logline == '.') 1760 break; 1761 if (size == 3 && 1762 memcmp(logline, ".+", 2) == 0) { 1763 rcsdelta_truncatelog(d, -1); 1764 break; 1765 } 1766 if (size >= 3 && 1767 memcmp(logline, "..", 2) == 0) { 1768 size--; 1769 logline++; 1770 } 1771 rcsdelta_appendlog(d, logline, size); 1772 logline = stream_getln(rd, &size); 1773 } 1774 break; 1775 case 'N': 1776 case 'n': 1777 /* XXX: Not supported. */ 1778 break; 1779 case 'S': 1780 state = proto_get_ascii(&line); 1781 if (state == NULL) 1782 return (UPDATER_ERR_PROTO); 1783 rcsdelta_setstate(d, state); 1784 break; 1785 case 'T': 1786 /* Do the same as in 'C' command. */ 1787 textline = stream_getln(rd, &size); 1788 while (textline != NULL) { 1789 if (size == 2 && *textline == '.') 1790 break; 1791 if (size == 3 && 1792 memcmp(textline, ".+", 2) == 0) { 1793 /* Truncate newline. */ 1794 rcsdelta_truncatetext(d, -1); 1795 break; 1796 } 1797 if (size >= 3 && 1798 memcmp(textline, "..", 2) == 0) { 1799 size--; 1800 textline++; 1801 } 1802 rcsdelta_appendtext(d, textline, size); 1803 textline = stream_getln(rd, &size); 1804 } 1805 break; 1806 } 1807 } 1808 1809 return (0); 1810} 1811 1812int 1813updater_append_file(struct updater *up, struct file_update *fup, off_t pos) 1814{ 1815 struct fattr *fa; 1816 struct stream *to; 1817 struct statusrec *sr; 1818 ssize_t nread; 1819 off_t bytes; 1820 char buf[BUFSIZE], md5[MD5_DIGEST_SIZE]; 1821 char *line, *cmd; 1822 int error, fd; 1823 1824 sr = &fup->srbuf; 1825 fa = sr->sr_serverattr; 1826 to = stream_open_file(fup->temppath, O_WRONLY | O_CREAT | O_TRUNC, 1827 0755); 1828 if (to == NULL) { 1829 xasprintf(&up->errmsg, "%s: Cannot open: %s", fup->temppath, 1830 strerror(errno)); 1831 return (UPDATER_ERR_MSG); 1832 } 1833 fd = open(fup->destpath, O_RDONLY); 1834 if (fd < 0) { 1835 xasprintf(&up->errmsg, "%s: Cannot open: %s", fup->destpath, 1836 strerror(errno)); 1837 return (UPDATER_ERR_MSG); 1838 } 1839 1840 stream_filter_start(to, STREAM_FILTER_MD5, md5); 1841 /* First write the existing content. */ 1842 while ((nread = read(fd, buf, BUFSIZE)) > 0) 1843 stream_write(to, buf, nread); 1844 close(fd); 1845 1846 bytes = fattr_filesize(fa) - pos; 1847 /* Append the new data. */ 1848 do { 1849 nread = stream_read(up->rd, buf, 1850 (BUFSIZE > bytes) ? bytes : BUFSIZE); 1851 bytes -= nread; 1852 stream_write(to, buf, nread); 1853 } while (bytes > 0); 1854 stream_close(to); 1855 1856 line = stream_getln(up->rd, NULL); 1857 if (line == NULL) 1858 return (UPDATER_ERR_PROTO); 1859 /* Check for EOF. */ 1860 if (!(*line == '.' || (strncmp(line, ".<", 2) != 0))) 1861 return (UPDATER_ERR_PROTO); 1862 line = stream_getln(up->rd, NULL); 1863 if (line == NULL) 1864 return (UPDATER_ERR_PROTO); 1865 1866 cmd = proto_get_ascii(&line); 1867 fup->wantmd5 = proto_get_ascii(&line); 1868 if (fup->wantmd5 == NULL || line != NULL || strcmp(cmd, "5") != 0) 1869 return (UPDATER_ERR_PROTO); 1870 1871 sr->sr_clientattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW); 1872 if (sr->sr_clientattr == NULL) 1873 return (UPDATER_ERR_PROTO); 1874 fattr_override(sr->sr_clientattr, sr->sr_serverattr, 1875 FA_MODTIME | FA_MASK); 1876 error = updater_updatefile(up, fup, md5, 0); 1877 fup->wantmd5 = NULL; /* So that it doesn't get freed. */ 1878 if (error) 1879 return (error); 1880 return (0); 1881} 1882 1883/* 1884 * Read file data from stream of checkout commands, and write it to the 1885 * destination. 1886 */ 1887static int 1888updater_read_checkout(struct stream *src, struct stream *dest) 1889{ 1890 ssize_t nbytes; 1891 size_t size; 1892 char *line; 1893 int first; 1894 1895 first = 1; 1896 line = stream_getln(src, &size); 1897 while (line != NULL) { 1898 if (line[size - 1] == '\n') 1899 size--; 1900 if ((size == 1 && *line == '.') || 1901 (size == 2 && strncmp(line, ".+", 2) == 0)) 1902 break; 1903 if (size >= 2 && strncmp(line, "..", 2) == 0) { 1904 size--; 1905 line++; 1906 } 1907 if (!first) { 1908 nbytes = stream_write(dest, "\n", 1); 1909 if (nbytes == -1) 1910 return (UPDATER_ERR_MSG); 1911 } 1912 nbytes = stream_write(dest, line, size); 1913 if (nbytes == -1) 1914 return (UPDATER_ERR_MSG); 1915 line = stream_getln(src, &size); 1916 first = 0; 1917 } 1918 if (line == NULL) 1919 return (UPDATER_ERR_READ); 1920 if (size == 1 && *line == '.') { 1921 nbytes = stream_write(dest, "\n", 1); 1922 if (nbytes == -1) 1923 return (UPDATER_ERR_MSG); 1924 } 1925 return (0); 1926} 1927 1928/* Update file using the rsync protocol. */ 1929static int 1930updater_rsync(struct updater *up, struct file_update *fup, size_t blocksize) 1931{ 1932 struct statusrec *sr; 1933 struct stream *to; 1934 char md5[MD5_DIGEST_SIZE]; 1935 ssize_t nbytes; 1936 size_t blocknum, blockstart, blockcount; 1937 char *buf, *line; 1938 int error, orig; 1939 1940 sr = &fup->srbuf; 1941 1942 lprintf(1, " Rsync %s\n", fup->coname); 1943 /* First open all files that we are going to work on. */ 1944 to = stream_open_file(fup->temppath, O_WRONLY | O_CREAT | O_TRUNC, 1945 0600); 1946 if (to == NULL) { 1947 xasprintf(&up->errmsg, "%s: Cannot create: %s", 1948 fup->temppath, strerror(errno)); 1949 return (UPDATER_ERR_MSG); 1950 } 1951 orig = open(fup->destpath, O_RDONLY); 1952 if (orig < 0) { 1953 xasprintf(&up->errmsg, "%s: Cannot open: %s", 1954 fup->destpath, strerror(errno)); 1955 return (UPDATER_ERR_MSG); 1956 } 1957 stream_filter_start(to, STREAM_FILTER_MD5, md5); 1958 1959 error = updater_read_checkout(up->rd, to); 1960 if (error) { 1961 xasprintf(&up->errmsg, "%s: Cannot write: %s", fup->temppath, 1962 strerror(errno)); 1963 return (error); 1964 } 1965 1966 /* Buffer must contain blocksize bytes. */ 1967 buf = xmalloc(blocksize); 1968 /* Done with the initial text, read and write chunks. */ 1969 line = stream_getln(up->rd, NULL); 1970 while (line != NULL) { 1971 if (strcmp(line, ".") == 0) 1972 break; 1973 error = UPDATER_ERR_PROTO; 1974 if (proto_get_sizet(&line, &blockstart, 10) != 0) 1975 goto bad; 1976 if (proto_get_sizet(&line, &blockcount, 10) != 0) 1977 goto bad; 1978 /* Read blocks from original file. */ 1979 lseek(orig, (blocksize * blockstart), SEEK_SET); 1980 error = UPDATER_ERR_MSG; 1981 for (blocknum = 0; blocknum < blockcount; blocknum++) { 1982 nbytes = read(orig, buf, blocksize); 1983 if (nbytes < 0) { 1984 xasprintf(&up->errmsg, "%s: Cannot read: %s", 1985 fup->destpath, strerror(errno)); 1986 goto bad; 1987 } 1988 nbytes = stream_write(to, buf, nbytes); 1989 if (nbytes == -1) { 1990 xasprintf(&up->errmsg, "%s: Cannot write: %s", 1991 fup->temppath, strerror(errno)); 1992 goto bad; 1993 } 1994 } 1995 /* Get the remaining text from the server. */ 1996 error = updater_read_checkout(up->rd, to); 1997 if (error) { 1998 xasprintf(&up->errmsg, "%s: Cannot write: %s", 1999 fup->temppath, strerror(errno)); 2000 goto bad; 2001 } 2002 line = stream_getln(up->rd, NULL); 2003 } 2004 stream_close(to); 2005 close(orig); 2006 2007 sr->sr_clientattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW); 2008 if (sr->sr_clientattr == NULL) 2009 return (UPDATER_ERR_PROTO); 2010 fattr_override(sr->sr_clientattr, sr->sr_serverattr, 2011 FA_MODTIME | FA_MASK); 2012 2013 error = updater_updatefile(up, fup, md5, 0); 2014 fup->wantmd5 = NULL; /* So that it doesn't get freed. */ 2015bad: 2016 free(buf); 2017 return (error); 2018} 2019