4 * This module implements a simple remote control protocol
6 * $DragonFly: src/bin/cpdup/hcproto.c,v 1.4 2008/04/14 05:40:51 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)
81 hc_slave(int fdin, int fdout)
83 hcc_slave(fdin, fdout, HCDispatchTable,
84 sizeof(HCDispatchTable) / sizeof(HCDispatchTable[0]));
89 * A HELLO RPC is sent on the initial connect.
92 hc_hello(struct HostConf *hc)
96 hctransaction_t trans;
100 bzero(hostbuf, sizeof(hostbuf));
101 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
106 trans = hcc_start_command(hc, HC_HELLO);
107 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
108 hcc_leaf_int32(trans, LC_VERSION, 1);
109 if ((head = hcc_finish_command(trans)) == NULL)
113 fprintf(stderr, "Connected to %s but remote returned error %d\n",
114 hc->host, head->error);
119 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
120 switch(item->leafid) {
122 fprintf(stderr, "Handshaked with %s\n", HCC_STRING(item));
126 hc->version = HCC_INT32(item);
131 fprintf(stderr, "Handshake failed with %s\n", hc->host);
136 rc_hello(hctransaction_t trans, struct HCHead *head __unused)
140 bzero(hostbuf, sizeof(hostbuf));
141 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
146 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
147 hcc_leaf_int32(trans, LC_VERSION, 1);
155 hc_stat(struct HostConf *hc, const char *path, struct stat *st)
158 hctransaction_t trans;
160 if (hc == NULL || hc->host == NULL)
161 return(stat(path, st));
163 trans = hcc_start_command(hc, HC_STAT);
164 hcc_leaf_string(trans, LC_PATH1, path);
165 if ((head = hcc_finish_command(trans)) == NULL)
169 return(hc_decode_stat(st, head));
173 hc_lstat(struct HostConf *hc, const char *path, struct stat *st)
176 hctransaction_t trans;
178 if (hc == NULL || hc->host == NULL)
179 return(lstat(path, st));
181 trans = hcc_start_command(hc, HC_LSTAT);
182 hcc_leaf_string(trans, LC_PATH1, path);
183 if ((head = hcc_finish_command(trans)) == NULL)
187 return(hc_decode_stat(st, head));
191 hc_decode_stat(struct stat *st, struct HCHead *head)
195 bzero(st, sizeof(*st));
196 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
197 switch(item->leafid) {
199 st->st_dev = HCC_INT32(item);
202 st->st_ino = HCC_INT64(item);
205 st->st_mode = HCC_INT32(item);
208 st->st_nlink = HCC_INT32(item);
211 st->st_uid = HCC_INT32(item);
214 st->st_gid = HCC_INT32(item);
217 st->st_rdev = HCC_INT32(item);
220 st->st_atime = (time_t)HCC_INT64(item);
223 st->st_mtime = (time_t)HCC_INT64(item);
226 st->st_ctime = (time_t)HCC_INT64(item);
229 st->st_size = HCC_INT64(item);
232 st->st_blocks = HCC_INT64(item);
235 st->st_blksize = HCC_INT32(item);
237 #ifdef _ST_FSMID_PRESENT_
239 st->st_fsmid = HCC_INT64(item);
242 #ifdef _ST_FLAGS_PRESENT_
244 st->st_flags = (u_int32_t)HCC_INT64(item);
253 rc_stat(hctransaction_t trans, struct HCHead *head)
257 const char *path = NULL;
259 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
260 switch(item->leafid) {
262 path = HCC_STRING(item);
268 if (stat(path, &st) < 0)
270 return (rc_encode_stat(trans, &st));
274 rc_lstat(hctransaction_t trans, struct HCHead *head)
278 const char *path = NULL;
280 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
281 switch(item->leafid) {
283 path = HCC_STRING(item);
289 if (lstat(path, &st) < 0)
291 return (rc_encode_stat(trans, &st));
295 rc_encode_stat(hctransaction_t trans, struct stat *st)
297 hcc_leaf_int32(trans, LC_DEV, st->st_dev);
298 hcc_leaf_int64(trans, LC_INO, st->st_ino);
299 hcc_leaf_int32(trans, LC_MODE, st->st_mode);
300 hcc_leaf_int32(trans, LC_NLINK, st->st_nlink);
301 hcc_leaf_int32(trans, LC_UID, st->st_uid);
302 hcc_leaf_int32(trans, LC_GID, st->st_gid);
303 hcc_leaf_int32(trans, LC_RDEV, st->st_rdev);
304 hcc_leaf_int64(trans, LC_ATIME, st->st_atime);
305 hcc_leaf_int64(trans, LC_MTIME, st->st_mtime);
306 hcc_leaf_int64(trans, LC_CTIME, st->st_ctime);
307 hcc_leaf_int64(trans, LC_FILESIZE, st->st_size);
308 hcc_leaf_int64(trans, LC_FILEBLKS, st->st_blocks);
309 hcc_leaf_int32(trans, LC_BLKSIZE, st->st_blksize);
310 #ifdef _ST_FSMID_PRESENT_
311 hcc_leaf_int64(trans, LC_FSMID, st->st_fsmid);
313 #ifdef _ST_FLAGS_PRESENT_
314 hcc_leaf_int64(trans, LC_FILEFLAGS, st->st_flags);
323 hc_opendir(struct HostConf *hc, const char *path)
325 hctransaction_t trans;
331 if (hc == NULL || hc->host == NULL)
332 return(opendir(path));
334 trans = hcc_start_command(hc, HC_OPENDIR);
335 hcc_leaf_string(trans, LC_PATH1, path);
336 if ((head = hcc_finish_command(trans)) == NULL)
340 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
341 switch(item->leafid) {
343 desc = HCC_INT32(item);
347 if (hcc_get_descriptor(hc, desc, HC_DESC_DIR)) {
348 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n",
352 den = malloc(sizeof(*den));
353 bzero(den, sizeof(*den));
354 hcc_set_descriptor(hc, desc, den, HC_DESC_DIR);
355 return((void *)desc);
359 rc_opendir(hctransaction_t trans, struct HCHead *head)
362 const char *path = NULL;
366 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
367 switch(item->leafid) {
369 path = HCC_STRING(item);
375 if ((dir = opendir(path)) == NULL) {
378 desc = hcc_alloc_descriptor(trans->hc, dir, HC_DESC_DIR);
379 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
388 hc_readdir(struct HostConf *hc, DIR *dir)
390 hctransaction_t trans;
395 if (hc == NULL || hc->host == NULL)
396 return(readdir(dir));
398 trans = hcc_start_command(hc, HC_READDIR);
399 hcc_leaf_int32(trans, LC_DESCRIPTOR, (int)dir);
400 if ((head = hcc_finish_command(trans)) == NULL)
403 return(NULL); /* XXX errno */
404 den = hcc_get_descriptor(hc, (int)dir, HC_DESC_DIR);
406 return(NULL); /* XXX errno */
409 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
410 switch(item->leafid) {
412 snprintf(den->d_name, sizeof(den->d_name), "%s", HCC_STRING(item));
415 den->d_fileno = HCC_INT64(item);
418 den->d_type = HCC_INT32(item);
422 if (den->d_name[0]) {
423 #ifdef _DIRENT_HAVE_D_NAMLEN
424 den->d_namlen = strlen(den->d_name);
428 return(NULL); /* XXX errno */
432 rc_readdir(hctransaction_t trans, struct HCHead *head)
438 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
439 switch(item->leafid) {
441 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
447 if ((den = readdir(dir)) != NULL) {
448 hcc_leaf_string(trans, LC_PATH1, den->d_name);
449 hcc_leaf_int64(trans, LC_INO, den->d_fileno);
450 hcc_leaf_int32(trans, LC_TYPE, den->d_type);
458 * XXX cpdup needs to check error code to avoid truncated dirs?
461 hc_closedir(struct HostConf *hc, DIR *dir)
463 hctransaction_t trans;
467 if (hc == NULL || hc->host == NULL)
468 return(closedir(dir));
469 den = hcc_get_descriptor(hc, (int)dir, HC_DESC_DIR);
472 hcc_set_descriptor(hc, (int)dir, NULL, HC_DESC_DIR);
474 trans = hcc_start_command(hc, HC_CLOSEDIR);
475 hcc_leaf_int32(trans, LC_DESCRIPTOR, (int)dir);
476 if ((head = hcc_finish_command(trans)) == NULL)
479 return(-1); /* XXX errno */
488 rc_closedir(hctransaction_t trans, struct HCHead *head)
493 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
494 switch(item->leafid) {
496 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
498 hcc_set_descriptor(trans->hc, HCC_INT32(item), NULL, HC_DESC_DIR);
504 return(closedir(dir));
511 hc_open(struct HostConf *hc, const char *path, int flags, mode_t mode)
513 hctransaction_t trans;
520 if (hc == NULL || hc->host == NULL) {
522 flags |= O_LARGEFILE;
524 return(open(path, flags, mode));
527 nflags = flags & XO_NATIVEMASK;
535 trans = hcc_start_command(hc, HC_OPEN);
536 hcc_leaf_string(trans, LC_PATH1, path);
537 hcc_leaf_int32(trans, LC_OFLAGS, nflags);
538 hcc_leaf_int32(trans, LC_MODE, mode);
540 if ((head = hcc_finish_command(trans)) == NULL)
544 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
545 switch(item->leafid) {
547 desc = HCC_INT32(item);
551 if (hcc_get_descriptor(hc, desc, HC_DESC_FD)) {
552 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n",
556 fdp = malloc(sizeof(int));
557 *fdp = desc; /* really just a dummy */
558 hcc_set_descriptor(hc, desc, fdp, HC_DESC_FD);
563 rc_open(hctransaction_t trans, struct HCHead *head)
566 const char *path = NULL;
574 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
575 switch(item->leafid) {
577 path = HCC_STRING(item);
580 nflags = HCC_INT32(item);
583 mode = HCC_INT32(item);
590 flags = nflags & XO_NATIVEMASK;
591 if (nflags & XO_CREAT)
593 if (nflags & XO_EXCL)
595 if (nflags & XO_TRUNC)
599 flags |= O_LARGEFILE;
601 if ((fd = open(path, flags, mode)) < 0) {
605 fdp = malloc(sizeof(int));
607 desc = hcc_alloc_descriptor(trans->hc, fdp, HC_DESC_FD);
608 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
616 hc_close(struct HostConf *hc, int fd)
618 hctransaction_t trans;
622 if (hc == NULL || hc->host == NULL)
625 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
628 hcc_set_descriptor(hc, fd, NULL, HC_DESC_FD);
630 trans = hcc_start_command(hc, HC_CLOSE);
631 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
632 if ((head = hcc_finish_command(trans)) == NULL)
643 rc_close(hctransaction_t trans, struct HCHead *head)
650 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
651 switch(item->leafid) {
653 desc = HCC_INT32(item);
659 if ((fdp = hcc_get_descriptor(trans->hc, desc, HC_DESC_FD)) == NULL)
663 hcc_set_descriptor(trans->hc, desc, NULL, HC_DESC_FD);
687 hc_read(struct HostConf *hc, int fd, void *buf, size_t bytes)
689 hctransaction_t trans;
695 if (hc == NULL || hc->host == NULL)
696 return(read(fd, buf, bytes));
698 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
702 size_t limit = getiolimit();
703 int n = (bytes > limit) ? limit : bytes;
706 trans = hcc_start_command(hc, HC_READ);
707 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
708 hcc_leaf_int32(trans, LC_BYTES, n);
709 if ((head = hcc_finish_command(trans)) == NULL)
713 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
714 switch(item->leafid) {
716 x = item->bytes - sizeof(*item);
719 bcopy(HCC_BINARYDATA(item), buf, x);
720 buf = (char *)buf + x;
736 rc_read(hctransaction_t trans, struct HCHead *head)
744 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
745 switch(item->leafid) {
747 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
750 bytes = HCC_INT32(item);
756 if (bytes < 0 || bytes > 32768)
758 n = read(*fdp, buf, bytes);
763 hcc_leaf_data(trans, LC_DATA, buf, n);
771 hc_write(struct HostConf *hc, int fd, const void *buf, size_t bytes)
773 hctransaction_t trans;
779 if (hc == NULL || hc->host == NULL)
780 return(write(fd, buf, bytes));
782 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
786 size_t limit = getiolimit();
787 int n = (bytes > limit) ? limit : bytes;
790 trans = hcc_start_command(hc, HC_WRITE);
791 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
792 hcc_leaf_data(trans, LC_DATA, buf, n);
793 if ((head = hcc_finish_command(trans)) == NULL)
797 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
798 switch(item->leafid) {
807 buf = (const char *)buf + x;
819 rc_write(hctransaction_t trans, struct HCHead *head)
826 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
827 switch(item->leafid) {
829 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
832 buf = HCC_BINARYDATA(item);
833 n = item->bytes - sizeof(*item);
839 if (n < 0 || n > 32768)
841 n = write(*fdp, buf, n);
845 hcc_leaf_int32(trans, LC_BYTES, n);
854 hc_remove(struct HostConf *hc, const char *path)
856 hctransaction_t trans;
859 if (hc == NULL || hc->host == NULL)
860 return(remove(path));
862 trans = hcc_start_command(hc, HC_REMOVE);
863 hcc_leaf_string(trans, LC_PATH1, path);
864 if ((head = hcc_finish_command(trans)) == NULL)
872 rc_remove(hctransaction_t trans __unused, struct HCHead *head)
875 const char *path = NULL;
877 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
878 switch(item->leafid) {
880 path = HCC_STRING(item);
886 return(remove(path));
893 hc_mkdir(struct HostConf *hc __unused, const char *path, mode_t mode)
895 hctransaction_t trans;
898 if (hc == NULL || hc->host == NULL)
899 return(mkdir(path, mode));
901 trans = hcc_start_command(hc, HC_MKDIR);
902 hcc_leaf_string(trans, LC_PATH1, path);
903 hcc_leaf_int32(trans, LC_MODE, mode);
904 if ((head = hcc_finish_command(trans)) == NULL)
912 rc_mkdir(hctransaction_t trans __unused, struct HCHead *head)
915 const char *path = NULL;
918 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
919 switch(item->leafid) {
921 path = HCC_STRING(item);
924 mode = HCC_INT32(item);
930 return(mkdir(path, mode));
937 hc_rmdir(struct HostConf *hc, const char *path)
939 hctransaction_t trans;
942 if (hc == NULL || hc->host == NULL)
945 trans = hcc_start_command(hc, HC_RMDIR);
946 hcc_leaf_string(trans, LC_PATH1, path);
947 if ((head = hcc_finish_command(trans)) == NULL)
955 rc_rmdir(hctransaction_t trans __unused, struct HCHead *head)
958 const char *path = NULL;
960 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
961 switch(item->leafid) {
963 path = HCC_STRING(item);
976 hc_chown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
978 hctransaction_t trans;
981 if (hc == NULL || hc->host == NULL)
982 return(chown(path, owner, group));
984 trans = hcc_start_command(hc, HC_CHOWN);
985 hcc_leaf_string(trans, LC_PATH1, path);
986 hcc_leaf_int32(trans, LC_UID, owner);
987 hcc_leaf_int32(trans, LC_GID, group);
988 if ((head = hcc_finish_command(trans)) == NULL)
996 rc_chown(hctransaction_t trans __unused, struct HCHead *head)
999 const char *path = NULL;
1000 uid_t uid = (uid_t)-1;
1001 gid_t gid = (gid_t)-1;
1003 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1004 switch(item->leafid) {
1006 path = HCC_STRING(item);
1009 uid = HCC_INT32(item);
1012 gid = HCC_INT32(item);
1018 return(chown(path, uid, gid));
1025 hc_lchown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
1027 hctransaction_t trans;
1028 struct HCHead *head;
1030 if (hc == NULL || hc->host == NULL)
1031 return(lchown(path, owner, group));
1033 trans = hcc_start_command(hc, HC_LCHOWN);
1034 hcc_leaf_string(trans, LC_PATH1, path);
1035 hcc_leaf_int32(trans, LC_UID, owner);
1036 hcc_leaf_int32(trans, LC_GID, group);
1037 if ((head = hcc_finish_command(trans)) == NULL)
1045 rc_lchown(hctransaction_t trans __unused, struct HCHead *head)
1047 struct HCLeaf *item;
1048 const char *path = NULL;
1049 uid_t uid = (uid_t)-1;
1050 gid_t gid = (gid_t)-1;
1052 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1053 switch(item->leafid) {
1055 path = HCC_STRING(item);
1058 uid = HCC_INT32(item);
1061 gid = HCC_INT32(item);
1067 return(lchown(path, uid, gid));
1074 hc_chmod(struct HostConf *hc, const char *path, mode_t mode)
1076 hctransaction_t trans;
1077 struct HCHead *head;
1079 if (hc == NULL || hc->host == NULL)
1080 return(chmod(path, mode));
1082 trans = hcc_start_command(hc, HC_CHMOD);
1083 hcc_leaf_string(trans, LC_PATH1, path);
1084 hcc_leaf_int32(trans, LC_MODE, mode);
1085 if ((head = hcc_finish_command(trans)) == NULL)
1093 rc_chmod(hctransaction_t trans __unused, struct HCHead *head)
1095 struct HCLeaf *item;
1096 const char *path = NULL;
1099 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1100 switch(item->leafid) {
1102 path = HCC_STRING(item);
1105 mode = HCC_INT32(item);
1111 return(chmod(path, mode));
1118 hc_mknod(struct HostConf *hc, const char *path, mode_t mode, dev_t rdev)
1120 hctransaction_t trans;
1121 struct HCHead *head;
1123 if (hc == NULL || hc->host == NULL)
1124 return(mknod(path, mode, rdev));
1126 trans = hcc_start_command(hc, HC_MKNOD);
1127 hcc_leaf_string(trans, LC_PATH1, path);
1128 hcc_leaf_int32(trans, LC_MODE, mode);
1129 hcc_leaf_int32(trans, LC_RDEV, rdev);
1130 if ((head = hcc_finish_command(trans)) == NULL)
1138 rc_mknod(hctransaction_t trans __unused, struct HCHead *head)
1140 struct HCLeaf *item;
1141 const char *path = NULL;
1145 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1146 switch(item->leafid) {
1148 path = HCC_STRING(item);
1151 mode = HCC_INT32(item);
1154 rdev = HCC_INT32(item);
1160 return(mknod(path, mode, rdev));
1167 hc_link(struct HostConf *hc, const char *name1, const char *name2)
1169 hctransaction_t trans;
1170 struct HCHead *head;
1172 if (hc == NULL || hc->host == NULL)
1173 return(link(name1, name2));
1175 trans = hcc_start_command(hc, HC_LINK);
1176 hcc_leaf_string(trans, LC_PATH1, name1);
1177 hcc_leaf_string(trans, LC_PATH2, name2);
1178 if ((head = hcc_finish_command(trans)) == NULL)
1186 rc_link(hctransaction_t trans __unused, struct HCHead *head)
1188 struct HCLeaf *item;
1189 const char *name1 = NULL;
1190 const char *name2 = NULL;
1192 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1193 switch(item->leafid) {
1195 name1 = HCC_STRING(item);
1198 name2 = HCC_STRING(item);
1202 if (name1 == NULL || name2 == NULL)
1204 return(link(name1, name2));
1207 #ifdef _ST_FLAGS_PRESENT_
1212 hc_chflags(struct HostConf *hc, const char *path, u_long flags)
1214 hctransaction_t trans;
1215 struct HCHead *head;
1217 if (hc == NULL || hc->host == NULL)
1218 return(chflags(path, flags));
1220 trans = hcc_start_command(hc, HC_CHFLAGS);
1221 hcc_leaf_string(trans, LC_PATH1, path);
1222 hcc_leaf_int64(trans, LC_FILEFLAGS, flags);
1223 if ((head = hcc_finish_command(trans)) == NULL)
1231 rc_chflags(hctransaction_t trans __unused, struct HCHead *head)
1233 struct HCLeaf *item;
1234 const char *path = NULL;
1237 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1238 switch(item->leafid) {
1240 path = HCC_STRING(item);
1243 flags = (u_long)HCC_INT64(item);
1249 return(chflags(path, flags));
1258 hc_readlink(struct HostConf *hc, const char *path, char *buf, int bufsiz)
1260 hctransaction_t trans;
1261 struct HCHead *head;
1262 struct HCLeaf *item;
1265 if (hc == NULL || hc->host == NULL)
1266 return(readlink(path, buf, bufsiz));
1268 trans = hcc_start_command(hc, HC_READLINK);
1269 hcc_leaf_string(trans, LC_PATH1, path);
1270 if ((head = hcc_finish_command(trans)) == NULL)
1276 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1277 switch(item->leafid) {
1279 r = item->bytes - sizeof(*item);
1284 bcopy(HCC_BINARYDATA(item), buf, r);
1292 rc_readlink(hctransaction_t trans, struct HCHead *head)
1294 struct HCLeaf *item;
1295 const char *path = NULL;
1299 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1300 switch(item->leafid) {
1302 path = HCC_STRING(item);
1308 r = readlink(path, buf, sizeof(buf));
1311 hcc_leaf_data(trans, LC_DATA, buf, r);
1319 hc_umask(struct HostConf *hc, mode_t numask)
1321 hctransaction_t trans;
1322 struct HCHead *head;
1323 struct HCLeaf *item;
1325 if (hc == NULL || hc->host == NULL)
1326 return(umask(numask));
1328 trans = hcc_start_command(hc, HC_UMASK);
1329 hcc_leaf_int32(trans, LC_MODE, numask);
1330 if ((head = hcc_finish_command(trans)) == NULL)
1336 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1337 switch(item->leafid) {
1339 numask = HCC_INT32(item);
1347 rc_umask(hctransaction_t trans, struct HCHead *head)
1349 struct HCLeaf *item;
1350 mode_t numask = ~0666;
1352 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1353 switch(item->leafid) {
1355 numask = HCC_INT32(item);
1359 numask = umask(numask);
1360 hcc_leaf_int32(trans, LC_MODE, numask);
1368 hc_symlink(struct HostConf *hc, const char *name1, const char *name2)
1370 hctransaction_t trans;
1371 struct HCHead *head;
1373 if (hc == NULL || hc->host == NULL)
1374 return(symlink(name1, name2));
1376 trans = hcc_start_command(hc, HC_SYMLINK);
1377 hcc_leaf_string(trans, LC_PATH1, name1);
1378 hcc_leaf_string(trans, LC_PATH2, name2);
1379 if ((head = hcc_finish_command(trans)) == NULL)
1387 rc_symlink(hctransaction_t trans __unused, struct HCHead *head)
1389 struct HCLeaf *item;
1390 const char *name1 = NULL;
1391 const char *name2 = NULL;
1393 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1394 switch(item->leafid) {
1396 name1 = HCC_STRING(item);
1399 name2 = HCC_STRING(item);
1403 if (name1 == NULL || name2 == NULL)
1405 return(symlink(name1, name2));
1412 hc_rename(struct HostConf *hc, const char *name1, const char *name2)
1414 hctransaction_t trans;
1415 struct HCHead *head;
1417 if (hc == NULL || hc->host == NULL)
1418 return(rename(name1, name2));
1420 trans = hcc_start_command(hc, HC_RENAME);
1421 hcc_leaf_string(trans, LC_PATH1, name1);
1422 hcc_leaf_string(trans, LC_PATH2, name2);
1423 if ((head = hcc_finish_command(trans)) == NULL)
1431 rc_rename(hctransaction_t trans __unused, struct HCHead *head)
1433 struct HCLeaf *item;
1434 const char *name1 = NULL;
1435 const char *name2 = NULL;
1437 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1438 switch(item->leafid) {
1440 name1 = HCC_STRING(item);
1443 name2 = HCC_STRING(item);
1447 if (name1 == NULL || name2 == NULL)
1449 return(rename(name1, name2));
1456 hc_utimes(struct HostConf *hc, const char *path, const struct timeval *times)
1458 hctransaction_t trans;
1459 struct HCHead *head;
1461 if (hc == NULL || hc->host == NULL)
1462 return(utimes(path, times));
1464 trans = hcc_start_command(hc, HC_UTIMES);
1465 hcc_leaf_string(trans, LC_PATH1, path);
1466 hcc_leaf_int64(trans, LC_ATIME, times[0].tv_sec);
1467 hcc_leaf_int64(trans, LC_MTIME, times[1].tv_sec);
1468 if ((head = hcc_finish_command(trans)) == NULL)
1476 rc_utimes(hctransaction_t trans __unused, struct HCHead *head)
1478 struct HCLeaf *item;
1479 struct timeval times[2];
1482 bzero(times, sizeof(times));
1485 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1486 switch(item->leafid) {
1488 path = HCC_STRING(item);
1491 times[0].tv_sec = HCC_INT64(item);
1494 times[1].tv_sec = HCC_INT64(item);
1500 return(utimes(path, times));