[Midnightbsd-cvs] src: bin/cpdup: Sync with DragonFly.
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Thu Apr 10 19:45:55 EDT 2008
Log Message:
-----------
Sync with DragonFly.
Matt added several features to cpdup including parallel transaction support for remote source or targets.
By default, this now compiles with pthreads support.
-l was added to force stdout and stderr to be line-buffered.
Also, we had to modify the casts for pointer types. It is nice to have amd64 build things since pointers aren't ints :)
Modified Files:
--------------
src/bin/cpdup:
BACKUPS (r1.1 -> r1.2)
Makefile (r1.1 -> r1.2)
PORTING (r1.1 -> r1.2)
cpdup.1 (r1.1 -> r1.2)
cpdup.c (r1.1 -> r1.2)
cpdup.h (r1.1 -> r1.2)
fsmid.c (r1.1 -> r1.2)
hclink.c (r1.1 -> r1.2)
hclink.h (r1.1 -> r1.2)
hcproto.c (r1.1 -> r1.2)
hcproto.h (r1.1 -> r1.2)
md5.c (r1.1 -> r1.2)
misc.c (r1.1 -> r1.2)
src/bin/cpdup/scripts:
crontab (r1.1 -> r1.2)
do_cleanup (r1.1 -> r1.2)
do_mirror (r1.1 -> r1.2)
do_mirror_host (r1.1 -> r1.2)
do_remote (r1.1 -> r1.2)
do_remote_host (r1.1 -> r1.2)
params (r1.1 -> r1.2)
-------------- next part --------------
Index: hcproto.c
===================================================================
RCS file: /home/cvs/src/bin/cpdup/hcproto.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/hcproto.c -L bin/cpdup/hcproto.c -u -r1.1 -r1.2
--- bin/cpdup/hcproto.c
+++ bin/cpdup/hcproto.c
@@ -3,51 +3,41 @@
*
* This module implements a simple remote control protocol
*
- * $MidnightBSD$
- * $DragonFly: src/bin/cpdup/hcproto.c,v 1.1 2006/08/13 20:51:40 dillon Exp $
+ * $DragonFly: src/bin/cpdup/hcproto.c,v 1.2 2008/04/10 22:09:08 dillon Exp $
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <errno.h>
-
+#include "cpdup.h"
#include "hclink.h"
#include "hcproto.h"
static int hc_decode_stat(struct stat *, struct HCHead *);
-static int rc_encode_stat(struct HostConf *, struct stat *);
+static int rc_encode_stat(hctransaction_t trans, struct stat *);
-static int rc_hello(struct HostConf *, struct HCHead *);
-static int rc_stat(struct HostConf *, struct HCHead *);
-static int rc_lstat(struct HostConf *, struct HCHead *);
-static int rc_opendir(struct HostConf *, struct HCHead *);
-static int rc_readdir(struct HostConf *, struct HCHead *);
-static int rc_closedir(struct HostConf *, struct HCHead *);
-static int rc_open(struct HostConf *, struct HCHead *);
-static int rc_close(struct HostConf *, struct HCHead *);
-static int rc_read(struct HostConf *, struct HCHead *);
-static int rc_write(struct HostConf *, struct HCHead *);
-static int rc_remove(struct HostConf *, struct HCHead *);
-static int rc_mkdir(struct HostConf *, struct HCHead *);
-static int rc_rmdir(struct HostConf *, struct HCHead *);
-static int rc_chown(struct HostConf *, struct HCHead *);
-static int rc_lchown(struct HostConf *, struct HCHead *);
-static int rc_chmod(struct HostConf *, struct HCHead *);
-static int rc_link(struct HostConf *, struct HCHead *);
+static int rc_hello(hctransaction_t trans, struct HCHead *);
+static int rc_stat(hctransaction_t trans, struct HCHead *);
+static int rc_lstat(hctransaction_t trans, struct HCHead *);
+static int rc_opendir(hctransaction_t trans, struct HCHead *);
+static int rc_readdir(hctransaction_t trans, struct HCHead *);
+static int rc_closedir(hctransaction_t trans, struct HCHead *);
+static int rc_open(hctransaction_t trans, struct HCHead *);
+static int rc_close(hctransaction_t trans, struct HCHead *);
+static int rc_read(hctransaction_t trans, struct HCHead *);
+static int rc_write(hctransaction_t trans, struct HCHead *);
+static int rc_remove(hctransaction_t trans, struct HCHead *);
+static int rc_mkdir(hctransaction_t trans, struct HCHead *);
+static int rc_rmdir(hctransaction_t trans, struct HCHead *);
+static int rc_chown(hctransaction_t trans, struct HCHead *);
+static int rc_lchown(hctransaction_t trans, struct HCHead *);
+static int rc_chmod(hctransaction_t trans, struct HCHead *);
+static int rc_link(hctransaction_t trans, struct HCHead *);
#ifdef _ST_FLAGS_PRESENT_
-static int rc_chflags(struct HostConf *, struct HCHead *);
+static int rc_chflags(hctransaction_t trans, struct HCHead *);
#endif
-static int rc_readlink(struct HostConf *, struct HCHead *);
-static int rc_umask(struct HostConf *, struct HCHead *);
-static int rc_symlink(struct HostConf *, struct HCHead *);
-static int rc_rename(struct HostConf *, struct HCHead *);
-static int rc_utimes(struct HostConf *, struct HCHead *);
+static int rc_readlink(hctransaction_t trans, struct HCHead *);
+static int rc_umask(hctransaction_t trans, struct HCHead *);
+static int rc_symlink(hctransaction_t trans, struct HCHead *);
+static int rc_rename(hctransaction_t trans, struct HCHead *);
+static int rc_utimes(hctransaction_t trans, struct HCHead *);
struct HCDesc HCDispatchTable[] = {
{ HC_HELLO, rc_hello },
@@ -101,6 +91,7 @@
{
struct HCHead *head;
struct HCLeaf *item;
+ hctransaction_t trans;
char hostbuf[256];
int error;
@@ -110,9 +101,10 @@
if (hostbuf[0] == 0)
hostbuf[0] = '?';
- hcc_start_command(hc, HC_HELLO);
- hcc_leaf_string(hc, LC_HELLOSTR, hostbuf);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_HELLO);
+ hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
+ hcc_leaf_int32(trans, LC_VERSION, 1);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error) {
@@ -127,6 +119,10 @@
case LC_HELLOSTR:
fprintf(stderr, "Handshaked with %s\n", HCC_STRING(item));
error = 0;
+ break;
+ case LC_VERSION:
+ hc->version = HCC_INT32(item);
+ break;
}
}
if (error < 0)
@@ -135,7 +131,7 @@
}
static int
-rc_hello(struct HostConf *hc, struct HCHead *head __unused)
+rc_hello(hctransaction_t trans, struct HCHead *head __unused)
{
char hostbuf[256];
@@ -145,7 +141,8 @@
if (hostbuf[0] == 0)
hostbuf[0] = '?';
- hcc_leaf_string(hc, LC_HELLOSTR, hostbuf);
+ hcc_leaf_string(trans, LC_HELLOSTR, hostbuf);
+ hcc_leaf_int32(trans, LC_VERSION, 1);
return(0);
}
@@ -156,13 +153,14 @@
hc_stat(struct HostConf *hc, const char *path, struct stat *st)
{
struct HCHead *head;
+ hctransaction_t trans;
if (hc == NULL || hc->host == NULL)
return(stat(path, st));
- hcc_start_command(hc, HC_STAT);
- hcc_leaf_string(hc, LC_PATH1, path);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_STAT);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -173,13 +171,14 @@
hc_lstat(struct HostConf *hc, const char *path, struct stat *st)
{
struct HCHead *head;
+ hctransaction_t trans;
if (hc == NULL || hc->host == NULL)
return(lstat(path, st));
- hcc_start_command(hc, HC_LSTAT);
- hcc_leaf_string(hc, LC_PATH1, path);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_LSTAT);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -249,7 +248,7 @@
}
static int
-rc_stat(struct HostConf *hc, struct HCHead *head)
+rc_stat(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
struct stat st;
@@ -266,11 +265,11 @@
return(-2);
if (stat(path, &st) < 0)
return(-1);
- return (rc_encode_stat(hc, &st));
+ return (rc_encode_stat(trans, &st));
}
static int
-rc_lstat(struct HostConf *hc, struct HCHead *head)
+rc_lstat(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
struct stat st;
@@ -287,30 +286,30 @@
return(-2);
if (lstat(path, &st) < 0)
return(-1);
- return (rc_encode_stat(hc, &st));
+ return (rc_encode_stat(trans, &st));
}
static int
-rc_encode_stat(struct HostConf *hc, struct stat *st)
+rc_encode_stat(hctransaction_t trans, struct stat *st)
{
- hcc_leaf_int32(hc, LC_DEV, st->st_dev);
- hcc_leaf_int64(hc, LC_INO, st->st_ino);
- hcc_leaf_int32(hc, LC_MODE, st->st_mode);
- hcc_leaf_int32(hc, LC_NLINK, st->st_nlink);
- hcc_leaf_int32(hc, LC_UID, st->st_uid);
- hcc_leaf_int32(hc, LC_GID, st->st_gid);
- hcc_leaf_int32(hc, LC_RDEV, st->st_rdev);
- hcc_leaf_int64(hc, LC_ATIME, st->st_atime);
- hcc_leaf_int64(hc, LC_MTIME, st->st_mtime);
- hcc_leaf_int64(hc, LC_CTIME, st->st_ctime);
- hcc_leaf_int64(hc, LC_FILESIZE, st->st_size);
- hcc_leaf_int64(hc, LC_FILEBLKS, st->st_blocks);
- hcc_leaf_int32(hc, LC_BLKSIZE, st->st_blksize);
+ hcc_leaf_int32(trans, LC_DEV, st->st_dev);
+ hcc_leaf_int64(trans, LC_INO, st->st_ino);
+ hcc_leaf_int32(trans, LC_MODE, st->st_mode);
+ hcc_leaf_int32(trans, LC_NLINK, st->st_nlink);
+ hcc_leaf_int32(trans, LC_UID, st->st_uid);
+ hcc_leaf_int32(trans, LC_GID, st->st_gid);
+ hcc_leaf_int32(trans, LC_RDEV, st->st_rdev);
+ hcc_leaf_int64(trans, LC_ATIME, st->st_atime);
+ hcc_leaf_int64(trans, LC_MTIME, st->st_mtime);
+ hcc_leaf_int64(trans, LC_CTIME, st->st_ctime);
+ hcc_leaf_int64(trans, LC_FILESIZE, st->st_size);
+ hcc_leaf_int64(trans, LC_FILEBLKS, st->st_blocks);
+ hcc_leaf_int32(trans, LC_BLKSIZE, st->st_blksize);
#ifdef _ST_FSMID_PRESENT_
- hcc_leaf_int64(hc, LC_FSMID, st->st_fsmid);
+ hcc_leaf_int64(trans, LC_FSMID, st->st_fsmid);
#endif
#ifdef _ST_FLAGS_PRESENT_
- hcc_leaf_int64(hc, LC_FILEFLAGS, st->st_flags);
+ hcc_leaf_int64(trans, LC_FILEFLAGS, st->st_flags);
#endif
return(0);
}
@@ -321,6 +320,7 @@
DIR *
hc_opendir(struct HostConf *hc, const char *path)
{
+ hctransaction_t trans;
struct HCHead *head;
struct HCLeaf *item;
struct dirent *den;
@@ -329,9 +329,9 @@
if (hc == NULL || hc->host == NULL)
return(opendir(path));
- hcc_start_command(hc, HC_OPENDIR);
- hcc_leaf_string(hc, LC_PATH1, path);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_OPENDIR);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(NULL);
if (head->error)
return(NULL);
@@ -354,7 +354,7 @@
}
static int
-rc_opendir(struct HostConf *hc, struct HCHead *head)
+rc_opendir(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
const char *path = NULL;
@@ -373,8 +373,8 @@
if ((dir = opendir(path)) == NULL) {
head->error = errno;
} else {
- desc = hcc_alloc_descriptor(hc, dir, HC_DESC_DIR);
- hcc_leaf_int32(hc, LC_DESCRIPTOR, desc);
+ desc = hcc_alloc_descriptor(trans->hc, dir, HC_DESC_DIR);
+ hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
}
return(0);
}
@@ -385,6 +385,7 @@
struct dirent *
hc_readdir(struct HostConf *hc, DIR *dir)
{
+ hctransaction_t trans;
struct HCHead *head;
struct HCLeaf *item;
struct dirent *den;
@@ -392,9 +393,9 @@
if (hc == NULL || hc->host == NULL)
return(readdir(dir));
- hcc_start_command(hc, HC_READDIR);
- hcc_leaf_int32(hc, LC_DESCRIPTOR, (long)dir);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_READDIR);
+ hcc_leaf_int32(trans, LC_DESCRIPTOR, (long)dir);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(NULL);
if (head->error)
return(NULL); /* XXX errno */
@@ -426,7 +427,7 @@
}
static int
-rc_readdir(struct HostConf *hc, struct HCHead *head)
+rc_readdir(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
struct dirent *den;
@@ -435,16 +436,16 @@
for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
switch(item->leafid) {
case LC_DESCRIPTOR:
- dir = hcc_get_descriptor(hc, HCC_INT32(item), HC_DESC_DIR);
+ dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
break;
}
}
if (dir == NULL)
return(-2);
if ((den = readdir(dir)) != NULL) {
- hcc_leaf_string(hc, LC_PATH1, den->d_name);
- hcc_leaf_int64(hc, LC_INO, den->d_fileno);
- hcc_leaf_int32(hc, LC_TYPE, den->d_type);
+ hcc_leaf_string(trans, LC_PATH1, den->d_name);
+ hcc_leaf_int64(trans, LC_INO, den->d_fileno);
+ hcc_leaf_int32(trans, LC_TYPE, den->d_type);
}
return(0);
}
@@ -457,6 +458,7 @@
int
hc_closedir(struct HostConf *hc, DIR *dir)
{
+ hctransaction_t trans;
struct HCHead *head;
struct dirent *den;
@@ -467,9 +469,9 @@
free(den);
hcc_set_descriptor(hc, (long)dir, NULL, HC_DESC_DIR);
- hcc_start_command(hc, HC_CLOSEDIR);
- hcc_leaf_int32(hc, LC_DESCRIPTOR, (long)dir);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_CLOSEDIR);
+ hcc_leaf_int32(trans, LC_DESCRIPTOR, (long)dir);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1); /* XXX errno */
@@ -481,7 +483,7 @@
}
static int
-rc_closedir(struct HostConf *hc, struct HCHead *head)
+rc_closedir(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
DIR *dir = NULL;
@@ -489,7 +491,7 @@
for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
switch(item->leafid) {
case LC_DESCRIPTOR:
- dir = hcc_get_descriptor(hc, HCC_INT32(item), HC_DESC_DIR);
+ dir = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_DIR);
break;
}
}
@@ -504,6 +506,7 @@
int
hc_open(struct HostConf *hc, const char *path, int flags, mode_t mode)
{
+ hctransaction_t trans;
struct HCHead *head;
struct HCLeaf *item;
int *fdp;
@@ -525,12 +528,12 @@
if (flags & O_TRUNC)
nflags |= XO_TRUNC;
- hcc_start_command(hc, HC_OPEN);
- hcc_leaf_string(hc, LC_PATH1, path);
- hcc_leaf_int32(hc, LC_OFLAGS, nflags);
- hcc_leaf_int32(hc, LC_MODE, mode);
+ trans = hcc_start_command(hc, HC_OPEN);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ hcc_leaf_int32(trans, LC_OFLAGS, nflags);
+ hcc_leaf_int32(trans, LC_MODE, mode);
- if ((head = hcc_finish_command(hc)) == NULL)
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -553,7 +556,7 @@
}
static int
-rc_open(struct HostConf *hc, struct HCHead *head)
+rc_open(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
const char *path = NULL;
@@ -597,8 +600,8 @@
}
fdp = malloc(sizeof(int));
*fdp = fd;
- desc = hcc_alloc_descriptor(hc, fdp, HC_DESC_FD);
- hcc_leaf_int32(hc, LC_DESCRIPTOR, desc);
+ desc = hcc_alloc_descriptor(trans->hc, fdp, HC_DESC_FD);
+ hcc_leaf_int32(trans, LC_DESCRIPTOR, desc);
return(0);
}
@@ -608,6 +611,7 @@
int
hc_close(struct HostConf *hc, int fd)
{
+ hctransaction_t trans;
struct HCHead *head;
int *fdp;
@@ -619,9 +623,9 @@
free(fdp);
hcc_set_descriptor(hc, fd, NULL, HC_DESC_FD);
- hcc_start_command(hc, HC_CLOSE);
- hcc_leaf_int32(hc, LC_DESCRIPTOR, fd);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_CLOSE);
+ hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -632,7 +636,7 @@
}
static int
-rc_close(struct HostConf *hc, struct HCHead *head)
+rc_close(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
int *fdp = NULL;
@@ -648,11 +652,11 @@
}
if (desc < 0)
return(-2);
- if ((fdp = hcc_get_descriptor(hc, desc, HC_DESC_FD)) == NULL)
+ if ((fdp = hcc_get_descriptor(trans->hc, desc, HC_DESC_FD)) == NULL)
return(-2);
fd = *fdp;
free(fdp);
- hcc_set_descriptor(hc, desc, NULL, HC_DESC_FD);
+ hcc_set_descriptor(trans->hc, desc, NULL, HC_DESC_FD);
return(close(fd));
}
@@ -662,6 +666,7 @@
ssize_t
hc_read(struct HostConf *hc, int fd, void *buf, size_t bytes)
{
+ hctransaction_t trans;
struct HCHead *head;
struct HCLeaf *item;
int *fdp;
@@ -677,10 +682,10 @@
int n = (bytes > 32768) ? 32768 : bytes;
int x = 0;
- hcc_start_command(hc, HC_READ);
- hcc_leaf_int32(hc, LC_DESCRIPTOR, fd);
- hcc_leaf_int32(hc, LC_BYTES, n);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_READ);
+ hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
+ hcc_leaf_int32(trans, LC_BYTES, n);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -707,7 +712,7 @@
}
static int
-rc_read(struct HostConf *hc, struct HCHead *head)
+rc_read(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
int *fdp = NULL;
@@ -718,7 +723,7 @@
for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
switch(item->leafid) {
case LC_DESCRIPTOR:
- fdp = hcc_get_descriptor(hc, HCC_INT32(item), HC_DESC_FD);
+ fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
break;
case LC_BYTES:
bytes = HCC_INT32(item);
@@ -734,7 +739,7 @@
head->error = errno;
return(0);
}
- hcc_leaf_data(hc, LC_DATA, buf, n);
+ hcc_leaf_data(trans, LC_DATA, buf, n);
return(0);
}
@@ -744,6 +749,7 @@
ssize_t
hc_write(struct HostConf *hc, int fd, const void *buf, size_t bytes)
{
+ hctransaction_t trans;
struct HCHead *head;
struct HCLeaf *item;
int *fdp;
@@ -759,10 +765,10 @@
int n = (bytes > 32768) ? 32768 : bytes;
int x = 0;
- hcc_start_command(hc, HC_WRITE);
- hcc_leaf_int32(hc, LC_DESCRIPTOR, fd);
- hcc_leaf_data(hc, LC_DATA, buf, n);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_WRITE);
+ hcc_leaf_int32(trans, LC_DESCRIPTOR, fd);
+ hcc_leaf_data(trans, LC_DATA, buf, n);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -788,7 +794,7 @@
}
static int
-rc_write(struct HostConf *hc, struct HCHead *head)
+rc_write(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
int *fdp = NULL;
@@ -798,7 +804,7 @@
for (item = hcc_firstitem(head); item; item = hcc_nextitem(head, item)) {
switch(item->leafid) {
case LC_DESCRIPTOR:
- fdp = hcc_get_descriptor(hc, HCC_INT32(item), HC_DESC_FD);
+ fdp = hcc_get_descriptor(trans->hc, HCC_INT32(item), HC_DESC_FD);
break;
case LC_DATA:
buf = HCC_BINARYDATA(item);
@@ -814,7 +820,7 @@
if (n < 0) {
head->error = errno;
} else {
- hcc_leaf_int32(hc, LC_BYTES, n);
+ hcc_leaf_int32(trans, LC_BYTES, n);
}
return(0);
}
@@ -825,14 +831,15 @@
int
hc_remove(struct HostConf *hc, const char *path)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(remove(path));
- hcc_start_command(hc, HC_REMOVE);
- hcc_leaf_string(hc, LC_PATH1, path);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_REMOVE);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -840,7 +847,7 @@
}
static int
-rc_remove(struct HostConf *hc __unused, struct HCHead *head)
+rc_remove(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
const char *path = NULL;
@@ -863,15 +870,16 @@
int
hc_mkdir(struct HostConf *hc __unused, const char *path, mode_t mode)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(mkdir(path, mode));
- hcc_start_command(hc, HC_MKDIR);
- hcc_leaf_string(hc, LC_PATH1, path);
- hcc_leaf_int32(hc, LC_MODE, mode);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_MKDIR);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ hcc_leaf_int32(trans, LC_MODE, mode);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -879,7 +887,7 @@
}
static int
-rc_mkdir(struct HostConf *hc __unused, struct HCHead *head)
+rc_mkdir(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
const char *path = NULL;
@@ -906,14 +914,15 @@
int
hc_rmdir(struct HostConf *hc, const char *path)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(rmdir(path));
- hcc_start_command(hc, HC_RMDIR);
- hcc_leaf_string(hc, LC_PATH1, path);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_RMDIR);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -921,7 +930,7 @@
}
static int
-rc_rmdir(struct HostConf *hc __unused, struct HCHead *head)
+rc_rmdir(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
const char *path = NULL;
@@ -944,16 +953,17 @@
int
hc_chown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(chown(path, owner, group));
- hcc_start_command(hc, HC_CHOWN);
- hcc_leaf_string(hc, LC_PATH1, path);
- hcc_leaf_int32(hc, LC_UID, owner);
- hcc_leaf_int32(hc, LC_GID, group);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_CHOWN);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ hcc_leaf_int32(trans, LC_UID, owner);
+ hcc_leaf_int32(trans, LC_GID, group);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -961,7 +971,7 @@
}
static int
-rc_chown(struct HostConf *hc __unused, struct HCHead *head)
+rc_chown(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
const char *path = NULL;
@@ -992,16 +1002,17 @@
int
hc_lchown(struct HostConf *hc, const char *path, uid_t owner, gid_t group)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(lchown(path, owner, group));
- hcc_start_command(hc, HC_LCHOWN);
- hcc_leaf_string(hc, LC_PATH1, path);
- hcc_leaf_int32(hc, LC_UID, owner);
- hcc_leaf_int32(hc, LC_GID, group);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_LCHOWN);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ hcc_leaf_int32(trans, LC_UID, owner);
+ hcc_leaf_int32(trans, LC_GID, group);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -1009,7 +1020,7 @@
}
static int
-rc_lchown(struct HostConf *hc __unused, struct HCHead *head)
+rc_lchown(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
const char *path = NULL;
@@ -1040,15 +1051,16 @@
int
hc_chmod(struct HostConf *hc, const char *path, mode_t mode)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(chmod(path, mode));
- hcc_start_command(hc, HC_CHMOD);
- hcc_leaf_string(hc, LC_PATH1, path);
- hcc_leaf_int32(hc, LC_MODE, mode);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_CHMOD);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ hcc_leaf_int32(trans, LC_MODE, mode);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -1056,7 +1068,7 @@
}
static int
-rc_chmod(struct HostConf *hc __unused, struct HCHead *head)
+rc_chmod(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
const char *path = NULL;
@@ -1083,15 +1095,16 @@
int
hc_link(struct HostConf *hc, const char *name1, const char *name2)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(link(name1, name2));
- hcc_start_command(hc, HC_LINK);
- hcc_leaf_string(hc, LC_PATH1, name1);
- hcc_leaf_string(hc, LC_PATH2, name2);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_LINK);
+ hcc_leaf_string(trans, LC_PATH1, name1);
+ hcc_leaf_string(trans, LC_PATH2, name2);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -1099,7 +1112,7 @@
}
static int
-rc_link(struct HostConf *hc __unused, struct HCHead *head)
+rc_link(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
const char *name1 = NULL;
@@ -1127,15 +1140,16 @@
int
hc_chflags(struct HostConf *hc, const char *path, u_long flags)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(chflags(path, flags));
- hcc_start_command(hc, HC_CHFLAGS);
- hcc_leaf_string(hc, LC_PATH1, path);
- hcc_leaf_int64(hc, LC_FILEFLAGS, flags);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_CHFLAGS);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ hcc_leaf_int64(trans, LC_FILEFLAGS, flags);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -1143,7 +1157,7 @@
}
static int
-rc_chflags(struct HostConf *hc __unused, struct HCHead *head)
+rc_chflags(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
const char *path = NULL;
@@ -1172,6 +1186,7 @@
int
hc_readlink(struct HostConf *hc, const char *path, char *buf, int bufsiz)
{
+ hctransaction_t trans;
struct HCHead *head;
struct HCLeaf *item;
int r;
@@ -1179,9 +1194,9 @@
if (hc == NULL || hc->host == NULL)
return(readlink(path, buf, bufsiz));
- hcc_start_command(hc, HC_READLINK);
- hcc_leaf_string(hc, LC_PATH1, path);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_READLINK);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -1203,7 +1218,7 @@
}
static int
-rc_readlink(struct HostConf *hc, struct HCHead *head)
+rc_readlink(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
const char *path = NULL;
@@ -1222,7 +1237,7 @@
r = readlink(path, buf, sizeof(buf));
if (r < 0)
return(-1);
- hcc_leaf_data(hc, LC_DATA, buf, r);
+ hcc_leaf_data(trans, LC_DATA, buf, r);
return(0);
}
@@ -1232,15 +1247,16 @@
mode_t
hc_umask(struct HostConf *hc, mode_t numask)
{
+ hctransaction_t trans;
struct HCHead *head;
struct HCLeaf *item;
if (hc == NULL || hc->host == NULL)
return(umask(numask));
- hcc_start_command(hc, HC_UMASK);
- hcc_leaf_int32(hc, LC_MODE, numask);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_UMASK);
+ hcc_leaf_int32(trans, LC_MODE, numask);
+ if ((head = hcc_finish_command(trans)) == NULL)
return((mode_t)-1);
if (head->error)
return((mode_t)-1);
@@ -1257,7 +1273,7 @@
}
static int
-rc_umask(struct HostConf *hc, struct HCHead *head)
+rc_umask(hctransaction_t trans, struct HCHead *head)
{
struct HCLeaf *item;
mode_t numask = ~0666;
@@ -1270,7 +1286,7 @@
}
}
numask = umask(numask);
- hcc_leaf_int32(hc, LC_MODE, numask);
+ hcc_leaf_int32(trans, LC_MODE, numask);
return(0);
}
@@ -1280,15 +1296,16 @@
int
hc_symlink(struct HostConf *hc, const char *name1, const char *name2)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(symlink(name1, name2));
- hcc_start_command(hc, HC_SYMLINK);
- hcc_leaf_string(hc, LC_PATH1, name1);
- hcc_leaf_string(hc, LC_PATH2, name2);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_SYMLINK);
+ hcc_leaf_string(trans, LC_PATH1, name1);
+ hcc_leaf_string(trans, LC_PATH2, name2);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -1296,7 +1313,7 @@
}
static int
-rc_symlink(struct HostConf *hc __unused, struct HCHead *head)
+rc_symlink(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
const char *name1 = NULL;
@@ -1323,15 +1340,16 @@
int
hc_rename(struct HostConf *hc, const char *name1, const char *name2)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(rename(name1, name2));
- hcc_start_command(hc, HC_RENAME);
- hcc_leaf_string(hc, LC_PATH1, name1);
- hcc_leaf_string(hc, LC_PATH2, name2);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_RENAME);
+ hcc_leaf_string(trans, LC_PATH1, name1);
+ hcc_leaf_string(trans, LC_PATH2, name2);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -1339,7 +1357,7 @@
}
static int
-rc_rename(struct HostConf *hc __unused, struct HCHead *head)
+rc_rename(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
const char *name1 = NULL;
@@ -1366,16 +1384,17 @@
int
hc_utimes(struct HostConf *hc, const char *path, const struct timeval *times)
{
+ hctransaction_t trans;
struct HCHead *head;
if (hc == NULL || hc->host == NULL)
return(utimes(path, times));
- hcc_start_command(hc, HC_UTIMES);
- hcc_leaf_string(hc, LC_PATH1, path);
- hcc_leaf_int64(hc, LC_ATIME, times[0].tv_sec);
- hcc_leaf_int64(hc, LC_MTIME, times[1].tv_sec);
- if ((head = hcc_finish_command(hc)) == NULL)
+ trans = hcc_start_command(hc, HC_UTIMES);
+ hcc_leaf_string(trans, LC_PATH1, path);
+ hcc_leaf_int64(trans, LC_ATIME, times[0].tv_sec);
+ hcc_leaf_int64(trans, LC_MTIME, times[1].tv_sec);
+ if ((head = hcc_finish_command(trans)) == NULL)
return(-1);
if (head->error)
return(-1);
@@ -1383,7 +1402,7 @@
}
static int
-rc_utimes(struct HostConf *hc __unused, struct HCHead *head)
+rc_utimes(hctransaction_t trans __unused, struct HCHead *head)
{
struct HCLeaf *item;
struct timeval times[2];
Index: hclink.h
===================================================================
RCS file: /home/cvs/src/bin/cpdup/hclink.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/hclink.h -L bin/cpdup/hclink.h -u -r1.1 -r1.2
--- bin/cpdup/hclink.h
+++ bin/cpdup/hclink.h
@@ -1,8 +1,8 @@
/*
* HCLINK.H
*
- * $MidnightBSD$
- * $DragonFly: src/bin/cpdup/hclink.h,v 1.1 2006/08/13 20:51:40 dillon Exp $
+ * $MIdnightBSD$
+ * $DragonFly: src/bin/cpdup/hclink.h,v 1.2 2008/04/10 22:09:08 dillon Exp $
*/
#ifndef _HCLINK_H_
@@ -15,23 +15,47 @@
void *data;
};
+struct HostConf;
+
+typedef struct HCTransaction {
+ struct HCTransaction *next;
+ struct HostConf *hc;
+ u_int16_t id; /* assigned transaction id */
+ int windex; /* output buffer index */
+ enum { HCT_IDLE, HCT_SENT, HCT_REPLIED } state;
+#if USE_PTHREADS
+ pthread_t tid;
+#endif
+ char rbuf[65536]; /* input buffer */
+ char wbuf[65536]; /* output buffer */
+} *hctransaction_t;
+
+#if USE_PTHREADS
+#define HCTHASH_SIZE 16
+#define HCTHASH_MASK (HCTHASH_SIZE - 1)
+#endif
+
struct HostConf {
- char *host; /* [user@]host */
- int fdin; /* pipe */
- int fdout; /* pipe */
- int error; /* permanent failure code */
- pid_t pid;
- int windex; /* output buffer index */
+ char *host; /* [user@]host */
+ int fdin; /* pipe */
+ int fdout; /* pipe */
+ int error; /* permanent failure code */
+ pid_t pid;
+ int version; /* cpdup protocol version */
struct HCHostDesc *hostdescs;
- char rbuf[65536]; /* output buffer */
- char wbuf[65536]; /* output buffer */
+#if USE_PTHREADS
+ pthread_mutex_t read_mutex;
+ hctransaction_t hct_hash[HCTHASH_SIZE];
+#else
+ struct HCTransaction trans;
+#endif
};
struct HCHead {
int32_t magic; /* magic number / byte ordering */
int32_t bytes; /* size of packet */
int16_t cmd; /* command code */
- int16_t id; /* transaction id */
+ u_int16_t id; /* transaction id */
int32_t error; /* error code (response) */
};
@@ -57,7 +81,7 @@
struct HCDesc {
int16_t cmd;
- int (*func)(struct HostConf *, struct HCHead *);
+ int (*func)(hctransaction_t, struct HCHead *);
};
/*
@@ -74,12 +98,12 @@
int hcc_connect(struct HostConf *hc);
int hcc_slave(int fdin, int fdout, struct HCDesc *descs, int count);
-void hcc_start_command(struct HostConf *hc, int16_t cmd);
-struct HCHead *hcc_finish_command(struct HostConf *hc);
-void hcc_leaf_string(struct HostConf *hc, int16_t leafid, const char *str);
-void hcc_leaf_data(struct HostConf *hc, int16_t leafid, const void *ptr, int bytes);
-void hcc_leaf_int32(struct HostConf *hc, int16_t leafid, int32_t value);
-void hcc_leaf_int64(struct HostConf *hc, int16_t leafid, int64_t value);
+hctransaction_t hcc_start_command(struct HostConf *hc, int16_t cmd);
+struct HCHead *hcc_finish_command(hctransaction_t trans);
+void hcc_leaf_string(hctransaction_t trans, int16_t leafid, const char *str);
+void hcc_leaf_data(hctransaction_t trans, int16_t leafid, const void *ptr, int bytes);
+void hcc_leaf_int32(hctransaction_t trans, int16_t leafid, int32_t value);
+void hcc_leaf_int64(hctransaction_t trans, int16_t leafid, int64_t value);
int hcc_alloc_descriptor(struct HostConf *hc, void *ptr, int type);
void *hcc_get_descriptor(struct HostConf *hc, int desc, int type);
Index: hcproto.h
===================================================================
RCS file: /home/cvs/src/bin/cpdup/hcproto.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/hcproto.h -L bin/cpdup/hcproto.h -u -r1.1 -r1.2
--- bin/cpdup/hcproto.h
+++ bin/cpdup/hcproto.h
@@ -2,7 +2,7 @@
* HCPROTO.H
*
* $MidnightBSD$
- * $DragonFly: src/bin/cpdup/hcproto.h,v 1.1 2006/08/13 20:51:40 dillon Exp $
+ * $DragonFly: src/bin/cpdup/hcproto.h,v 1.2 2008/04/10 22:09:08 dillon Exp $
*/
#ifndef _HCPROTO_H_
@@ -58,6 +58,7 @@
#define LC_DATA (0x0025|LCF_BINARY)
#define LC_TYPE (0x0026|LCF_INT32)
#define LC_BLKSIZE (0x0027|LCF_INT32)
+#define LC_VERSION (0x0028|LCF_INT32)
#define XO_NATIVEMASK 3 /* passed through directly */
#define XO_CREAT 0x00010000
Index: cpdup.1
===================================================================
RCS file: /home/cvs/src/bin/cpdup/cpdup.1,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/cpdup.1 -L bin/cpdup/cpdup.1 -u -r1.1 -r1.2
--- bin/cpdup/cpdup.1
+++ bin/cpdup/cpdup.1
@@ -2,10 +2,9 @@
.\" use and distribute based on the DragonFly copyright. Supplied as-is,
.\" USE WITH EXTREME CAUTION.
.\"
-.\"
.\" $MidnightBSD$
-.\" $DragonFly: src/bin/cpdup/cpdup.1,v 1.24 2007/05/13 18:33:55 swildner Exp $
-.Dd October 28, 1999
+.\" $DragonFly: src/bin/cpdup/cpdup.1,v 1.28 2008/04/10 22:09:08 dillon Exp $
+.Dd March 22, 2008
.Dt CPDUP 1
.Os
.Sh NAME
@@ -20,6 +19,7 @@
.Op Fl s0
.Op Fl i0
.Op Fl j0
+.Op Fl p<num>
.Op Fl q
.Op Fl o
.Op Fl m
@@ -31,6 +31,7 @@
.Fl M
.Ar file
.Oc
+.Op Fl V
.Op Fl S
.Op Fl k
.Oo
@@ -94,11 +95,17 @@
.It Fl s0
Disable the disallow-file-replaces-directory safety feature. This
safety feature is enabled by default to prevent user mistakes from blowing
-away everything accidently.
+away everything accidentally.
.It Fl i0
Do not request confirmation when removing something.
.It Fl j0
Do not try to recreate CHR or BLK devices.
+.It Fl l
+Line buffer verbose output.
+.It Fl p<number>
+Use threaded transactions with up to the specified number of threads.
+This typically improves operation when a remote host specification is
+given.
.It Fl q
Quiet operation
.It Fl o
@@ -122,8 +129,8 @@
via
.Ar path
is identical to the source.
-Note that a remote host specification should not be used in this option,
-but the path will be relative to the target machine.
+Note that a remote host specification should not be used for this option's
+path, but the path will be relative to the target machine.
.Pp
This allows one to use
.Nm
@@ -146,10 +153,25 @@
.Nm
must record the paths for all files it encounters while it operates
and it is possible that you may run the process out of memory.
+.Pp
+The file found vi the hardlink path will be byte-by-byte compared with the
+source if the
+.Fl V
+or
+.Fl f
+option is also used, otherwise only the stat info is checked to determine
+whether it matches the source.
.It Fl M Ar file
Works the same as
.Fl m
but allows you to specify the name of the MD5 checkfile.
+.It Fl V
+This forces the contents of regular files to be verified, even if the
+files appear to the be the same. Whereas the
+.Fl f
+(force) option forces a copy regardless, this option will avoid rewriting
+the target if everything matches and the contents are verified to be the
+same.
.It Fl S
This places
.Nm
Index: fsmid.c
===================================================================
RCS file: /home/cvs/src/bin/cpdup/fsmid.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/fsmid.c -L bin/cpdup/fsmid.c -u -r1.1 -r1.2
--- bin/cpdup/fsmid.c
+++ bin/cpdup/fsmid.c
@@ -4,8 +4,8 @@
* (c) Copyright 1997-1999,2006 by Matthew Dillon. Permission to
* use and distribute based on the FreeBSD copyright.
*
- * $MidnightBSD$
- * $DragonFly: src/bin/cpdup/fsmid.c,v 1.1 2006/04/25 21:30:45 dillon Exp $
+ * $MIdnightBSD$
+ * $DragonFly: src/bin/cpdup/fsmid.c,v 1.2 2008/03/22 18:09:16 dillon Exp $
*/
#include "cpdup.h"
@@ -123,7 +123,7 @@
* extracting fid_Name - name may contain embedded control
* characters.
*/
- CountReadBytes += nlen+1;
+ CountSourceReadBytes += nlen+1;
node->fid_Name = fextract(fi, nlen, &c, EOF);
if (c != '\n') {
fprintf(stderr, "Error parsing FSMID Cache: %s (%c)\n", FSMIDDCache, c);
Index: misc.c
===================================================================
RCS file: /home/cvs/src/bin/cpdup/misc.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/misc.c -L bin/cpdup/misc.c -u -r1.1 -r1.2
--- bin/cpdup/misc.c
+++ bin/cpdup/misc.c
@@ -1,8 +1,8 @@
/*
* MISC.C
*
- * $MidnightBSD$
- * $DragonFly: src/bin/cpdup/misc.c,v 1.8 2006/09/16 18:18:05 dillon Exp $
+ * $MIdnightBSD$
+ * $DragonFly: src/bin/cpdup/misc.c,v 1.11 2008/04/10 22:09:08 dillon Exp $
*/
#include "cpdup.h"
@@ -97,6 +97,9 @@
" -I display performance summary\n"
" -f force update even if files look the same\n"
" -i0 do NOT confirm when removing something\n"
+ " -l force line-buffered stdout/stderr\n"
+ " -pN N parallel transactions for for remote\n"
+ " source or destination\n"
" -s0 disable safeties - allow files to overwrite directories\n"
" -q quiet operation\n"
" -o do not remove any files, just overwrite/add\n"
@@ -108,10 +111,14 @@
" copying if the compare fails\n"
" -M file -m+specify MD5 checkfile, else .MD5_CHECKSUMS\n"
" copy if md5 check fails\n"
+ " -H path hardlink from path to target instead of copying\n"
+ " source to target, if source matches path.\n"
+ " -V verify file contents even if they appear\n"
+ " to be the same.\n"
#endif
" -x use .cpignore as exclusion file\n"
" -X file specify exclusion file\n"
- " Version 1.07 by Matt Dillon and Dima Ruban\n"
+ " Version 1.09 by Matt Dillon and Dima Ruban\n"
);
exit(0);
} else {
Index: cpdup.h
===================================================================
RCS file: /home/cvs/src/bin/cpdup/cpdup.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/cpdup.h -L bin/cpdup/cpdup.h -u -r1.1 -r1.2
--- bin/cpdup/cpdup.h
+++ bin/cpdup/cpdup.h
@@ -2,7 +2,7 @@
* CPDUP.H
*
* $MidnightBSD$
- * $DragonFly: src/bin/cpdup/cpdup.h,v 1.5 2006/08/18 01:13:51 dillon Exp $
+ * $DragonFly: src/bin/cpdup/cpdup.h,v 1.7 2008/04/10 22:09:08 dillon Exp $
*/
#include <sys/param.h>
@@ -26,6 +26,9 @@
#ifndef NOMD5
#include <md5.h>
#endif
+#if USE_PTHREADS
+#include <pthread.h>
+#endif
void logstd(const char *ctl, ...);
void logerr(const char *ctl, ...);
@@ -48,7 +51,11 @@
extern int64_t CountSourceBytes;
extern int64_t CountSourceItems;
extern int64_t CountCopiedItems;
-extern int64_t CountReadBytes;
+extern int64_t CountSourceReadBytes;
+extern int64_t CountTargetReadBytes;
extern int64_t CountWriteBytes;
extern int64_t CountRemovedItems;
+#if USE_PTHREADS
+extern pthread_mutex_t MasterMutex;
+#endif
Index: hclink.c
===================================================================
RCS file: /home/cvs/src/bin/cpdup/hclink.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/hclink.c -L bin/cpdup/hclink.c -u -r1.1 -r1.2
--- bin/cpdup/hclink.c
+++ bin/cpdup/hclink.c
@@ -4,24 +4,15 @@
* This module implements a simple remote control protocol
*
* $MidnightBSD$
- * $DragonFly: src/bin/cpdup/hclink.c,v 1.4 2007/01/17 02:34:10 pavalos Exp $
+ * $DragonFly: src/bin/cpdup/hclink.c,v 1.5 2008/04/10 22:09:08 dillon Exp $
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <assert.h>
-#include <errno.h>
-
+#include "cpdup.h"
#include "hclink.h"
#include "hcproto.h"
-static struct HCHead *hcc_read_command(struct HostConf *hc);
+static struct HCHead *hcc_read_command(hctransaction_t trans, int anypkt);
+static void hcc_start_reply(hctransaction_t trans, struct HCHead *rhead);
int
hcc_connect(struct HostConf *hc)
@@ -67,7 +58,7 @@
}
static int
-rc_badop(struct HostConf *hc __unused, struct HCHead *head)
+rc_badop(hctransaction_t trans __unused, struct HCHead *head)
{
head->error = EOPNOTSUPP;
return(0);
@@ -79,12 +70,14 @@
struct HostConf hcslave;
struct HCHead *head;
struct HCHead *whead;
- int (*dispatch[256])(struct HostConf *, struct HCHead *);
+ struct HCTransaction trans;
+ int (*dispatch[256])(hctransaction_t, struct HCHead *);
int aligned_bytes;
int i;
int r;
bzero(&hcslave, sizeof(hcslave));
+ bzero(&trans, sizeof(trans));
for (i = 0; i < count; ++i) {
struct HCDesc *desc = &descs[i];
assert(desc->cmd >= 0 && desc->cmd < 256);
@@ -96,6 +89,7 @@
}
hcslave.fdin = fdin;
hcslave.fdout = fdout;
+ trans.hc = &hcslave;
/*
* Process commands on fdin and write out results on fdout
@@ -104,7 +98,7 @@
/*
* Get the command
*/
- head = hcc_read_command(&hcslave);
+ head = hcc_read_command(&trans, 1);
if (head == NULL)
break;
@@ -112,8 +106,10 @@
* Start the reply and dispatch, then process the return code.
*/
head->error = 0;
- hcc_start_command(&hcslave, head->cmd | HCF_REPLY);
- r = dispatch[head->cmd & 255](&hcslave, head);
+ hcc_start_reply(&trans, head);
+
+ r = dispatch[head->cmd & 255](&trans, head);
+
switch(r) {
case -2:
head->error = EINVAL;
@@ -131,10 +127,10 @@
/*
* Write out the reply
*/
- whead = (void *)hcslave.wbuf;
- whead->bytes = hcslave.windex;
+ whead = (void *)trans.wbuf;
+ whead->bytes = trans.windex;
whead->error = head->error;
- aligned_bytes = HCC_ALIGN(hcslave.windex);
+ aligned_bytes = HCC_ALIGN(trans.windex);
#ifdef DEBUG
hcc_debug_dump(whead);
#endif
@@ -147,53 +143,175 @@
/*
* This reads a command from fdin, fixes up the byte ordering, and returns
* a pointer to HCHead.
+ *
+ * If id is -1 we do not match response id's
*/
static
struct HCHead *
-hcc_read_command(struct HostConf *hc)
+hcc_read_command(hctransaction_t trans, int anypkt)
{
- struct HCHead *head;
+ struct HostConf *hc = trans->hc;
+ hctransaction_t fill;
+ struct HCHead tmp;
int aligned_bytes;
int n;
int r;
- n = 0;
- while (n < (int)sizeof(struct HCHead)) {
- r = read(hc->fdin, hc->rbuf + n, sizeof(struct HCHead) - n);
- if (r <= 0)
- return(NULL);
- n += r;
- }
- head = (void *)hc->rbuf;
- assert(head->bytes >= (int)sizeof(*head) && head->bytes < 65536);
- assert(head->magic == HCMAGIC);
- aligned_bytes = HCC_ALIGN(head->bytes);
- while (n < aligned_bytes) {
- r = read(hc->fdin, hc->rbuf + n, aligned_bytes - n);
- if (r <= 0)
- return(NULL);
- n += r;
+#if USE_PTHREADS
+ /*
+ * Shortcut if the reply has already been read in by another thread.
+ */
+ if (trans->state == HCT_REPLIED) {
+ return((void *)trans->rbuf);
}
+ pthread_mutex_unlock(&MasterMutex);
+ pthread_mutex_lock(&hc->read_mutex);
+#endif
+ while (trans->state != HCT_REPLIED) {
+ n = 0;
+ while (n < (int)sizeof(struct HCHead)) {
+ r = read(hc->fdin, (char *)&tmp + n, sizeof(struct HCHead) - n);
+ if (r <= 0)
+ goto fail;
+ n += r;
+ }
+
+ assert(tmp.bytes >= (int)sizeof(tmp) && tmp.bytes < 65536);
+ assert(tmp.magic == HCMAGIC);
+
+ if (anypkt == 0 && tmp.id != trans->id && trans->hc->version > 0) {
+#if USE_PTHREADS
+ for (fill = trans->hc->hct_hash[tmp.id & HCTHASH_MASK];
+ fill;
+ fill = fill->next)
+ {
+ if (fill->state == HCT_SENT && fill->id == tmp.id)
+ break;
+ }
+ if (fill == NULL)
+#endif
+ {
+ fprintf(stderr,
+ "cpdup hlink protocol error with %s (%04x %04x)\n",
+ trans->hc->host, trans->id, tmp.id);
+ exit(1);
+ }
+ } else {
+ fill = trans;
+ }
+
+ bcopy(&tmp, fill->rbuf, n);
+ aligned_bytes = HCC_ALIGN(tmp.bytes);
+
+ while (n < aligned_bytes) {
+ r = read(hc->fdin, fill->rbuf + n, aligned_bytes - n);
+ if (r <= 0)
+ goto fail;
+ n += r;
+ }
#ifdef DEBUG
- hcc_debug_dump(head);
+ hcc_debug_dump(head);
+#endif
+ fill->state = HCT_REPLIED;
+ }
+#if USE_PTHREADS
+ pthread_mutex_lock(&MasterMutex);
+ pthread_mutex_unlock(&hc->read_mutex);
+#endif
+ return((void *)trans->rbuf);
+fail:
+#if USE_PTHREADS
+ pthread_mutex_lock(&MasterMutex);
+ pthread_mutex_unlock(&hc->read_mutex);
#endif
- return(head);
+ return(NULL);
+}
+
+#if USE_PTHREADS
+
+static
+hctransaction_t
+hcc_get_trans(struct HostConf *hc)
+{
+ hctransaction_t trans;
+ hctransaction_t scan;
+ pthread_t tid = pthread_self();
+ int i;
+
+ i = ((intptr_t)tid >> 7) & HCTHASH_MASK;
+
+ for (trans = hc->hct_hash[i]; trans; trans = trans->next) {
+ if (trans->tid == tid)
+ break;
+ }
+ if (trans == NULL) {
+ trans = malloc(sizeof(*trans));
+ bzero(trans, sizeof(*trans));
+ trans->tid = tid;
+ trans->id = i;
+ do {
+ for (scan = hc->hct_hash[i]; scan; scan = scan->next) {
+ if (scan->id == trans->id) {
+ trans->id += HCTHASH_SIZE;
+ break;
+ }
+ }
+ } while (scan != NULL);
+
+ trans->next = hc->hct_hash[i];
+ hc->hct_hash[i] = trans;
+ }
+ return(trans);
+}
+
+#else
+
+static
+hctransaction_t
+hcc_get_trans(struct HostConf *hc)
+{
+ return(&hc->trans);
}
+#endif
+
/*
* Initialize for a new command
*/
-void
+hctransaction_t
hcc_start_command(struct HostConf *hc, int16_t cmd)
{
- struct HCHead *whead = (void *)hc->wbuf;
+ struct HCHead *whead;
+ hctransaction_t trans;
+ trans = hcc_get_trans(hc);
+
+ whead = (void *)trans->wbuf;
whead->magic = HCMAGIC;
whead->bytes = 0;
whead->cmd = cmd;
- whead->id = 0;
+ whead->id = trans->id;
whead->error = 0;
- hc->windex = sizeof(*whead);
+
+ trans->windex = sizeof(*whead);
+ trans->hc = hc;
+ trans->state = HCT_IDLE;
+
+ return(trans);
+}
+
+static void
+hcc_start_reply(hctransaction_t trans, struct HCHead *rhead)
+{
+ struct HCHead *whead = (void *)trans->wbuf;
+
+ whead->magic = HCMAGIC;
+ whead->bytes = 0;
+ whead->cmd = rhead->cmd | HCF_REPLY;
+ whead->id = rhead->id;
+ whead->error = 0;
+
+ trans->windex = sizeof(*whead);
}
/*
@@ -201,16 +319,20 @@
* Return the HCHead of the reply.
*/
struct HCHead *
-hcc_finish_command(struct HostConf *hc)
+hcc_finish_command(hctransaction_t trans)
{
struct HCHead *whead;
struct HCHead *rhead;
int aligned_bytes;
+ int16_t wcmd;
+
+ whead = (void *)trans->wbuf;
+ whead->bytes = trans->windex;
+ aligned_bytes = HCC_ALIGN(trans->windex);
- whead = (void *)hc->wbuf;
- whead->bytes = hc->windex;
- aligned_bytes = HCC_ALIGN(hc->windex);
- if (write(hc->fdout, whead, aligned_bytes) != aligned_bytes) {
+ trans->state = HCT_SENT;
+
+ if (write(trans->hc->fdout, whead, aligned_bytes) != aligned_bytes) {
#ifdef __error
*__error = EIO;
#else
@@ -218,20 +340,28 @@
#endif
if (whead->cmd < 0x0010)
return(NULL);
- fprintf(stderr, "cpdup lost connection to %s\n", hc->host);
+ fprintf(stderr, "cpdup lost connection to %s\n", trans->hc->host);
exit(1);
}
- if ((rhead = hcc_read_command(hc)) == NULL) {
+
+ wcmd = whead->cmd;
+
+ /*
+ * whead is invalid when we call hcc_read_command() because
+ * we may switch to another thread.
+ */
+ if ((rhead = hcc_read_command(trans, 0)) == NULL) {
#ifdef __error
*__error = EIO;
#else
errno = EIO;
#endif
- if (whead->cmd < 0x0010)
+ if (wcmd < 0x0010)
return(NULL);
- fprintf(stderr, "cpdup lost connection to %s\n", hc->host);
+ fprintf(stderr, "cpdup lost connection to %s\n", trans->hc->host);
exit(1);
}
+
if (rhead->error) {
#ifdef __error
*__error = rhead->error;
@@ -243,60 +373,60 @@
}
void
-hcc_leaf_string(struct HostConf *hc, int16_t leafid, const char *str)
+hcc_leaf_string(hctransaction_t trans, int16_t leafid, const char *str)
{
struct HCLeaf *item;
int bytes = strlen(str) + 1;
- item = (void *)(hc->wbuf + hc->windex);
- assert(hc->windex + sizeof(*item) + bytes < 65536);
+ item = (void *)(trans->wbuf + trans->windex);
+ assert(trans->windex + sizeof(*item) + bytes < 65536);
item->leafid = leafid;
item->reserved = 0;
item->bytes = sizeof(*item) + bytes;
bcopy(str, item + 1, bytes);
- hc->windex = HCC_ALIGN(hc->windex + item->bytes);
+ trans->windex = HCC_ALIGN(trans->windex + item->bytes);
}
void
-hcc_leaf_data(struct HostConf *hc, int16_t leafid, const void *ptr, int bytes)
+hcc_leaf_data(hctransaction_t trans, int16_t leafid, const void *ptr, int bytes)
{
struct HCLeaf *item;
- item = (void *)(hc->wbuf + hc->windex);
- assert(hc->windex + sizeof(*item) + bytes < 65536);
+ item = (void *)(trans->wbuf + trans->windex);
+ assert(trans->windex + sizeof(*item) + bytes < 65536);
item->leafid = leafid;
item->reserved = 0;
item->bytes = sizeof(*item) + bytes;
bcopy(ptr, item + 1, bytes);
- hc->windex = HCC_ALIGN(hc->windex + item->bytes);
+ trans->windex = HCC_ALIGN(trans->windex + item->bytes);
}
void
-hcc_leaf_int32(struct HostConf *hc, int16_t leafid, int32_t value)
+hcc_leaf_int32(hctransaction_t trans, int16_t leafid, int32_t value)
{
struct HCLeaf *item;
- item = (void *)(hc->wbuf + hc->windex);
- assert(hc->windex + sizeof(*item) + sizeof(value) < 65536);
+ item = (void *)(trans->wbuf + trans->windex);
+ assert(trans->windex + sizeof(*item) + sizeof(value) < 65536);
item->leafid = leafid;
item->reserved = 0;
item->bytes = sizeof(*item) + sizeof(value);
*(int32_t *)(item + 1) = value;
- hc->windex = HCC_ALIGN(hc->windex + item->bytes);
+ trans->windex = HCC_ALIGN(trans->windex + item->bytes);
}
void
-hcc_leaf_int64(struct HostConf *hc, int16_t leafid, int64_t value)
+hcc_leaf_int64(hctransaction_t trans, int16_t leafid, int64_t value)
{
struct HCLeaf *item;
- item = (void *)(hc->wbuf + hc->windex);
- assert(hc->windex + sizeof(*item) + sizeof(value) < 65536);
+ item = (void *)(trans->wbuf + trans->windex);
+ assert(trans->windex + sizeof(*item) + sizeof(value) < 65536);
item->leafid = leafid;
item->reserved = 0;
item->bytes = sizeof(*item) + sizeof(value);
*(int64_t *)(item + 1) = value;
- hc->windex = HCC_ALIGN(hc->windex + item->bytes);
+ trans->windex = HCC_ALIGN(trans->windex + item->bytes);
}
int
Index: PORTING
===================================================================
RCS file: /home/cvs/src/bin/cpdup/PORTING,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/PORTING -L bin/cpdup/PORTING -u -r1.1 -r1.2
--- bin/cpdup/PORTING
+++ bin/cpdup/PORTING
@@ -1,4 +1,4 @@
-$MidnightBSD$
+$MIdnightBSD$
$DragonFly: src/bin/cpdup/PORTING,v 1.1 2006/09/16 21:57:08 dillon Exp $
PORTING CPDUP
Index: md5.c
===================================================================
RCS file: /home/cvs/src/bin/cpdup/md5.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/md5.c -L bin/cpdup/md5.c -u -r1.1 -r1.2
--- bin/cpdup/md5.c
+++ bin/cpdup/md5.c
@@ -5,8 +5,8 @@
* use and distribute based on the FreeBSD copyright. Supplied as-is,
* USE WITH EXTREME CAUTION.
*
- * $MidnightBSD$
- * $DragonFly: src/bin/cpdup/md5.c,v 1.1 2006/04/25 21:30:45 dillon Exp $
+ * $MIdnightBSD$
+ * $DragonFly: src/bin/cpdup/md5.c,v 1.2 2008/03/22 18:09:16 dillon Exp $
*/
#include "cpdup.h"
@@ -20,7 +20,7 @@
static MD5Node *md5_lookup(const char *sfile);
static void md5_cache(const char *spath, int sdirlen);
-static char *doMD5File(const char *filename, char *buf);
+static char *doMD5File(const char *filename, char *buf, int is_target);
static char *MD5SCache; /* cache source directory name */
static MD5Node *MD5Base;
@@ -127,7 +127,7 @@
* extracting md_Name - name may contain embedded control
* characters.
*/
- CountReadBytes += nlen+1;
+ CountSourceReadBytes += nlen+1;
node->md_Name = fextract(fi, nlen, &c, EOF);
if (c != '\n') {
fprintf(stderr, "Error parsing MD5 Cache: %s (%c)\n", MD5SCache, c);
@@ -206,7 +206,7 @@
*/
if (dpath == NULL) {
- char *scode = doMD5File(spath, NULL);
+ char *scode = doMD5File(spath, NULL, 0);
r = 0;
if (node->md_Code == NULL) {
@@ -229,16 +229,16 @@
*/
if (node->md_Code == NULL) {
- node->md_Code = doMD5File(spath, NULL);
+ node->md_Code = doMD5File(spath, NULL, 0);
MD5SCacheDirty = 1;
}
- dcode = doMD5File(dpath, NULL);
+ dcode = doMD5File(dpath, NULL, 1);
if (dcode) {
if (strcmp(node->md_Code, dcode) == 0) {
r = 0;
} else {
- char *scode = doMD5File(spath, NULL);
+ char *scode = doMD5File(spath, NULL, 0);
if (strcmp(node->md_Code, scode) == 0) {
free(scode);
@@ -256,15 +256,16 @@
}
char *
-doMD5File(const char *filename, char *buf)
+doMD5File(const char *filename, char *buf, int is_target)
{
if (SummaryOpt) {
struct stat st;
if (stat(filename, &st) == 0) {
- u_int64_t size = st.st_blocks * 512;
- if (st.st_size % 512)
- size += st.st_size % 512 - 512;
- CountReadBytes += size;
+ u_int64_t size = st.st_size;
+ if (is_target)
+ CountTargetReadBytes += size;
+ else
+ CountSourceReadBytes += size;
}
}
return MD5File(filename, buf);
Index: Makefile
===================================================================
RCS file: /home/cvs/src/bin/cpdup/Makefile,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/Makefile -L bin/cpdup/Makefile -u -r1.1 -r1.2
--- bin/cpdup/Makefile
+++ bin/cpdup/Makefile
@@ -1,10 +1,14 @@
# $MidnightBSD$
-# $DragonFly: src/bin/cpdup/Makefile,v 1.6 2006/08/13 20:51:40 dillon Exp $
+# $DragonFly: src/bin/cpdup/Makefile,v 1.7 2008/04/10 22:09:08 dillon Exp $
#
PROG= cpdup
SRCS= cpdup.c hcproto.c hclink.c misc.c fsmid.c
+.if !defined(NOPTHREADS)
+CFLAGS += -DUSE_PTHREADS=1 -pthread
+.endif
+
.if !defined(NOMD5)
SRCS+= md5.c
.endif
Index: cpdup.c
===================================================================
RCS file: /home/cvs/src/bin/cpdup/cpdup.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/cpdup.c -L bin/cpdup/cpdup.c -u -r1.1 -r1.2
--- bin/cpdup/cpdup.c
+++ bin/cpdup/cpdup.c
@@ -46,7 +46,7 @@
* the 'previous' version (supplied with -H path).
*
* $MidnightBSD$
- * $DragonFly: src/bin/cpdup/cpdup.c,v 1.18 2006/09/21 04:09:28 dillon Exp $
+ * $DragonFly: src/bin/cpdup/cpdup.c,v 1.20 2008/04/10 22:09:08 dillon Exp $
*/
/*-
@@ -60,7 +60,7 @@
#include "hclink.h"
#include "hcproto.h"
-#define HSIZE 16384
+#define HSIZE 8192
#define HMASK (HSIZE-1)
#define HLSIZE 8192
#define HLMASK (HLSIZE - 1)
@@ -90,6 +90,19 @@
char name[0];
};
+typedef struct copy_info {
+ char *spath;
+ char *dpath;
+ dev_t sdevNo;
+ dev_t ddevNo;
+#ifdef USE_PTHREADS
+ struct copy_info *parent;
+ pthread_cond_t cond;
+ int children;
+ int r;
+#endif
+} *copy_info_t;
+
struct hlink *hltable[HLSIZE];
void RemoveRecur(const char *dpath, dev_t devNo);
@@ -99,13 +112,14 @@
static struct hlink *hltlookup(struct stat *);
static struct hlink *hltadd(struct stat *, const char *);
static char *checkHLPath(struct stat *st, const char *spath, const char *dpath);
+static int validate_check(const char *spath, const char *dpath);
static int shash(const char *s);
static void hltdelete(struct hlink *);
int YesNo(const char *path);
static int xrename(const char *src, const char *dst, u_long flags);
static int xlink(const char *src, const char *dst, u_long flags);
int WildCmp(const char *s1, const char *s2);
-int DoCopy(const char *spath, const char *dpath, dev_t sdevNo, dev_t ddevNo);
+static int DoCopy(copy_info_t info);
int AskConfirmation = 1;
int SafetyOpt = 1;
@@ -120,6 +134,9 @@
int SlaveOpt;
int EnableDirectoryRetries;
int DstBaseLen;
+int ValidateOpt;
+int CurParallel;
+int MaxParallel = -1;
char IOBuf1[65536];
char IOBuf2[65536];
const char *UseCpFile;
@@ -130,13 +147,19 @@
int64_t CountSourceBytes;
int64_t CountSourceItems;
int64_t CountCopiedItems;
-int64_t CountReadBytes;
+int64_t CountSourceReadBytes;
+int64_t CountTargetReadBytes;
int64_t CountWriteBytes;
int64_t CountRemovedItems;
+int64_t CountLinkedItems;
struct HostConf SrcHost;
struct HostConf DstHost;
+#if USE_PTHREADS
+pthread_mutex_t MasterMutex;
+#endif
+
int
main(int ac, char **av)
{
@@ -145,9 +168,17 @@
char *dst = NULL;
char *ptr;
struct timeval start;
+ struct copy_info info;
signal(SIGPIPE, SIG_IGN);
+#if USE_PTHREADS
+ pthread_mutex_init(&SrcHost.read_mutex, NULL);
+ pthread_mutex_init(&DstHost.read_mutex, NULL);
+ pthread_mutex_init(&MasterMutex, NULL);
+ pthread_mutex_lock(&MasterMutex);
+#endif
+
gettimeofday(&start, NULL);
for (i = 1; i < ac; ++i) {
int v = 1;
@@ -179,6 +210,13 @@
if (*ptr >= '0' && *ptr <= '9')
VerboseOpt = strtol(ptr, NULL, 0);
break;
+ case 'l':
+ setlinebuf(stdout);
+ setlinebuf(stderr);
+ break;
+ case 'V':
+ ValidateOpt = v;
+ break;
case 'I':
SummaryOpt = v;
break;
@@ -206,6 +244,9 @@
case 'j':
DeviceOpt = v;
break;
+ case 'p':
+ MaxParallel = v;
+ break;
case 's':
SafetyOpt = v;
break;
@@ -283,12 +324,28 @@
fatal(NULL);
/* not reached */
}
+#if USE_PTHREADS
+ info.r = 0;
+ info.children = 0;
+ pthread_cond_init(&info.cond, NULL);
+#endif
if (dst) {
DstBaseLen = strlen(dst);
- i = DoCopy(src, dst, (dev_t)-1, (dev_t)-1);
+ info.spath = src;
+ info.dpath = dst;
+ info.sdevNo = (dev_t)-1;
+ info.ddevNo = (dev_t)-1;
+ i = DoCopy(&info);
} else {
- i = DoCopy(src, NULL, (dev_t)-1, (dev_t)-1);
+ info.spath = src;
+ info.dpath = NULL;
+ info.sdevNo = (dev_t)-1;
+ info.ddevNo = (dev_t)-1;
+ i = DoCopy(&info);
}
+#if USE_PTHREADS
+ pthread_cond_destroy(&info.cond);
+#endif
#ifndef NOMD5
md5_flush();
#endif
@@ -299,28 +356,35 @@
struct timeval end;
gettimeofday(&end, NULL);
+#if 0
+ /* don't count stat's in our byte statistics */
CountSourceBytes += sizeof(struct stat) * CountSourceItems;
- CountReadBytes += sizeof(struct stat) * CountSourceItems;
+ CountSourceReadBytes += sizeof(struct stat) * CountSourceItems;
CountWriteBytes += sizeof(struct stat) * CountCopiedItems;
CountWriteBytes += sizeof(struct stat) * CountRemovedItems;
+#endif
duration = end.tv_sec - start.tv_sec;
duration *= 1000000;
duration += end.tv_usec - start.tv_usec;
if (duration == 0) duration = 1;
logstd("cpdup completed successfully\n");
- logstd("%lld bytes source %lld bytes read %lld bytes written (%.1fX speedup)\n",
+ logstd("%lld bytes source, %lld src bytes read, %lld tgt bytes read\n"
+ "%lld bytes written (%.1fX speedup)\n",
(long long)CountSourceBytes,
- (long long)CountReadBytes,
+ (long long)CountSourceReadBytes,
+ (long long)CountTargetReadBytes,
(long long)CountWriteBytes,
- ((double)CountSourceBytes * 2.0) / ((double)(CountReadBytes + CountWriteBytes)));
- logstd("%lld source items %lld items copied %lld things deleted\n",
+ ((double)CountSourceBytes * 2.0) / ((double)(CountSourceReadBytes + CountTargetReadBytes + CountWriteBytes)));
+ logstd("%lld source items, %lld items copied, %lld items linked, "
+ "%lld things deleted\n",
(long long)CountSourceItems,
(long long)CountCopiedItems,
+ (long long)CountLinkedItems,
(long long)CountRemovedItems);
logstd("%.1f seconds %5d Kbytes/sec synced %5d Kbytes/sec scanned\n",
(float)duration / (float)1000000,
- (long)((long)1000000 * (CountReadBytes + CountWriteBytes) / duration / 1024.0),
+ (long)((long)1000000 * (CountSourceReadBytes + CountTargetReadBytes + CountWriteBytes) / duration / 1024.0),
(long)((long)1000000 * CountSourceBytes / duration / 1024.0));
}
exit((i == 0) ? 0 : 1);
@@ -396,9 +460,7 @@
{
struct stat sthl;
char *hpath;
- int fd1;
- int fd2;
- int good;
+ int error;
asprintf(&hpath, "%s%s", UseHLPath, dpath + DstBaseLen);
@@ -416,30 +478,11 @@
}
/*
- * If ForceOpt is set we have to compare the files
+ * If ForceOpt or ValidateOpt is set we have to compare the files
*/
- if (ForceOpt) {
- fd1 = hc_open(&SrcHost, spath, O_RDONLY, 0);
- fd2 = hc_open(&DstHost, hpath, O_RDONLY, 0);
- good = 0;
-
- if (fd1 >= 0 && fd2 >= 0) {
- int n;
-
- while ((n = hc_read(&SrcHost, fd1, IOBuf1, sizeof(IOBuf1))) > 0) {
- if (hc_read(&DstHost, fd2, IOBuf2, sizeof(IOBuf2)) != n)
- break;
- if (bcmp(IOBuf1, IOBuf2, n) != 0)
- break;
- }
- if (n == 0)
- good = 1;
- }
- if (fd1 >= 0)
- hc_close(&SrcHost, fd1);
- if (fd2 >= 0)
- hc_close(&DstHost, fd2);
- if (good == 0) {
+ if (ForceOpt || ValidateOpt) {
+ error = validate_check(spath, hpath);
+ if (error) {
free(hpath);
hpath = NULL;
}
@@ -447,37 +490,101 @@
return(hpath);
}
+/*
+ * Return 0 if the contents of the file <spath> matches the contents of
+ * the file <dpath>.
+ */
+static int
+validate_check(const char *spath, const char *dpath)
+{
+ int error;
+ int fd1;
+ int fd2;
+
+ fd1 = hc_open(&SrcHost, spath, O_RDONLY, 0);
+ fd2 = hc_open(&DstHost, dpath, O_RDONLY, 0);
+ error = -1;
+
+ if (fd1 >= 0 && fd2 >= 0) {
+ int n;
+ int x;
+
+ while ((n = hc_read(&SrcHost, fd1, IOBuf1, sizeof(IOBuf1))) > 0) {
+ CountSourceReadBytes += n;
+ x = hc_read(&DstHost, fd2, IOBuf2, sizeof(IOBuf2));
+ if (x > 0)
+ CountTargetReadBytes += x;
+ if (x != n)
+ break;
+ if (bcmp(IOBuf1, IOBuf2, n) != 0)
+ break;
+ }
+ if (n == 0)
+ error = 0;
+ }
+ if (fd1 >= 0)
+ hc_close(&SrcHost, fd1);
+ if (fd2 >= 0)
+ hc_close(&DstHost, fd2);
+ return (error);
+}
+#if USE_PTHREADS
+
+static void *
+DoCopyThread(void *arg)
+{
+ copy_info_t cinfo = arg;
+ char *spath = cinfo->spath;
+ char *dpath = cinfo->dpath;
+
+ pthread_cond_init(&cinfo->cond, NULL);
+ pthread_mutex_lock(&MasterMutex);
+ cinfo->r += DoCopy(cinfo);
+ /* cinfo arguments invalid on return */
+ --cinfo->parent->children;
+ --CurParallel;
+ pthread_cond_signal(&cinfo->parent->cond);
+ pthread_mutex_unlock(&MasterMutex);
+ free(spath);
+ if (dpath)
+ free(dpath);
+ pthread_cond_destroy(&cinfo->cond);
+ free(cinfo);
+ return(NULL);
+}
+
+#endif
+
int
-DoCopy(const char *spath, const char *dpath, dev_t sdevNo, dev_t ddevNo)
+DoCopy(copy_info_t info)
{
+ const char *spath = info->spath;
+ const char *dpath = info->dpath;
+ dev_t sdevNo = info->sdevNo;
+ dev_t ddevNo = info->ddevNo;
struct stat st1;
struct stat st2;
int r, mres, fres, st2Valid;
struct hlink *hln;
- List list;
+ List *list = malloc(sizeof(List));
u_int64_t size;
- InitList(&list);
+ InitList(list);
r = mres = fres = st2Valid = 0;
size = 0;
hln = NULL;
- if (hc_lstat(&SrcHost, spath, &st1) != 0)
- return(0);
-#ifdef SF_SNAPSHOT
- /* skip snapshot files: we cannot handle files larger than file system */
- if (st1.st_flags & SF_SNAPSHOT)
- return(0);
-#endif
+ if (hc_lstat(&SrcHost, spath, &st1) != 0) {
+ r = 0;
+ goto done;
+ }
st2.st_mode = 0; /* in case lstat fails */
st2.st_flags = 0; /* in case lstat fails */
if (dpath && hc_lstat(&DstHost, dpath, &st2) == 0)
st2Valid = 1;
if (S_ISREG(st1.st_mode)) {
- size = st1.st_blocks * 512;
- if (st1.st_size % 512)
- size += st1.st_size % 512 - 512;
+ size = st1.st_size;
}
/*
@@ -498,7 +605,8 @@
if (hln->nlinked == st1.st_nlink)
hltdelete(hln);
CountSourceItems++;
- return 0;
+ r = 0;
+ goto done;
} else {
/*
* hard link is not correct, attempt to unlink it
@@ -538,7 +646,8 @@
}
CountSourceItems++;
CountCopiedItems++;
- return 0;
+ r = 0;
+ goto done;
}
}
} else {
@@ -580,7 +689,8 @@
else
logstd("%-32s nochange\n", (dpath ? dpath : spath));
}
- return(0);
+ r = 0;
+ goto done;
}
#endif
} else {
@@ -590,11 +700,15 @@
st1.st_gid == st2.st_gid &&
st1.st_mtime == st2.st_mtime
#ifndef NOMD5
- && (UseMD5Opt == 0 || (mres = md5_check(spath, dpath)) == 0)
+ && (UseMD5Opt == 0 || !S_ISREG(st1.st_mode) ||
+ (mres = md5_check(spath, dpath)) == 0)
#endif
#ifdef _ST_FSMID_PRESENT_
- && (UseFSMIDOpt == 0 || (fres = fsmid_check(st1.st_fsmid, dpath)) == 0)
+ && (UseFSMIDOpt == 0 ||
+ (fres = fsmid_check(st1.st_fsmid, dpath)) == 0)
#endif
+ && (ValidateOpt == 0 || !S_ISREG(st1.st_mode) ||
+ validate_check(spath, dpath) == 0)
) {
if (hln)
hln->dino = st2.st_ino;
@@ -606,13 +720,15 @@
#endif
if (UseFSMIDOpt)
logstd("%-32s fsmid-nochange\n", (dpath ? dpath : spath));
+ else if (ValidateOpt)
+ logstd("%-32s nochange (contents validated)\n", (dpath ? dpath : spath));
else
logstd("%-32s nochange\n", (dpath ? dpath : spath));
}
CountSourceBytes += size;
CountSourceItems++;
-
- return(0);
+ r = 0;
+ goto done;
}
}
}
@@ -622,7 +738,8 @@
(dpath ? dpath : spath)
);
++r; /* XXX */
- return(0); /* continue with the cpdup anyway */
+ r = 0;
+ goto done; /* continue with the cpdup anyway */
}
if (QuietOpt == 0 || AskConfirmation) {
logstd("%-32s WARNING: non-directory source will blow away\n"
@@ -703,15 +820,15 @@
} else {
fpath = mprintf("%s/%s", spath, UseCpFile);
}
- AddList(&list, strrchr(fpath, '/') + 1, 1);
+ AddList(list, strrchr(fpath, '/') + 1, 1);
if ((fi = fopen(fpath, "r")) != NULL) {
while (fgets(buf, sizeof(buf), fi) != NULL) {
int l = strlen(buf);
- CountReadBytes += l;
+ CountSourceReadBytes += l;
if (l && buf[l-1] == '\n')
buf[--l] = 0;
if (buf[0] && buf[0] != '#')
- AddList(&list, buf, 1);
+ AddList(list, buf, 1);
}
fclose(fi);
}
@@ -726,9 +843,9 @@
* would otherwise overwrite the one we maintain on the target.
*/
if (UseMD5Opt)
- AddList(&list, MD5CacheFile, 1);
+ AddList(list, MD5CacheFile, 1);
if (UseFSMIDOpt)
- AddList(&list, FSMIDCacheFile, 1);
+ AddList(list, FSMIDCacheFile, 1);
while (noLoop == 0 && (den = hc_readdir(&SrcHost, dir)) != NULL) {
/*
@@ -745,25 +862,54 @@
/*
* ignore if on .cpignore list
*/
- if (AddList(&list, den->d_name, 0) == 1) {
+ if (AddList(list, den->d_name, 0) == 1) {
continue;
}
nspath = mprintf("%s/%s", spath, den->d_name);
if (dpath)
ndpath = mprintf("%s/%s", dpath, den->d_name);
- r += DoCopy(
- nspath,
- ndpath,
- sdevNo,
- ddevNo
- );
- free(nspath);
- if (ndpath)
- free(ndpath);
+
+#if USE_PTHREADS
+ if (CurParallel < MaxParallel) {
+ copy_info_t cinfo = malloc(sizeof(*cinfo));
+ pthread_t dummy_thr = NULL;
+
+ bzero(cinfo, sizeof(*cinfo));
+ cinfo->spath = nspath;
+ cinfo->dpath = ndpath;
+ cinfo->sdevNo = sdevNo;
+ cinfo->ddevNo = ddevNo;
+ cinfo->parent = info;
+ ++CurParallel;
+ ++info->children;
+ pthread_create(&dummy_thr, NULL, DoCopyThread, cinfo);
+ } else
+#endif
+ {
+ info->spath = nspath;
+ info->dpath = ndpath;
+ info->sdevNo = sdevNo;
+ info->ddevNo = ddevNo;
+ r += DoCopy(info);
+ free(nspath);
+ if (ndpath)
+ free(ndpath);
+ }
}
hc_closedir(&SrcHost, dir);
+#if USE_PTHREADS
+ /*
+ * Wait for our children to finish
+ */
+ while (info->children) {
+ pthread_cond_wait(&info->cond, &MasterMutex);
+ }
+ r += info->r;
+ info->r = 0;
+#endif
+
/*
* Remove files/directories from destination that do not appear
* in the source.
@@ -782,7 +928,7 @@
* If object does not exist in source or .cpignore
* then recursively remove it.
*/
- if (AddList(&list, den->d_name, 3) == 3) {
+ if (AddList(list, den->d_name, 3) == 3) {
char *ndpath;
ndpath = mprintf("%s/%s", dpath, den->d_name);
@@ -872,6 +1018,7 @@
if (st2Valid)
hc_remove(&DstHost, dpath);
if (hc_link(&DstHost, hpath, dpath) == 0) {
+ ++CountLinkedItems;
if (VerboseOpt) {
logstd("%-32s hardlinked(-H)\n",
(dpath ? dpath : spath));
@@ -936,7 +1083,7 @@
hc_chflags(&DstHost, dpath, st1.st_flags);
#endif
}
- CountReadBytes += size;
+ CountSourceReadBytes += size;
CountWriteBytes += size;
CountSourceBytes += size;
CountSourceItems++;
@@ -1015,8 +1162,9 @@
logstd("%-32s nochange\n", (dpath ? dpath : spath));
}
CountSourceBytes += n1;
- CountReadBytes += n1;
- if (n2 > 0) CountReadBytes += n2;
+ CountSourceReadBytes += n1;
+ if (n2 > 0)
+ CountTargetReadBytes += n2;
CountSourceItems++;
} else {
r = 1;
@@ -1060,7 +1208,9 @@
}
CountSourceItems++;
}
- ResetList(&list);
+done:
+ ResetList(list);
+ free(list);
return (r);
}
@@ -1341,6 +1491,8 @@
errno = e;
#endif
}
+ if (r == 0)
+ ++CountLinkedItems;
return(r);
}
Index: do_cleanup
===================================================================
RCS file: /home/cvs/src/bin/cpdup/scripts/do_cleanup,v
retrieving revision 1.1
retrieving revision 1.2
diff -L bin/cpdup/scripts/do_cleanup -L bin/cpdup/scripts/do_cleanup -u -r1.1 -r1.2
--- bin/cpdup/scripts/do_cleanup
+++ bin/cpdup/scripts/do_cleanup
@@ -1,6 +1,6 @@
#!/bin/csh
#
-# $MidnightBSD$
+# $MIdnightBSD$
# $DragonFly: src/bin/cpdup/scripts/do_cleanup,v 1.1 2006/09/16 21:57:10 dillon Exp $
source params
More information about the Midnightbsd-cvs
mailing list