4 * This module implements a simple remote control protocol
6 * $DragonFly: src/bin/cpdup/hcproto.c,v 1.3 2008/04/11 07:31:05 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_link(hctransaction_t trans, struct HCHead *);
33 #ifdef _ST_FLAGS_PRESENT_
34 static int rc_chflags(hctransaction_t trans, struct HCHead *);
36 static int rc_readlink(hctransaction_t trans, struct HCHead *);
37 static int rc_umask(hctransaction_t trans, struct HCHead *);
38 static int rc_symlink(hctransaction_t trans, struct HCHead *);
39 static int rc_rename(hctransaction_t trans, struct HCHead *);
40 static int rc_utimes(hctransaction_t trans, struct HCHead *);
42 struct HCDesc HCDispatchTable[] = {
43 { HC_HELLO, rc_hello },
45 { HC_LSTAT, rc_lstat },
46 { HC_OPENDIR, rc_opendir },
47 { HC_READDIR, rc_readdir },
48 { HC_CLOSEDIR, rc_closedir },
50 { HC_CLOSE, rc_close },
52 { HC_WRITE, rc_write },
53 { HC_REMOVE, rc_remove },
54 { HC_MKDIR, rc_mkdir },
55 { HC_RMDIR, rc_rmdir },
56 { HC_CHOWN, rc_chown },
57 { HC_LCHOWN, rc_lchown },
58 { HC_CHMOD, rc_chmod },
60 #ifdef _ST_FLAGS_PRESENT_
61 { HC_CHFLAGS, rc_chflags },
63 { HC_READLINK, rc_readlink },
64 { HC_UMASK, rc_umask },
65 { HC_SYMLINK, rc_symlink },
66 { HC_RENAME, rc_rename },
67 { HC_UTIMES, rc_utimes },
71 hc_connect(struct HostConf *hc)
73 if (hcc_connect(hc) < 0)
79 hc_slave(int fdin, int fdout)
81 hcc_slave(fdin, fdout, HCDispatchTable,
82 sizeof(HCDispatchTable) / sizeof(HCDispatchTable[0]));
87 * A HELLO RPC is sent on the initial connect.
90 hc_hello(struct HostConf *hc)
94 hctransaction_t trans;
98 bzero(hostbuf, sizeof(hostbuf));
99 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
104 trans = hcc_start_command(hc, HC_HELLO);
105 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
106 hcc_leaf_int32(trans, LC_VERSION, 1);
107 if ((head = hcc_finish_command(trans)) == NULL)
111 fprintf(stderr, "Connected to %s but remote returned error %d\n",
112 hc->host, head->error);
117 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
118 switch(item->leafid) {
120 fprintf(stderr, "Handshaked with %s\n", HCC_STRING(item));
124 hc->version = HCC_INT32(item);
129 fprintf(stderr, "Handshake failed with %s\n", hc->host);
134 rc_hello(hctransaction_t trans, struct HCHead *head __unused)
138 bzero(hostbuf, sizeof(hostbuf));
139 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
144 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
145 hcc_leaf_int32(trans, LC_VERSION, 1);
153 hc_stat(struct HostConf *hc, const char *path, struct stat *st)
156 hctransaction_t trans;
158 if (hc == NULL || hc->host == NULL)
159 return(stat(path, st));
161 trans = hcc_start_command(hc, HC_STAT);
162 hcc_leaf_string(trans, LC_PATH1, path);
163 if ((head = hcc_finish_command(trans)) == NULL)
167 return(hc_decode_stat(st, head));
171 hc_lstat(struct HostConf *hc, const char *path, struct stat *st)
174 hctransaction_t trans;
176 if (hc == NULL || hc->host == NULL)
177 return(lstat(path, st));
179 trans = hcc_start_command(hc, HC_LSTAT);
180 hcc_leaf_string(trans, LC_PATH1, path);
181 if ((head = hcc_finish_command(trans)) == NULL)
185 return(hc_decode_stat(st, head));
189 hc_decode_stat(struct stat *st, struct HCHead *head)
193 bzero(st, sizeof(*st));
194 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
195 switch(item->leafid) {
197 st->st_dev = HCC_INT32(item);
200 st->st_ino = HCC_INT64(item);
203 st->st_mode = HCC_INT32(item);
206 st->st_nlink = HCC_INT32(item);
209 st->st_uid = HCC_INT32(item);
212 st->st_gid = HCC_INT32(item);
215 st->st_rdev = HCC_INT32(item);
218 st->st_atime = (time_t)HCC_INT64(item);
221 st->st_mtime = (time_t)HCC_INT64(item);
224 st->st_ctime = (time_t)HCC_INT64(item);
227 st->st_size = HCC_INT64(item);
230 st->st_blocks = HCC_INT64(item);
233 st->st_blksize = HCC_INT32(item);
235 #ifdef _ST_FSMID_PRESENT_
237 st->st_fsmid = HCC_INT64(item);
240 #ifdef _ST_FLAGS_PRESENT_
242 st->st_flags = (u_int32_t)HCC_INT64(item);
251 rc_stat(hctransaction_t trans, struct HCHead *head)
255 const char *path = NULL;
257 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
258 switch(item->leafid) {
260 path = HCC_STRING(item);
266 if (stat(path, &st) < 0)
268 return (rc_encode_stat(trans, &st));
272 rc_lstat(hctransaction_t trans, struct HCHead *head)
276 const char *path = NULL;
278 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
279 switch(item->leafid) {
281 path = HCC_STRING(item);
287 if (lstat(path, &st) < 0)
289 return (rc_encode_stat(trans, &st));
293 rc_encode_stat(hctransaction_t trans, struct stat *st)
295 hcc_leaf_int32(trans, LC_DEV, st->st_dev);
296 hcc_leaf_int64(trans, LC_INO, st->st_ino);
297 hcc_leaf_int32(trans, LC_MODE, st->st_mode);
298 hcc_leaf_int32(trans, LC_NLINK, st->st_nlink);
299 hcc_leaf_int32(trans, LC_UID, st->st_uid);
300 hcc_leaf_int32(trans, LC_GID, st->st_gid);
301 hcc_leaf_int32(trans, LC_RDEV, st->st_rdev);
302 hcc_leaf_int64(trans, LC_ATIME, st->st_atime);
303 hcc_leaf_int64(trans, LC_MTIME, st->st_mtime);
304 hcc_leaf_int64(trans, LC_CTIME, st->st_ctime);
305 hcc_leaf_int64(trans, LC_FILESIZE, st->st_size);
306 hcc_leaf_int64(trans, LC_FILEBLKS, st->st_blocks);
307 hcc_leaf_int32(trans, LC_BLKSIZE, st->st_blksize);
308 #ifdef _ST_FSMID_PRESENT_
309 hcc_leaf_int64(trans, LC_FSMID, st->st_fsmid);
311 #ifdef _ST_FLAGS_PRESENT_
312 hcc_leaf_int64(trans, LC_FILEFLAGS, st->st_flags);
321 hc_opendir(struct HostConf *hc, const char *path)
323 hctransaction_t trans;
329 if (hc == NULL || hc->host == NULL)
330 return(opendir(path));
332 trans = hcc_start_command(hc, HC_OPENDIR);
333 hcc_leaf_string(trans, LC_PATH1, path);
334 if ((head = hcc_finish_command(trans)) == NULL)
338 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
339 switch(item->leafid) {
341 desc = HCC_INT32(item);
345 if (hcc_get_descriptor(hc, desc, HC_DESC_DIR)) {
346 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n",
350 den = malloc(sizeof(*den));
351 bzero(den, sizeof(*den));
352 hcc_set_descriptor(hc, desc, den, HC_DESC_DIR);
353 return((void *)desc);
357 rc_opendir(hctransaction_t trans, struct HCHead *head)
360 const char *path = NULL;
364 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
365 switch(item->leafid) {
367 path = HCC_STRING(item);
373 if ((dir = opendir(path)) == NULL) {
376 desc = hcc_alloc_descriptor(trans->hc, dir, HC_DESC_DIR);
377 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
386 hc_readdir(struct HostConf *hc, DIR *dir)
388 hctransaction_t trans;
393 if (hc == NULL || hc->host == NULL)
394 return(readdir(dir));
396 trans = hcc_start_command(hc, HC_READDIR);
397 hcc_leaf_int32(trans, LC_DESCRIPTOR, (int)dir);
398 if ((head = hcc_finish_command(trans)) == NULL)
401 return(NULL); /* XXX errno */
402 den = hcc_get_descriptor(hc, (int)dir, HC_DESC_DIR);
404 return(NULL); /* XXX errno */
407 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
408 switch(item->leafid) {
410 snprintf(den->d_name, sizeof(den->d_name), "%s", HCC_STRING(item));
413 den->d_fileno = HCC_INT64(item);
416 den->d_type = HCC_INT32(item);
420 if (den->d_name[0]) {
421 #ifdef _DIRENT_HAVE_D_NAMLEN
422 den->d_namlen = strlen(den->d_name);
426 return(NULL); /* XXX errno */
430 rc_readdir(hctransaction_t trans, struct HCHead *head)
436 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
437 switch(item->leafid) {
439 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
445 if ((den = readdir(dir)) != NULL) {
446 hcc_leaf_string(trans, LC_PATH1, den->d_name);
447 hcc_leaf_int64(trans, LC_INO, den->d_fileno);
448 hcc_leaf_int32(trans, LC_TYPE, den->d_type);
456 * XXX cpdup needs to check error code to avoid truncated dirs?
459 hc_closedir(struct HostConf *hc, DIR *dir)
461 hctransaction_t trans;
465 if (hc == NULL || hc->host == NULL)
466 return(closedir(dir));
467 den = hcc_get_descriptor(hc, (int)dir, HC_DESC_DIR);
470 hcc_set_descriptor(hc, (int)dir, NULL, HC_DESC_DIR);
472 trans = hcc_start_command(hc, HC_CLOSEDIR);
473 hcc_leaf_int32(trans, LC_DESCRIPTOR, (int)dir);
474 if ((head = hcc_finish_command(trans)) == NULL)
477 return(-1); /* XXX errno */
486 rc_closedir(hctransaction_t trans, struct HCHead *head)
491 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
492 switch(item->leafid) {
494 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
500 return(closedir(dir));
507 hc_open(struct HostConf *hc, const char *path, int flags, mode_t mode)
509 hctransaction_t trans;
516 if (hc == NULL || hc->host == NULL) {
518 flags |= O_LARGEFILE;
520 return(open(path, flags, mode));
523 nflags = flags & XO_NATIVEMASK;
531 trans = hcc_start_command(hc, HC_OPEN);
532 hcc_leaf_string(trans, LC_PATH1, path);
533 hcc_leaf_int32(trans, LC_OFLAGS, nflags);
534 hcc_leaf_int32(trans, LC_MODE, mode);
536 if ((head = hcc_finish_command(trans)) == NULL)
540 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
541 switch(item->leafid) {
543 desc = HCC_INT32(item);
547 if (hcc_get_descriptor(hc, desc, HC_DESC_FD)) {
548 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n",
552 fdp = malloc(sizeof(int));
553 *fdp = desc; /* really just a dummy */
554 hcc_set_descriptor(hc, desc, fdp, HC_DESC_FD);
559 rc_open(hctransaction_t trans, struct HCHead *head)
562 const char *path = NULL;
570 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
571 switch(item->leafid) {
573 path = HCC_STRING(item);
576 nflags = HCC_INT32(item);
579 mode = HCC_INT32(item);
586 flags = nflags & XO_NATIVEMASK;
587 if (nflags & XO_CREAT)
589 if (nflags & XO_EXCL)
591 if (nflags & XO_TRUNC)
595 flags |= O_LARGEFILE;
597 if ((fd = open(path, flags, mode)) < 0) {
601 fdp = malloc(sizeof(int));
603 desc = hcc_alloc_descriptor(trans->hc, fdp, HC_DESC_FD);
604 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
612 hc_close(struct HostConf *hc, int fd)
614 hctransaction_t trans;
618 if (hc == NULL || hc->host == NULL)
621 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
624 hcc_set_descriptor(hc, fd, NULL, HC_DESC_FD);
626 trans = hcc_start_command(hc, HC_CLOSE);
627 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
628 if ((head = hcc_finish_command(trans)) == NULL)
639 rc_close(hctransaction_t trans, struct HCHead *head)
646 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
647 switch(item->leafid) {
649 desc = HCC_INT32(item);
655 if ((fdp = hcc_get_descriptor(trans->hc, desc, HC_DESC_FD)) == NULL)
659 hcc_set_descriptor(trans->hc, desc, NULL, HC_DESC_FD);
683 hc_read(struct HostConf *hc, int fd, void *buf, size_t bytes)
685 hctransaction_t trans;
691 if (hc == NULL || hc->host == NULL)
692 return(read(fd, buf, bytes));
694 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
698 size_t limit = getiolimit();
699 int n = (bytes > limit) ? limit : bytes;
702 trans = hcc_start_command(hc, HC_READ);
703 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
704 hcc_leaf_int32(trans, LC_BYTES, n);
705 if ((head = hcc_finish_command(trans)) == NULL)
709 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
710 switch(item->leafid) {
712 x = item->bytes - sizeof(*item);
715 bcopy(HCC_BINARYDATA(item), buf, x);
716 buf = (char *)buf + x;
732 rc_read(hctransaction_t trans, struct HCHead *head)
740 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
741 switch(item->leafid) {
743 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
746 bytes = HCC_INT32(item);
752 if (bytes < 0 || bytes > 32768)
754 n = read(*fdp, buf, bytes);
759 hcc_leaf_data(trans, LC_DATA, buf, n);
767 hc_write(struct HostConf *hc, int fd, const void *buf, size_t bytes)
769 hctransaction_t trans;
775 if (hc == NULL || hc->host == NULL)
776 return(write(fd, buf, bytes));
778 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
782 size_t limit = getiolimit();
783 int n = (bytes > limit) ? limit : bytes;
786 trans = hcc_start_command(hc, HC_WRITE);
787 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
788 hcc_leaf_data(trans, LC_DATA, buf, n);
789 if ((head = hcc_finish_command(trans)) == NULL)
793 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
794 switch(item->leafid) {
803 buf = (const char *)buf + x;
815 rc_write(hctransaction_t trans, struct HCHead *head)
822 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
823 switch(item->leafid) {
825 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
828 buf = HCC_BINARYDATA(item);
829 n = item->bytes - sizeof(*item);
835 if (n < 0 || n > 32768)
837 n = write(*fdp, buf, n);
841 hcc_leaf_int32(trans, LC_BYTES, n);
850 hc_remove(struct HostConf *hc, const char *path)
852 hctransaction_t trans;
855 if (hc == NULL || hc->host == NULL)
856 return(remove(path));
858 trans = hcc_start_command(hc, HC_REMOVE);
859 hcc_leaf_string(trans, LC_PATH1, path);
860 if ((head = hcc_finish_command(trans)) == NULL)
868 rc_remove(hctransaction_t trans __unused, struct HCHead *head)
871 const char *path = NULL;
873 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
874 switch(item->leafid) {
876 path = HCC_STRING(item);
882 return(remove(path));
889 hc_mkdir(struct HostConf *hc __unused, const char *path, mode_t mode)
891 hctransaction_t trans;
894 if (hc == NULL || hc->host == NULL)
895 return(mkdir(path, mode));
897 trans = hcc_start_command(hc, HC_MKDIR);
898 hcc_leaf_string(trans, LC_PATH1, path);
899 hcc_leaf_int32(trans, LC_MODE, mode);
900 if ((head = hcc_finish_command(trans)) == NULL)
908 rc_mkdir(hctransaction_t trans __unused, struct HCHead *head)
911 const char *path = NULL;
914 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
915 switch(item->leafid) {
917 path = HCC_STRING(item);
920 mode = HCC_INT32(item);
926 return(mkdir(path, mode));
933 hc_rmdir(struct HostConf *hc, const char *path)
935 hctransaction_t trans;
938 if (hc == NULL || hc->host == NULL)
941 trans = hcc_start_command(hc, HC_RMDIR);
942 hcc_leaf_string(trans, LC_PATH1, path);
943 if ((head = hcc_finish_command(trans)) == NULL)
951 rc_rmdir(hctransaction_t trans __unused, struct HCHead *head)
954 const char *path = NULL;
956 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
957 switch(item->leafid) {
959 path = HCC_STRING(item);
972 hc_chown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
974 hctransaction_t trans;
977 if (hc == NULL || hc->host == NULL)
978 return(chown(path, owner, group));
980 trans = hcc_start_command(hc, HC_CHOWN);
981 hcc_leaf_string(trans, LC_PATH1, path);
982 hcc_leaf_int32(trans, LC_UID, owner);
983 hcc_leaf_int32(trans, LC_GID, group);
984 if ((head = hcc_finish_command(trans)) == NULL)
992 rc_chown(hctransaction_t trans __unused, struct HCHead *head)
995 const char *path = NULL;
996 uid_t uid = (uid_t)-1;
997 gid_t gid = (gid_t)-1;
999 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1000 switch(item->leafid) {
1002 path = HCC_STRING(item);
1005 uid = HCC_INT32(item);
1008 gid = HCC_INT32(item);
1014 return(chown(path, uid, gid));
1021 hc_lchown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
1023 hctransaction_t trans;
1024 struct HCHead *head;
1026 if (hc == NULL || hc->host == NULL)
1027 return(lchown(path, owner, group));
1029 trans = hcc_start_command(hc, HC_LCHOWN);
1030 hcc_leaf_string(trans, LC_PATH1, path);
1031 hcc_leaf_int32(trans, LC_UID, owner);
1032 hcc_leaf_int32(trans, LC_GID, group);
1033 if ((head = hcc_finish_command(trans)) == NULL)
1041 rc_lchown(hctransaction_t trans __unused, struct HCHead *head)
1043 struct HCLeaf *item;
1044 const char *path = NULL;
1045 uid_t uid = (uid_t)-1;
1046 gid_t gid = (gid_t)-1;
1048 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1049 switch(item->leafid) {
1051 path = HCC_STRING(item);
1054 uid = HCC_INT32(item);
1057 gid = HCC_INT32(item);
1063 return(lchown(path, uid, gid));
1070 hc_chmod(struct HostConf *hc, const char *path, mode_t mode)
1072 hctransaction_t trans;
1073 struct HCHead *head;
1075 if (hc == NULL || hc->host == NULL)
1076 return(chmod(path, mode));
1078 trans = hcc_start_command(hc, HC_CHMOD);
1079 hcc_leaf_string(trans, LC_PATH1, path);
1080 hcc_leaf_int32(trans, LC_MODE, mode);
1081 if ((head = hcc_finish_command(trans)) == NULL)
1089 rc_chmod(hctransaction_t trans __unused, struct HCHead *head)
1091 struct HCLeaf *item;
1092 const char *path = NULL;
1095 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1096 switch(item->leafid) {
1098 path = HCC_STRING(item);
1101 mode = HCC_INT32(item);
1107 return(chmod(path, mode));
1114 hc_link(struct HostConf *hc, const char *name1, const char *name2)
1116 hctransaction_t trans;
1117 struct HCHead *head;
1119 if (hc == NULL || hc->host == NULL)
1120 return(link(name1, name2));
1122 trans = hcc_start_command(hc, HC_LINK);
1123 hcc_leaf_string(trans, LC_PATH1, name1);
1124 hcc_leaf_string(trans, LC_PATH2, name2);
1125 if ((head = hcc_finish_command(trans)) == NULL)
1133 rc_link(hctransaction_t trans __unused, struct HCHead *head)
1135 struct HCLeaf *item;
1136 const char *name1 = NULL;
1137 const char *name2 = NULL;
1139 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1140 switch(item->leafid) {
1142 name1 = HCC_STRING(item);
1145 name2 = HCC_STRING(item);
1149 if (name1 == NULL || name2 == NULL)
1151 return(link(name1, name2));
1154 #ifdef _ST_FLAGS_PRESENT_
1159 hc_chflags(struct HostConf *hc, const char *path, u_long flags)
1161 hctransaction_t trans;
1162 struct HCHead *head;
1164 if (hc == NULL || hc->host == NULL)
1165 return(chflags(path, flags));
1167 trans = hcc_start_command(hc, HC_CHFLAGS);
1168 hcc_leaf_string(trans, LC_PATH1, path);
1169 hcc_leaf_int64(trans, LC_FILEFLAGS, flags);
1170 if ((head = hcc_finish_command(trans)) == NULL)
1178 rc_chflags(hctransaction_t trans __unused, struct HCHead *head)
1180 struct HCLeaf *item;
1181 const char *path = NULL;
1184 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1185 switch(item->leafid) {
1187 path = HCC_STRING(item);
1190 flags = (u_long)HCC_INT64(item);
1196 return(chflags(path, flags));
1205 hc_readlink(struct HostConf *hc, const char *path, char *buf, int bufsiz)
1207 hctransaction_t trans;
1208 struct HCHead *head;
1209 struct HCLeaf *item;
1212 if (hc == NULL || hc->host == NULL)
1213 return(readlink(path, buf, bufsiz));
1215 trans = hcc_start_command(hc, HC_READLINK);
1216 hcc_leaf_string(trans, LC_PATH1, path);
1217 if ((head = hcc_finish_command(trans)) == NULL)
1223 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1224 switch(item->leafid) {
1226 r = item->bytes - sizeof(*item);
1231 bcopy(HCC_BINARYDATA(item), buf, r);
1239 rc_readlink(hctransaction_t trans, struct HCHead *head)
1241 struct HCLeaf *item;
1242 const char *path = NULL;
1246 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1247 switch(item->leafid) {
1249 path = HCC_STRING(item);
1255 r = readlink(path, buf, sizeof(buf));
1258 hcc_leaf_data(trans, LC_DATA, buf, r);
1266 hc_umask(struct HostConf *hc, mode_t numask)
1268 hctransaction_t trans;
1269 struct HCHead *head;
1270 struct HCLeaf *item;
1272 if (hc == NULL || hc->host == NULL)
1273 return(umask(numask));
1275 trans = hcc_start_command(hc, HC_UMASK);
1276 hcc_leaf_int32(trans, LC_MODE, numask);
1277 if ((head = hcc_finish_command(trans)) == NULL)
1283 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1284 switch(item->leafid) {
1286 numask = HCC_INT32(item);
1294 rc_umask(hctransaction_t trans, struct HCHead *head)
1296 struct HCLeaf *item;
1297 mode_t numask = ~0666;
1299 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1300 switch(item->leafid) {
1302 numask = HCC_INT32(item);
1306 numask = umask(numask);
1307 hcc_leaf_int32(trans, LC_MODE, numask);
1315 hc_symlink(struct HostConf *hc, const char *name1, const char *name2)
1317 hctransaction_t trans;
1318 struct HCHead *head;
1320 if (hc == NULL || hc->host == NULL)
1321 return(symlink(name1, name2));
1323 trans = hcc_start_command(hc, HC_SYMLINK);
1324 hcc_leaf_string(trans, LC_PATH1, name1);
1325 hcc_leaf_string(trans, LC_PATH2, name2);
1326 if ((head = hcc_finish_command(trans)) == NULL)
1334 rc_symlink(hctransaction_t trans __unused, struct HCHead *head)
1336 struct HCLeaf *item;
1337 const char *name1 = NULL;
1338 const char *name2 = NULL;
1340 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1341 switch(item->leafid) {
1343 name1 = HCC_STRING(item);
1346 name2 = HCC_STRING(item);
1350 if (name1 == NULL || name2 == NULL)
1352 return(symlink(name1, name2));
1359 hc_rename(struct HostConf *hc, const char *name1, const char *name2)
1361 hctransaction_t trans;
1362 struct HCHead *head;
1364 if (hc == NULL || hc->host == NULL)
1365 return(rename(name1, name2));
1367 trans = hcc_start_command(hc, HC_RENAME);
1368 hcc_leaf_string(trans, LC_PATH1, name1);
1369 hcc_leaf_string(trans, LC_PATH2, name2);
1370 if ((head = hcc_finish_command(trans)) == NULL)
1378 rc_rename(hctransaction_t trans __unused, struct HCHead *head)
1380 struct HCLeaf *item;
1381 const char *name1 = NULL;
1382 const char *name2 = NULL;
1384 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1385 switch(item->leafid) {
1387 name1 = HCC_STRING(item);
1390 name2 = HCC_STRING(item);
1394 if (name1 == NULL || name2 == NULL)
1396 return(rename(name1, name2));
1403 hc_utimes(struct HostConf *hc, const char *path, const struct timeval *times)
1405 hctransaction_t trans;
1406 struct HCHead *head;
1408 if (hc == NULL || hc->host == NULL)
1409 return(utimes(path, times));
1411 trans = hcc_start_command(hc, HC_UTIMES);
1412 hcc_leaf_string(trans, LC_PATH1, path);
1413 hcc_leaf_int64(trans, LC_ATIME, times[0].tv_sec);
1414 hcc_leaf_int64(trans, LC_MTIME, times[1].tv_sec);
1415 if ((head = hcc_finish_command(trans)) == NULL)
1423 rc_utimes(hctransaction_t trans __unused, struct HCHead *head)
1425 struct HCLeaf *item;
1426 struct timeval times[2];
1429 bzero(times, sizeof(times));
1432 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1433 switch(item->leafid) {
1435 path = HCC_STRING(item);
1438 times[0].tv_sec = HCC_INT64(item);
1441 times[1].tv_sec = HCC_INT64(item);
1447 return(utimes(path, times));