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