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