4 * This module implements a simple remote control protocol
6 * $DragonFly: src/bin/cpdup/hcproto.c,v 1.6 2008/04/16 17:38:19 dillon Exp $
13 static int hc_decode_stat(struct stat *, struct HCHead *);
14 static int rc_encode_stat(hctransaction_t trans, struct stat *);
16 static int rc_hello(hctransaction_t trans, struct HCHead *);
17 static int rc_stat(hctransaction_t trans, struct HCHead *);
18 static int rc_lstat(hctransaction_t trans, struct HCHead *);
19 static int rc_opendir(hctransaction_t trans, struct HCHead *);
20 static int rc_readdir(hctransaction_t trans, struct HCHead *);
21 static int rc_closedir(hctransaction_t trans, struct HCHead *);
22 static int rc_open(hctransaction_t trans, struct HCHead *);
23 static int rc_close(hctransaction_t trans, struct HCHead *);
24 static int rc_read(hctransaction_t trans, struct HCHead *);
25 static int rc_write(hctransaction_t trans, struct HCHead *);
26 static int rc_remove(hctransaction_t trans, struct HCHead *);
27 static int rc_mkdir(hctransaction_t trans, struct HCHead *);
28 static int rc_rmdir(hctransaction_t trans, struct HCHead *);
29 static int rc_chown(hctransaction_t trans, struct HCHead *);
30 static int rc_lchown(hctransaction_t trans, struct HCHead *);
31 static int rc_chmod(hctransaction_t trans, struct HCHead *);
32 static int rc_mknod(hctransaction_t trans, struct HCHead *);
33 static int rc_link(hctransaction_t trans, struct HCHead *);
34 #ifdef _ST_FLAGS_PRESENT_
35 static int rc_chflags(hctransaction_t trans, struct HCHead *);
37 static int rc_readlink(hctransaction_t trans, struct HCHead *);
38 static int rc_umask(hctransaction_t trans, struct HCHead *);
39 static int rc_symlink(hctransaction_t trans, struct HCHead *);
40 static int rc_rename(hctransaction_t trans, struct HCHead *);
41 static int rc_utimes(hctransaction_t trans, struct HCHead *);
43 struct HCDesc HCDispatchTable[] = {
44 { HC_HELLO, rc_hello },
46 { HC_LSTAT, rc_lstat },
47 { HC_OPENDIR, rc_opendir },
48 { HC_READDIR, rc_readdir },
49 { HC_CLOSEDIR, rc_closedir },
51 { HC_CLOSE, rc_close },
53 { HC_WRITE, rc_write },
54 { HC_REMOVE, rc_remove },
55 { HC_MKDIR, rc_mkdir },
56 { HC_RMDIR, rc_rmdir },
57 { HC_CHOWN, rc_chown },
58 { HC_LCHOWN, rc_lchown },
59 { HC_CHMOD, rc_chmod },
60 { HC_MKNOD, rc_mknod },
62 #ifdef _ST_FLAGS_PRESENT_
63 { HC_CHFLAGS, rc_chflags },
65 { HC_READLINK, rc_readlink },
66 { HC_UMASK, rc_umask },
67 { HC_SYMLINK, rc_symlink },
68 { HC_RENAME, rc_rename },
69 { HC_UTIMES, rc_utimes },
73 hc_connect(struct HostConf *hc)
75 if (hcc_connect(hc) < 0) {
76 fprintf(stderr, "Unable to connect to %s\n", hc->host);
83 hc_slave(int fdin, int fdout)
85 hcc_slave(fdin, fdout, HCDispatchTable,
86 sizeof(HCDispatchTable) / sizeof(HCDispatchTable[0]));
91 * A HELLO RPC is sent on the initial connect.
94 hc_hello(struct HostConf *hc)
98 hctransaction_t trans;
102 bzero(hostbuf, sizeof(hostbuf));
103 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
108 trans = hcc_start_command(hc, HC_HELLO);
109 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
110 hcc_leaf_int32(trans, LC_VERSION, HCPROTO_VERSION);
111 if ((head = hcc_finish_command(trans)) == NULL) {
112 fprintf(stderr, "Connected to %s but remote failed to complete hello\n",
118 fprintf(stderr, "Connected to %s but remote returned error %d\n",
119 hc->host, head->error);
124 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
125 switch(item->leafid) {
127 fprintf(stderr, "Handshaked with %s\n", HCC_STRING(item));
131 hc->version = HCC_INT32(item);
135 if (hc->version < HCPROTO_VERSION_COMPAT) {
136 fprintf(stderr, "Remote cpdup at %s has an incompatible version\n",
141 fprintf(stderr, "Handshake failed with %s\n", hc->host);
146 rc_hello(hctransaction_t trans, struct HCHead *head __unused)
150 bzero(hostbuf, sizeof(hostbuf));
151 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
156 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
157 hcc_leaf_int32(trans, LC_VERSION, HCPROTO_VERSION);
165 hc_stat(struct HostConf *hc, const char *path, struct stat *st)
168 hctransaction_t trans;
170 if (hc == NULL || hc->host == NULL)
171 return(stat(path, st));
173 trans = hcc_start_command(hc, HC_STAT);
174 hcc_leaf_string(trans, LC_PATH1, path);
175 if ((head = hcc_finish_command(trans)) == NULL)
179 return(hc_decode_stat(st, head));
183 hc_lstat(struct HostConf *hc, const char *path, struct stat *st)
186 hctransaction_t trans;
188 if (hc == NULL || hc->host == NULL)
189 return(lstat(path, st));
191 trans = hcc_start_command(hc, HC_LSTAT);
192 hcc_leaf_string(trans, LC_PATH1, path);
193 if ((head = hcc_finish_command(trans)) == NULL)
197 return(hc_decode_stat(st, head));
201 hc_decode_stat(struct stat *st, struct HCHead *head)
205 bzero(st, sizeof(*st));
206 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
207 switch(item->leafid) {
209 st->st_dev = HCC_INT32(item);
212 st->st_ino = HCC_INT64(item);
215 st->st_mode = HCC_INT32(item);
218 st->st_nlink = HCC_INT32(item);
221 st->st_uid = HCC_INT32(item);
224 st->st_gid = HCC_INT32(item);
227 st->st_rdev = HCC_INT32(item);
230 st->st_atime = (time_t)HCC_INT64(item);
233 st->st_mtime = (time_t)HCC_INT64(item);
236 st->st_ctime = (time_t)HCC_INT64(item);
239 st->st_size = HCC_INT64(item);
242 st->st_blocks = HCC_INT64(item);
245 st->st_blksize = HCC_INT32(item);
247 #ifdef _ST_FSMID_PRESENT_
249 st->st_fsmid = HCC_INT64(item);
252 #ifdef _ST_FLAGS_PRESENT_
254 st->st_flags = (u_int32_t)HCC_INT64(item);
263 rc_stat(hctransaction_t trans, struct HCHead *head)
267 const char *path = NULL;
269 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
270 switch(item->leafid) {
272 path = HCC_STRING(item);
278 if (stat(path, &st) < 0)
280 return (rc_encode_stat(trans, &st));
284 rc_lstat(hctransaction_t trans, struct HCHead *head)
288 const char *path = NULL;
290 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
291 switch(item->leafid) {
293 path = HCC_STRING(item);
299 if (lstat(path, &st) < 0)
301 return (rc_encode_stat(trans, &st));
305 rc_encode_stat(hctransaction_t trans, struct stat *st)
307 hcc_leaf_int32(trans, LC_DEV, st->st_dev);
308 hcc_leaf_int64(trans, LC_INO, st->st_ino);
309 hcc_leaf_int32(trans, LC_MODE, st->st_mode);
310 hcc_leaf_int32(trans, LC_NLINK, st->st_nlink);
311 hcc_leaf_int32(trans, LC_UID, st->st_uid);
312 hcc_leaf_int32(trans, LC_GID, st->st_gid);
313 hcc_leaf_int32(trans, LC_RDEV, st->st_rdev);
314 hcc_leaf_int64(trans, LC_ATIME, st->st_atime);
315 hcc_leaf_int64(trans, LC_MTIME, st->st_mtime);
316 hcc_leaf_int64(trans, LC_CTIME, st->st_ctime);
317 hcc_leaf_int64(trans, LC_FILESIZE, st->st_size);
318 hcc_leaf_int64(trans, LC_FILEBLKS, st->st_blocks);
319 hcc_leaf_int32(trans, LC_BLKSIZE, st->st_blksize);
320 #ifdef _ST_FSMID_PRESENT_
321 hcc_leaf_int64(trans, LC_FSMID, st->st_fsmid);
323 #ifdef _ST_FLAGS_PRESENT_
324 hcc_leaf_int64(trans, LC_FILEFLAGS, st->st_flags);
333 hc_opendir(struct HostConf *hc, const char *path)
335 hctransaction_t trans;
341 if (hc == NULL || hc->host == NULL)
342 return(opendir(path));
344 trans = hcc_start_command(hc, HC_OPENDIR);
345 hcc_leaf_string(trans, LC_PATH1, path);
346 if ((head = hcc_finish_command(trans)) == NULL)
350 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
351 switch(item->leafid) {
353 desc = HCC_INT32(item);
357 if (hcc_get_descriptor(hc, desc, HC_DESC_DIR)) {
358 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n",
362 den = malloc(sizeof(*den));
363 bzero(den, sizeof(*den));
364 hcc_set_descriptor(hc, desc, den, HC_DESC_DIR);
365 return((void *)desc);
369 rc_opendir(hctransaction_t trans, struct HCHead *head)
372 const char *path = NULL;
376 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
377 switch(item->leafid) {
379 path = HCC_STRING(item);
385 if ((dir = opendir(path)) == NULL) {
388 desc = hcc_alloc_descriptor(trans->hc, dir, HC_DESC_DIR);
389 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
398 hc_readdir(struct HostConf *hc, DIR *dir)
400 hctransaction_t trans;
405 if (hc == NULL || hc->host == NULL)
406 return(readdir(dir));
408 trans = hcc_start_command(hc, HC_READDIR);
409 hcc_leaf_int32(trans, LC_DESCRIPTOR, (int)dir);
410 if ((head = hcc_finish_command(trans)) == NULL)
413 return(NULL); /* XXX errno */
414 den = hcc_get_descriptor(hc, (int)dir, HC_DESC_DIR);
416 return(NULL); /* XXX errno */
419 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
420 switch(item->leafid) {
422 snprintf(den->d_name, sizeof(den->d_name), "%s", HCC_STRING(item));
425 den->d_fileno = HCC_INT64(item);
428 den->d_type = HCC_INT32(item);
432 if (den->d_name[0]) {
433 #ifdef _DIRENT_HAVE_D_NAMLEN
434 den->d_namlen = strlen(den->d_name);
438 return(NULL); /* XXX errno */
442 rc_readdir(hctransaction_t trans, struct HCHead *head)
448 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
449 switch(item->leafid) {
451 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
457 if ((den = readdir(dir)) != NULL) {
458 hcc_leaf_string(trans, LC_PATH1, den->d_name);
459 hcc_leaf_int64(trans, LC_INO, den->d_fileno);
460 hcc_leaf_int32(trans, LC_TYPE, den->d_type);
468 * XXX cpdup needs to check error code to avoid truncated dirs?
471 hc_closedir(struct HostConf *hc, DIR *dir)
473 hctransaction_t trans;
477 if (hc == NULL || hc->host == NULL)
478 return(closedir(dir));
479 den = hcc_get_descriptor(hc, (int)dir, HC_DESC_DIR);
482 hcc_set_descriptor(hc, (int)dir, NULL, HC_DESC_DIR);
484 trans = hcc_start_command(hc, HC_CLOSEDIR);
485 hcc_leaf_int32(trans, LC_DESCRIPTOR, (int)dir);
486 if ((head = hcc_finish_command(trans)) == NULL)
489 return(-1); /* XXX errno */
498 rc_closedir(hctransaction_t trans, struct HCHead *head)
503 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
504 switch(item->leafid) {
506 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
508 hcc_set_descriptor(trans->hc, HCC_INT32(item), NULL, HC_DESC_DIR);
514 return(closedir(dir));
521 hc_open(struct HostConf *hc, const char *path, int flags, mode_t mode)
523 hctransaction_t trans;
530 if (hc == NULL || hc->host == NULL) {
532 flags |= O_LARGEFILE;
534 return(open(path, flags, mode));
537 nflags = flags & XO_NATIVEMASK;
545 trans = hcc_start_command(hc, HC_OPEN);
546 hcc_leaf_string(trans, LC_PATH1, path);
547 hcc_leaf_int32(trans, LC_OFLAGS, nflags);
548 hcc_leaf_int32(trans, LC_MODE, mode);
550 if ((head = hcc_finish_command(trans)) == NULL)
554 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
555 switch(item->leafid) {
557 desc = HCC_INT32(item);
561 if (hcc_get_descriptor(hc, desc, HC_DESC_FD)) {
562 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n",
566 fdp = malloc(sizeof(int));
567 *fdp = desc; /* really just a dummy */
568 hcc_set_descriptor(hc, desc, fdp, HC_DESC_FD);
573 rc_open(hctransaction_t trans, struct HCHead *head)
576 const char *path = NULL;
584 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
585 switch(item->leafid) {
587 path = HCC_STRING(item);
590 nflags = HCC_INT32(item);
593 mode = HCC_INT32(item);
600 flags = nflags & XO_NATIVEMASK;
601 if (nflags & XO_CREAT)
603 if (nflags & XO_EXCL)
605 if (nflags & XO_TRUNC)
609 flags |= O_LARGEFILE;
611 if ((fd = open(path, flags, mode)) < 0) {
615 fdp = malloc(sizeof(int));
617 desc = hcc_alloc_descriptor(trans->hc, fdp, HC_DESC_FD);
618 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
626 hc_close(struct HostConf *hc, int fd)
628 hctransaction_t trans;
632 if (hc == NULL || hc->host == NULL)
635 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
638 hcc_set_descriptor(hc, fd, NULL, HC_DESC_FD);
640 trans = hcc_start_command(hc, HC_CLOSE);
641 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
642 if ((head = hcc_finish_command(trans)) == NULL)
653 rc_close(hctransaction_t trans, struct HCHead *head)
660 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
661 switch(item->leafid) {
663 desc = HCC_INT32(item);
669 if ((fdp = hcc_get_descriptor(trans->hc, desc, HC_DESC_FD)) == NULL)
673 hcc_set_descriptor(trans->hc, desc, NULL, HC_DESC_FD);
697 hc_read(struct HostConf *hc, int fd, void *buf, size_t bytes)
699 hctransaction_t trans;
705 if (hc == NULL || hc->host == NULL)
706 return(read(fd, buf, bytes));
708 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
712 size_t limit = getiolimit();
713 int n = (bytes > limit) ? limit : bytes;
716 trans = hcc_start_command(hc, HC_READ);
717 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
718 hcc_leaf_int32(trans, LC_BYTES, n);
719 if ((head = hcc_finish_command(trans)) == NULL)
723 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
724 switch(item->leafid) {
726 x = item->bytes - sizeof(*item);
729 bcopy(HCC_BINARYDATA(item), buf, x);
730 buf = (char *)buf + x;
746 rc_read(hctransaction_t trans, struct HCHead *head)
754 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
755 switch(item->leafid) {
757 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
760 bytes = HCC_INT32(item);
766 if (bytes < 0 || bytes > 32768)
768 n = read(*fdp, buf, bytes);
773 hcc_leaf_data(trans, LC_DATA, buf, n);
781 hc_write(struct HostConf *hc, int fd, const void *buf, size_t bytes)
783 hctransaction_t trans;
789 if (hc == NULL || hc->host == NULL)
790 return(write(fd, buf, bytes));
792 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
796 size_t limit = getiolimit();
797 int n = (bytes > limit) ? limit : bytes;
800 trans = hcc_start_command(hc, HC_WRITE);
801 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
802 hcc_leaf_data(trans, LC_DATA, buf, n);
803 if ((head = hcc_finish_command(trans)) == NULL)
807 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
808 switch(item->leafid) {
817 buf = (const char *)buf + x;
829 rc_write(hctransaction_t trans, struct HCHead *head)
836 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
837 switch(item->leafid) {
839 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
842 buf = HCC_BINARYDATA(item);
843 n = item->bytes - sizeof(*item);
849 if (n < 0 || n > 32768)
851 n = write(*fdp, buf, n);
855 hcc_leaf_int32(trans, LC_BYTES, n);
864 hc_remove(struct HostConf *hc, const char *path)
866 hctransaction_t trans;
869 if (hc == NULL || hc->host == NULL)
870 return(remove(path));
872 trans = hcc_start_command(hc, HC_REMOVE);
873 hcc_leaf_string(trans, LC_PATH1, path);
874 if ((head = hcc_finish_command(trans)) == NULL)
882 rc_remove(hctransaction_t trans __unused, struct HCHead *head)
885 const char *path = NULL;
887 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
888 switch(item->leafid) {
890 path = HCC_STRING(item);
896 return(remove(path));
903 hc_mkdir(struct HostConf *hc __unused, const char *path, mode_t mode)
905 hctransaction_t trans;
908 if (hc == NULL || hc->host == NULL)
909 return(mkdir(path, mode));
911 trans = hcc_start_command(hc, HC_MKDIR);
912 hcc_leaf_string(trans, LC_PATH1, path);
913 hcc_leaf_int32(trans, LC_MODE, mode);
914 if ((head = hcc_finish_command(trans)) == NULL)
922 rc_mkdir(hctransaction_t trans __unused, struct HCHead *head)
925 const char *path = NULL;
928 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
929 switch(item->leafid) {
931 path = HCC_STRING(item);
934 mode = HCC_INT32(item);
940 return(mkdir(path, mode));
947 hc_rmdir(struct HostConf *hc, const char *path)
949 hctransaction_t trans;
952 if (hc == NULL || hc->host == NULL)
955 trans = hcc_start_command(hc, HC_RMDIR);
956 hcc_leaf_string(trans, LC_PATH1, path);
957 if ((head = hcc_finish_command(trans)) == NULL)
965 rc_rmdir(hctransaction_t trans __unused, struct HCHead *head)
968 const char *path = NULL;
970 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
971 switch(item->leafid) {
973 path = HCC_STRING(item);
986 hc_chown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
988 hctransaction_t trans;
991 if (hc == NULL || hc->host == NULL)
992 return(chown(path, owner, group));
994 trans = hcc_start_command(hc, HC_CHOWN);
995 hcc_leaf_string(trans, LC_PATH1, path);
996 hcc_leaf_int32(trans, LC_UID, owner);
997 hcc_leaf_int32(trans, LC_GID, group);
998 if ((head = hcc_finish_command(trans)) == NULL)
1006 rc_chown(hctransaction_t trans __unused, struct HCHead *head)
1008 struct HCLeaf *item;
1009 const char *path = NULL;
1010 uid_t uid = (uid_t)-1;
1011 gid_t gid = (gid_t)-1;
1013 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1014 switch(item->leafid) {
1016 path = HCC_STRING(item);
1019 uid = HCC_INT32(item);
1022 gid = HCC_INT32(item);
1028 return(chown(path, uid, gid));
1035 hc_lchown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
1037 hctransaction_t trans;
1038 struct HCHead *head;
1040 if (hc == NULL || hc->host == NULL)
1041 return(lchown(path, owner, group));
1043 trans = hcc_start_command(hc, HC_LCHOWN);
1044 hcc_leaf_string(trans, LC_PATH1, path);
1045 hcc_leaf_int32(trans, LC_UID, owner);
1046 hcc_leaf_int32(trans, LC_GID, group);
1047 if ((head = hcc_finish_command(trans)) == NULL)
1055 rc_lchown(hctransaction_t trans __unused, struct HCHead *head)
1057 struct HCLeaf *item;
1058 const char *path = NULL;
1059 uid_t uid = (uid_t)-1;
1060 gid_t gid = (gid_t)-1;
1062 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1063 switch(item->leafid) {
1065 path = HCC_STRING(item);
1068 uid = HCC_INT32(item);
1071 gid = HCC_INT32(item);
1077 return(lchown(path, uid, gid));
1084 hc_chmod(struct HostConf *hc, const char *path, mode_t mode)
1086 hctransaction_t trans;
1087 struct HCHead *head;
1089 if (hc == NULL || hc->host == NULL)
1090 return(chmod(path, mode));
1092 trans = hcc_start_command(hc, HC_CHMOD);
1093 hcc_leaf_string(trans, LC_PATH1, path);
1094 hcc_leaf_int32(trans, LC_MODE, mode);
1095 if ((head = hcc_finish_command(trans)) == NULL)
1103 rc_chmod(hctransaction_t trans __unused, struct HCHead *head)
1105 struct HCLeaf *item;
1106 const char *path = NULL;
1109 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1110 switch(item->leafid) {
1112 path = HCC_STRING(item);
1115 mode = HCC_INT32(item);
1121 return(chmod(path, mode));
1128 hc_mknod(struct HostConf *hc, const char *path, mode_t mode, dev_t rdev)
1130 hctransaction_t trans;
1131 struct HCHead *head;
1133 if (hc == NULL || hc->host == NULL)
1134 return(mknod(path, mode, rdev));
1136 trans = hcc_start_command(hc, HC_MKNOD);
1137 hcc_leaf_string(trans, LC_PATH1, path);
1138 hcc_leaf_int32(trans, LC_MODE, mode);
1139 hcc_leaf_int32(trans, LC_RDEV, rdev);
1140 if ((head = hcc_finish_command(trans)) == NULL)
1148 rc_mknod(hctransaction_t trans __unused, struct HCHead *head)
1150 struct HCLeaf *item;
1151 const char *path = NULL;
1155 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1156 switch(item->leafid) {
1158 path = HCC_STRING(item);
1161 mode = HCC_INT32(item);
1164 rdev = HCC_INT32(item);
1170 return(mknod(path, mode, rdev));
1177 hc_link(struct HostConf *hc, const char *name1, const char *name2)
1179 hctransaction_t trans;
1180 struct HCHead *head;
1182 if (hc == NULL || hc->host == NULL)
1183 return(link(name1, name2));
1185 trans = hcc_start_command(hc, HC_LINK);
1186 hcc_leaf_string(trans, LC_PATH1, name1);
1187 hcc_leaf_string(trans, LC_PATH2, name2);
1188 if ((head = hcc_finish_command(trans)) == NULL)
1196 rc_link(hctransaction_t trans __unused, struct HCHead *head)
1198 struct HCLeaf *item;
1199 const char *name1 = NULL;
1200 const char *name2 = NULL;
1202 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1203 switch(item->leafid) {
1205 name1 = HCC_STRING(item);
1208 name2 = HCC_STRING(item);
1212 if (name1 == NULL || name2 == NULL)
1214 return(link(name1, name2));
1217 #ifdef _ST_FLAGS_PRESENT_
1222 hc_chflags(struct HostConf *hc, const char *path, u_long flags)
1224 hctransaction_t trans;
1225 struct HCHead *head;
1227 if (hc == NULL || hc->host == NULL)
1228 return(chflags(path, flags));
1230 trans = hcc_start_command(hc, HC_CHFLAGS);
1231 hcc_leaf_string(trans, LC_PATH1, path);
1232 hcc_leaf_int64(trans, LC_FILEFLAGS, flags);
1233 if ((head = hcc_finish_command(trans)) == NULL)
1241 rc_chflags(hctransaction_t trans __unused, struct HCHead *head)
1243 struct HCLeaf *item;
1244 const char *path = NULL;
1247 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1248 switch(item->leafid) {
1250 path = HCC_STRING(item);
1253 flags = (u_long)HCC_INT64(item);
1259 return(chflags(path, flags));
1268 hc_readlink(struct HostConf *hc, const char *path, char *buf, int bufsiz)
1270 hctransaction_t trans;
1271 struct HCHead *head;
1272 struct HCLeaf *item;
1275 if (hc == NULL || hc->host == NULL)
1276 return(readlink(path, buf, bufsiz));
1278 trans = hcc_start_command(hc, HC_READLINK);
1279 hcc_leaf_string(trans, LC_PATH1, path);
1280 if ((head = hcc_finish_command(trans)) == NULL)
1286 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1287 switch(item->leafid) {
1289 r = item->bytes - sizeof(*item);
1294 bcopy(HCC_BINARYDATA(item), buf, r);
1302 rc_readlink(hctransaction_t trans, struct HCHead *head)
1304 struct HCLeaf *item;
1305 const char *path = NULL;
1309 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1310 switch(item->leafid) {
1312 path = HCC_STRING(item);
1318 r = readlink(path, buf, sizeof(buf));
1321 hcc_leaf_data(trans, LC_DATA, buf, r);
1329 hc_umask(struct HostConf *hc, mode_t numask)
1331 hctransaction_t trans;
1332 struct HCHead *head;
1333 struct HCLeaf *item;
1335 if (hc == NULL || hc->host == NULL)
1336 return(umask(numask));
1338 trans = hcc_start_command(hc, HC_UMASK);
1339 hcc_leaf_int32(trans, LC_MODE, numask);
1340 if ((head = hcc_finish_command(trans)) == NULL)
1346 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1347 switch(item->leafid) {
1349 numask = HCC_INT32(item);
1357 rc_umask(hctransaction_t trans, struct HCHead *head)
1359 struct HCLeaf *item;
1360 mode_t numask = ~0666;
1362 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1363 switch(item->leafid) {
1365 numask = HCC_INT32(item);
1369 numask = umask(numask);
1370 hcc_leaf_int32(trans, LC_MODE, numask);
1378 hc_symlink(struct HostConf *hc, const char *name1, const char *name2)
1380 hctransaction_t trans;
1381 struct HCHead *head;
1383 if (hc == NULL || hc->host == NULL)
1384 return(symlink(name1, name2));
1386 trans = hcc_start_command(hc, HC_SYMLINK);
1387 hcc_leaf_string(trans, LC_PATH1, name1);
1388 hcc_leaf_string(trans, LC_PATH2, name2);
1389 if ((head = hcc_finish_command(trans)) == NULL)
1397 rc_symlink(hctransaction_t trans __unused, struct HCHead *head)
1399 struct HCLeaf *item;
1400 const char *name1 = NULL;
1401 const char *name2 = NULL;
1403 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1404 switch(item->leafid) {
1406 name1 = HCC_STRING(item);
1409 name2 = HCC_STRING(item);
1413 if (name1 == NULL || name2 == NULL)
1415 return(symlink(name1, name2));
1422 hc_rename(struct HostConf *hc, const char *name1, const char *name2)
1424 hctransaction_t trans;
1425 struct HCHead *head;
1427 if (hc == NULL || hc->host == NULL)
1428 return(rename(name1, name2));
1430 trans = hcc_start_command(hc, HC_RENAME);
1431 hcc_leaf_string(trans, LC_PATH1, name1);
1432 hcc_leaf_string(trans, LC_PATH2, name2);
1433 if ((head = hcc_finish_command(trans)) == NULL)
1441 rc_rename(hctransaction_t trans __unused, struct HCHead *head)
1443 struct HCLeaf *item;
1444 const char *name1 = NULL;
1445 const char *name2 = NULL;
1447 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1448 switch(item->leafid) {
1450 name1 = HCC_STRING(item);
1453 name2 = HCC_STRING(item);
1457 if (name1 == NULL || name2 == NULL)
1459 return(rename(name1, name2));
1466 hc_utimes(struct HostConf *hc, const char *path, const struct timeval *times)
1468 hctransaction_t trans;
1469 struct HCHead *head;
1471 if (hc == NULL || hc->host == NULL)
1472 return(utimes(path, times));
1474 trans = hcc_start_command(hc, HC_UTIMES);
1475 hcc_leaf_string(trans, LC_PATH1, path);
1476 hcc_leaf_int64(trans, LC_ATIME, times[0].tv_sec);
1477 hcc_leaf_int64(trans, LC_MTIME, times[1].tv_sec);
1478 if ((head = hcc_finish_command(trans)) == NULL)
1486 rc_utimes(hctransaction_t trans __unused, struct HCHead *head)
1488 struct HCLeaf *item;
1489 struct timeval times[2];
1492 bzero(times, sizeof(times));
1495 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1496 switch(item->leafid) {
1498 path = HCC_STRING(item);
1501 times[0].tv_sec = HCC_INT64(item);
1504 times[1].tv_sec = HCC_INT64(item);
1510 return(utimes(path, times));