4 * This module implements a simple remote control protocol
6 * $DragonFly: src/bin/cpdup/hcproto.c,v 1.8 2008/11/11 04:36:00 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 },
72 static int chown_warning;
73 static int chflags_warning;
76 * If not running as root generate a silent warning and return no error.
78 * If running as root return an error.
81 silentwarning(int *didwarn, const char *ctl, ...)
89 fprintf(stderr, "WARNING: Not running as root, ");
91 vfprintf(stderr, ctl, va);
98 hc_connect(struct HostConf *hc)
100 if (hcc_connect(hc) < 0) {
101 fprintf(stderr, "Unable to connect to %s\n", hc->host);
104 return(hc_hello(hc));
108 hc_slave(int fdin, int fdout)
110 hcc_slave(fdin, fdout, HCDispatchTable,
111 sizeof(HCDispatchTable) / sizeof(HCDispatchTable[0]));
116 * A HELLO RPC is sent on the initial connect.
119 hc_hello(struct HostConf *hc)
123 hctransaction_t trans;
127 bzero(hostbuf, sizeof(hostbuf));
128 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
133 trans = hcc_start_command(hc, HC_HELLO);
134 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
135 hcc_leaf_int32(trans, LC_VERSION, HCPROTO_VERSION);
136 if ((head = hcc_finish_command(trans)) == NULL) {
137 fprintf(stderr, "Connected to %s but remote failed to complete hello\n",
143 fprintf(stderr, "Connected to %s but remote returned error %d\n",
144 hc->host, head->error);
149 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
150 switch(item->leafid) {
152 fprintf(stderr, "Handshaked with %s\n", HCC_STRING(item));
156 hc->version = HCC_INT32(item);
160 if (hc->version < HCPROTO_VERSION_COMPAT) {
161 fprintf(stderr, "Remote cpdup at %s has an incompatible version\n",
166 fprintf(stderr, "Handshake failed with %s\n", hc->host);
171 rc_hello(hctransaction_t trans, struct HCHead *head __unused)
175 bzero(hostbuf, sizeof(hostbuf));
176 if (gethostname(hostbuf, sizeof(hostbuf) - 1) < 0)
181 hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
182 hcc_leaf_int32(trans, LC_VERSION, HCPROTO_VERSION);
190 hc_stat(struct HostConf *hc, const char *path, struct stat *st)
193 hctransaction_t trans;
195 if (hc == NULL || hc->host == NULL)
196 return(stat(path, st));
198 trans = hcc_start_command(hc, HC_STAT);
199 hcc_leaf_string(trans, LC_PATH1, path);
200 if ((head = hcc_finish_command(trans)) == NULL)
204 return(hc_decode_stat(st, head));
208 hc_lstat(struct HostConf *hc, const char *path, struct stat *st)
211 hctransaction_t trans;
213 if (hc == NULL || hc->host == NULL)
214 return(lstat(path, st));
216 trans = hcc_start_command(hc, HC_LSTAT);
217 hcc_leaf_string(trans, LC_PATH1, path);
218 if ((head = hcc_finish_command(trans)) == NULL)
222 return(hc_decode_stat(st, head));
226 hc_decode_stat(struct stat *st, struct HCHead *head)
230 bzero(st, sizeof(*st));
231 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
232 switch(item->leafid) {
234 st->st_dev = HCC_INT32(item);
237 st->st_ino = HCC_INT64(item);
240 st->st_mode = HCC_INT32(item);
243 st->st_nlink = HCC_INT32(item);
246 st->st_uid = HCC_INT32(item);
249 st->st_gid = HCC_INT32(item);
252 st->st_rdev = HCC_INT32(item);
255 st->st_atime = (time_t)HCC_INT64(item);
258 st->st_mtime = (time_t)HCC_INT64(item);
261 st->st_ctime = (time_t)HCC_INT64(item);
264 st->st_size = HCC_INT64(item);
267 st->st_blocks = HCC_INT64(item);
270 st->st_blksize = HCC_INT32(item);
272 #ifdef _ST_FSMID_PRESENT_
274 st->st_fsmid = HCC_INT64(item);
277 #ifdef _ST_FLAGS_PRESENT_
279 st->st_flags = (u_int32_t)HCC_INT64(item);
288 rc_stat(hctransaction_t trans, struct HCHead *head)
292 const char *path = NULL;
294 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
295 switch(item->leafid) {
297 path = HCC_STRING(item);
303 if (stat(path, &st) < 0)
305 return (rc_encode_stat(trans, &st));
309 rc_lstat(hctransaction_t trans, struct HCHead *head)
313 const char *path = NULL;
315 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
316 switch(item->leafid) {
318 path = HCC_STRING(item);
324 if (lstat(path, &st) < 0)
326 return (rc_encode_stat(trans, &st));
330 rc_encode_stat(hctransaction_t trans, struct stat *st)
332 hcc_leaf_int32(trans, LC_DEV, st->st_dev);
333 hcc_leaf_int64(trans, LC_INO, st->st_ino);
334 hcc_leaf_int32(trans, LC_MODE, st->st_mode);
335 hcc_leaf_int32(trans, LC_NLINK, st->st_nlink);
336 hcc_leaf_int32(trans, LC_UID, st->st_uid);
337 hcc_leaf_int32(trans, LC_GID, st->st_gid);
338 hcc_leaf_int32(trans, LC_RDEV, st->st_rdev);
339 hcc_leaf_int64(trans, LC_ATIME, st->st_atime);
340 hcc_leaf_int64(trans, LC_MTIME, st->st_mtime);
341 hcc_leaf_int64(trans, LC_CTIME, st->st_ctime);
342 hcc_leaf_int64(trans, LC_FILESIZE, st->st_size);
343 hcc_leaf_int64(trans, LC_FILEBLKS, st->st_blocks);
344 hcc_leaf_int32(trans, LC_BLKSIZE, st->st_blksize);
345 #ifdef _ST_FSMID_PRESENT_
346 hcc_leaf_int64(trans, LC_FSMID, st->st_fsmid);
348 #ifdef _ST_FLAGS_PRESENT_
349 hcc_leaf_int64(trans, LC_FILEFLAGS, st->st_flags);
358 hc_opendir(struct HostConf *hc, const char *path)
360 hctransaction_t trans;
366 if (hc == NULL || hc->host == NULL)
367 return(opendir(path));
369 trans = hcc_start_command(hc, HC_OPENDIR);
370 hcc_leaf_string(trans, LC_PATH1, path);
371 if ((head = hcc_finish_command(trans)) == NULL)
375 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
376 switch(item->leafid) {
378 desc = HCC_INT32(item);
382 if (hcc_get_descriptor(hc, desc, HC_DESC_DIR)) {
383 fprintf(stderr, "hc_opendir: remote reused active descriptor %jd\n",
387 den = malloc(sizeof(*den));
388 bzero(den, sizeof(*den));
389 hcc_set_descriptor(hc, desc, den, HC_DESC_DIR);
390 return((void *)desc);
394 rc_opendir(hctransaction_t trans, struct HCHead *head)
397 const char *path = NULL;
401 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
402 switch(item->leafid) {
404 path = HCC_STRING(item);
410 if ((dir = opendir(path)) == NULL) {
413 desc = hcc_alloc_descriptor(trans->hc, dir, HC_DESC_DIR);
414 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
423 hc_readdir(struct HostConf *hc, DIR *dir)
425 hctransaction_t trans;
430 if (hc == NULL || hc->host == NULL)
431 return(readdir(dir));
433 trans = hcc_start_command(hc, HC_READDIR);
434 hcc_leaf_int32(trans, LC_DESCRIPTOR, (intptr_t)dir);
435 if ((head = hcc_finish_command(trans)) == NULL)
438 return(NULL); /* XXX errno */
439 den = hcc_get_descriptor(hc, (intptr_t)dir, HC_DESC_DIR);
441 return(NULL); /* XXX errno */
444 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
445 switch(item->leafid) {
447 snprintf(den->d_name, sizeof(den->d_name), "%s", HCC_STRING(item));
450 den->d_fileno = HCC_INT64(item);
453 den->d_type = HCC_INT32(item);
457 if (den->d_name[0]) {
458 #ifdef _DIRENT_HAVE_D_NAMLEN
459 den->d_namlen = strlen(den->d_name);
463 return(NULL); /* XXX errno */
467 rc_readdir(hctransaction_t trans, struct HCHead *head)
473 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
474 switch(item->leafid) {
476 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
482 if ((den = readdir(dir)) != NULL) {
483 hcc_leaf_string(trans, LC_PATH1, den->d_name);
484 hcc_leaf_int64(trans, LC_INO, den->d_fileno);
485 hcc_leaf_int32(trans, LC_TYPE, den->d_type);
493 * XXX cpdup needs to check error code to avoid truncated dirs?
496 hc_closedir(struct HostConf *hc, DIR *dir)
498 hctransaction_t trans;
502 if (hc == NULL || hc->host == NULL)
503 return(closedir(dir));
504 den = hcc_get_descriptor(hc, (intptr_t)dir, HC_DESC_DIR);
507 hcc_set_descriptor(hc, (intptr_t)dir, NULL, HC_DESC_DIR);
509 trans = hcc_start_command(hc, HC_CLOSEDIR);
510 hcc_leaf_int32(trans, LC_DESCRIPTOR, (intptr_t)dir);
511 if ((head = hcc_finish_command(trans)) == NULL)
514 return(-1); /* XXX errno */
523 rc_closedir(hctransaction_t trans, struct HCHead *head)
528 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
529 switch(item->leafid) {
531 dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
533 hcc_set_descriptor(trans->hc, HCC_INT32(item), NULL, HC_DESC_DIR);
539 return(closedir(dir));
546 hc_open(struct HostConf *hc, const char *path, int flags, mode_t mode)
548 hctransaction_t trans;
555 if (hc == NULL || hc->host == NULL) {
557 flags |= O_LARGEFILE;
559 return(open(path, flags, mode));
562 nflags = flags & XO_NATIVEMASK;
570 trans = hcc_start_command(hc, HC_OPEN);
571 hcc_leaf_string(trans, LC_PATH1, path);
572 hcc_leaf_int32(trans, LC_OFLAGS, nflags);
573 hcc_leaf_int32(trans, LC_MODE, mode);
575 if ((head = hcc_finish_command(trans)) == NULL)
579 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
580 switch(item->leafid) {
582 desc = HCC_INT32(item);
586 if (hcc_get_descriptor(hc, desc, HC_DESC_FD)) {
587 fprintf(stderr, "hc_opendir: remote reused active descriptor %d\n",
591 fdp = malloc(sizeof(int));
592 *fdp = desc; /* really just a dummy */
593 hcc_set_descriptor(hc, desc, fdp, HC_DESC_FD);
598 rc_open(hctransaction_t trans, struct HCHead *head)
601 const char *path = NULL;
609 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
610 switch(item->leafid) {
612 path = HCC_STRING(item);
615 nflags = HCC_INT32(item);
618 mode = HCC_INT32(item);
625 flags = nflags & XO_NATIVEMASK;
626 if (nflags & XO_CREAT)
628 if (nflags & XO_EXCL)
630 if (nflags & XO_TRUNC)
634 flags |= O_LARGEFILE;
636 if ((fd = open(path, flags, mode)) < 0) {
640 fdp = malloc(sizeof(int));
642 desc = hcc_alloc_descriptor(trans->hc, fdp, HC_DESC_FD);
643 hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
651 hc_close(struct HostConf *hc, int fd)
653 hctransaction_t trans;
657 if (hc == NULL || hc->host == NULL)
660 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
663 hcc_set_descriptor(hc, fd, NULL, HC_DESC_FD);
665 trans = hcc_start_command(hc, HC_CLOSE);
666 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
667 if ((head = hcc_finish_command(trans)) == NULL)
678 rc_close(hctransaction_t trans, struct HCHead *head)
685 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
686 switch(item->leafid) {
688 desc = HCC_INT32(item);
694 if ((fdp = hcc_get_descriptor(trans->hc, desc, HC_DESC_FD)) == NULL)
698 hcc_set_descriptor(trans->hc, desc, NULL, HC_DESC_FD);
722 hc_read(struct HostConf *hc, int fd, void *buf, size_t bytes)
724 hctransaction_t trans;
730 if (hc == NULL || hc->host == NULL)
731 return(read(fd, buf, bytes));
733 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
737 size_t limit = getiolimit();
738 int n = (bytes > limit) ? limit : bytes;
741 trans = hcc_start_command(hc, HC_READ);
742 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
743 hcc_leaf_int32(trans, LC_BYTES, n);
744 if ((head = hcc_finish_command(trans)) == NULL)
748 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
749 switch(item->leafid) {
751 x = item->bytes - sizeof(*item);
754 bcopy(HCC_BINARYDATA(item), buf, x);
755 buf = (char *)buf + x;
771 rc_read(hctransaction_t trans, struct HCHead *head)
779 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
780 switch(item->leafid) {
782 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
785 bytes = HCC_INT32(item);
791 if (bytes < 0 || bytes > 32768)
793 n = read(*fdp, buf, bytes);
798 hcc_leaf_data(trans, LC_DATA, buf, n);
806 hc_write(struct HostConf *hc, int fd, const void *buf, size_t bytes)
808 hctransaction_t trans;
814 if (hc == NULL || hc->host == NULL)
815 return(write(fd, buf, bytes));
817 fdp = hcc_get_descriptor(hc, fd, HC_DESC_FD);
821 size_t limit = getiolimit();
822 int n = (bytes > limit) ? limit : bytes;
825 trans = hcc_start_command(hc, HC_WRITE);
826 hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
827 hcc_leaf_data(trans, LC_DATA, buf, n);
828 if ((head = hcc_finish_command(trans)) == NULL)
832 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
833 switch(item->leafid) {
842 buf = (const char *)buf + x;
854 rc_write(hctransaction_t trans, struct HCHead *head)
861 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
862 switch(item->leafid) {
864 fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
867 buf = HCC_BINARYDATA(item);
868 n = item->bytes - sizeof(*item);
874 if (n < 0 || n > 32768)
876 n = write(*fdp, buf, n);
880 hcc_leaf_int32(trans, LC_BYTES, n);
888 * NOTE: This function returns -errno if an error occured.
891 hc_remove(struct HostConf *hc, const char *path)
893 hctransaction_t trans;
897 if (hc == NULL || hc->host == NULL) {
904 trans = hcc_start_command(hc, HC_REMOVE);
905 hcc_leaf_string(trans, LC_PATH1, path);
906 if ((head = hcc_finish_command(trans)) == NULL)
909 return(-(int)head->error);
914 rc_remove(hctransaction_t trans __unused, struct HCHead *head)
917 const char *path = NULL;
919 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
920 switch(item->leafid) {
922 path = HCC_STRING(item);
928 return(remove(path));
935 hc_mkdir(struct HostConf *hc __unused, const char *path, mode_t mode)
937 hctransaction_t trans;
940 if (hc == NULL || hc->host == NULL)
941 return(mkdir(path, mode));
943 trans = hcc_start_command(hc, HC_MKDIR);
944 hcc_leaf_string(trans, LC_PATH1, path);
945 hcc_leaf_int32(trans, LC_MODE, mode);
946 if ((head = hcc_finish_command(trans)) == NULL)
954 rc_mkdir(hctransaction_t trans __unused, struct HCHead *head)
957 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);
966 mode = HCC_INT32(item);
972 return(mkdir(path, mode));
979 hc_rmdir(struct HostConf *hc, const char *path)
981 hctransaction_t trans;
984 if (hc == NULL || hc->host == NULL)
987 trans = hcc_start_command(hc, HC_RMDIR);
988 hcc_leaf_string(trans, LC_PATH1, path);
989 if ((head = hcc_finish_command(trans)) == NULL)
997 rc_rmdir(hctransaction_t trans __unused, struct HCHead *head)
1000 const char *path = NULL;
1002 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1003 switch(item->leafid) {
1005 path = HCC_STRING(item);
1011 return(rmdir(path));
1017 * Almost silently ignore chowns that fail if we are not root.
1020 hc_chown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
1022 hctransaction_t trans;
1023 struct HCHead *head;
1026 if (hc == NULL || hc->host == NULL) {
1027 rc = chown(path, owner, group);
1029 rc = silentwarning(&chown_warning, "file ownership may differ\n");
1033 trans = hcc_start_command(hc, HC_CHOWN);
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_chown(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;
1053 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1054 switch(item->leafid) {
1056 path = HCC_STRING(item);
1059 uid = HCC_INT32(item);
1062 gid = HCC_INT32(item);
1068 rc = chown(path, uid, gid);
1070 rc = silentwarning(&chown_warning, "file ownership may differ\n");
1078 hc_lchown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
1080 hctransaction_t trans;
1081 struct HCHead *head;
1084 if (hc == NULL || hc->host == NULL) {
1085 rc = lchown(path, owner, group);
1087 rc = silentwarning(&chown_warning, "file ownership may differ\n");
1091 trans = hcc_start_command(hc, HC_LCHOWN);
1092 hcc_leaf_string(trans, LC_PATH1, path);
1093 hcc_leaf_int32(trans, LC_UID, owner);
1094 hcc_leaf_int32(trans, LC_GID, group);
1095 if ((head = hcc_finish_command(trans)) == NULL)
1103 rc_lchown(hctransaction_t trans __unused, struct HCHead *head)
1105 struct HCLeaf *item;
1106 const char *path = NULL;
1107 uid_t uid = (uid_t)-1;
1108 gid_t gid = (gid_t)-1;
1111 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1112 switch(item->leafid) {
1114 path = HCC_STRING(item);
1117 uid = HCC_INT32(item);
1120 gid = HCC_INT32(item);
1126 rc = lchown(path, uid, gid);
1128 rc = silentwarning(&chown_warning, "file ownership may differ\n");
1136 hc_chmod(struct HostConf *hc, const char *path, mode_t mode)
1138 hctransaction_t trans;
1139 struct HCHead *head;
1141 if (hc == NULL || hc->host == NULL)
1142 return(chmod(path, mode));
1144 trans = hcc_start_command(hc, HC_CHMOD);
1145 hcc_leaf_string(trans, LC_PATH1, path);
1146 hcc_leaf_int32(trans, LC_MODE, mode);
1147 if ((head = hcc_finish_command(trans)) == NULL)
1155 rc_chmod(hctransaction_t trans __unused, struct HCHead *head)
1157 struct HCLeaf *item;
1158 const char *path = NULL;
1161 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1162 switch(item->leafid) {
1164 path = HCC_STRING(item);
1167 mode = HCC_INT32(item);
1173 return(chmod(path, mode));
1180 hc_mknod(struct HostConf *hc, const char *path, mode_t mode, dev_t rdev)
1182 hctransaction_t trans;
1183 struct HCHead *head;
1185 if (hc == NULL || hc->host == NULL)
1186 return(mknod(path, mode, rdev));
1188 trans = hcc_start_command(hc, HC_MKNOD);
1189 hcc_leaf_string(trans, LC_PATH1, path);
1190 hcc_leaf_int32(trans, LC_MODE, mode);
1191 hcc_leaf_int32(trans, LC_RDEV, rdev);
1192 if ((head = hcc_finish_command(trans)) == NULL)
1200 rc_mknod(hctransaction_t trans __unused, struct HCHead *head)
1202 struct HCLeaf *item;
1203 const char *path = NULL;
1207 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1208 switch(item->leafid) {
1210 path = HCC_STRING(item);
1213 mode = HCC_INT32(item);
1216 rdev = HCC_INT32(item);
1222 return(mknod(path, mode, rdev));
1229 hc_link(struct HostConf *hc, const char *name1, const char *name2)
1231 hctransaction_t trans;
1232 struct HCHead *head;
1234 if (hc == NULL || hc->host == NULL)
1235 return(link(name1, name2));
1237 trans = hcc_start_command(hc, HC_LINK);
1238 hcc_leaf_string(trans, LC_PATH1, name1);
1239 hcc_leaf_string(trans, LC_PATH2, name2);
1240 if ((head = hcc_finish_command(trans)) == NULL)
1248 rc_link(hctransaction_t trans __unused, struct HCHead *head)
1250 struct HCLeaf *item;
1251 const char *name1 = NULL;
1252 const char *name2 = NULL;
1254 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1255 switch(item->leafid) {
1257 name1 = HCC_STRING(item);
1260 name2 = HCC_STRING(item);
1264 if (name1 == NULL || name2 == NULL)
1266 return(link(name1, name2));
1269 #ifdef _ST_FLAGS_PRESENT_
1274 hc_chflags(struct HostConf *hc, const char *path, u_long flags)
1276 hctransaction_t trans;
1277 struct HCHead *head;
1280 if (hc == NULL || hc->host == NULL) {
1281 rc = chflags(path, flags);
1283 if (RunningAsUser) {
1284 flags &= UF_SETTABLE;
1285 rc = chflags(path, flags);
1288 rc = silentwarning(&chflags_warning, "file flags may differ\n");
1293 trans = hcc_start_command(hc, HC_CHFLAGS);
1294 hcc_leaf_string(trans, LC_PATH1, path);
1295 hcc_leaf_int64(trans, LC_FILEFLAGS, flags);
1296 if ((head = hcc_finish_command(trans)) == NULL)
1304 rc_chflags(hctransaction_t trans __unused, struct HCHead *head)
1306 struct HCLeaf *item;
1307 const char *path = NULL;
1311 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1312 switch(item->leafid) {
1314 path = HCC_STRING(item);
1317 flags = (u_long)HCC_INT64(item);
1323 rc = chflags(path, flags);
1325 if (RunningAsUser) {
1326 flags &= UF_SETTABLE;
1327 rc = chflags(path, flags);
1330 rc = silentwarning(&chflags_warning, "file flags may differ\n");
1341 hc_readlink(struct HostConf *hc, const char *path, char *buf, int bufsiz)
1343 hctransaction_t trans;
1344 struct HCHead *head;
1345 struct HCLeaf *item;
1348 if (hc == NULL || hc->host == NULL)
1349 return(readlink(path, buf, bufsiz));
1351 trans = hcc_start_command(hc, HC_READLINK);
1352 hcc_leaf_string(trans, LC_PATH1, path);
1353 if ((head = hcc_finish_command(trans)) == NULL)
1359 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1360 switch(item->leafid) {
1362 r = item->bytes - sizeof(*item);
1367 bcopy(HCC_BINARYDATA(item), buf, r);
1375 rc_readlink(hctransaction_t trans, struct HCHead *head)
1377 struct HCLeaf *item;
1378 const char *path = NULL;
1382 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1383 switch(item->leafid) {
1385 path = HCC_STRING(item);
1391 r = readlink(path, buf, sizeof(buf));
1394 hcc_leaf_data(trans, LC_DATA, buf, r);
1402 hc_umask(struct HostConf *hc, mode_t numask)
1404 hctransaction_t trans;
1405 struct HCHead *head;
1406 struct HCLeaf *item;
1408 if (hc == NULL || hc->host == NULL)
1409 return(umask(numask));
1411 trans = hcc_start_command(hc, HC_UMASK);
1412 hcc_leaf_int32(trans, LC_MODE, numask);
1413 if ((head = hcc_finish_command(trans)) == NULL)
1419 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1420 switch(item->leafid) {
1422 numask = HCC_INT32(item);
1430 rc_umask(hctransaction_t trans, struct HCHead *head)
1432 struct HCLeaf *item;
1433 mode_t numask = ~0666;
1435 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1436 switch(item->leafid) {
1438 numask = HCC_INT32(item);
1442 numask = umask(numask);
1443 hcc_leaf_int32(trans, LC_MODE, numask);
1451 hc_symlink(struct HostConf *hc, const char *name1, const char *name2)
1453 hctransaction_t trans;
1454 struct HCHead *head;
1456 if (hc == NULL || hc->host == NULL)
1457 return(symlink(name1, name2));
1459 trans = hcc_start_command(hc, HC_SYMLINK);
1460 hcc_leaf_string(trans, LC_PATH1, name1);
1461 hcc_leaf_string(trans, LC_PATH2, name2);
1462 if ((head = hcc_finish_command(trans)) == NULL)
1470 rc_symlink(hctransaction_t trans __unused, struct HCHead *head)
1472 struct HCLeaf *item;
1473 const char *name1 = NULL;
1474 const char *name2 = NULL;
1476 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1477 switch(item->leafid) {
1479 name1 = HCC_STRING(item);
1482 name2 = HCC_STRING(item);
1486 if (name1 == NULL || name2 == NULL)
1488 return(symlink(name1, name2));
1495 hc_rename(struct HostConf *hc, const char *name1, const char *name2)
1497 hctransaction_t trans;
1498 struct HCHead *head;
1500 if (hc == NULL || hc->host == NULL)
1501 return(rename(name1, name2));
1503 trans = hcc_start_command(hc, HC_RENAME);
1504 hcc_leaf_string(trans, LC_PATH1, name1);
1505 hcc_leaf_string(trans, LC_PATH2, name2);
1506 if ((head = hcc_finish_command(trans)) == NULL)
1514 rc_rename(hctransaction_t trans __unused, struct HCHead *head)
1516 struct HCLeaf *item;
1517 const char *name1 = NULL;
1518 const char *name2 = NULL;
1520 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1521 switch(item->leafid) {
1523 name1 = HCC_STRING(item);
1526 name2 = HCC_STRING(item);
1530 if (name1 == NULL || name2 == NULL)
1532 return(rename(name1, name2));
1539 hc_utimes(struct HostConf *hc, const char *path, const struct timeval *times)
1541 hctransaction_t trans;
1542 struct HCHead *head;
1544 if (hc == NULL || hc->host == NULL)
1545 return(utimes(path, times));
1547 trans = hcc_start_command(hc, HC_UTIMES);
1548 hcc_leaf_string(trans, LC_PATH1, path);
1549 hcc_leaf_int64(trans, LC_ATIME, times[0].tv_sec);
1550 hcc_leaf_int64(trans, LC_MTIME, times[1].tv_sec);
1551 if ((head = hcc_finish_command(trans)) == NULL)
1559 rc_utimes(hctransaction_t trans __unused, struct HCHead *head)
1561 struct HCLeaf *item;
1562 struct timeval times[2];
1565 bzero(times, sizeof(times));
1568 for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
1569 switch(item->leafid) {
1571 path = HCC_STRING(item);
1574 times[0].tv_sec = HCC_INT64(item);
1577 times[1].tv_sec = HCC_INT64(item);
1583 return(utimes(path, times));