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