4 * This module implements a simple remote control protocol
6 * $DragonFly: src/bin/cpdup/hcproto.c,v 1.5 2008/04/16 17:30:56 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);
130 if (hc->version < 2) {
131 fprintf(stderr, "Remote cpdup at %s has an incompatible version\n",
136 fprintf(stderr, "Handshake failed with %s\n", hc->host);
141 rc_hello(hctransaction_t trans, struct HCHead *head __unused)
145 bzero(hostbuf, sizeof(hostbuf));
146 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
151 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
152 hcc_leaf_int32(trans, LC_VERSION, 1);
160 hc_stat(struct HostConf *hc, const char *path, struct stat *st)
163 hctransaction_t trans;
165 if (hc == NULL || hc->host == NULL)
166 return(stat(path, st));
168 trans = hcc_start_command(hc, HC_STAT);
169 hcc_leaf_string(trans, LC_PATH1, path);
170 if ((head = hcc_finish_command(trans)) == NULL)
174 return(hc_decode_stat(st, head));
178 hc_lstat(struct HostConf *hc, const char *path, struct stat *st)
181 hctransaction_t trans;
183 if (hc == NULL || hc->host == NULL)
184 return(lstat(path, st));
186 trans = hcc_start_command(hc, HC_LSTAT);
187 hcc_leaf_string(trans, LC_PATH1, path);
188 if ((head = hcc_finish_command(trans)) == NULL)
192 return(hc_decode_stat(st, head));
196 hc_decode_stat(struct stat *st, struct HCHead *head)
200 bzero(st, sizeof(*st));
201 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
202 switch(item->leafid) {
204 st->st_dev = HCC_INT32(item);
207 st->st_ino = HCC_INT64(item);
210 st->st_mode = HCC_INT32(item);
213 st->st_nlink = HCC_INT32(item);
216 st->st_uid = HCC_INT32(item);
219 st->st_gid = HCC_INT32(item);
222 st->st_rdev = HCC_INT32(item);
225 st->st_atime = (time_t)HCC_INT64(item);
228 st->st_mtime = (time_t)HCC_INT64(item);
231 st->st_ctime = (time_t)HCC_INT64(item);
234 st->st_size = HCC_INT64(item);
237 st->st_blocks = HCC_INT64(item);
240 st->st_blksize = HCC_INT32(item);
242 #ifdef _ST_FSMID_PRESENT_
244 st->st_fsmid = HCC_INT64(item);
247 #ifdef _ST_FLAGS_PRESENT_
249 st->st_flags = (u_int32_t)HCC_INT64(item);
258 rc_stat(hctransaction_t trans, struct HCHead *head)
262 const char *path = NULL;
264 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
265 switch(item->leafid) {
267 path = HCC_STRING(item);
273 if (stat(path, &st) < 0)
275 return (rc_encode_stat(trans, &st));
279 rc_lstat(hctransaction_t trans, struct HCHead *head)
283 const char *path = NULL;
285 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
286 switch(item->leafid) {
288 path = HCC_STRING(item);
294 if (lstat(path, &st) < 0)
296 return (rc_encode_stat(trans, &st));
300 rc_encode_stat(hctransaction_t trans, struct stat *st)
302 hcc_leaf_int32(trans, LC_DEV, st->st_dev);
303 hcc_leaf_int64(trans, LC_INO, st->st_ino);
304 hcc_leaf_int32(trans, LC_MODE, st->st_mode);
305 hcc_leaf_int32(trans, LC_NLINK, st->st_nlink);
306 hcc_leaf_int32(trans, LC_UID, st->st_uid);
307 hcc_leaf_int32(trans, LC_GID, st->st_gid);
308 hcc_leaf_int32(trans, LC_RDEV, st->st_rdev);
309 hcc_leaf_int64(trans, LC_ATIME, st->st_atime);
310 hcc_leaf_int64(trans, LC_MTIME, st->st_mtime);
311 hcc_leaf_int64(trans, LC_CTIME, st->st_ctime);
312 hcc_leaf_int64(trans, LC_FILESIZE, st->st_size);
313 hcc_leaf_int64(trans, LC_FILEBLKS, st->st_blocks);
314 hcc_leaf_int32(trans, LC_BLKSIZE, st->st_blksize);
315 #ifdef _ST_FSMID_PRESENT_
316 hcc_leaf_int64(trans, LC_FSMID, st->st_fsmid);
318 #ifdef _ST_FLAGS_PRESENT_
319 hcc_leaf_int64(trans, LC_FILEFLAGS, st->st_flags);
328 hc_opendir(struct HostConf *hc, const char *path)
330 hctransaction_t trans;
336 if (hc == NULL || hc->host == NULL)
337 return(opendir(path));
339 trans = hcc_start_command(hc, HC_OPENDIR);
340 hcc_leaf_string(trans, LC_PATH1, path);
341 if ((head = hcc_finish_command(trans)) == NULL)
345 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
346 switch(item->leafid) {
348 desc = HCC_INT32(item);
352 if (hcc_get_descriptor(hc, desc, HC_DESC_DIR)) {
353 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n",
357 den = malloc(sizeof(*den));
358 bzero(den, sizeof(*den));
359 hcc_set_descriptor(hc, desc, den, HC_DESC_DIR);
360 return((void *)desc);
364 rc_opendir(hctransaction_t trans, struct HCHead *head)
367 const char *path = NULL;
371 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
372 switch(item->leafid) {
374 path = HCC_STRING(item);
380 if ((dir = opendir(path)) == NULL) {
383 desc = hcc_alloc_descriptor(trans->hc, dir, HC_DESC_DIR);
384 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
393 hc_readdir(struct HostConf *hc, DIR *dir)
395 hctransaction_t trans;
400 if (hc == NULL || hc->host == NULL)
401 return(readdir(dir));
403 trans = hcc_start_command(hc, HC_READDIR);
404 hcc_leaf_int32(trans, LC_DESCRIPTOR, (int)dir);
405 if ((head = hcc_finish_command(trans)) == NULL)
408 return(NULL); /* XXX errno */
409 den = hcc_get_descriptor(hc, (int)dir, HC_DESC_DIR);
411 return(NULL); /* XXX errno */
414 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
415 switch(item->leafid) {
417 snprintf(den->d_name, sizeof(den->d_name), "%s", HCC_STRING(item));
420 den->d_fileno = HCC_INT64(item);
423 den->d_type = HCC_INT32(item);
427 if (den->d_name[0]) {
428 #ifdef _DIRENT_HAVE_D_NAMLEN
429 den->d_namlen = strlen(den->d_name);
433 return(NULL); /* XXX errno */
437 rc_readdir(hctransaction_t trans, struct HCHead *head)
443 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
444 switch(item->leafid) {
446 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
452 if ((den = readdir(dir)) != NULL) {
453 hcc_leaf_string(trans, LC_PATH1, den->d_name);
454 hcc_leaf_int64(trans, LC_INO, den->d_fileno);
455 hcc_leaf_int32(trans, LC_TYPE, den->d_type);
463 * XXX cpdup needs to check error code to avoid truncated dirs?
466 hc_closedir(struct HostConf *hc, DIR *dir)
468 hctransaction_t trans;
472 if (hc == NULL || hc->host == NULL)
473 return(closedir(dir));
474 den = hcc_get_descriptor(hc, (int)dir, HC_DESC_DIR);
477 hcc_set_descriptor(hc, (int)dir, NULL, HC_DESC_DIR);
479 trans = hcc_start_command(hc, HC_CLOSEDIR);
480 hcc_leaf_int32(trans, LC_DESCRIPTOR, (int)dir);
481 if ((head = hcc_finish_command(trans)) == NULL)
484 return(-1); /* XXX errno */
493 rc_closedir(hctransaction_t trans, struct HCHead *head)
498 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
499 switch(item->leafid) {
501 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
503 hcc_set_descriptor(trans->hc, HCC_INT32(item), NULL, HC_DESC_DIR);
509 return(closedir(dir));
516 hc_open(struct HostConf *hc, const char *path, int flags, mode_t mode)
518 hctransaction_t trans;
525 if (hc == NULL || hc->host == NULL) {
527 flags |= O_LARGEFILE;
529 return(open(path, flags, mode));
532 nflags = flags & XO_NATIVEMASK;
540 trans = hcc_start_command(hc, HC_OPEN);
541 hcc_leaf_string(trans, LC_PATH1, path);
542 hcc_leaf_int32(trans, LC_OFLAGS, nflags);
543 hcc_leaf_int32(trans, LC_MODE, mode);
545 if ((head = hcc_finish_command(trans)) == NULL)
549 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
550 switch(item->leafid) {
552 desc = HCC_INT32(item);
556 if (hcc_get_descriptor(hc, desc, HC_DESC_FD)) {
557 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n",
561 fdp = malloc(sizeof(int));
562 *fdp = desc; /* really just a dummy */
563 hcc_set_descriptor(hc, desc, fdp, HC_DESC_FD);
568 rc_open(hctransaction_t trans, struct HCHead *head)
571 const char *path = NULL;
579 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
580 switch(item->leafid) {
582 path = HCC_STRING(item);
585 nflags = HCC_INT32(item);
588 mode = HCC_INT32(item);
595 flags = nflags & XO_NATIVEMASK;
596 if (nflags & XO_CREAT)
598 if (nflags & XO_EXCL)
600 if (nflags & XO_TRUNC)
604 flags |= O_LARGEFILE;
606 if ((fd = open(path, flags, mode)) < 0) {
610 fdp = malloc(sizeof(int));
612 desc = hcc_alloc_descriptor(trans->hc, fdp, HC_DESC_FD);
613 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
621 hc_close(struct HostConf *hc, int fd)
623 hctransaction_t trans;
627 if (hc == NULL || hc->host == NULL)
630 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
633 hcc_set_descriptor(hc, fd, NULL, HC_DESC_FD);
635 trans = hcc_start_command(hc, HC_CLOSE);
636 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
637 if ((head = hcc_finish_command(trans)) == NULL)
648 rc_close(hctransaction_t trans, struct HCHead *head)
655 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
656 switch(item->leafid) {
658 desc = HCC_INT32(item);
664 if ((fdp = hcc_get_descriptor(trans->hc, desc, HC_DESC_FD)) == NULL)
668 hcc_set_descriptor(trans->hc, desc, NULL, HC_DESC_FD);
692 hc_read(struct HostConf *hc, int fd, void *buf, size_t bytes)
694 hctransaction_t trans;
700 if (hc == NULL || hc->host == NULL)
701 return(read(fd, buf, bytes));
703 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
707 size_t limit = getiolimit();
708 int n = (bytes > limit) ? limit : bytes;
711 trans = hcc_start_command(hc, HC_READ);
712 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
713 hcc_leaf_int32(trans, LC_BYTES, n);
714 if ((head = hcc_finish_command(trans)) == NULL)
718 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
719 switch(item->leafid) {
721 x = item->bytes - sizeof(*item);
724 bcopy(HCC_BINARYDATA(item), buf, x);
725 buf = (char *)buf + x;
741 rc_read(hctransaction_t trans, struct HCHead *head)
749 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
750 switch(item->leafid) {
752 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
755 bytes = HCC_INT32(item);
761 if (bytes < 0 || bytes > 32768)
763 n = read(*fdp, buf, bytes);
768 hcc_leaf_data(trans, LC_DATA, buf, n);
776 hc_write(struct HostConf *hc, int fd, const void *buf, size_t bytes)
778 hctransaction_t trans;
784 if (hc == NULL || hc->host == NULL)
785 return(write(fd, buf, bytes));
787 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
791 size_t limit = getiolimit();
792 int n = (bytes > limit) ? limit : bytes;
795 trans = hcc_start_command(hc, HC_WRITE);
796 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
797 hcc_leaf_data(trans, LC_DATA, buf, n);
798 if ((head = hcc_finish_command(trans)) == NULL)
802 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
803 switch(item->leafid) {
812 buf = (const char *)buf + x;
824 rc_write(hctransaction_t trans, struct HCHead *head)
831 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
832 switch(item->leafid) {
834 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
837 buf = HCC_BINARYDATA(item);
838 n = item->bytes - sizeof(*item);
844 if (n < 0 || n > 32768)
846 n = write(*fdp, buf, n);
850 hcc_leaf_int32(trans, LC_BYTES, n);
859 hc_remove(struct HostConf *hc, const char *path)
861 hctransaction_t trans;
864 if (hc == NULL || hc->host == NULL)
865 return(remove(path));
867 trans = hcc_start_command(hc, HC_REMOVE);
868 hcc_leaf_string(trans, LC_PATH1, path);
869 if ((head = hcc_finish_command(trans)) == NULL)
877 rc_remove(hctransaction_t trans __unused, struct HCHead *head)
880 const char *path = NULL;
882 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
883 switch(item->leafid) {
885 path = HCC_STRING(item);
891 return(remove(path));
898 hc_mkdir(struct HostConf *hc __unused, const char *path, mode_t mode)
900 hctransaction_t trans;
903 if (hc == NULL || hc->host == NULL)
904 return(mkdir(path, mode));
906 trans = hcc_start_command(hc, HC_MKDIR);
907 hcc_leaf_string(trans, LC_PATH1, path);
908 hcc_leaf_int32(trans, LC_MODE, mode);
909 if ((head = hcc_finish_command(trans)) == NULL)
917 rc_mkdir(hctransaction_t trans __unused, struct HCHead *head)
920 const char *path = NULL;
923 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
924 switch(item->leafid) {
926 path = HCC_STRING(item);
929 mode = HCC_INT32(item);
935 return(mkdir(path, mode));
942 hc_rmdir(struct HostConf *hc, const char *path)
944 hctransaction_t trans;
947 if (hc == NULL || hc->host == NULL)
950 trans = hcc_start_command(hc, HC_RMDIR);
951 hcc_leaf_string(trans, LC_PATH1, path);
952 if ((head = hcc_finish_command(trans)) == NULL)
960 rc_rmdir(hctransaction_t trans __unused, struct HCHead *head)
963 const char *path = NULL;
965 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
966 switch(item->leafid) {
968 path = HCC_STRING(item);
981 hc_chown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
983 hctransaction_t trans;
986 if (hc == NULL || hc->host == NULL)
987 return(chown(path, owner, group));
989 trans = hcc_start_command(hc, HC_CHOWN);
990 hcc_leaf_string(trans, LC_PATH1, path);
991 hcc_leaf_int32(trans, LC_UID, owner);
992 hcc_leaf_int32(trans, LC_GID, group);
993 if ((head = hcc_finish_command(trans)) == NULL)
1001 rc_chown(hctransaction_t trans __unused, struct HCHead *head)
1003 struct HCLeaf *item;
1004 const char *path = NULL;
1005 uid_t uid = (uid_t)-1;
1006 gid_t gid = (gid_t)-1;
1008 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1009 switch(item->leafid) {
1011 path = HCC_STRING(item);
1014 uid = HCC_INT32(item);
1017 gid = HCC_INT32(item);
1023 return(chown(path, uid, gid));
1030 hc_lchown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
1032 hctransaction_t trans;
1033 struct HCHead *head;
1035 if (hc == NULL || hc->host == NULL)
1036 return(lchown(path, owner, group));
1038 trans = hcc_start_command(hc, HC_LCHOWN);
1039 hcc_leaf_string(trans, LC_PATH1, path);
1040 hcc_leaf_int32(trans, LC_UID, owner);
1041 hcc_leaf_int32(trans, LC_GID, group);
1042 if ((head = hcc_finish_command(trans)) == NULL)
1050 rc_lchown(hctransaction_t trans __unused, struct HCHead *head)
1052 struct HCLeaf *item;
1053 const char *path = NULL;
1054 uid_t uid = (uid_t)-1;
1055 gid_t gid = (gid_t)-1;
1057 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1058 switch(item->leafid) {
1060 path = HCC_STRING(item);
1063 uid = HCC_INT32(item);
1066 gid = HCC_INT32(item);
1072 return(lchown(path, uid, gid));
1079 hc_chmod(struct HostConf *hc, const char *path, mode_t mode)
1081 hctransaction_t trans;
1082 struct HCHead *head;
1084 if (hc == NULL || hc->host == NULL)
1085 return(chmod(path, mode));
1087 trans = hcc_start_command(hc, HC_CHMOD);
1088 hcc_leaf_string(trans, LC_PATH1, path);
1089 hcc_leaf_int32(trans, LC_MODE, mode);
1090 if ((head = hcc_finish_command(trans)) == NULL)
1098 rc_chmod(hctransaction_t trans __unused, struct HCHead *head)
1100 struct HCLeaf *item;
1101 const char *path = NULL;
1104 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1105 switch(item->leafid) {
1107 path = HCC_STRING(item);
1110 mode = HCC_INT32(item);
1116 return(chmod(path, mode));
1123 hc_mknod(struct HostConf *hc, const char *path, mode_t mode, dev_t rdev)
1125 hctransaction_t trans;
1126 struct HCHead *head;
1128 if (hc == NULL || hc->host == NULL)
1129 return(mknod(path, mode, rdev));
1131 trans = hcc_start_command(hc, HC_MKNOD);
1132 hcc_leaf_string(trans, LC_PATH1, path);
1133 hcc_leaf_int32(trans, LC_MODE, mode);
1134 hcc_leaf_int32(trans, LC_RDEV, rdev);
1135 if ((head = hcc_finish_command(trans)) == NULL)
1143 rc_mknod(hctransaction_t trans __unused, struct HCHead *head)
1145 struct HCLeaf *item;
1146 const char *path = NULL;
1150 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1151 switch(item->leafid) {
1153 path = HCC_STRING(item);
1156 mode = HCC_INT32(item);
1159 rdev = HCC_INT32(item);
1165 return(mknod(path, mode, rdev));
1172 hc_link(struct HostConf *hc, const char *name1, const char *name2)
1174 hctransaction_t trans;
1175 struct HCHead *head;
1177 if (hc == NULL || hc->host == NULL)
1178 return(link(name1, name2));
1180 trans = hcc_start_command(hc, HC_LINK);
1181 hcc_leaf_string(trans, LC_PATH1, name1);
1182 hcc_leaf_string(trans, LC_PATH2, name2);
1183 if ((head = hcc_finish_command(trans)) == NULL)
1191 rc_link(hctransaction_t trans __unused, struct HCHead *head)
1193 struct HCLeaf *item;
1194 const char *name1 = NULL;
1195 const char *name2 = NULL;
1197 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1198 switch(item->leafid) {
1200 name1 = HCC_STRING(item);
1203 name2 = HCC_STRING(item);
1207 if (name1 == NULL || name2 == NULL)
1209 return(link(name1, name2));
1212 #ifdef _ST_FLAGS_PRESENT_
1217 hc_chflags(struct HostConf *hc, const char *path, u_long flags)
1219 hctransaction_t trans;
1220 struct HCHead *head;
1222 if (hc == NULL || hc->host == NULL)
1223 return(chflags(path, flags));
1225 trans = hcc_start_command(hc, HC_CHFLAGS);
1226 hcc_leaf_string(trans, LC_PATH1, path);
1227 hcc_leaf_int64(trans, LC_FILEFLAGS, flags);
1228 if ((head = hcc_finish_command(trans)) == NULL)
1236 rc_chflags(hctransaction_t trans __unused, struct HCHead *head)
1238 struct HCLeaf *item;
1239 const char *path = NULL;
1242 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1243 switch(item->leafid) {
1245 path = HCC_STRING(item);
1248 flags = (u_long)HCC_INT64(item);
1254 return(chflags(path, flags));
1263 hc_readlink(struct HostConf *hc, const char *path, char *buf, int bufsiz)
1265 hctransaction_t trans;
1266 struct HCHead *head;
1267 struct HCLeaf *item;
1270 if (hc == NULL || hc->host == NULL)
1271 return(readlink(path, buf, bufsiz));
1273 trans = hcc_start_command(hc, HC_READLINK);
1274 hcc_leaf_string(trans, LC_PATH1, path);
1275 if ((head = hcc_finish_command(trans)) == NULL)
1281 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1282 switch(item->leafid) {
1284 r = item->bytes - sizeof(*item);
1289 bcopy(HCC_BINARYDATA(item), buf, r);
1297 rc_readlink(hctransaction_t trans, struct HCHead *head)
1299 struct HCLeaf *item;
1300 const char *path = NULL;
1304 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1305 switch(item->leafid) {
1307 path = HCC_STRING(item);
1313 r = readlink(path, buf, sizeof(buf));
1316 hcc_leaf_data(trans, LC_DATA, buf, r);
1324 hc_umask(struct HostConf *hc, mode_t numask)
1326 hctransaction_t trans;
1327 struct HCHead *head;
1328 struct HCLeaf *item;
1330 if (hc == NULL || hc->host == NULL)
1331 return(umask(numask));
1333 trans = hcc_start_command(hc, HC_UMASK);
1334 hcc_leaf_int32(trans, LC_MODE, numask);
1335 if ((head = hcc_finish_command(trans)) == NULL)
1341 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1342 switch(item->leafid) {
1344 numask = HCC_INT32(item);
1352 rc_umask(hctransaction_t trans, struct HCHead *head)
1354 struct HCLeaf *item;
1355 mode_t numask = ~0666;
1357 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1358 switch(item->leafid) {
1360 numask = HCC_INT32(item);
1364 numask = umask(numask);
1365 hcc_leaf_int32(trans, LC_MODE, numask);
1373 hc_symlink(struct HostConf *hc, const char *name1, const char *name2)
1375 hctransaction_t trans;
1376 struct HCHead *head;
1378 if (hc == NULL || hc->host == NULL)
1379 return(symlink(name1, name2));
1381 trans = hcc_start_command(hc, HC_SYMLINK);
1382 hcc_leaf_string(trans, LC_PATH1, name1);
1383 hcc_leaf_string(trans, LC_PATH2, name2);
1384 if ((head = hcc_finish_command(trans)) == NULL)
1392 rc_symlink(hctransaction_t trans __unused, struct HCHead *head)
1394 struct HCLeaf *item;
1395 const char *name1 = NULL;
1396 const char *name2 = NULL;
1398 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1399 switch(item->leafid) {
1401 name1 = HCC_STRING(item);
1404 name2 = HCC_STRING(item);
1408 if (name1 == NULL || name2 == NULL)
1410 return(symlink(name1, name2));
1417 hc_rename(struct HostConf *hc, const char *name1, const char *name2)
1419 hctransaction_t trans;
1420 struct HCHead *head;
1422 if (hc == NULL || hc->host == NULL)
1423 return(rename(name1, name2));
1425 trans = hcc_start_command(hc, HC_RENAME);
1426 hcc_leaf_string(trans, LC_PATH1, name1);
1427 hcc_leaf_string(trans, LC_PATH2, name2);
1428 if ((head = hcc_finish_command(trans)) == NULL)
1436 rc_rename(hctransaction_t trans __unused, struct HCHead *head)
1438 struct HCLeaf *item;
1439 const char *name1 = NULL;
1440 const char *name2 = NULL;
1442 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1443 switch(item->leafid) {
1445 name1 = HCC_STRING(item);
1448 name2 = HCC_STRING(item);
1452 if (name1 == NULL || name2 == NULL)
1454 return(rename(name1, name2));
1461 hc_utimes(struct HostConf *hc, const char *path, const struct timeval *times)
1463 hctransaction_t trans;
1464 struct HCHead *head;
1466 if (hc == NULL || hc->host == NULL)
1467 return(utimes(path, times));
1469 trans = hcc_start_command(hc, HC_UTIMES);
1470 hcc_leaf_string(trans, LC_PATH1, path);
1471 hcc_leaf_int64(trans, LC_ATIME, times[0].tv_sec);
1472 hcc_leaf_int64(trans, LC_MTIME, times[1].tv_sec);
1473 if ((head = hcc_finish_command(trans)) == NULL)
1481 rc_utimes(hctransaction_t trans __unused, struct HCHead *head)
1483 struct HCLeaf *item;
1484 struct timeval times[2];
1487 bzero(times, sizeof(times));
1490 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1491 switch(item->leafid) {
1493 path = HCC_STRING(item);
1496 times[0].tv_sec = HCC_INT64(item);
1499 times[1].tv_sec = HCC_INT64(item);
1505 return(utimes(path, times));