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
},
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 %jd\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
, (intptr_t)dir
);
410 if ((head
= hcc_finish_command(trans
)) == NULL
)
413 return(NULL
); /* XXX errno */
414 den
= hcc_get_descriptor(hc
, (intptr_t)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
, (intptr_t)dir
, HC_DESC_DIR
);
482 hcc_set_descriptor(hc
, (intptr_t)dir
, NULL
, HC_DESC_DIR
);
484 trans
= hcc_start_command(hc
, HC_CLOSEDIR
);
485 hcc_leaf_int32(trans
, LC_DESCRIPTOR
, (intptr_t)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
);
863 * NOTE: This function returns -errno if an error occured.
866 hc_remove(struct HostConf
*hc
, const char *path
)
868 hctransaction_t trans
;
872 if (hc
== NULL
|| hc
->host
== NULL
) {
879 trans
= hcc_start_command(hc
, HC_REMOVE
);
880 hcc_leaf_string(trans
, LC_PATH1
, path
);
881 if ((head
= hcc_finish_command(trans
)) == NULL
)
884 return(-(int)head
->error
);
889 rc_remove(hctransaction_t trans __unused
, struct HCHead
*head
)
892 const char *path
= NULL
;
894 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
895 switch(item
->leafid
) {
897 path
= HCC_STRING(item
);
903 return(remove(path
));
910 hc_mkdir(struct HostConf
*hc __unused
, const char *path
, mode_t mode
)
912 hctransaction_t trans
;
915 if (hc
== NULL
|| hc
->host
== NULL
)
916 return(mkdir(path
, mode
));
918 trans
= hcc_start_command(hc
, HC_MKDIR
);
919 hcc_leaf_string(trans
, LC_PATH1
, path
);
920 hcc_leaf_int32(trans
, LC_MODE
, mode
);
921 if ((head
= hcc_finish_command(trans
)) == NULL
)
929 rc_mkdir(hctransaction_t trans __unused
, struct HCHead
*head
)
932 const char *path
= NULL
;
935 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
936 switch(item
->leafid
) {
938 path
= HCC_STRING(item
);
941 mode
= HCC_INT32(item
);
947 return(mkdir(path
, mode
));
954 hc_rmdir(struct HostConf
*hc
, const char *path
)
956 hctransaction_t trans
;
959 if (hc
== NULL
|| hc
->host
== NULL
)
962 trans
= hcc_start_command(hc
, HC_RMDIR
);
963 hcc_leaf_string(trans
, LC_PATH1
, path
);
964 if ((head
= hcc_finish_command(trans
)) == NULL
)
972 rc_rmdir(hctransaction_t trans __unused
, struct HCHead
*head
)
975 const char *path
= NULL
;
977 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
978 switch(item
->leafid
) {
980 path
= HCC_STRING(item
);
993 hc_chown(struct HostConf
*hc
, const char *path
, uid_t owner
, gid_t group
)
995 hctransaction_t trans
;
998 if (hc
== NULL
|| hc
->host
== NULL
)
999 return(chown(path
, owner
, group
));
1001 trans
= hcc_start_command(hc
, HC_CHOWN
);
1002 hcc_leaf_string(trans
, LC_PATH1
, path
);
1003 hcc_leaf_int32(trans
, LC_UID
, owner
);
1004 hcc_leaf_int32(trans
, LC_GID
, group
);
1005 if ((head
= hcc_finish_command(trans
)) == NULL
)
1013 rc_chown(hctransaction_t trans __unused
, struct HCHead
*head
)
1015 struct HCLeaf
*item
;
1016 const char *path
= NULL
;
1017 uid_t uid
= (uid_t
)-1;
1018 gid_t gid
= (gid_t
)-1;
1020 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1021 switch(item
->leafid
) {
1023 path
= HCC_STRING(item
);
1026 uid
= HCC_INT32(item
);
1029 gid
= HCC_INT32(item
);
1035 return(chown(path
, uid
, gid
));
1042 hc_lchown(struct HostConf
*hc
, const char *path
, uid_t owner
, gid_t group
)
1044 hctransaction_t trans
;
1045 struct HCHead
*head
;
1047 if (hc
== NULL
|| hc
->host
== NULL
)
1048 return(lchown(path
, owner
, group
));
1050 trans
= hcc_start_command(hc
, HC_LCHOWN
);
1051 hcc_leaf_string(trans
, LC_PATH1
, path
);
1052 hcc_leaf_int32(trans
, LC_UID
, owner
);
1053 hcc_leaf_int32(trans
, LC_GID
, group
);
1054 if ((head
= hcc_finish_command(trans
)) == NULL
)
1062 rc_lchown(hctransaction_t trans __unused
, struct HCHead
*head
)
1064 struct HCLeaf
*item
;
1065 const char *path
= NULL
;
1066 uid_t uid
= (uid_t
)-1;
1067 gid_t gid
= (gid_t
)-1;
1069 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1070 switch(item
->leafid
) {
1072 path
= HCC_STRING(item
);
1075 uid
= HCC_INT32(item
);
1078 gid
= HCC_INT32(item
);
1084 return(lchown(path
, uid
, gid
));
1091 hc_chmod(struct HostConf
*hc
, const char *path
, mode_t mode
)
1093 hctransaction_t trans
;
1094 struct HCHead
*head
;
1096 if (hc
== NULL
|| hc
->host
== NULL
)
1097 return(chmod(path
, mode
));
1099 trans
= hcc_start_command(hc
, HC_CHMOD
);
1100 hcc_leaf_string(trans
, LC_PATH1
, path
);
1101 hcc_leaf_int32(trans
, LC_MODE
, mode
);
1102 if ((head
= hcc_finish_command(trans
)) == NULL
)
1110 rc_chmod(hctransaction_t trans __unused
, struct HCHead
*head
)
1112 struct HCLeaf
*item
;
1113 const char *path
= NULL
;
1116 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1117 switch(item
->leafid
) {
1119 path
= HCC_STRING(item
);
1122 mode
= HCC_INT32(item
);
1128 return(chmod(path
, mode
));
1135 hc_mknod(struct HostConf
*hc
, const char *path
, mode_t mode
, dev_t rdev
)
1137 hctransaction_t trans
;
1138 struct HCHead
*head
;
1140 if (hc
== NULL
|| hc
->host
== NULL
)
1141 return(mknod(path
, mode
, rdev
));
1143 trans
= hcc_start_command(hc
, HC_MKNOD
);
1144 hcc_leaf_string(trans
, LC_PATH1
, path
);
1145 hcc_leaf_int32(trans
, LC_MODE
, mode
);
1146 hcc_leaf_int32(trans
, LC_RDEV
, rdev
);
1147 if ((head
= hcc_finish_command(trans
)) == NULL
)
1155 rc_mknod(hctransaction_t trans __unused
, struct HCHead
*head
)
1157 struct HCLeaf
*item
;
1158 const char *path
= NULL
;
1162 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1163 switch(item
->leafid
) {
1165 path
= HCC_STRING(item
);
1168 mode
= HCC_INT32(item
);
1171 rdev
= HCC_INT32(item
);
1177 return(mknod(path
, mode
, rdev
));
1184 hc_link(struct HostConf
*hc
, const char *name1
, const char *name2
)
1186 hctransaction_t trans
;
1187 struct HCHead
*head
;
1189 if (hc
== NULL
|| hc
->host
== NULL
)
1190 return(link(name1
, name2
));
1192 trans
= hcc_start_command(hc
, HC_LINK
);
1193 hcc_leaf_string(trans
, LC_PATH1
, name1
);
1194 hcc_leaf_string(trans
, LC_PATH2
, name2
);
1195 if ((head
= hcc_finish_command(trans
)) == NULL
)
1203 rc_link(hctransaction_t trans __unused
, struct HCHead
*head
)
1205 struct HCLeaf
*item
;
1206 const char *name1
= NULL
;
1207 const char *name2
= NULL
;
1209 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1210 switch(item
->leafid
) {
1212 name1
= HCC_STRING(item
);
1215 name2
= HCC_STRING(item
);
1219 if (name1
== NULL
|| name2
== NULL
)
1221 return(link(name1
, name2
));
1224 #ifdef _ST_FLAGS_PRESENT_
1229 hc_chflags(struct HostConf
*hc
, const char *path
, u_long flags
)
1231 hctransaction_t trans
;
1232 struct HCHead
*head
;
1234 if (hc
== NULL
|| hc
->host
== NULL
)
1235 return(chflags(path
, flags
));
1237 trans
= hcc_start_command(hc
, HC_CHFLAGS
);
1238 hcc_leaf_string(trans
, LC_PATH1
, path
);
1239 hcc_leaf_int64(trans
, LC_FILEFLAGS
, flags
);
1240 if ((head
= hcc_finish_command(trans
)) == NULL
)
1248 rc_chflags(hctransaction_t trans __unused
, struct HCHead
*head
)
1250 struct HCLeaf
*item
;
1251 const char *path
= NULL
;
1254 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1255 switch(item
->leafid
) {
1257 path
= HCC_STRING(item
);
1260 flags
= (u_long
)HCC_INT64(item
);
1266 return(chflags(path
, flags
));
1275 hc_readlink(struct HostConf
*hc
, const char *path
, char *buf
, int bufsiz
)
1277 hctransaction_t trans
;
1278 struct HCHead
*head
;
1279 struct HCLeaf
*item
;
1282 if (hc
== NULL
|| hc
->host
== NULL
)
1283 return(readlink(path
, buf
, bufsiz
));
1285 trans
= hcc_start_command(hc
, HC_READLINK
);
1286 hcc_leaf_string(trans
, LC_PATH1
, path
);
1287 if ((head
= hcc_finish_command(trans
)) == NULL
)
1293 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1294 switch(item
->leafid
) {
1296 r
= item
->bytes
- sizeof(*item
);
1301 bcopy(HCC_BINARYDATA(item
), buf
, r
);
1309 rc_readlink(hctransaction_t trans
, struct HCHead
*head
)
1311 struct HCLeaf
*item
;
1312 const char *path
= NULL
;
1316 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1317 switch(item
->leafid
) {
1319 path
= HCC_STRING(item
);
1325 r
= readlink(path
, buf
, sizeof(buf
));
1328 hcc_leaf_data(trans
, LC_DATA
, buf
, r
);
1336 hc_umask(struct HostConf
*hc
, mode_t numask
)
1338 hctransaction_t trans
;
1339 struct HCHead
*head
;
1340 struct HCLeaf
*item
;
1342 if (hc
== NULL
|| hc
->host
== NULL
)
1343 return(umask(numask
));
1345 trans
= hcc_start_command(hc
, HC_UMASK
);
1346 hcc_leaf_int32(trans
, LC_MODE
, numask
);
1347 if ((head
= hcc_finish_command(trans
)) == NULL
)
1353 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1354 switch(item
->leafid
) {
1356 numask
= HCC_INT32(item
);
1364 rc_umask(hctransaction_t trans
, struct HCHead
*head
)
1366 struct HCLeaf
*item
;
1367 mode_t numask
= ~0666;
1369 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1370 switch(item
->leafid
) {
1372 numask
= HCC_INT32(item
);
1376 numask
= umask(numask
);
1377 hcc_leaf_int32(trans
, LC_MODE
, numask
);
1385 hc_symlink(struct HostConf
*hc
, const char *name1
, const char *name2
)
1387 hctransaction_t trans
;
1388 struct HCHead
*head
;
1390 if (hc
== NULL
|| hc
->host
== NULL
)
1391 return(symlink(name1
, name2
));
1393 trans
= hcc_start_command(hc
, HC_SYMLINK
);
1394 hcc_leaf_string(trans
, LC_PATH1
, name1
);
1395 hcc_leaf_string(trans
, LC_PATH2
, name2
);
1396 if ((head
= hcc_finish_command(trans
)) == NULL
)
1404 rc_symlink(hctransaction_t trans __unused
, struct HCHead
*head
)
1406 struct HCLeaf
*item
;
1407 const char *name1
= NULL
;
1408 const char *name2
= NULL
;
1410 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1411 switch(item
->leafid
) {
1413 name1
= HCC_STRING(item
);
1416 name2
= HCC_STRING(item
);
1420 if (name1
== NULL
|| name2
== NULL
)
1422 return(symlink(name1
, name2
));
1429 hc_rename(struct HostConf
*hc
, const char *name1
, const char *name2
)
1431 hctransaction_t trans
;
1432 struct HCHead
*head
;
1434 if (hc
== NULL
|| hc
->host
== NULL
)
1435 return(rename(name1
, name2
));
1437 trans
= hcc_start_command(hc
, HC_RENAME
);
1438 hcc_leaf_string(trans
, LC_PATH1
, name1
);
1439 hcc_leaf_string(trans
, LC_PATH2
, name2
);
1440 if ((head
= hcc_finish_command(trans
)) == NULL
)
1448 rc_rename(hctransaction_t trans __unused
, struct HCHead
*head
)
1450 struct HCLeaf
*item
;
1451 const char *name1
= NULL
;
1452 const char *name2
= NULL
;
1454 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1455 switch(item
->leafid
) {
1457 name1
= HCC_STRING(item
);
1460 name2
= HCC_STRING(item
);
1464 if (name1
== NULL
|| name2
== NULL
)
1466 return(rename(name1
, name2
));
1473 hc_utimes(struct HostConf
*hc
, const char *path
, const struct timeval
*times
)
1475 hctransaction_t trans
;
1476 struct HCHead
*head
;
1478 if (hc
== NULL
|| hc
->host
== NULL
)
1479 return(utimes(path
, times
));
1481 trans
= hcc_start_command(hc
, HC_UTIMES
);
1482 hcc_leaf_string(trans
, LC_PATH1
, path
);
1483 hcc_leaf_int64(trans
, LC_ATIME
, times
[0].tv_sec
);
1484 hcc_leaf_int64(trans
, LC_MTIME
, times
[1].tv_sec
);
1485 if ((head
= hcc_finish_command(trans
)) == NULL
)
1493 rc_utimes(hctransaction_t trans __unused
, struct HCHead
*head
)
1495 struct HCLeaf
*item
;
1496 struct timeval times
[2];
1499 bzero(times
, sizeof(times
));
1502 for (item
= hcc_firstitem(head
); item
; item
= hcc_nextitem(head
, item
)) {
1503 switch(item
->leafid
) {
1505 path
= HCC_STRING(item
);
1508 times
[0].tv_sec
= HCC_INT64(item
);
1511 times
[1].tv_sec
= HCC_INT64(item
);
1517 return(utimes(path
, times
));