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
));