Remove unneeded comma.
[dragonfly/vkernel-mp.git] / bin / cpdup / hcproto.c
blob54fcacafdd625f2a2efddfb04a4a22f313e74eb8
1 /*
2 * HCPROTO.C
4 * This module implements a simple remote control protocol
6 * $DragonFly: src/bin/cpdup/hcproto.c,v 1.1 2006/08/13 22:51:40 dillon Exp $
7 */
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>
19 #include "hclink.h"
20 #include "hcproto.h"
22 static int hc_decode_stat(struct stat *, struct HCHead *);
23 static int rc_encode_stat(struct HostConf *, struct stat *);
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 *);
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 },
79 int
80 hc_connect(struct HostConf *hc)
82 if (hcc_connect(hc) < 0)
83 return(-1);
84 return(hc_hello(hc));
87 void
88 hc_slave(int fdin, int fdout)
90 hcc_slave(fdin, fdout, HCDispatchTable,
91 sizeof(HCDispatchTable) / sizeof(HCDispatchTable[0]));
96 * A HELLO RPC is sent on the initial connect.
98 int
99 hc_hello(struct HostConf *hc)
101 struct HCHead *head;
102 struct HCLeaf *item;
103 char hostbuf[256];
104 int error;
106 bzero(hostbuf, sizeof(hostbuf));
107 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
108 return(-1);
109 if (hostbuf[0] == 0)
110 hostbuf[0] = '?';
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);
117 if (head->error) {
118 fprintf(stderr, "Connected to %s but remote returned error %d\n",
119 hc->host, head->error);
120 return(-1);
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;
131 if (error < 0)
132 fprintf(stderr, "Handshake failed with %s\n", hc->host);
133 return (error);
136 static int
137 rc_hello(struct HostConf *hc, struct HCHead *head __unused)
139 char hostbuf[256];
141 bzero(hostbuf, sizeof(hostbuf));
142 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
143 return(-1);
144 if (hostbuf[0] == 0)
145 hostbuf[0] = '?';
147 hcc_leaf_string(hc, LC_HELLOSTR, hostbuf);
148 return(0);
152 * STAT, LSTAT
155 hc_stat(struct HostConf *hc, const char *path, struct stat *st)
157 struct HCHead *head;
159 if (hc == NULL || hc->host == NULL)
160 return(stat(path, st));
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));
172 hc_lstat(struct HostConf *hc, const char *path, struct stat *st)
174 struct HCHead *head;
176 if (hc == NULL || hc->host == NULL)
177 return(lstat(path, st));
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));
188 static int
189 hc_decode_stat(struct stat *st, struct HCHead *head)
191 struct HCLeaf *item;
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
247 return(0);
250 static int
251 rc_stat(struct HostConf *hc, struct HCHead *head)
253 struct HCLeaf *item;
254 struct stat st;
255 const char *path = NULL;
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;
264 if (path == NULL)
265 return(-2);
266 if (stat(path, &st) < 0)
267 return(-1);
268 return (rc_encode_stat(hc, &st));
271 static int
272 rc_lstat(struct HostConf *hc, struct HCHead *head)
274 struct HCLeaf *item;
275 struct stat st;
276 const char *path = NULL;
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;
285 if (path == NULL)
286 return(-2);
287 if (lstat(path, &st) < 0)
288 return(-1);
289 return (rc_encode_stat(hc, &st));
292 static int
293 rc_encode_stat(struct HostConf *hc, struct stat *st)
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);
318 * OPENDIR
320 DIR *
321 hc_opendir(struct HostConf *hc, const char *path)
323 struct HCHead *head;
324 struct HCLeaf *item;
325 struct dirent *den;
326 int desc = 0;
328 if (hc == NULL || hc->host == NULL)
329 return(opendir(path));
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;
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);
349 den = malloc(sizeof(*den));
350 bzero(den, sizeof(*den));
351 hcc_set_descriptor(hc, desc, den, HC_DESC_DIR);
352 return((void *)desc);
355 static int
356 rc_opendir(struct HostConf *hc, struct HCHead *head)
358 struct HCLeaf *item;
359 const char *path = NULL;
360 DIR *dir;
361 int desc;
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;
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);
378 return(0);
382 * READDIR
384 struct dirent *
385 hc_readdir(struct HostConf *hc, DIR *dir)
387 struct HCHead *head;
388 struct HCLeaf *item;
389 struct dirent *den;
391 if (hc == NULL || hc->host == NULL)
392 return(readdir(dir));
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;
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);
424 return(NULL); /* XXX errno */
427 static int
428 rc_readdir(struct HostConf *hc, struct HCHead *head)
430 struct HCLeaf *item;
431 struct dirent *den;
432 DIR *dir = NULL;
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;
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);
448 return(0);
452 * CLOSEDIR
454 * XXX cpdup needs to check error code to avoid truncated dirs?
457 hc_closedir(struct HostConf *hc, DIR *dir)
459 struct HCHead *head;
460 struct dirent *den;
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);
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);
482 static int
483 rc_closedir(struct HostConf *hc, struct HCHead *head)
485 struct HCLeaf *item;
486 DIR *dir = NULL;
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;
495 if (dir == NULL)
496 return(-2);
497 return(closedir(dir));
501 * OPEN
504 hc_open(struct HostConf *hc, const char *path, int flags, mode_t mode)
506 struct HCHead *head;
507 struct HCLeaf *item;
508 int *fdp;
509 int desc = 0;
510 int nflags;
512 if (hc == NULL || hc->host == NULL) {
513 #ifdef O_LARGEFILE
514 flags |= O_LARGEFILE;
515 #endif
516 return(open(path, flags, mode));
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;
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);
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;
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);
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);
554 static int
555 rc_open(struct HostConf *hc, struct HCHead *head)
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;
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;
579 if (path == NULL)
580 return(-2);
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;
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);
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);
605 * CLOSE
608 hc_close(struct HostConf *hc, int fd)
610 struct HCHead *head;
611 int *fdp;
613 if (hc == NULL || hc->host == NULL)
614 return(close(fd));
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);
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);
633 static int
634 rc_close(struct HostConf *hc, struct HCHead *head)
636 struct HCLeaf *item;
637 int *fdp = NULL;
638 int fd;
639 int desc = -1;
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;
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));
659 * READ
661 ssize_t
662 hc_read(struct HostConf *hc, int fd, void *buf, size_t bytes)
664 struct HCHead *head;
665 struct HCLeaf *item;
666 int *fdp;
667 int r;
669 if (hc == NULL || hc->host == NULL)
670 return(read(fd, buf, bytes));
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;
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;
699 if (x < n)
700 break;
702 return(r);
703 } else {
704 return(-1);
708 static int
709 rc_read(struct HostConf *hc, struct HCHead *head)
711 struct HCLeaf *item;
712 int *fdp = NULL;
713 char buf[32768];
714 int bytes = -1;
715 int n;
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;
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);
736 hcc_leaf_data(hc, LC_DATA, buf, n);
737 return(0);
741 * WRITE
743 ssize_t
744 hc_write(struct HostConf *hc, int fd, const void *buf, size_t bytes)
746 struct HCHead *head;
747 struct HCLeaf *item;
748 int *fdp;
749 int r;
751 if (hc == NULL || hc->host == NULL)
752 return(write(fd, buf, bytes));
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;
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;
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;
783 return(r);
784 } else {
785 return(-1);
789 static int
790 rc_write(struct HostConf *hc, struct HCHead *head)
792 struct HCLeaf *item;
793 int *fdp = NULL;
794 void *buf = NULL;
795 int n = -1;
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;
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);
818 return(0);
822 * REMOVE
825 hc_remove(struct HostConf *hc, const char *path)
827 struct HCHead *head;
829 if (hc == NULL || hc->host == NULL)
830 return(remove(path));
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);
841 static int
842 rc_remove(struct HostConf *hc __unused, struct HCHead *head)
844 struct HCLeaf *item;
845 const char *path = NULL;
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;
854 if (path == NULL)
855 return(-2);
856 return(remove(path));
860 * MKDIR
863 hc_mkdir(struct HostConf *hc __unused, const char *path, mode_t mode)
865 struct HCHead *head;
867 if (hc == NULL || hc->host == NULL)
868 return(mkdir(path, mode));
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);
880 static int
881 rc_mkdir(struct HostConf *hc __unused, struct HCHead *head)
883 struct HCLeaf *item;
884 const char *path = NULL;
885 mode_t mode = 0777;
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;
897 if (path == NULL)
898 return(-1);
899 return(mkdir(path, mode));
903 * RMDIR
906 hc_rmdir(struct HostConf *hc, const char *path)
908 struct HCHead *head;
910 if (hc == NULL || hc->host == NULL)
911 return(rmdir(path));
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);
922 static int
923 rc_rmdir(struct HostConf *hc __unused, struct HCHead *head)
925 struct HCLeaf *item;
926 const char *path = NULL;
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;
935 if (path == NULL)
936 return(-1);
937 return(rmdir(path));
941 * CHOWN
944 hc_chown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
946 struct HCHead *head;
948 if (hc == NULL || hc->host == NULL)
949 return(chown(path, owner, group));
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);
962 static int
963 rc_chown(struct HostConf *hc __unused, struct HCHead *head)
965 struct HCLeaf *item;
966 const char *path = NULL;
967 uid_t uid = (uid_t)-1;
968 gid_t gid = (gid_t)-1;
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;
983 if (path == NULL)
984 return(-1);
985 return(chown(path, uid, gid));
989 * LCHOWN
992 hc_lchown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
994 struct HCHead *head;
996 if (hc == NULL || hc->host == NULL)
997 return(lchown(path, owner, group));
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);
1010 static int
1011 rc_lchown(struct HostConf *hc __unused, struct HCHead *head)
1013 struct HCLeaf *item;
1014 const char *path = NULL;
1015 uid_t uid = (uid_t)-1;
1016 gid_t gid = (gid_t)-1;
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;
1031 if (path == NULL)
1032 return(-1);
1033 return(lchown(path, uid, gid));
1037 * CHMOD
1040 hc_chmod(struct HostConf *hc, const char *path, mode_t mode)
1042 struct HCHead *head;
1044 if (hc == NULL || hc->host == NULL)
1045 return(chmod(path, mode));
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);
1057 static int
1058 rc_chmod(struct HostConf *hc __unused, struct HCHead *head)
1060 struct HCLeaf *item;
1061 const char *path = NULL;
1062 mode_t mode = 0666;
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;
1074 if (path == NULL)
1075 return(-1);
1076 return(chmod(path, mode));
1080 * LINK
1083 hc_link(struct HostConf *hc, const char *name1, const char *name2)
1085 struct HCHead *head;
1087 if (hc == NULL || hc->host == NULL)
1088 return(link(name1, name2));
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);
1100 static int
1101 rc_link(struct HostConf *hc __unused, struct HCHead *head)
1103 struct HCLeaf *item;
1104 const char *name1 = NULL;
1105 const char *name2 = NULL;
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;
1117 if (name1 == NULL || name2 == NULL)
1118 return(-2);
1119 return(link(name1, name2));
1122 #ifdef _ST_FLAGS_PRESENT_
1124 * CHFLAGS
1127 hc_chflags(struct HostConf *hc, const char *path, u_long flags)
1129 struct HCHead *head;
1131 if (hc == NULL || hc->host == NULL)
1132 return(chflags(path, flags));
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);
1144 static int
1145 rc_chflags(struct HostConf *hc __unused, struct HCHead *head)
1147 struct HCLeaf *item;
1148 const char *path = NULL;
1149 u_long flags = 0;
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;
1161 if (path == NULL)
1162 return(-2);
1163 return(chflags(path, flags));
1166 #endif
1169 * READLINK
1172 hc_readlink(struct HostConf *hc, const char *path, char *buf, int bufsiz)
1174 struct HCHead *head;
1175 struct HCLeaf *item;
1176 int r;
1178 if (hc == NULL || hc->host == NULL)
1179 return(readlink(path, buf, bufsiz));
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);
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;
1201 return(r);
1204 static int
1205 rc_readlink(struct HostConf *hc, struct HCHead *head)
1207 struct HCLeaf *item;
1208 const char *path = NULL;
1209 char buf[1024];
1210 int r;
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;
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);
1229 * UMASK
1231 mode_t
1232 hc_umask(struct HostConf *hc, mode_t numask)
1234 struct HCHead *head;
1235 struct HCLeaf *item;
1237 if (hc == NULL || hc->host == NULL)
1238 return(umask(numask));
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);
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;
1255 return(numask);
1258 static int
1259 rc_umask(struct HostConf *hc, struct HCHead *head)
1261 struct HCLeaf *item;
1262 mode_t numask = ~0666;
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;
1271 numask = umask(numask);
1272 hcc_leaf_int32(hc, LC_MODE, numask);
1273 return(0);
1277 * SYMLINK
1280 hc_symlink(struct HostConf *hc, const char *name1, const char *name2)
1282 struct HCHead *head;
1284 if (hc == NULL || hc->host == NULL)
1285 return(symlink(name1, name2));
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);
1297 static int
1298 rc_symlink(struct HostConf *hc __unused, struct HCHead *head)
1300 struct HCLeaf *item;
1301 const char *name1 = NULL;
1302 const char *name2 = NULL;
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;
1314 if (name1 == NULL || name2 == NULL)
1315 return(-2);
1316 return(symlink(name1, name2));
1320 * RENAME
1323 hc_rename(struct HostConf *hc, const char *name1, const char *name2)
1325 struct HCHead *head;
1327 if (hc == NULL || hc->host == NULL)
1328 return(rename(name1, name2));
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);
1340 static int
1341 rc_rename(struct HostConf *hc __unused, struct HCHead *head)
1343 struct HCLeaf *item;
1344 const char *name1 = NULL;
1345 const char *name2 = NULL;
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;
1357 if (name1 == NULL || name2 == NULL)
1358 return(-2);
1359 return(rename(name1, name2));
1363 * UTIMES
1366 hc_utimes(struct HostConf *hc, const char *path, const struct timeval *times)
1368 struct HCHead *head;
1370 if (hc == NULL || hc->host == NULL)
1371 return(utimes(path, times));
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);
1384 static int
1385 rc_utimes(struct HostConf *hc __unused, struct HCHead *head)
1387 struct HCLeaf *item;
1388 struct timeval times[2];
1389 const char *path;
1391 bzero(times, sizeof(times));
1392 path = NULL;
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;
1407 if (path == NULL)
1408 return(-2);
1409 return(utimes(path, times));