1 /* 2 * HCPROTO.C 3 * 4 * This module implements a simple remote control protocol 5 * 6 * $DragonFly: src/bin/cpdup/hcproto.c,v 1.1 2006/08/13 20:51:40 dillon Exp $ 7 */ 8 9 #include <sys/types.h> 10 #include <sys/stat.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <unistd.h> 14 #include <string.h> 15 #include <fcntl.h> 16 #include <dirent.h> 17 #include <errno.h> 18 19 #include "hclink.h" 20 #include "hcproto.h" 21 22 static int hc_decode_stat(struct stat *, struct HCHead *); 23 static int rc_encode_stat(struct HostConf *, struct stat *); 24 25 static int rc_hello(struct HostConf *, struct HCHead *); 26 static int rc_stat(struct HostConf *, struct HCHead *); 27 static int rc_lstat(struct HostConf *, struct HCHead *); 28 static int rc_opendir(struct HostConf *, struct HCHead *); 29 static int rc_readdir(struct HostConf *, struct HCHead *); 30 static int rc_closedir(struct HostConf *, struct HCHead *); 31 static int rc_open(struct HostConf *, struct HCHead *); 32 static int rc_close(struct HostConf *, struct HCHead *); 33 static int rc_read(struct HostConf *, struct HCHead *); 34 static int rc_write(struct HostConf *, struct HCHead *); 35 static int rc_remove(struct HostConf *, struct HCHead *); 36 static int rc_mkdir(struct HostConf *, struct HCHead *); 37 static int rc_rmdir(struct HostConf *, struct HCHead *); 38 static int rc_chown(struct HostConf *, struct HCHead *); 39 static int rc_lchown(struct HostConf *, struct HCHead *); 40 static int rc_chmod(struct HostConf *, struct HCHead *); 41 static int rc_link(struct HostConf *, struct HCHead *); 42 #ifdef _ST_FLAGS_PRESENT_ 43 static int rc_chflags(struct HostConf *, struct HCHead *); 44 #endif 45 static int rc_readlink(struct HostConf *, struct HCHead *); 46 static int rc_umask(struct HostConf *, struct HCHead *); 47 static int rc_symlink(struct HostConf *, struct HCHead *); 48 static int rc_rename(struct HostConf *, struct HCHead *); 49 static int rc_utimes(struct HostConf *, struct HCHead *); 50 51 struct HCDesc HCDispatchTable[] = { 52 { HC_HELLO, rc_hello }, 53 { HC_STAT, rc_stat }, 54 { HC_LSTAT, rc_lstat }, 55 { HC_OPENDIR, rc_opendir }, 56 { HC_READDIR, rc_readdir }, 57 { HC_CLOSEDIR, rc_closedir }, 58 { HC_OPEN, rc_open }, 59 { HC_CLOSE, rc_close }, 60 { HC_READ, rc_read }, 61 { HC_WRITE, rc_write }, 62 { HC_REMOVE, rc_remove }, 63 { HC_MKDIR, rc_mkdir }, 64 { HC_RMDIR, rc_rmdir }, 65 { HC_CHOWN, rc_chown }, 66 { HC_LCHOWN, rc_lchown }, 67 { HC_CHMOD, rc_chmod }, 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 }; 78 79 int 80 hc_connect(struct HostConf *hc) 81 { 82 if (hcc_connect(hc) < 0) 83 return(-1); 84 return(hc_hello(hc)); 85 } 86 87 void 88 hc_slave(int fdin, int fdout) 89 { 90 hcc_slave(fdin, fdout, HCDispatchTable, 91 sizeof(HCDispatchTable) / sizeof(HCDispatchTable[0])); 92 93 } 94 95 /* 96 * A HELLO RPC is sent on the initial connect. 97 */ 98 int 99 hc_hello(struct HostConf *hc) 100 { 101 struct HCHead *head; 102 struct HCLeaf *item; 103 char hostbuf[256]; 104 int error; 105 106 bzero(hostbuf, sizeof(hostbuf)); 107 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0) 108 return(-1); 109 if (hostbuf[0] == 0) 110 hostbuf[0] = '?'; 111 112 hcc_start_command(hc, HC_HELLO); 113 hcc_leaf_string(hc, LC_HELLOSTR, hostbuf); 114 if ((head = hcc_finish_command(hc)) == NULL) 115 return(-1); 116 117 if (head->error) { 118 fprintf(stderr, "Connected to %s but remote returned error %d\n", 119 hc->host, head->error); 120 return(-1); 121 } 122 123 error = -1; 124 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 125 switch(item->leafid) { 126 case LC_HELLOSTR: 127 fprintf(stderr, "Handshaked with %s\n", HCC_STRING(item)); 128 error = 0; 129 } 130 } 131 if (error < 0) 132 fprintf(stderr, "Handshake failed with %s\n", hc->host); 133 return (error); 134 } 135 136 static int 137 rc_hello(struct HostConf *hc, struct HCHead *head __unused) 138 { 139 char hostbuf[256]; 140 141 bzero(hostbuf, sizeof(hostbuf)); 142 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0) 143 return(-1); 144 if (hostbuf[0] == 0) 145 hostbuf[0] = '?'; 146 147 hcc_leaf_string(hc, LC_HELLOSTR, hostbuf); 148 return(0); 149 } 150 151 /* 152 * STAT, LSTAT 153 */ 154 int 155 hc_stat(struct HostConf *hc, const char *path, struct stat *st) 156 { 157 struct HCHead *head; 158 159 if (hc == NULL || hc->host == NULL) 160 return(stat(path, st)); 161 162 hcc_start_command(hc, HC_STAT); 163 hcc_leaf_string(hc, LC_PATH1, path); 164 if ((head = hcc_finish_command(hc)) == NULL) 165 return(-1); 166 if (head->error) 167 return(-1); 168 return(hc_decode_stat(st, head)); 169 } 170 171 int 172 hc_lstat(struct HostConf *hc, const char *path, struct stat *st) 173 { 174 struct HCHead *head; 175 176 if (hc == NULL || hc->host == NULL) 177 return(lstat(path, st)); 178 179 hcc_start_command(hc, HC_LSTAT); 180 hcc_leaf_string(hc, LC_PATH1, path); 181 if ((head = hcc_finish_command(hc)) == NULL) 182 return(-1); 183 if (head->error) 184 return(-1); 185 return(hc_decode_stat(st, head)); 186 } 187 188 static int 189 hc_decode_stat(struct stat *st, struct HCHead *head) 190 { 191 struct HCLeaf *item; 192 193 bzero(st, sizeof(*st)); 194 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 195 switch(item->leafid) { 196 case LC_DEV: 197 st->st_dev = HCC_INT32(item); 198 break; 199 case LC_INO: 200 st->st_ino = HCC_INT64(item); 201 break; 202 case LC_MODE: 203 st->st_mode = HCC_INT32(item); 204 break; 205 case LC_NLINK: 206 st->st_nlink = HCC_INT32(item); 207 break; 208 case LC_UID: 209 st->st_uid = HCC_INT32(item); 210 break; 211 case LC_GID: 212 st->st_gid = HCC_INT32(item); 213 break; 214 case LC_RDEV: 215 st->st_rdev = HCC_INT32(item); 216 break; 217 case LC_ATIME: 218 st->st_atime = (time_t)HCC_INT64(item); 219 break; 220 case LC_MTIME: 221 st->st_mtime = (time_t)HCC_INT64(item); 222 break; 223 case LC_CTIME: 224 st->st_ctime = (time_t)HCC_INT64(item); 225 break; 226 case LC_FILESIZE: 227 st->st_size = HCC_INT64(item); 228 break; 229 case LC_FILEBLKS: 230 st->st_blocks = HCC_INT64(item); 231 break; 232 case LC_BLKSIZE: 233 st->st_blksize = HCC_INT32(item); 234 break; 235 #ifdef _ST_FSMID_PRESENT_ 236 case LC_FSMID: 237 st->st_fsmid = HCC_INT64(item); 238 break; 239 #endif 240 #ifdef _ST_FLAGS_PRESENT_ 241 case LC_FILEFLAGS: 242 st->st_flags = (u_int32_t)HCC_INT64(item); 243 break; 244 #endif 245 } 246 } 247 return(0); 248 } 249 250 static int 251 rc_stat(struct HostConf *hc, struct HCHead *head) 252 { 253 struct HCLeaf *item; 254 struct stat st; 255 const char *path = NULL; 256 257 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 258 switch(item->leafid) { 259 case LC_PATH1: 260 path = HCC_STRING(item); 261 break; 262 } 263 } 264 if (path == NULL) 265 return(-2); 266 if (stat(path, &st) < 0) 267 return(-1); 268 return (rc_encode_stat(hc, &st)); 269 } 270 271 static int 272 rc_lstat(struct HostConf *hc, struct HCHead *head) 273 { 274 struct HCLeaf *item; 275 struct stat st; 276 const char *path = NULL; 277 278 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 279 switch(item->leafid) { 280 case LC_PATH1: 281 path = HCC_STRING(item); 282 break; 283 } 284 } 285 if (path == NULL) 286 return(-2); 287 if (lstat(path, &st) < 0) 288 return(-1); 289 return (rc_encode_stat(hc, &st)); 290 } 291 292 static int 293 rc_encode_stat(struct HostConf *hc, struct stat *st) 294 { 295 hcc_leaf_int32(hc, LC_DEV, st->st_dev); 296 hcc_leaf_int64(hc, LC_INO, st->st_ino); 297 hcc_leaf_int32(hc, LC_MODE, st->st_mode); 298 hcc_leaf_int32(hc, LC_NLINK, st->st_nlink); 299 hcc_leaf_int32(hc, LC_UID, st->st_uid); 300 hcc_leaf_int32(hc, LC_GID, st->st_gid); 301 hcc_leaf_int32(hc, LC_RDEV, st->st_rdev); 302 hcc_leaf_int64(hc, LC_ATIME, st->st_atime); 303 hcc_leaf_int64(hc, LC_MTIME, st->st_mtime); 304 hcc_leaf_int64(hc, LC_CTIME, st->st_ctime); 305 hcc_leaf_int64(hc, LC_FILESIZE, st->st_size); 306 hcc_leaf_int64(hc, LC_FILEBLKS, st->st_blocks); 307 hcc_leaf_int32(hc, LC_BLKSIZE, st->st_blksize); 308 #ifdef _ST_FSMID_PRESENT_ 309 hcc_leaf_int64(hc, LC_FSMID, st->st_fsmid); 310 #endif 311 #ifdef _ST_FLAGS_PRESENT_ 312 hcc_leaf_int64(hc, LC_FILEFLAGS, st->st_flags); 313 #endif 314 return(0); 315 } 316 317 /* 318 * OPENDIR 319 */ 320 DIR * 321 hc_opendir(struct HostConf *hc, const char *path) 322 { 323 struct HCHead *head; 324 struct HCLeaf *item; 325 struct dirent *den; 326 int desc = 0; 327 328 if (hc == NULL || hc->host == NULL) 329 return(opendir(path)); 330 331 hcc_start_command(hc, HC_OPENDIR); 332 hcc_leaf_string(hc, LC_PATH1, path); 333 if ((head = hcc_finish_command(hc)) == NULL) 334 return(NULL); 335 if (head->error) 336 return(NULL); 337 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 338 switch(item->leafid) { 339 case LC_DESCRIPTOR: 340 desc = HCC_INT32(item); 341 break; 342 } 343 } 344 if (hcc_get_descriptor(hc, desc, HC_DESC_DIR)) { 345 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n", 346 desc); 347 return(NULL); 348 } 349 den = malloc(sizeof(*den)); 350 bzero(den, sizeof(*den)); 351 hcc_set_descriptor(hc, desc, den, HC_DESC_DIR); 352 return((void *)desc); 353 } 354 355 static int 356 rc_opendir(struct HostConf *hc, struct HCHead *head) 357 { 358 struct HCLeaf *item; 359 const char *path = NULL; 360 DIR *dir; 361 int desc; 362 363 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 364 switch(item->leafid) { 365 case LC_PATH1: 366 path = HCC_STRING(item); 367 break; 368 } 369 } 370 if (path == NULL) 371 return(-2); 372 if ((dir = opendir(path)) == NULL) { 373 head->error = errno; 374 } else { 375 desc = hcc_alloc_descriptor(hc, dir, HC_DESC_DIR); 376 hcc_leaf_int32(hc, LC_DESCRIPTOR, desc); 377 } 378 return(0); 379 } 380 381 /* 382 * READDIR 383 */ 384 struct dirent * 385 hc_readdir(struct HostConf *hc, DIR *dir) 386 { 387 struct HCHead *head; 388 struct HCLeaf *item; 389 struct dirent *den; 390 391 if (hc == NULL || hc->host == NULL) 392 return(readdir(dir)); 393 394 hcc_start_command(hc, HC_READDIR); 395 hcc_leaf_int32(hc, LC_DESCRIPTOR, (int)dir); 396 if ((head = hcc_finish_command(hc)) == NULL) 397 return(NULL); 398 if (head->error) 399 return(NULL); /* XXX errno */ 400 den = hcc_get_descriptor(hc, (int)dir, HC_DESC_DIR); 401 if (den == NULL) 402 return(NULL); /* XXX errno */ 403 if (den->d_name) 404 den->d_name[0] = 0; 405 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 406 switch(item->leafid) { 407 case LC_PATH1: 408 snprintf(den->d_name, sizeof(den->d_name), "%s", HCC_STRING(item)); 409 break; 410 case LC_INO: 411 den->d_fileno = HCC_INT64(item); 412 break; 413 case LC_TYPE: 414 den->d_type = HCC_INT32(item); 415 break; 416 } 417 } 418 if (den->d_name[0]) { 419 #ifdef _DIRENT_HAVE_D_NAMLEN 420 den->d_namlen = strlen(den->d_name); 421 #endif 422 return(den); 423 } 424 return(NULL); /* XXX errno */ 425 } 426 427 static int 428 rc_readdir(struct HostConf *hc, struct HCHead *head) 429 { 430 struct HCLeaf *item; 431 struct dirent *den; 432 DIR *dir = NULL; 433 434 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 435 switch(item->leafid) { 436 case LC_DESCRIPTOR: 437 dir = hcc_get_descriptor(hc, HCC_INT32(item), HC_DESC_DIR); 438 break; 439 } 440 } 441 if (dir == NULL) 442 return(-2); 443 if ((den = readdir(dir)) != NULL) { 444 hcc_leaf_string(hc, LC_PATH1, den->d_name); 445 hcc_leaf_int64(hc, LC_INO, den->d_fileno); 446 hcc_leaf_int32(hc, LC_TYPE, den->d_type); 447 } 448 return(0); 449 } 450 451 /* 452 * CLOSEDIR 453 * 454 * XXX cpdup needs to check error code to avoid truncated dirs? 455 */ 456 int 457 hc_closedir(struct HostConf *hc, DIR *dir) 458 { 459 struct HCHead *head; 460 struct dirent *den; 461 462 if (hc == NULL || hc->host == NULL) 463 return(closedir(dir)); 464 den = hcc_get_descriptor(hc, (int)dir, HC_DESC_DIR); 465 if (den) { 466 free(den); 467 hcc_set_descriptor(hc, (int)dir, NULL, HC_DESC_DIR); 468 469 hcc_start_command(hc, HC_CLOSEDIR); 470 hcc_leaf_int32(hc, LC_DESCRIPTOR, (int)dir); 471 if ((head = hcc_finish_command(hc)) == NULL) 472 return(-1); 473 if (head->error) 474 return(-1); /* XXX errno */ 475 return(0); 476 } else { 477 /* errno */ 478 return(-1); 479 } 480 } 481 482 static int 483 rc_closedir(struct HostConf *hc, struct HCHead *head) 484 { 485 struct HCLeaf *item; 486 DIR *dir = NULL; 487 488 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 489 switch(item->leafid) { 490 case LC_DESCRIPTOR: 491 dir = hcc_get_descriptor(hc, HCC_INT32(item), HC_DESC_DIR); 492 break; 493 } 494 } 495 if (dir == NULL) 496 return(-2); 497 return(closedir(dir)); 498 } 499 500 /* 501 * OPEN 502 */ 503 int 504 hc_open(struct HostConf *hc, const char *path, int flags, mode_t mode) 505 { 506 struct HCHead *head; 507 struct HCLeaf *item; 508 int *fdp; 509 int desc = 0; 510 int nflags; 511 512 if (hc == NULL || hc->host == NULL) { 513 #ifdef O_LARGEFILE 514 flags |= O_LARGEFILE; 515 #endif 516 return(open(path, flags, mode)); 517 } 518 519 nflags = flags & XO_NATIVEMASK; 520 if (flags & O_CREAT) 521 nflags |= XO_CREAT; 522 if (flags & O_EXCL) 523 nflags |= XO_EXCL; 524 if (flags & O_TRUNC) 525 nflags |= XO_TRUNC; 526 527 hcc_start_command(hc, HC_OPEN); 528 hcc_leaf_string(hc, LC_PATH1, path); 529 hcc_leaf_int32(hc, LC_OFLAGS, nflags); 530 hcc_leaf_int32(hc, LC_MODE, mode); 531 532 if ((head = hcc_finish_command(hc)) == NULL) 533 return(-1); 534 if (head->error) 535 return(-1); 536 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 537 switch(item->leafid) { 538 case LC_DESCRIPTOR: 539 desc = HCC_INT32(item); 540 break; 541 } 542 } 543 if (hcc_get_descriptor(hc, desc, HC_DESC_FD)) { 544 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n", 545 desc); 546 return(-1); 547 } 548 fdp = malloc(sizeof(int)); 549 *fdp = desc; /* really just a dummy */ 550 hcc_set_descriptor(hc, desc, fdp, HC_DESC_FD); 551 return(desc); 552 } 553 554 static int 555 rc_open(struct HostConf *hc, struct HCHead *head) 556 { 557 struct HCLeaf *item; 558 const char *path = NULL; 559 int nflags = 0; 560 int flags; 561 mode_t mode = 0666; 562 int desc; 563 int *fdp; 564 int fd; 565 566 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 567 switch(item->leafid) { 568 case LC_PATH1: 569 path = HCC_STRING(item); 570 break; 571 case LC_OFLAGS: 572 nflags = HCC_INT32(item); 573 break; 574 case LC_MODE: 575 mode = HCC_INT32(item); 576 break; 577 } 578 } 579 if (path == NULL) 580 return(-2); 581 582 flags = nflags & XO_NATIVEMASK; 583 if (nflags & XO_CREAT) 584 flags |= O_CREAT; 585 if (nflags & XO_EXCL) 586 flags |= O_EXCL; 587 if (nflags & XO_TRUNC) 588 flags |= O_TRUNC; 589 590 #ifdef O_LARGEFILE 591 flags |= O_LARGEFILE; 592 #endif 593 if ((fd = open(path, flags, mode)) < 0) { 594 head->error = errno; 595 return(0); 596 } 597 fdp = malloc(sizeof(int)); 598 *fdp = fd; 599 desc = hcc_alloc_descriptor(hc, fdp, HC_DESC_FD); 600 hcc_leaf_int32(hc, LC_DESCRIPTOR, desc); 601 return(0); 602 } 603 604 /* 605 * CLOSE 606 */ 607 int 608 hc_close(struct HostConf *hc, int fd) 609 { 610 struct HCHead *head; 611 int *fdp; 612 613 if (hc == NULL || hc->host == NULL) 614 return(close(fd)); 615 616 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD); 617 if (fdp) { 618 free(fdp); 619 hcc_set_descriptor(hc, fd, NULL, HC_DESC_FD); 620 621 hcc_start_command(hc, HC_CLOSE); 622 hcc_leaf_int32(hc, LC_DESCRIPTOR, fd); 623 if ((head = hcc_finish_command(hc)) == NULL) 624 return(-1); 625 if (head->error) 626 return(-1); 627 return(0); 628 } else { 629 return(-1); 630 } 631 } 632 633 static int 634 rc_close(struct HostConf *hc, struct HCHead *head) 635 { 636 struct HCLeaf *item; 637 int *fdp = NULL; 638 int fd; 639 int desc = -1; 640 641 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 642 switch(item->leafid) { 643 case LC_DESCRIPTOR: 644 desc = HCC_INT32(item); 645 break; 646 } 647 } 648 if (desc < 0) 649 return(-2); 650 if ((fdp = hcc_get_descriptor(hc, desc, HC_DESC_FD)) == NULL) 651 return(-2); 652 fd = *fdp; 653 free(fdp); 654 hcc_set_descriptor(hc, desc, NULL, HC_DESC_FD); 655 return(close(fd)); 656 } 657 658 /* 659 * READ 660 */ 661 ssize_t 662 hc_read(struct HostConf *hc, int fd, void *buf, size_t bytes) 663 { 664 struct HCHead *head; 665 struct HCLeaf *item; 666 int *fdp; 667 int r; 668 669 if (hc == NULL || hc->host == NULL) 670 return(read(fd, buf, bytes)); 671 672 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD); 673 if (fdp) { 674 r = 0; 675 while (bytes) { 676 int n = (bytes > 32768) ? 32768 : bytes; 677 int x = 0; 678 679 hcc_start_command(hc, HC_READ); 680 hcc_leaf_int32(hc, LC_DESCRIPTOR, fd); 681 hcc_leaf_int32(hc, LC_BYTES, n); 682 if ((head = hcc_finish_command(hc)) == NULL) 683 return(-1); 684 if (head->error) 685 return(-1); 686 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 687 switch(item->leafid) { 688 case LC_DATA: 689 x = item->bytes - sizeof(*item); 690 if (x > (int)bytes) 691 x = (int)bytes; 692 bcopy(HCC_BINARYDATA(item), buf, x); 693 buf = (char *)buf + x; 694 bytes -= (size_t)x; 695 r += x; 696 break; 697 } 698 } 699 if (x < n) 700 break; 701 } 702 return(r); 703 } else { 704 return(-1); 705 } 706 } 707 708 static int 709 rc_read(struct HostConf *hc, struct HCHead *head) 710 { 711 struct HCLeaf *item; 712 int *fdp = NULL; 713 char buf[32768]; 714 int bytes = -1; 715 int n; 716 717 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 718 switch(item->leafid) { 719 case LC_DESCRIPTOR: 720 fdp = hcc_get_descriptor(hc, HCC_INT32(item), HC_DESC_FD); 721 break; 722 case LC_BYTES: 723 bytes = HCC_INT32(item); 724 break; 725 } 726 } 727 if (fdp == NULL) 728 return(-2); 729 if (bytes < 0 || bytes > 32768) 730 return(-2); 731 n = read(*fdp, buf, bytes); 732 if (n < 0) { 733 head->error = errno; 734 return(0); 735 } 736 hcc_leaf_data(hc, LC_DATA, buf, n); 737 return(0); 738 } 739 740 /* 741 * WRITE 742 */ 743 ssize_t 744 hc_write(struct HostConf *hc, int fd, const void *buf, size_t bytes) 745 { 746 struct HCHead *head; 747 struct HCLeaf *item; 748 int *fdp; 749 int r; 750 751 if (hc == NULL || hc->host == NULL) 752 return(write(fd, buf, bytes)); 753 754 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD); 755 if (fdp) { 756 r = 0; 757 while (bytes) { 758 int n = (bytes > 32768) ? 32768 : bytes; 759 int x = 0; 760 761 hcc_start_command(hc, HC_WRITE); 762 hcc_leaf_int32(hc, LC_DESCRIPTOR, fd); 763 hcc_leaf_data(hc, LC_DATA, buf, n); 764 if ((head = hcc_finish_command(hc)) == NULL) 765 return(-1); 766 if (head->error) 767 return(-1); 768 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 769 switch(item->leafid) { 770 case LC_BYTES: 771 x = HCC_INT32(item); 772 break; 773 } 774 } 775 if (x < 0 || x > n) 776 return(-1); 777 r += x; 778 buf = (const char *)buf + x; 779 bytes -= x; 780 if (x < n) 781 break; 782 } 783 return(r); 784 } else { 785 return(-1); 786 } 787 } 788 789 static int 790 rc_write(struct HostConf *hc, struct HCHead *head) 791 { 792 struct HCLeaf *item; 793 int *fdp = NULL; 794 void *buf = NULL; 795 int n = -1; 796 797 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 798 switch(item->leafid) { 799 case LC_DESCRIPTOR: 800 fdp = hcc_get_descriptor(hc, HCC_INT32(item), HC_DESC_FD); 801 break; 802 case LC_DATA: 803 buf = HCC_BINARYDATA(item); 804 n = item->bytes - sizeof(*item); 805 break; 806 } 807 } 808 if (fdp == NULL) 809 return(-2); 810 if (n < 0 || n > 32768) 811 return(-2); 812 n = write(*fdp, buf, n); 813 if (n < 0) { 814 head->error = errno; 815 } else { 816 hcc_leaf_int32(hc, LC_BYTES, n); 817 } 818 return(0); 819 } 820 821 /* 822 * REMOVE 823 */ 824 int 825 hc_remove(struct HostConf *hc, const char *path) 826 { 827 struct HCHead *head; 828 829 if (hc == NULL || hc->host == NULL) 830 return(remove(path)); 831 832 hcc_start_command(hc, HC_REMOVE); 833 hcc_leaf_string(hc, LC_PATH1, path); 834 if ((head = hcc_finish_command(hc)) == NULL) 835 return(-1); 836 if (head->error) 837 return(-1); 838 return(0); 839 } 840 841 static int 842 rc_remove(struct HostConf *hc __unused, struct HCHead *head) 843 { 844 struct HCLeaf *item; 845 const char *path = NULL; 846 847 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 848 switch(item->leafid) { 849 case LC_PATH1: 850 path = HCC_STRING(item); 851 break; 852 } 853 } 854 if (path == NULL) 855 return(-2); 856 return(remove(path)); 857 } 858 859 /* 860 * MKDIR 861 */ 862 int 863 hc_mkdir(struct HostConf *hc __unused, const char *path, mode_t mode) 864 { 865 struct HCHead *head; 866 867 if (hc == NULL || hc->host == NULL) 868 return(mkdir(path, mode)); 869 870 hcc_start_command(hc, HC_MKDIR); 871 hcc_leaf_string(hc, LC_PATH1, path); 872 hcc_leaf_int32(hc, LC_MODE, mode); 873 if ((head = hcc_finish_command(hc)) == NULL) 874 return(-1); 875 if (head->error) 876 return(-1); 877 return(0); 878 } 879 880 static int 881 rc_mkdir(struct HostConf *hc __unused, struct HCHead *head) 882 { 883 struct HCLeaf *item; 884 const char *path = NULL; 885 mode_t mode = 0777; 886 887 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 888 switch(item->leafid) { 889 case LC_PATH1: 890 path = HCC_STRING(item); 891 break; 892 case LC_MODE: 893 mode = HCC_INT32(item); 894 break; 895 } 896 } 897 if (path == NULL) 898 return(-1); 899 return(mkdir(path, mode)); 900 } 901 902 /* 903 * RMDIR 904 */ 905 int 906 hc_rmdir(struct HostConf *hc, const char *path) 907 { 908 struct HCHead *head; 909 910 if (hc == NULL || hc->host == NULL) 911 return(rmdir(path)); 912 913 hcc_start_command(hc, HC_RMDIR); 914 hcc_leaf_string(hc, LC_PATH1, path); 915 if ((head = hcc_finish_command(hc)) == NULL) 916 return(-1); 917 if (head->error) 918 return(-1); 919 return(0); 920 } 921 922 static int 923 rc_rmdir(struct HostConf *hc __unused, struct HCHead *head) 924 { 925 struct HCLeaf *item; 926 const char *path = NULL; 927 928 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 929 switch(item->leafid) { 930 case LC_PATH1: 931 path = HCC_STRING(item); 932 break; 933 } 934 } 935 if (path == NULL) 936 return(-1); 937 return(rmdir(path)); 938 } 939 940 /* 941 * CHOWN 942 */ 943 int 944 hc_chown(struct HostConf *hc, const char *path, uid_t owner, gid_t group) 945 { 946 struct HCHead *head; 947 948 if (hc == NULL || hc->host == NULL) 949 return(chown(path, owner, group)); 950 951 hcc_start_command(hc, HC_CHOWN); 952 hcc_leaf_string(hc, LC_PATH1, path); 953 hcc_leaf_int32(hc, LC_UID, owner); 954 hcc_leaf_int32(hc, LC_GID, group); 955 if ((head = hcc_finish_command(hc)) == NULL) 956 return(-1); 957 if (head->error) 958 return(-1); 959 return(0); 960 } 961 962 static int 963 rc_chown(struct HostConf *hc __unused, struct HCHead *head) 964 { 965 struct HCLeaf *item; 966 const char *path = NULL; 967 uid_t uid = (uid_t)-1; 968 gid_t gid = (gid_t)-1; 969 970 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 971 switch(item->leafid) { 972 case LC_PATH1: 973 path = HCC_STRING(item); 974 break; 975 case LC_UID: 976 uid = HCC_INT32(item); 977 break; 978 case LC_GID: 979 gid = HCC_INT32(item); 980 break; 981 } 982 } 983 if (path == NULL) 984 return(-1); 985 return(chown(path, uid, gid)); 986 } 987 988 /* 989 * LCHOWN 990 */ 991 int 992 hc_lchown(struct HostConf *hc, const char *path, uid_t owner, gid_t group) 993 { 994 struct HCHead *head; 995 996 if (hc == NULL || hc->host == NULL) 997 return(lchown(path, owner, group)); 998 999 hcc_start_command(hc, HC_LCHOWN); 1000 hcc_leaf_string(hc, LC_PATH1, path); 1001 hcc_leaf_int32(hc, LC_UID, owner); 1002 hcc_leaf_int32(hc, LC_GID, group); 1003 if ((head = hcc_finish_command(hc)) == NULL) 1004 return(-1); 1005 if (head->error) 1006 return(-1); 1007 return(0); 1008 } 1009 1010 static int 1011 rc_lchown(struct HostConf *hc __unused, struct HCHead *head) 1012 { 1013 struct HCLeaf *item; 1014 const char *path = NULL; 1015 uid_t uid = (uid_t)-1; 1016 gid_t gid = (gid_t)-1; 1017 1018 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1019 switch(item->leafid) { 1020 case LC_PATH1: 1021 path = HCC_STRING(item); 1022 break; 1023 case LC_UID: 1024 uid = HCC_INT32(item); 1025 break; 1026 case LC_GID: 1027 gid = HCC_INT32(item); 1028 break; 1029 } 1030 } 1031 if (path == NULL) 1032 return(-1); 1033 return(lchown(path, uid, gid)); 1034 } 1035 1036 /* 1037 * CHMOD 1038 */ 1039 int 1040 hc_chmod(struct HostConf *hc, const char *path, mode_t mode) 1041 { 1042 struct HCHead *head; 1043 1044 if (hc == NULL || hc->host == NULL) 1045 return(chmod(path, mode)); 1046 1047 hcc_start_command(hc, HC_CHMOD); 1048 hcc_leaf_string(hc, LC_PATH1, path); 1049 hcc_leaf_int32(hc, LC_MODE, mode); 1050 if ((head = hcc_finish_command(hc)) == NULL) 1051 return(-1); 1052 if (head->error) 1053 return(-1); 1054 return(0); 1055 } 1056 1057 static int 1058 rc_chmod(struct HostConf *hc __unused, struct HCHead *head) 1059 { 1060 struct HCLeaf *item; 1061 const char *path = NULL; 1062 mode_t mode = 0666; 1063 1064 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1065 switch(item->leafid) { 1066 case LC_PATH1: 1067 path = HCC_STRING(item); 1068 break; 1069 case LC_MODE: 1070 mode = HCC_INT32(item); 1071 break; 1072 } 1073 } 1074 if (path == NULL) 1075 return(-1); 1076 return(chmod(path, mode)); 1077 } 1078 1079 /* 1080 * LINK 1081 */ 1082 int 1083 hc_link(struct HostConf *hc, const char *name1, const char *name2) 1084 { 1085 struct HCHead *head; 1086 1087 if (hc == NULL || hc->host == NULL) 1088 return(link(name1, name2)); 1089 1090 hcc_start_command(hc, HC_LINK); 1091 hcc_leaf_string(hc, LC_PATH1, name1); 1092 hcc_leaf_string(hc, LC_PATH2, name2); 1093 if ((head = hcc_finish_command(hc)) == NULL) 1094 return(-1); 1095 if (head->error) 1096 return(-1); 1097 return(0); 1098 } 1099 1100 static int 1101 rc_link(struct HostConf *hc __unused, struct HCHead *head) 1102 { 1103 struct HCLeaf *item; 1104 const char *name1 = NULL; 1105 const char *name2 = NULL; 1106 1107 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1108 switch(item->leafid) { 1109 case LC_PATH1: 1110 name1 = HCC_STRING(item); 1111 break; 1112 case LC_PATH2: 1113 name2 = HCC_STRING(item); 1114 break; 1115 } 1116 } 1117 if (name1 == NULL || name2 == NULL) 1118 return(-2); 1119 return(link(name1, name2)); 1120 } 1121 1122 #ifdef _ST_FLAGS_PRESENT_ 1123 /* 1124 * CHFLAGS 1125 */ 1126 int 1127 hc_chflags(struct HostConf *hc, const char *path, u_long flags) 1128 { 1129 struct HCHead *head; 1130 1131 if (hc == NULL || hc->host == NULL) 1132 return(chflags(path, flags)); 1133 1134 hcc_start_command(hc, HC_CHFLAGS); 1135 hcc_leaf_string(hc, LC_PATH1, path); 1136 hcc_leaf_int64(hc, LC_FILEFLAGS, flags); 1137 if ((head = hcc_finish_command(hc)) == NULL) 1138 return(-1); 1139 if (head->error) 1140 return(-1); 1141 return(0); 1142 } 1143 1144 static int 1145 rc_chflags(struct HostConf *hc __unused, struct HCHead *head) 1146 { 1147 struct HCLeaf *item; 1148 const char *path = NULL; 1149 u_long flags = 0; 1150 1151 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1152 switch(item->leafid) { 1153 case LC_PATH1: 1154 path = HCC_STRING(item); 1155 break; 1156 case LC_FILEFLAGS: 1157 flags = (u_long)HCC_INT64(item); 1158 break; 1159 } 1160 } 1161 if (path == NULL) 1162 return(-2); 1163 return(chflags(path, flags)); 1164 } 1165 1166 #endif 1167 1168 /* 1169 * READLINK 1170 */ 1171 int 1172 hc_readlink(struct HostConf *hc, const char *path, char *buf, int bufsiz) 1173 { 1174 struct HCHead *head; 1175 struct HCLeaf *item; 1176 int r; 1177 1178 if (hc == NULL || hc->host == NULL) 1179 return(readlink(path, buf, bufsiz)); 1180 1181 hcc_start_command(hc, HC_READLINK); 1182 hcc_leaf_string(hc, LC_PATH1, path); 1183 if ((head = hcc_finish_command(hc)) == NULL) 1184 return(-1); 1185 if (head->error) 1186 return(-1); 1187 1188 r = 0; 1189 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1190 switch(item->leafid) { 1191 case LC_DATA: 1192 r = item->bytes - sizeof(*item); 1193 if (r < 0) 1194 r = 0; 1195 if (r > bufsiz) 1196 r = bufsiz; 1197 bcopy(HCC_BINARYDATA(item), buf, r); 1198 break; 1199 } 1200 } 1201 return(r); 1202 } 1203 1204 static int 1205 rc_readlink(struct HostConf *hc, struct HCHead *head) 1206 { 1207 struct HCLeaf *item; 1208 const char *path = NULL; 1209 char buf[1024]; 1210 int r; 1211 1212 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1213 switch(item->leafid) { 1214 case LC_PATH1: 1215 path = HCC_STRING(item); 1216 break; 1217 } 1218 } 1219 if (path == NULL) 1220 return(-2); 1221 r = readlink(path, buf, sizeof(buf)); 1222 if (r < 0) 1223 return(-1); 1224 hcc_leaf_data(hc, LC_DATA, buf, r); 1225 return(0); 1226 } 1227 1228 /* 1229 * UMASK 1230 */ 1231 mode_t 1232 hc_umask(struct HostConf *hc, mode_t numask) 1233 { 1234 struct HCHead *head; 1235 struct HCLeaf *item; 1236 1237 if (hc == NULL || hc->host == NULL) 1238 return(umask(numask)); 1239 1240 hcc_start_command(hc, HC_UMASK); 1241 hcc_leaf_int32(hc, LC_MODE, numask); 1242 if ((head = hcc_finish_command(hc)) == NULL) 1243 return((mode_t)-1); 1244 if (head->error) 1245 return((mode_t)-1); 1246 1247 numask = ~0666; 1248 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1249 switch(item->leafid) { 1250 case LC_MODE: 1251 numask = HCC_INT32(item); 1252 break; 1253 } 1254 } 1255 return(numask); 1256 } 1257 1258 static int 1259 rc_umask(struct HostConf *hc, struct HCHead *head) 1260 { 1261 struct HCLeaf *item; 1262 mode_t numask = ~0666; 1263 1264 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1265 switch(item->leafid) { 1266 case LC_MODE: 1267 numask = HCC_INT32(item); 1268 break; 1269 } 1270 } 1271 numask = umask(numask); 1272 hcc_leaf_int32(hc, LC_MODE, numask); 1273 return(0); 1274 } 1275 1276 /* 1277 * SYMLINK 1278 */ 1279 int 1280 hc_symlink(struct HostConf *hc, const char *name1, const char *name2) 1281 { 1282 struct HCHead *head; 1283 1284 if (hc == NULL || hc->host == NULL) 1285 return(symlink(name1, name2)); 1286 1287 hcc_start_command(hc, HC_SYMLINK); 1288 hcc_leaf_string(hc, LC_PATH1, name1); 1289 hcc_leaf_string(hc, LC_PATH2, name2); 1290 if ((head = hcc_finish_command(hc)) == NULL) 1291 return(-1); 1292 if (head->error) 1293 return(-1); 1294 return(0); 1295 } 1296 1297 static int 1298 rc_symlink(struct HostConf *hc __unused, struct HCHead *head) 1299 { 1300 struct HCLeaf *item; 1301 const char *name1 = NULL; 1302 const char *name2 = NULL; 1303 1304 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1305 switch(item->leafid) { 1306 case LC_PATH1: 1307 name1 = HCC_STRING(item); 1308 break; 1309 case LC_PATH2: 1310 name2 = HCC_STRING(item); 1311 break; 1312 } 1313 } 1314 if (name1 == NULL || name2 == NULL) 1315 return(-2); 1316 return(symlink(name1, name2)); 1317 } 1318 1319 /* 1320 * RENAME 1321 */ 1322 int 1323 hc_rename(struct HostConf *hc, const char *name1, const char *name2) 1324 { 1325 struct HCHead *head; 1326 1327 if (hc == NULL || hc->host == NULL) 1328 return(rename(name1, name2)); 1329 1330 hcc_start_command(hc, HC_RENAME); 1331 hcc_leaf_string(hc, LC_PATH1, name1); 1332 hcc_leaf_string(hc, LC_PATH2, name2); 1333 if ((head = hcc_finish_command(hc)) == NULL) 1334 return(-1); 1335 if (head->error) 1336 return(-1); 1337 return(0); 1338 } 1339 1340 static int 1341 rc_rename(struct HostConf *hc __unused, struct HCHead *head) 1342 { 1343 struct HCLeaf *item; 1344 const char *name1 = NULL; 1345 const char *name2 = NULL; 1346 1347 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1348 switch(item->leafid) { 1349 case LC_PATH1: 1350 name1 = HCC_STRING(item); 1351 break; 1352 case LC_PATH2: 1353 name2 = HCC_STRING(item); 1354 break; 1355 } 1356 } 1357 if (name1 == NULL || name2 == NULL) 1358 return(-2); 1359 return(rename(name1, name2)); 1360 } 1361 1362 /* 1363 * UTIMES 1364 */ 1365 int 1366 hc_utimes(struct HostConf *hc, const char *path, const struct timeval *times) 1367 { 1368 struct HCHead *head; 1369 1370 if (hc == NULL || hc->host == NULL) 1371 return(utimes(path, times)); 1372 1373 hcc_start_command(hc, HC_UTIMES); 1374 hcc_leaf_string(hc, LC_PATH1, path); 1375 hcc_leaf_int64(hc, LC_ATIME, times[0].tv_sec); 1376 hcc_leaf_int64(hc, LC_MTIME, times[1].tv_sec); 1377 if ((head = hcc_finish_command(hc)) == NULL) 1378 return(-1); 1379 if (head->error) 1380 return(-1); 1381 return(0); 1382 } 1383 1384 static int 1385 rc_utimes(struct HostConf *hc __unused, struct HCHead *head) 1386 { 1387 struct HCLeaf *item; 1388 struct timeval times[2]; 1389 const char *path; 1390 1391 bzero(times, sizeof(times)); 1392 path = NULL; 1393 1394 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) { 1395 switch(item->leafid) { 1396 case LC_PATH1: 1397 path = HCC_STRING(item); 1398 break; 1399 case LC_ATIME: 1400 times[0].tv_sec = HCC_INT64(item); 1401 break; 1402 case LC_MTIME: 1403 times[1].tv_sec = HCC_INT64(item); 1404 break; 1405 } 1406 } 1407 if (path == NULL) 1408 return(-2); 1409 return(utimes(path, times)); 1410 } 1411