1 /* 2 * HCPROTO.C 3 * 4 * This module implements a simple remote control protocol 5 * 6 * $DragonFly: src/bin/cpdup/hcproto.c,v 1.8 2008/11/11 04:36:00 dillon Exp $ 7 */ 8 9 #include "cpdup.h" 10 #include "hclink.h" 11 #include "hcproto.h" 12 13 static int hc_decode_stat(hctransaction_t trans, struct stat *, struct HCHead *); 14 static int hc_decode_stat_item(struct stat *st, struct HCLeaf *item); 15 static int rc_encode_stat(hctransaction_t trans, struct stat *); 16 17 static int rc_hello(hctransaction_t trans, struct HCHead *); 18 static int rc_stat(hctransaction_t trans, struct HCHead *); 19 static int rc_lstat(hctransaction_t trans, struct HCHead *); 20 static int rc_opendir(hctransaction_t trans, struct HCHead *); 21 static int rc_readdir(hctransaction_t trans, struct HCHead *); 22 static int rc_closedir(hctransaction_t trans, struct HCHead *); 23 static int rc_scandir(hctransaction_t trans, struct HCHead *); 24 static int rc_open(hctransaction_t trans, struct HCHead *); 25 static int rc_close(hctransaction_t trans, struct HCHead *); 26 static int rc_read(hctransaction_t trans, struct HCHead *); 27 static int rc_readfile(hctransaction_t trans, struct HCHead *); 28 static int rc_write(hctransaction_t trans, struct HCHead *); 29 static int rc_remove(hctransaction_t trans, struct HCHead *); 30 static int rc_mkdir(hctransaction_t trans, struct HCHead *); 31 static int rc_rmdir(hctransaction_t trans, struct HCHead *); 32 static int rc_chown(hctransaction_t trans, struct HCHead *); 33 static int rc_lchown(hctransaction_t trans, struct HCHead *); 34 static int rc_chmod(hctransaction_t trans, struct HCHead *); 35 static int rc_mknod(hctransaction_t trans, struct HCHead *); 36 static int rc_link(hctransaction_t trans, struct HCHead *); 37 #ifdef _ST_FLAGS_PRESENT_ 38 static int rc_chflags(hctransaction_t trans, struct HCHead *); 39 #endif 40 static int rc_readlink(hctransaction_t trans, struct HCHead *); 41 static int rc_umask(hctransaction_t trans, struct HCHead *); 42 static int rc_symlink(hctransaction_t trans, struct HCHead *); 43 static int rc_rename(hctransaction_t trans, struct HCHead *); 44 static int rc_utimes(hctransaction_t trans, struct HCHead *); 45 static int rc_geteuid(hctransaction_t trans, struct HCHead *); 46 static int rc_getgroups(hctransaction_t trans, struct HCHead *); 47 48 static int getmygroups(gid_t **gidlist); 49 50 static int silentwarning(int *, const char *, ...) __printflike(2, 3); 51 52 static struct HCDesc HCDispatchTable[] = { 53 { HC_HELLO, rc_hello }, 54 { HC_STAT, rc_stat }, 55 { HC_LSTAT, rc_lstat }, 56 { HC_OPENDIR, rc_opendir }, 57 { HC_READDIR, rc_readdir }, 58 { HC_CLOSEDIR, rc_closedir }, 59 { HC_OPEN, rc_open }, 60 { HC_CLOSE, rc_close }, 61 { HC_READ, rc_read }, 62 { HC_WRITE, rc_write }, 63 { HC_REMOVE, rc_remove }, 64 { HC_MKDIR, rc_mkdir }, 65 { HC_RMDIR, rc_rmdir }, 66 { HC_CHOWN, rc_chown }, 67 { HC_LCHOWN, rc_lchown }, 68 { HC_CHMOD, rc_chmod }, 69 { HC_MKNOD, rc_mknod }, 70 { HC_LINK, rc_link }, 71 #ifdef _ST_FLAGS_PRESENT_ 72 { HC_CHFLAGS, rc_chflags }, 73 #endif 74 { HC_READLINK, rc_readlink }, 75 { HC_UMASK, rc_umask }, 76 { HC_SYMLINK, rc_symlink }, 77 { HC_RENAME, rc_rename }, 78 { HC_UTIMES, rc_utimes }, 79 { HC_GETEUID, rc_geteuid }, 80 { HC_GETGROUPS, rc_getgroups }, 81 { HC_SCANDIR, rc_scandir }, 82 { HC_READFILE, rc_readfile }, 83 }; 84 85 static int chown_warning; 86 static int chflags_warning; 87 88 /* 89 * If not running as root generate a silent warning and return no error. 90 * 91 * If running as root return an error. 92 */ 93 static int 94 silentwarning(int *didwarn, const char *ctl, ...) 95 { 96 va_list va; 97 98 if (DstRootPrivs) 99 return(-1); 100 if (*didwarn == 0 && QuietOpt == 0) { 101 *didwarn = 1; 102 fprintf(stderr, "WARNING: Not running as root, "); 103 va_start(va, ctl); 104 vfprintf(stderr, ctl, va); 105 va_end(va); 106 } 107 return(0); 108 } 109 110 int 111 hc_connect(struct HostConf *hc, int readonly) 112 { 113 if (hcc_connect(hc, readonly) < 0) { 114 fprintf(stderr, "Unable to connect to %s\n", hc->host); 115 return(-1); 116 } 117 return(hc_hello(hc)); 118 } 119 120 void 121 hc_slave(int fdin, int fdout) 122 { 123 hcc_slave(fdin, fdout, HCDispatchTable, 124 sizeof(HCDispatchTable) / sizeof(HCDispatchTable[0])); 125 } 126 127 /* 128 * A HELLO RPC is sent on the initial connect. 129 */ 130 int 131 hc_hello(struct HostConf *hc) 132 { 133 struct HCHead *head; 134 struct HCLeaf *item; 135 hctransaction_t trans; 136 char hostbuf[256]; 137 int error; 138 139 bzero(hostbuf, sizeof(hostbuf)); 140 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0) 141 return(-1); 142 if (hostbuf[0] == 0) 143 hostbuf[0] = '?'; 144 145 trans = hcc_start_command(hc, HC_HELLO); 146 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf); 147 hcc_leaf_int32(trans, LC_VERSION, HCPROTO_VERSION); 148 if (UseCpFile) 149 hcc_leaf_string(trans, LC_PATH1, UseCpFile); 150 if ((head = hcc_finish_command(trans)) == NULL) { 151 fprintf(stderr, "Connected to %s but remote failed to complete hello\n", 152 hc->host); 153 return(-1); 154 } 155 156 if (head->error) { 157 fprintf(stderr, "Connected to %s but remote returned error %d\n", 158 hc->host, head->error); 159 return(-1); 160 } 161 162 error = -1; 163 FOR_EACH_ITEM(item, trans, head) { 164 switch(item->leafid) { 165 case LC_HELLOSTR: 166 if (QuietOpt == 0) 167 fprintf(stderr, "Handshaked with %s\n", HCC_STRING(item)); 168 error = 0; 169 break; 170 case LC_VERSION: 171 hc->version = HCC_INT32(item); 172 break; 173 } 174 } 175 if (hc->version < HCPROTO_VERSION_COMPAT) { 176 fprintf(stderr, "Remote cpdup at %s has an incompatible version\n", 177 hc->host); 178 error = -1; 179 } else if (hc->version < HCPROTO_VERSION && QuietOpt == 0) { 180 fprintf(stderr, "WARNING: Remote cpdup at %s has a lower version, " 181 "expect reduced speed\n", hc->host); 182 } 183 if (error < 0) 184 fprintf(stderr, "Handshake failed with %s\n", hc->host); 185 return (error); 186 } 187 188 static int 189 rc_hello(hctransaction_t trans, struct HCHead *head) 190 { 191 struct HCLeaf *item; 192 char hostbuf[256]; 193 194 FOR_EACH_ITEM(item, trans, head) { 195 if (item->leafid == LC_PATH1) 196 UseCpFile = strdup(HCC_STRING(item)); 197 } 198 199 bzero(hostbuf, sizeof(hostbuf)); 200 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0) 201 return(-1); 202 if (hostbuf[0] == 0) 203 hostbuf[0] = '?'; 204 205 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf); 206 hcc_leaf_int32(trans, LC_VERSION, HCPROTO_VERSION); 207 return(0); 208 } 209 210 /* 211 * STAT, LSTAT 212 */ 213 int 214 hc_stat(struct HostConf *hc, const char *path, struct stat *st) 215 { 216 struct HCHead *head; 217 hctransaction_t trans; 218 219 if (hc == NULL || hc->host == NULL) 220 return(stat(path, st)); 221 222 trans = hcc_start_command(hc, HC_STAT); 223 hcc_leaf_string(trans, LC_PATH1, path); 224 if ((head = hcc_finish_command(trans)) == NULL) 225 return(-1); 226 if (head->error) 227 return(-1); 228 return(hc_decode_stat(trans, st, head)); 229 } 230 231 int 232 hc_lstat(struct HostConf *hc, const char *path, struct stat *st) 233 { 234 struct HCHead *head; 235 hctransaction_t trans; 236 237 if (hc == NULL || hc->host == NULL) 238 return(lstat(path, st)); 239 240 trans = hcc_start_command(hc, HC_LSTAT); 241 hcc_leaf_string(trans, LC_PATH1, path); 242 if ((head = hcc_finish_command(trans)) == NULL) 243 return(-1); 244 if (head->error) 245 return(-1); 246 return(hc_decode_stat(trans, st, head)); 247 } 248 249 static int 250 hc_decode_stat(hctransaction_t trans, struct stat *st, struct HCHead *head) 251 { 252 struct HCLeaf *item; 253 254 bzero(st, sizeof(*st)); 255 FOR_EACH_ITEM(item, trans, head) 256 hc_decode_stat_item(st, item); 257 return(0); 258 } 259 260 static int 261 hc_decode_stat_item(struct stat *st, struct HCLeaf *item) 262 { 263 switch(item->leafid) { 264 case LC_DEV: 265 st->st_dev = HCC_INT32(item); 266 break; 267 case LC_INO: 268 st->st_ino = HCC_INT64(item); 269 break; 270 case LC_MODE: 271 st->st_mode = HCC_INT32(item); 272 break; 273 case LC_NLINK: 274 st->st_nlink = HCC_INT32(item); 275 break; 276 case LC_UID: 277 st->st_uid = HCC_INT32(item); 278 break; 279 case LC_GID: 280 st->st_gid = HCC_INT32(item); 281 break; 282 case LC_RDEV: 283 st->st_rdev = HCC_INT32(item); 284 break; 285 case LC_ATIME: 286 st->st_atime = (time_t)HCC_INT64(item); 287 break; 288 case LC_MTIME: 289 st->st_mtime = (time_t)HCC_INT64(item); 290 break; 291 case LC_CTIME: 292 st->st_ctime = (time_t)HCC_INT64(item); 293 break; 294 case LC_FILESIZE: 295 st->st_size = HCC_INT64(item); 296 break; 297 case LC_FILEBLKS: 298 st->st_blocks = HCC_INT64(item); 299 break; 300 case LC_BLKSIZE: 301 st->st_blksize = HCC_INT32(item); 302 break; 303 #ifdef _ST_FSMID_PRESENT_ 304 case LC_FSMID: 305 st->st_fsmid = HCC_INT64(item); 306 break; 307 #endif 308 #ifdef _ST_FLAGS_PRESENT_ 309 case LC_FILEFLAGS: 310 st->st_flags = (uint32_t)HCC_INT64(item); 311 break; 312 #endif 313 } 314 return(0); 315 } 316 317 static int 318 rc_stat(hctransaction_t trans, struct HCHead *head) 319 { 320 struct HCLeaf *item; 321 struct stat st; 322 const char *path = NULL; 323 324 FOR_EACH_ITEM(item, trans, head) { 325 if (item->leafid == LC_PATH1) 326 path = HCC_STRING(item); 327 } 328 if (path == NULL) 329 return(-2); 330 if (stat(path, &st) < 0) 331 return(-1); 332 return (rc_encode_stat(trans, &st)); 333 } 334 335 static int 336 rc_lstat(hctransaction_t trans, struct HCHead *head) 337 { 338 struct HCLeaf *item; 339 struct stat st; 340 const char *path = NULL; 341 342 FOR_EACH_ITEM(item, trans, head) { 343 if (item->leafid == LC_PATH1) 344 path = HCC_STRING(item); 345 } 346 if (path == NULL) 347 return(-2); 348 if (lstat(path, &st) < 0) 349 return(-1); 350 return (rc_encode_stat(trans, &st)); 351 } 352 353 /* 354 * Encode all entries of a stat structure. 355 * 356 * CAUTION: If you add any more entries here, be sure to 357 * increase the STAT_MAX_NUM_ENTRIES value! 358 */ 359 #define STAT_MAX_NUM_ENTRIES 18 360 static int 361 rc_encode_stat(hctransaction_t trans, struct stat *st) 362 { 363 hcc_leaf_int32(trans, LC_DEV, st->st_dev); 364 hcc_leaf_int64(trans, LC_INO, st->st_ino); 365 hcc_leaf_int32(trans, LC_MODE, st->st_mode); 366 hcc_leaf_int32(trans, LC_NLINK, st->st_nlink); 367 hcc_leaf_int32(trans, LC_UID, st->st_uid); 368 hcc_leaf_int32(trans, LC_GID, st->st_gid); 369 hcc_leaf_int32(trans, LC_RDEV, st->st_rdev); 370 hcc_leaf_int64(trans, LC_ATIME, st->st_atime); 371 hcc_leaf_int64(trans, LC_MTIME, st->st_mtime); 372 hcc_leaf_int64(trans, LC_CTIME, st->st_ctime); 373 hcc_leaf_int64(trans, LC_FILESIZE, st->st_size); 374 hcc_leaf_int64(trans, LC_FILEBLKS, st->st_blocks); 375 hcc_leaf_int32(trans, LC_BLKSIZE, st->st_blksize); 376 #ifdef _ST_FSMID_PRESENT_ 377 hcc_leaf_int64(trans, LC_FSMID, st->st_fsmid); 378 #endif 379 #ifdef _ST_FLAGS_PRESENT_ 380 hcc_leaf_int64(trans, LC_FILEFLAGS, st->st_flags); 381 #endif 382 return(0); 383 } 384 385 /* 386 * OPENDIR 387 */ 388 DIR * 389 hc_opendir(struct HostConf *hc, const char *path) 390 { 391 hctransaction_t trans; 392 struct HCHead *head; 393 394 if (hc == NULL || hc->host == NULL) 395 return(opendir(path)); 396 397 if (hc->version <= 3) { /* compatibility: HC_SCANDIR not supported */ 398 struct HCLeaf *item; 399 struct HCDirEntry *den; 400 intptr_t desc = 0; 401 402 trans = hcc_start_command(hc, HC_OPENDIR); 403 hcc_leaf_string(trans, LC_PATH1, path); 404 if ((head = hcc_finish_command(trans)) == NULL) 405 return (NULL); 406 if (head->error) 407 return (NULL); 408 FOR_EACH_ITEM(item, trans, head) { 409 if (item->leafid == LC_DESCRIPTOR) 410 desc = HCC_INT32(item); 411 } 412 if (hcc_get_descriptor(hc, desc, HC_DESC_DIR)) { 413 fprintf(stderr, "hc_opendir: remote reused active descriptor %jd\n", 414 (intmax_t)desc); 415 return (NULL); 416 } 417 den = malloc(sizeof(*den)); 418 hcc_set_descriptor(hc, desc, den, HC_DESC_DIR); 419 return ((void *)desc); 420 } 421 422 /* hc->version >= 4: use HC_SCANDIR */ 423 trans = hcc_start_command(hc, HC_SCANDIR); 424 hcc_leaf_string(trans, LC_PATH1, path); 425 if ((head = hcc_finish_command(trans)) == NULL || head->error) 426 return (NULL); 427 return ((void *)head); 428 } 429 430 static int 431 rc_opendir(hctransaction_t trans, struct HCHead *head) 432 { 433 struct HCLeaf *item; 434 const char *path = NULL; 435 DIR *dir; 436 int desc; 437 438 FOR_EACH_ITEM(item, trans, head) { 439 if (item->leafid == LC_PATH1) 440 path = HCC_STRING(item); 441 } 442 if (path == NULL) 443 return(-2); 444 if ((dir = opendir(path)) == NULL) { 445 head->error = errno; 446 } else { 447 desc = hcc_alloc_descriptor(trans->hc, dir, HC_DESC_DIR); 448 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc); 449 } 450 return(0); 451 } 452 453 /* 454 * READDIR 455 */ 456 struct HCDirEntry * 457 hc_readdir(struct HostConf *hc, DIR *dir, struct stat **statpp) 458 { 459 int stat_ok = 0; 460 struct HCHead *head; 461 struct HCLeaf *item; 462 static struct HCDirEntry denbuf; 463 464 *statpp = NULL; 465 if (hc == NULL || hc->host == NULL) { 466 struct dirent *sysden; 467 468 if ((sysden = readdir(dir)) == NULL) 469 return (NULL); 470 strlcpy(denbuf.d_name, sysden->d_name, MAXNAMLEN + 1); 471 return (&denbuf); 472 } 473 474 if (hc->version <= 3) { /* compatibility: HC_SCANDIR not supported */ 475 hctransaction_t trans; 476 struct HCDirEntry *den; 477 478 trans = hcc_start_command(hc, HC_READDIR); 479 hcc_leaf_int32(trans, LC_DESCRIPTOR, (intptr_t)dir); 480 if ((head = hcc_finish_command(trans)) == NULL) 481 return (NULL); 482 if (head->error) 483 return (NULL); /* XXX errno */ 484 den = hcc_get_descriptor(hc, (intptr_t)dir, HC_DESC_DIR); 485 if (den == NULL) 486 return (NULL); /* XXX errno */ 487 den->d_name[0] = 0; 488 FOR_EACH_ITEM(item, trans, head) { 489 if (item->leafid == LC_PATH1) 490 strlcpy(den->d_name, HCC_STRING(item), MAXNAMLEN + 1); 491 } 492 return (den->d_name[0] ? den : NULL); 493 } 494 495 /* hc->version >= 4: using HC_SCANDIR */ 496 denbuf.d_name[0] = 0; 497 head = (void *)dir; 498 *statpp = malloc(sizeof(struct stat)); 499 bzero(*statpp, sizeof(struct stat)); 500 while ((item = hcc_nextchaineditem(hc, head)) != NULL) { 501 if (item->leafid == LC_PATH1) { /* this must be the last item */ 502 strlcpy(denbuf.d_name, HCC_STRING(item), MAXNAMLEN + 1); 503 break; 504 } else { 505 stat_ok = 1; 506 hc_decode_stat_item(*statpp, item); 507 } 508 } 509 if (!stat_ok) { 510 free(*statpp); 511 *statpp = NULL; 512 } 513 if (hc->trans.state == HCT_FAIL) 514 return NULL; 515 return (denbuf.d_name[0] ? &denbuf : NULL); 516 } 517 518 static int 519 rc_readdir(hctransaction_t trans, struct HCHead *head) 520 { 521 struct HCLeaf *item; 522 struct dirent *den; 523 DIR *dir = NULL; 524 525 FOR_EACH_ITEM(item, trans, head) { 526 if (item->leafid == LC_DESCRIPTOR) 527 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR); 528 } 529 if (dir == NULL) 530 return(-2); 531 if ((den = readdir(dir)) != NULL) 532 hcc_leaf_string(trans, LC_PATH1, den->d_name); 533 return(0); 534 } 535 536 /* 537 * CLOSEDIR 538 * 539 * XXX cpdup needs to check error code to avoid truncated dirs? 540 */ 541 int 542 hc_closedir(struct HostConf *hc, DIR *dir) 543 { 544 struct HCHead *head; 545 546 if (hc == NULL || hc->host == NULL) 547 return(closedir(dir)); 548 549 if (hc->version <= 3) { /* compatibility: HC_SCANDIR not supported */ 550 hctransaction_t trans; 551 struct dirent *den; 552 553 if ((den = hcc_get_descriptor(hc, (intptr_t)dir, HC_DESC_DIR)) != NULL) { 554 free(den); 555 hcc_set_descriptor(hc, (intptr_t)dir, NULL, HC_DESC_DIR); 556 trans = hcc_start_command(hc, HC_CLOSEDIR); 557 hcc_leaf_int32(trans, LC_DESCRIPTOR, (intptr_t)dir); 558 if ((head = hcc_finish_command(trans)) == NULL) 559 return (-1); 560 if (head->error) 561 return (-1); /* XXX errno */ 562 return (0); 563 } else { 564 /* errno */ 565 return(-1); 566 } 567 } 568 569 /* hc->version >= 4: using HC_SCANDIR */ 570 head = (void *)dir; 571 /* skip any remaining items if the directory is closed prematurely */ 572 while (hcc_nextchaineditem(hc, head) != NULL) 573 /*nothing*/ ; 574 if (hc->trans.state == HCT_FAIL || head->error) 575 return (-1); 576 return (0); 577 } 578 579 static int 580 rc_closedir(hctransaction_t trans, struct HCHead *head) 581 { 582 struct HCLeaf *item; 583 DIR *dir = NULL; 584 585 FOR_EACH_ITEM(item, trans, head) { 586 if (item->leafid == LC_DESCRIPTOR) { 587 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR); 588 if (dir != NULL) { 589 hcc_set_descriptor(trans->hc, HCC_INT32(item), 590 NULL, HC_DESC_DIR); 591 } 592 } 593 } 594 if (dir == NULL) 595 return(-2); 596 return(closedir(dir)); 597 } 598 599 /* 600 * SCANDIR 601 */ 602 static int 603 rc_scandir(hctransaction_t trans, struct HCHead *head) 604 { 605 struct HCLeaf *item; 606 const char *path = NULL; 607 struct dirent *den; 608 DIR *dir; 609 char *fpath; 610 struct stat st; 611 612 FOR_EACH_ITEM(item, trans, head) { 613 if (item->leafid == LC_PATH1) 614 path = HCC_STRING(item); 615 } 616 if (path == NULL) 617 return (-2); 618 if ((dir = opendir(path)) == NULL) 619 return (-1); 620 while ((den = readdir(dir)) != NULL) { 621 if (den->d_name[0] == '.' && (den->d_name[1] == '\0' || 622 (den->d_name[1] == '.' && den->d_name[2] == '\0'))) 623 continue; /* skip "." and ".." */ 624 /* 625 * Check if there's enough space left in the current packet. 626 * We have at most STAT_MAX_NUM_ENTRIES pieces of data, of which 627 * one is a string, so we use strlen() + 1 (terminating zero). 628 * The remaining ones are numbers; we assume sizeof(int64_t) so 629 * we're on the safe side. 630 */ 631 if (!hcc_check_space(trans, head, STAT_MAX_NUM_ENTRIES, 632 (STAT_MAX_NUM_ENTRIES - 1) * sizeof(int64_t) + 633 strlen(den->d_name) + 1)) { 634 closedir(dir); 635 return (-1); 636 } 637 fpath = mprintf("%s/%s", path, den->d_name); 638 if (lstat(fpath, &st) == 0) 639 rc_encode_stat(trans, &st); 640 /* The name must be the last item! */ 641 hcc_leaf_string(trans, LC_PATH1, den->d_name); 642 free(fpath); 643 } 644 return (closedir(dir)); 645 } 646 647 /* 648 * OPEN 649 */ 650 int 651 hc_open(struct HostConf *hc, const char *path, int flags, mode_t mode) 652 { 653 hctransaction_t trans; 654 struct HCHead *head; 655 struct HCLeaf *item; 656 int *fdp; 657 int desc = 0; 658 int nflags; 659 660 if (NotForRealOpt && (flags & O_CREAT)) 661 return(0x7FFFFFFF); 662 663 if (hc == NULL || hc->host == NULL) { 664 #ifdef O_LARGEFILE 665 flags |= O_LARGEFILE; 666 #endif 667 return(open(path, flags, mode)); 668 } 669 670 if ((flags & (O_WRONLY | O_RDWR)) == 0 && hc->version >= 4) { 671 trans = hcc_start_command(hc, HC_READFILE); 672 hcc_leaf_string(trans, LC_PATH1, path); 673 if ((head = hcc_finish_command(trans)) == NULL || head->error) 674 return (-1); 675 head->magic = 0; /* used to indicate offset within buffer */ 676 return (1); /* dummy */ 677 } 678 679 nflags = flags & XO_NATIVEMASK; 680 if (flags & O_CREAT) 681 nflags |= XO_CREAT; 682 if (flags & O_EXCL) 683 nflags |= XO_EXCL; 684 if (flags & O_TRUNC) 685 nflags |= XO_TRUNC; 686 687 trans = hcc_start_command(hc, HC_OPEN); 688 hcc_leaf_string(trans, LC_PATH1, path); 689 hcc_leaf_int32(trans, LC_OFLAGS, nflags); 690 hcc_leaf_int32(trans, LC_MODE, mode); 691 692 if ((head = hcc_finish_command(trans)) == NULL) 693 return(-1); 694 if (head->error) 695 return(-1); 696 FOR_EACH_ITEM(item, trans, head) { 697 if (item->leafid == LC_DESCRIPTOR) 698 desc = HCC_INT32(item); 699 } 700 if (hcc_get_descriptor(hc, desc, HC_DESC_FD)) { 701 fprintf(stderr, "hc_open: remote reused active descriptor %d\n", 702 desc); 703 return(-1); 704 } 705 fdp = malloc(sizeof(int)); 706 *fdp = desc; /* really just a dummy */ 707 hcc_set_descriptor(hc, desc, fdp, HC_DESC_FD); 708 return(desc); 709 } 710 711 static int 712 rc_open(hctransaction_t trans, struct HCHead *head) 713 { 714 struct HCLeaf *item; 715 const char *path = NULL; 716 int nflags = 0; 717 int flags; 718 mode_t mode = 0666; 719 int desc; 720 int *fdp; 721 int fd; 722 723 FOR_EACH_ITEM(item, trans, head) { 724 switch(item->leafid) { 725 case LC_PATH1: 726 path = HCC_STRING(item); 727 break; 728 case LC_OFLAGS: 729 nflags = HCC_INT32(item); 730 break; 731 case LC_MODE: 732 mode = HCC_INT32(item); 733 break; 734 } 735 } 736 if (path == NULL) 737 return(-2); 738 739 flags = nflags & XO_NATIVEMASK; 740 if (nflags & XO_CREAT) 741 flags |= O_CREAT; 742 if (nflags & XO_EXCL) 743 flags |= O_EXCL; 744 if (nflags & XO_TRUNC) 745 flags |= O_TRUNC; 746 747 if (ReadOnlyOpt) { 748 if (flags & (O_WRONLY | O_RDWR | O_CREAT | O_TRUNC)) { 749 head->error = EACCES; 750 return (0); 751 } 752 flags |= O_RDONLY; 753 } 754 755 #ifdef O_LARGEFILE 756 flags |= O_LARGEFILE; 757 #endif 758 if ((fd = open(path, flags, mode)) < 0) 759 return(-1); 760 fdp = malloc(sizeof(int)); 761 *fdp = fd; 762 desc = hcc_alloc_descriptor(trans->hc, fdp, HC_DESC_FD); 763 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc); 764 return(0); 765 } 766 767 /* 768 * CLOSE 769 */ 770 int 771 hc_close(struct HostConf *hc, int fd) 772 { 773 hctransaction_t trans; 774 struct HCHead *head; 775 int *fdp; 776 777 if (NotForRealOpt && fd == 0x7FFFFFFF) 778 return(0); 779 if (hc == NULL || hc->host == NULL) 780 return(close(fd)); 781 782 if (fd == 1 && hc->version >= 4) { /* using HC_READFILE */ 783 head = (void *)hc->trans.rbuf; 784 /* skip any remaining items if the file is closed prematurely */ 785 while (hcc_nextchaineditem(hc, head) != NULL) 786 /*nothing*/ ; 787 if (hc->trans.state == HCT_FAIL || head->error) 788 return (-1); 789 return (0); 790 } 791 792 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD); 793 if (fdp) { 794 free(fdp); 795 hcc_set_descriptor(hc, fd, NULL, HC_DESC_FD); 796 797 trans = hcc_start_command(hc, HC_CLOSE); 798 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd); 799 if ((head = hcc_finish_command(trans)) == NULL) 800 return(-1); 801 if (head->error) 802 return(-1); 803 return(0); 804 } else { 805 return(-1); 806 } 807 } 808 809 static int 810 rc_close(hctransaction_t trans, struct HCHead *head) 811 { 812 struct HCLeaf *item; 813 int *fdp = NULL; 814 int fd; 815 int desc = -1; 816 817 FOR_EACH_ITEM(item, trans, head) { 818 if (item->leafid == LC_DESCRIPTOR) 819 desc = HCC_INT32(item); 820 } 821 if (desc < 0) 822 return(-2); 823 if ((fdp = hcc_get_descriptor(trans->hc, desc, HC_DESC_FD)) == NULL) 824 return(-2); 825 fd = *fdp; 826 free(fdp); 827 hcc_set_descriptor(trans->hc, desc, NULL, HC_DESC_FD); 828 return(close(fd)); 829 } 830 831 static int 832 getiolimit(void) 833 { 834 return(32768); 835 } 836 837 /* 838 * READ 839 */ 840 ssize_t 841 hc_read(struct HostConf *hc, int fd, void *buf, size_t bytes) 842 { 843 hctransaction_t trans; 844 struct HCHead *head; 845 struct HCLeaf *item; 846 int *fdp; 847 int offset; 848 int r = 0; 849 int x = 0; 850 851 if (hc == NULL || hc->host == NULL) 852 return(read(fd, buf, bytes)); 853 854 if (fd == 1 && hc->version >= 4) { /* using HC_READFILE */ 855 head = (void *)hc->trans.rbuf; 856 while (bytes) { 857 if ((offset = head->magic) != 0) { 858 item = hcc_currentchaineditem(hc, head); 859 } else { 860 item = hcc_nextchaineditem(hc, head); 861 } 862 if (item == NULL) { 863 if (hc->trans.state == HCT_FAIL) 864 r = -1; 865 return (r); 866 } 867 if (item->leafid != LC_DATA) 868 return (-1); 869 x = item->bytes - sizeof(*item) - offset; 870 if (x > (int)bytes) { 871 x = (int)bytes; 872 head->magic += x; /* leave bytes in the buffer */ 873 } 874 else 875 head->magic = 0; /* all bytes used up */ 876 bcopy((char *)HCC_BINARYDATA(item) + offset, buf, x); 877 buf = (char *)buf + x; 878 bytes -= (size_t)x; 879 r += x; 880 } 881 return (r); 882 } 883 884 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD); 885 if (fdp) { 886 while (bytes) { 887 size_t limit = getiolimit(); 888 int n = (bytes > limit) ? limit : bytes; 889 890 trans = hcc_start_command(hc, HC_READ); 891 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd); 892 hcc_leaf_int32(trans, LC_BYTES, n); 893 if ((head = hcc_finish_command(trans)) == NULL) 894 return(-1); 895 if (head->error) 896 return(-1); 897 FOR_EACH_ITEM(item, trans, head) { 898 if (item->leafid == LC_DATA) { 899 x = item->bytes - sizeof(*item); 900 if (x > (int)bytes) 901 x = (int)bytes; 902 bcopy(HCC_BINARYDATA(item), buf, x); 903 buf = (char *)buf + x; 904 bytes -= (size_t)x; 905 r += x; 906 } 907 } 908 if (x < n) 909 break; 910 } 911 return(r); 912 } else { 913 return(-1); 914 } 915 } 916 917 static int 918 rc_read(hctransaction_t trans, struct HCHead *head) 919 { 920 struct HCLeaf *item; 921 int *fdp = NULL; 922 char buf[32768]; 923 int bytes = -1; 924 int n; 925 926 FOR_EACH_ITEM(item, trans, head) { 927 switch(item->leafid) { 928 case LC_DESCRIPTOR: 929 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD); 930 break; 931 case LC_BYTES: 932 bytes = HCC_INT32(item); 933 break; 934 } 935 } 936 if (fdp == NULL) 937 return(-2); 938 if (bytes < 0 || bytes > 32768) 939 return(-2); 940 n = read(*fdp, buf, bytes); 941 if (n < 0) 942 return(-1); 943 hcc_leaf_data(trans, LC_DATA, buf, n); 944 return(0); 945 } 946 947 /* 948 * READFILE 949 */ 950 static int 951 rc_readfile(hctransaction_t trans, struct HCHead *head) 952 { 953 struct HCLeaf *item; 954 const char *path = NULL; 955 char buf[32768]; 956 int n; 957 int fd; 958 959 FOR_EACH_ITEM(item, trans, head) { 960 if (item->leafid == LC_PATH1) 961 path = HCC_STRING(item); 962 } 963 if (path == NULL) 964 return (-2); 965 if ((fd = open(path, O_RDONLY)) < 0) 966 return(-1); 967 while ((n = read(fd, buf, 32768)) >= 0) { 968 if (!hcc_check_space(trans, head, 1, n)) { 969 close(fd); 970 return (-1); 971 } 972 hcc_leaf_data(trans, LC_DATA, buf, n); 973 if (n == 0) 974 break; 975 } 976 if (n < 0) { 977 close(fd); 978 return (-1); 979 } 980 return (close(fd)); 981 } 982 983 /* 984 * WRITE 985 */ 986 ssize_t 987 hc_write(struct HostConf *hc, int fd, const void *buf, size_t bytes) 988 { 989 hctransaction_t trans; 990 struct HCHead *head; 991 struct HCLeaf *item; 992 int *fdp; 993 int r; 994 995 if (NotForRealOpt) 996 return(bytes); 997 998 if (hc == NULL || hc->host == NULL) 999 return(write(fd, buf, bytes)); 1000 1001 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD); 1002 if (fdp) { 1003 r = 0; 1004 while (bytes) { 1005 size_t limit = getiolimit(); 1006 int n = (bytes > limit) ? limit : bytes; 1007 int x = 0; 1008 1009 trans = hcc_start_command(hc, HC_WRITE); 1010 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd); 1011 hcc_leaf_data(trans, LC_DATA, buf, n); 1012 if ((head = hcc_finish_command(trans)) == NULL) 1013 return(-1); 1014 if (head->error) 1015 return(-1); 1016 FOR_EACH_ITEM(item, trans, head) { 1017 if (item->leafid == LC_BYTES) 1018 x = HCC_INT32(item); 1019 } 1020 if (x < 0 || x > n) 1021 return(-1); 1022 r += x; 1023 buf = (const char *)buf + x; 1024 bytes -= x; 1025 if (x < n) 1026 break; 1027 } 1028 return(r); 1029 } else { 1030 return(-1); 1031 } 1032 } 1033 1034 static int 1035 rc_write(hctransaction_t trans, struct HCHead *head) 1036 { 1037 struct HCLeaf *item; 1038 int *fdp = NULL; 1039 void *buf = NULL; 1040 int n = -1; 1041 1042 FOR_EACH_ITEM(item, trans, head) { 1043 switch(item->leafid) { 1044 case LC_DESCRIPTOR: 1045 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD); 1046 break; 1047 case LC_DATA: 1048 buf = HCC_BINARYDATA(item); 1049 n = item->bytes - sizeof(*item); 1050 break; 1051 } 1052 } 1053 if (ReadOnlyOpt) { 1054 head->error = EACCES; 1055 return (0); 1056 } 1057 if (fdp == NULL) 1058 return(-2); 1059 if (n < 0 || n > 32768) 1060 return(-2); 1061 n = write(*fdp, buf, n); 1062 if (n < 0) 1063 return (-1); 1064 hcc_leaf_int32(trans, LC_BYTES, n); 1065 return(0); 1066 } 1067 1068 /* 1069 * REMOVE 1070 * 1071 * NOTE: This function returns -errno if an error occured. 1072 */ 1073 int 1074 hc_remove(struct HostConf *hc, const char *path) 1075 { 1076 hctransaction_t trans; 1077 struct HCHead *head; 1078 int res; 1079 1080 if (NotForRealOpt) 1081 return(0); 1082 if (hc == NULL || hc->host == NULL) { 1083 res = remove(path); 1084 if (res < 0) 1085 res = -errno; 1086 return(res); 1087 } 1088 1089 trans = hcc_start_command(hc, HC_REMOVE); 1090 hcc_leaf_string(trans, LC_PATH1, path); 1091 if ((head = hcc_finish_command(trans)) == NULL) 1092 return(-EIO); 1093 if (head->error) 1094 return(-(int)head->error); 1095 return(0); 1096 } 1097 1098 static int 1099 rc_remove(hctransaction_t trans, struct HCHead *head) 1100 { 1101 struct HCLeaf *item; 1102 const char *path = NULL; 1103 1104 FOR_EACH_ITEM(item, trans, head) { 1105 if (item->leafid == LC_PATH1) 1106 path = HCC_STRING(item); 1107 } 1108 if (path == NULL) 1109 return(-2); 1110 if (ReadOnlyOpt) { 1111 head->error = EACCES; 1112 return (0); 1113 } 1114 return(remove(path)); 1115 } 1116 1117 /* 1118 * MKDIR 1119 */ 1120 int 1121 hc_mkdir(struct HostConf *hc, const char *path, mode_t mode) 1122 { 1123 hctransaction_t trans; 1124 struct HCHead *head; 1125 1126 if (NotForRealOpt) 1127 return(0); 1128 if (hc == NULL || hc->host == NULL) 1129 return(mkdir(path, mode)); 1130 1131 trans = hcc_start_command(hc, HC_MKDIR); 1132 hcc_leaf_string(trans, LC_PATH1, path); 1133 hcc_leaf_int32(trans, LC_MODE, mode); 1134 if ((head = hcc_finish_command(trans)) == NULL) 1135 return(-1); 1136 if (head->error) 1137 return(-1); 1138 return(0); 1139 } 1140 1141 static int 1142 rc_mkdir(hctransaction_t trans, struct HCHead *head) 1143 { 1144 struct HCLeaf *item; 1145 const char *path = NULL; 1146 mode_t mode = 0777; 1147 1148 FOR_EACH_ITEM(item, trans, head) { 1149 switch(item->leafid) { 1150 case LC_PATH1: 1151 path = HCC_STRING(item); 1152 break; 1153 case LC_MODE: 1154 mode = HCC_INT32(item); 1155 break; 1156 } 1157 } 1158 if (ReadOnlyOpt) { 1159 head->error = EACCES; 1160 return (0); 1161 } 1162 if (path == NULL) 1163 return(-2); 1164 return(mkdir(path, mode)); 1165 } 1166 1167 /* 1168 * RMDIR 1169 */ 1170 int 1171 hc_rmdir(struct HostConf *hc, const char *path) 1172 { 1173 hctransaction_t trans; 1174 struct HCHead *head; 1175 1176 if (NotForRealOpt) 1177 return(0); 1178 if (hc == NULL || hc->host == NULL) 1179 return(rmdir(path)); 1180 1181 trans = hcc_start_command(hc, HC_RMDIR); 1182 hcc_leaf_string(trans, LC_PATH1, path); 1183 if ((head = hcc_finish_command(trans)) == NULL) 1184 return(-1); 1185 if (head->error) 1186 return(-1); 1187 return(0); 1188 } 1189 1190 static int 1191 rc_rmdir(hctransaction_t trans, struct HCHead *head) 1192 { 1193 struct HCLeaf *item; 1194 const char *path = NULL; 1195 1196 FOR_EACH_ITEM(item, trans, head) { 1197 if (item->leafid == LC_PATH1) 1198 path = HCC_STRING(item); 1199 } 1200 if (ReadOnlyOpt) { 1201 head->error = EACCES; 1202 return (0); 1203 } 1204 if (path == NULL) 1205 return(-2); 1206 return(rmdir(path)); 1207 } 1208 1209 /* 1210 * CHOWN 1211 * 1212 * Almost silently ignore chowns that fail if we are not root. 1213 */ 1214 int 1215 hc_chown(struct HostConf *hc, const char *path, uid_t owner, gid_t group) 1216 { 1217 hctransaction_t trans; 1218 struct HCHead *head; 1219 int rc; 1220 1221 if (NotForRealOpt) 1222 return(0); 1223 if (!DstRootPrivs) 1224 owner = -1; 1225 1226 if (hc == NULL || hc->host == NULL) { 1227 rc = chown(path, owner, group); 1228 if (rc < 0) 1229 rc = silentwarning(&chown_warning, "file ownership may differ\n"); 1230 return(rc); 1231 } 1232 1233 trans = hcc_start_command(hc, HC_CHOWN); 1234 hcc_leaf_string(trans, LC_PATH1, path); 1235 hcc_leaf_int32(trans, LC_UID, owner); 1236 hcc_leaf_int32(trans, LC_GID, group); 1237 if ((head = hcc_finish_command(trans)) == NULL) 1238 return(-1); 1239 if (head->error) 1240 return(-1); 1241 return(0); 1242 } 1243 1244 static int 1245 rc_chown(hctransaction_t trans, struct HCHead *head) 1246 { 1247 struct HCLeaf *item; 1248 const char *path = NULL; 1249 uid_t uid = (uid_t)-1; 1250 gid_t gid = (gid_t)-1; 1251 int rc; 1252 1253 FOR_EACH_ITEM(item, trans, head) { 1254 switch(item->leafid) { 1255 case LC_PATH1: 1256 path = HCC_STRING(item); 1257 break; 1258 case LC_UID: 1259 uid = HCC_INT32(item); 1260 break; 1261 case LC_GID: 1262 gid = HCC_INT32(item); 1263 break; 1264 } 1265 } 1266 if (ReadOnlyOpt) { 1267 head->error = EACCES; 1268 return (0); 1269 } 1270 if (path == NULL) 1271 return(-2); 1272 rc = chown(path, uid, gid); 1273 if (rc < 0) 1274 rc = silentwarning(&chown_warning, "file ownership may differ\n"); 1275 return(rc); 1276 } 1277 1278 /* 1279 * LCHOWN 1280 */ 1281 int 1282 hc_lchown(struct HostConf *hc, const char *path, uid_t owner, gid_t group) 1283 { 1284 hctransaction_t trans; 1285 struct HCHead *head; 1286 int rc; 1287 1288 if (NotForRealOpt) 1289 return(0); 1290 if (!DstRootPrivs) 1291 owner = -1; 1292 1293 if (hc == NULL || hc->host == NULL) { 1294 rc = lchown(path, owner, group); 1295 if (rc < 0) 1296 rc = silentwarning(&chown_warning, "file ownership may differ\n"); 1297 return(rc); 1298 } 1299 1300 trans = hcc_start_command(hc, HC_LCHOWN); 1301 hcc_leaf_string(trans, LC_PATH1, path); 1302 hcc_leaf_int32(trans, LC_UID, owner); 1303 hcc_leaf_int32(trans, LC_GID, group); 1304 if ((head = hcc_finish_command(trans)) == NULL) 1305 return(-1); 1306 if (head->error) 1307 return(-1); 1308 return(0); 1309 } 1310 1311 static int 1312 rc_lchown(hctransaction_t trans, struct HCHead *head) 1313 { 1314 struct HCLeaf *item; 1315 const char *path = NULL; 1316 uid_t uid = (uid_t)-1; 1317 gid_t gid = (gid_t)-1; 1318 int rc; 1319 1320 FOR_EACH_ITEM(item, trans, head) { 1321 switch(item->leafid) { 1322 case LC_PATH1: 1323 path = HCC_STRING(item); 1324 break; 1325 case LC_UID: 1326 uid = HCC_INT32(item); 1327 break; 1328 case LC_GID: 1329 gid = HCC_INT32(item); 1330 break; 1331 } 1332 } 1333 if (ReadOnlyOpt) { 1334 head->error = EACCES; 1335 return (0); 1336 } 1337 if (path == NULL) 1338 return(-2); 1339 rc = lchown(path, uid, gid); 1340 if (rc < 0) 1341 rc = silentwarning(&chown_warning, "file ownership may differ\n"); 1342 return(rc); 1343 } 1344 1345 /* 1346 * CHMOD 1347 */ 1348 int 1349 hc_chmod(struct HostConf *hc, const char *path, mode_t mode) 1350 { 1351 hctransaction_t trans; 1352 struct HCHead *head; 1353 1354 if (NotForRealOpt) 1355 return(0); 1356 if (hc == NULL || hc->host == NULL) 1357 return(chmod(path, mode)); 1358 1359 trans = hcc_start_command(hc, HC_CHMOD); 1360 hcc_leaf_string(trans, LC_PATH1, path); 1361 hcc_leaf_int32(trans, LC_MODE, mode); 1362 if ((head = hcc_finish_command(trans)) == NULL) 1363 return(-1); 1364 if (head->error) 1365 return(-1); 1366 return(0); 1367 } 1368 1369 static int 1370 rc_chmod(hctransaction_t trans, struct HCHead *head) 1371 { 1372 struct HCLeaf *item; 1373 const char *path = NULL; 1374 mode_t mode = 0666; 1375 1376 FOR_EACH_ITEM(item, trans, head) { 1377 switch(item->leafid) { 1378 case LC_PATH1: 1379 path = HCC_STRING(item); 1380 break; 1381 case LC_MODE: 1382 mode = HCC_INT32(item); 1383 break; 1384 } 1385 } 1386 if (ReadOnlyOpt) { 1387 head->error = EACCES; 1388 return (0); 1389 } 1390 if (path == NULL) 1391 return(-2); 1392 return(chmod(path, mode)); 1393 } 1394 1395 /* 1396 * MKNOD 1397 */ 1398 int 1399 hc_mknod(struct HostConf *hc, const char *path, mode_t mode, dev_t rdev) 1400 { 1401 hctransaction_t trans; 1402 struct HCHead *head; 1403 1404 if (NotForRealOpt) 1405 return(0); 1406 if (!DstRootPrivs) { 1407 /* mknod() requires root privs, so don't bother. */ 1408 errno = EPERM; 1409 return (-1); 1410 } 1411 1412 if (hc == NULL || hc->host == NULL) 1413 return(mknod(path, mode, rdev)); 1414 1415 trans = hcc_start_command(hc, HC_MKNOD); 1416 hcc_leaf_string(trans, LC_PATH1, path); 1417 hcc_leaf_int32(trans, LC_MODE, mode); 1418 hcc_leaf_int32(trans, LC_RDEV, rdev); 1419 if ((head = hcc_finish_command(trans)) == NULL) 1420 return(-1); 1421 if (head->error) 1422 return(-1); 1423 return(0); 1424 } 1425 1426 static int 1427 rc_mknod(hctransaction_t trans, struct HCHead *head) 1428 { 1429 struct HCLeaf *item; 1430 const char *path = NULL; 1431 mode_t mode = 0666; 1432 dev_t rdev = 0; 1433 1434 FOR_EACH_ITEM(item, trans, head) { 1435 switch(item->leafid) { 1436 case LC_PATH1: 1437 path = HCC_STRING(item); 1438 break; 1439 case LC_MODE: 1440 mode = HCC_INT32(item); 1441 break; 1442 case LC_RDEV: 1443 rdev = HCC_INT32(item); 1444 break; 1445 } 1446 } 1447 if (ReadOnlyOpt) { 1448 head->error = EACCES; 1449 return (0); 1450 } 1451 if (path == NULL) 1452 return(-2); 1453 return(mknod(path, mode, rdev)); 1454 } 1455 1456 /* 1457 * LINK 1458 */ 1459 int 1460 hc_link(struct HostConf *hc, const char *name1, const char *name2) 1461 { 1462 hctransaction_t trans; 1463 struct HCHead *head; 1464 1465 if (NotForRealOpt) 1466 return(0); 1467 if (hc == NULL || hc->host == NULL) 1468 return(link(name1, name2)); 1469 1470 trans = hcc_start_command(hc, HC_LINK); 1471 hcc_leaf_string(trans, LC_PATH1, name1); 1472 hcc_leaf_string(trans, LC_PATH2, name2); 1473 if ((head = hcc_finish_command(trans)) == NULL) 1474 return(-1); 1475 if (head->error) 1476 return(-1); 1477 return(0); 1478 } 1479 1480 static int 1481 rc_link(hctransaction_t trans, struct HCHead *head) 1482 { 1483 struct HCLeaf *item; 1484 const char *name1 = NULL; 1485 const char *name2 = NULL; 1486 1487 FOR_EACH_ITEM(item, trans, head) { 1488 switch(item->leafid) { 1489 case LC_PATH1: 1490 name1 = HCC_STRING(item); 1491 break; 1492 case LC_PATH2: 1493 name2 = HCC_STRING(item); 1494 break; 1495 } 1496 } 1497 if (ReadOnlyOpt) { 1498 head->error = EACCES; 1499 return (-0); 1500 } 1501 if (name1 == NULL || name2 == NULL) 1502 return(-2); 1503 return(link(name1, name2)); 1504 } 1505 1506 #ifdef _ST_FLAGS_PRESENT_ 1507 /* 1508 * CHFLAGS 1509 */ 1510 int 1511 hc_chflags(struct HostConf *hc, const char *path, u_long flags) 1512 { 1513 hctransaction_t trans; 1514 struct HCHead *head; 1515 int rc; 1516 1517 if (NotForRealOpt) 1518 return(0); 1519 if (!DstRootPrivs) 1520 flags &= UF_SETTABLE; 1521 1522 if (hc == NULL || hc->host == NULL) { 1523 if ((rc = chflags(path, flags)) < 0) 1524 rc = silentwarning(&chflags_warning, "file flags may differ\n"); 1525 return (rc); 1526 } 1527 1528 trans = hcc_start_command(hc, HC_CHFLAGS); 1529 hcc_leaf_string(trans, LC_PATH1, path); 1530 hcc_leaf_int64(trans, LC_FILEFLAGS, flags); 1531 if ((head = hcc_finish_command(trans)) == NULL) 1532 return(-1); 1533 if (head->error) 1534 return(-1); 1535 return(0); 1536 } 1537 1538 static int 1539 rc_chflags(hctransaction_t trans, struct HCHead *head) 1540 { 1541 struct HCLeaf *item; 1542 const char *path = NULL; 1543 u_long flags = 0; 1544 int rc; 1545 1546 FOR_EACH_ITEM(item, trans, head) { 1547 switch(item->leafid) { 1548 case LC_PATH1: 1549 path = HCC_STRING(item); 1550 break; 1551 case LC_FILEFLAGS: 1552 flags = (u_long)HCC_INT64(item); 1553 break; 1554 } 1555 } 1556 if (ReadOnlyOpt) { 1557 head->error = EACCES; 1558 return (0); 1559 } 1560 if (path == NULL) 1561 return(-2); 1562 if ((rc = chflags(path, flags)) < 0) 1563 rc = silentwarning(&chflags_warning, "file flags may differ\n"); 1564 return(rc); 1565 } 1566 1567 #endif 1568 1569 /* 1570 * READLINK 1571 */ 1572 int 1573 hc_readlink(struct HostConf *hc, const char *path, char *buf, int bufsiz) 1574 { 1575 hctransaction_t trans; 1576 struct HCHead *head; 1577 struct HCLeaf *item; 1578 int r; 1579 1580 if (hc == NULL || hc->host == NULL) 1581 return(readlink(path, buf, bufsiz)); 1582 1583 trans = hcc_start_command(hc, HC_READLINK); 1584 hcc_leaf_string(trans, LC_PATH1, path); 1585 if ((head = hcc_finish_command(trans)) == NULL) 1586 return(-1); 1587 if (head->error) 1588 return(-1); 1589 1590 r = 0; 1591 FOR_EACH_ITEM(item, trans, head) { 1592 if (item->leafid == LC_DATA) { 1593 r = item->bytes - sizeof(*item); 1594 if (r < 0) 1595 r = 0; 1596 if (r > bufsiz) 1597 r = bufsiz; 1598 bcopy(HCC_BINARYDATA(item), buf, r); 1599 } 1600 } 1601 return(r); 1602 } 1603 1604 static int 1605 rc_readlink(hctransaction_t trans, struct HCHead *head) 1606 { 1607 struct HCLeaf *item; 1608 const char *path = NULL; 1609 char buf[1024]; 1610 int r; 1611 1612 FOR_EACH_ITEM(item, trans, head) { 1613 if (item->leafid == LC_PATH1) 1614 path = HCC_STRING(item); 1615 } 1616 if (path == NULL) 1617 return(-2); 1618 r = readlink(path, buf, sizeof(buf)); 1619 if (r < 0) 1620 return(-1); 1621 hcc_leaf_data(trans, LC_DATA, buf, r); 1622 return(0); 1623 } 1624 1625 /* 1626 * UMASK 1627 */ 1628 mode_t 1629 hc_umask(struct HostConf *hc, mode_t numask) 1630 { 1631 hctransaction_t trans; 1632 struct HCHead *head; 1633 struct HCLeaf *item; 1634 1635 if (NotForRealOpt) 1636 return(umask(numask)); 1637 if (hc == NULL || hc->host == NULL) 1638 return(umask(numask)); 1639 1640 trans = hcc_start_command(hc, HC_UMASK); 1641 hcc_leaf_int32(trans, LC_MODE, numask); 1642 if ((head = hcc_finish_command(trans)) == NULL) 1643 return((mode_t)-1); 1644 if (head->error) 1645 return((mode_t)-1); 1646 1647 numask = (mode_t) ~0666U; 1648 FOR_EACH_ITEM(item, trans, head) { 1649 if (item->leafid == LC_MODE) 1650 numask = HCC_INT32(item); 1651 } 1652 return(numask); 1653 } 1654 1655 static int 1656 rc_umask(hctransaction_t trans, struct HCHead *head) 1657 { 1658 struct HCLeaf *item; 1659 mode_t numask = (mode_t) ~0666U; 1660 1661 FOR_EACH_ITEM(item, trans, head) { 1662 if (item->leafid == LC_MODE) 1663 numask = HCC_INT32(item); 1664 } 1665 numask = umask(numask); 1666 hcc_leaf_int32(trans, LC_MODE, numask); 1667 return(0); 1668 } 1669 1670 /* 1671 * SYMLINK 1672 */ 1673 int 1674 hc_symlink(struct HostConf *hc, const char *name1, const char *name2) 1675 { 1676 hctransaction_t trans; 1677 struct HCHead *head; 1678 1679 if (NotForRealOpt) 1680 return(0); 1681 if (hc == NULL || hc->host == NULL) 1682 return(symlink(name1, name2)); 1683 1684 trans = hcc_start_command(hc, HC_SYMLINK); 1685 hcc_leaf_string(trans, LC_PATH1, name1); 1686 hcc_leaf_string(trans, LC_PATH2, name2); 1687 if ((head = hcc_finish_command(trans)) == NULL) 1688 return(-1); 1689 if (head->error) 1690 return(-1); 1691 return(0); 1692 } 1693 1694 static int 1695 rc_symlink(hctransaction_t trans, struct HCHead *head) 1696 { 1697 struct HCLeaf *item; 1698 const char *name1 = NULL; 1699 const char *name2 = NULL; 1700 1701 FOR_EACH_ITEM(item, trans, head) { 1702 switch(item->leafid) { 1703 case LC_PATH1: 1704 name1 = HCC_STRING(item); 1705 break; 1706 case LC_PATH2: 1707 name2 = HCC_STRING(item); 1708 break; 1709 } 1710 } 1711 if (ReadOnlyOpt) { 1712 head->error = EACCES; 1713 return (0); 1714 } 1715 if (name1 == NULL || name2 == NULL) 1716 return(-2); 1717 return(symlink(name1, name2)); 1718 } 1719 1720 /* 1721 * RENAME 1722 */ 1723 int 1724 hc_rename(struct HostConf *hc, const char *name1, const char *name2) 1725 { 1726 hctransaction_t trans; 1727 struct HCHead *head; 1728 1729 if (NotForRealOpt) 1730 return(0); 1731 if (hc == NULL || hc->host == NULL) 1732 return(rename(name1, name2)); 1733 1734 trans = hcc_start_command(hc, HC_RENAME); 1735 hcc_leaf_string(trans, LC_PATH1, name1); 1736 hcc_leaf_string(trans, LC_PATH2, name2); 1737 if ((head = hcc_finish_command(trans)) == NULL) 1738 return(-1); 1739 if (head->error) 1740 return(-1); 1741 return(0); 1742 } 1743 1744 static int 1745 rc_rename(hctransaction_t trans, struct HCHead *head) 1746 { 1747 struct HCLeaf *item; 1748 const char *name1 = NULL; 1749 const char *name2 = NULL; 1750 1751 FOR_EACH_ITEM(item, trans, head) { 1752 switch(item->leafid) { 1753 case LC_PATH1: 1754 name1 = HCC_STRING(item); 1755 break; 1756 case LC_PATH2: 1757 name2 = HCC_STRING(item); 1758 break; 1759 } 1760 } 1761 if (ReadOnlyOpt) { 1762 head->error = EACCES; 1763 return (0); 1764 } 1765 if (name1 == NULL || name2 == NULL) 1766 return(-2); 1767 return(rename(name1, name2)); 1768 } 1769 1770 /* 1771 * UTIMES 1772 */ 1773 int 1774 hc_utimes(struct HostConf *hc, const char *path, const struct timeval *times) 1775 { 1776 hctransaction_t trans; 1777 struct HCHead *head; 1778 1779 if (NotForRealOpt) 1780 return(0); 1781 if (hc == NULL || hc->host == NULL) 1782 return(utimes(path, times)); 1783 1784 trans = hcc_start_command(hc, HC_UTIMES); 1785 hcc_leaf_string(trans, LC_PATH1, path); 1786 hcc_leaf_int64(trans, LC_ATIME, times[0].tv_sec); 1787 hcc_leaf_int64(trans, LC_MTIME, times[1].tv_sec); 1788 if ((head = hcc_finish_command(trans)) == NULL) 1789 return(-1); 1790 if (head->error) 1791 return(-1); 1792 return(0); 1793 } 1794 1795 static int 1796 rc_utimes(hctransaction_t trans, struct HCHead *head) 1797 { 1798 struct HCLeaf *item; 1799 struct timeval times[2]; 1800 const char *path; 1801 1802 bzero(times, sizeof(times)); 1803 path = NULL; 1804 1805 FOR_EACH_ITEM(item, trans, head) { 1806 switch(item->leafid) { 1807 case LC_PATH1: 1808 path = HCC_STRING(item); 1809 break; 1810 case LC_ATIME: 1811 times[0].tv_sec = HCC_INT64(item); 1812 break; 1813 case LC_MTIME: 1814 times[1].tv_sec = HCC_INT64(item); 1815 break; 1816 } 1817 } 1818 if (ReadOnlyOpt) { 1819 head->error = EACCES; 1820 return (0); 1821 } 1822 if (path == NULL) 1823 return(-2); 1824 return(utimes(path, times)); 1825 } 1826 1827 uid_t 1828 hc_geteuid(struct HostConf *hc) 1829 { 1830 hctransaction_t trans; 1831 struct HCHead *head; 1832 struct HCLeaf *item; 1833 1834 if (hc == NULL || hc->host == NULL) 1835 return (geteuid()); 1836 1837 if (hc->version < 3) { 1838 fprintf(stderr, "WARNING: Remote client uses old protocol version\n"); 1839 /* Return 0 on error, so the caller assumes root privileges. */ 1840 return (0); 1841 } 1842 1843 trans = hcc_start_command(hc, HC_GETEUID); 1844 if ((head = hcc_finish_command(trans)) == NULL || head->error) 1845 return(0); 1846 FOR_EACH_ITEM(item, trans, head) { 1847 if (item->leafid == LC_UID) 1848 return (HCC_INT32(item)); 1849 } 1850 return(0); /* shouldn't happen */ 1851 } 1852 1853 static int 1854 rc_geteuid(hctransaction_t trans, struct HCHead *head __unused) 1855 { 1856 hcc_leaf_int32(trans, LC_UID, geteuid()); 1857 return (0); 1858 } 1859 1860 static int 1861 getmygroups(gid_t **gidlist) 1862 { 1863 int count; 1864 1865 if ((count = getgroups(0, *gidlist)) > 0) { 1866 if ((*gidlist = malloc(count * sizeof(gid_t))) != NULL) { 1867 if ((count = getgroups(count, *gidlist)) <= 0) 1868 free(*gidlist); 1869 } 1870 else 1871 count = -1; 1872 } 1873 else 1874 *gidlist = NULL; 1875 return (count); 1876 } 1877 1878 int 1879 hc_getgroups(struct HostConf *hc, gid_t **gidlist) 1880 { 1881 int count, i; 1882 hctransaction_t trans; 1883 struct HCHead *head; 1884 struct HCLeaf *item; 1885 1886 if (hc == NULL || hc->host == NULL) 1887 return (getmygroups(gidlist)); 1888 1889 i = 0; 1890 count = 0; 1891 *gidlist = NULL; 1892 1893 if (hc->version < 3) { 1894 fprintf(stderr, "WARNING: Remote client uses old protocol version\n"); 1895 return (-1); 1896 } 1897 1898 trans = hcc_start_command(hc, HC_GETGROUPS); 1899 if ((head = hcc_finish_command(trans)) == NULL || head->error) 1900 return(-1); 1901 FOR_EACH_ITEM(item, trans, head) { 1902 switch(item->leafid) { 1903 case LC_COUNT: 1904 count = HCC_INT32(item); 1905 if (*gidlist != NULL) { /* protocol error */ 1906 free(*gidlist); 1907 *gidlist = NULL; 1908 return (-1); 1909 } 1910 if ((*gidlist = malloc(count * sizeof(gid_t))) == NULL) 1911 return (-1); 1912 break; 1913 case LC_GID: 1914 if (*gidlist == NULL || i >= count) { /* protocol error */ 1915 if (*gidlist != NULL) 1916 free(*gidlist); 1917 *gidlist = NULL; 1918 return (-1); 1919 } 1920 (*gidlist)[i++] = HCC_INT32(item); 1921 break; 1922 } 1923 } 1924 return (count); 1925 } 1926 1927 static int 1928 rc_getgroups(hctransaction_t trans, struct HCHead *head __unused) 1929 { 1930 int count, i; 1931 gid_t *gidlist; 1932 1933 if ((count = getmygroups(&gidlist)) < 0) 1934 return (-1); 1935 hcc_leaf_int32(trans, LC_COUNT, count); 1936 for (i = 0; i < count; i++) 1937 hcc_leaf_int32(trans, LC_GID, gidlist[i]); 1938 if (gidlist != NULL) 1939 free(gidlist); 1940 return (0); 1941 } 1942