Added the new --partial-dir option.
This commit is contained in:
@@ -111,7 +111,8 @@ void _exit_cleanup(int code, const char *file, int line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cleanup_got_literal && cleanup_fname && keep_partial) {
|
if (cleanup_got_literal && cleanup_fname && keep_partial
|
||||||
|
&& handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
|
||||||
char *fname = cleanup_fname;
|
char *fname = cleanup_fname;
|
||||||
cleanup_fname = NULL;
|
cleanup_fname = NULL;
|
||||||
if (cleanup_fd_r != -1)
|
if (cleanup_fd_r != -1)
|
||||||
|
|||||||
13
generator.c
13
generator.c
@@ -42,6 +42,7 @@ extern int size_only;
|
|||||||
extern int io_timeout;
|
extern int io_timeout;
|
||||||
extern int protocol_version;
|
extern int protocol_version;
|
||||||
extern int always_checksum;
|
extern int always_checksum;
|
||||||
|
extern char *partial_dir;
|
||||||
extern char *compare_dest;
|
extern char *compare_dest;
|
||||||
extern int link_dest;
|
extern int link_dest;
|
||||||
extern int whole_file;
|
extern int whole_file;
|
||||||
@@ -285,7 +286,7 @@ static void recv_generator(char *fname, struct file_struct *file, int i,
|
|||||||
statret = link_stat(fname, &st, keep_dirlinks && S_ISDIR(file->mode));
|
statret = link_stat(fname, &st, keep_dirlinks && S_ISDIR(file->mode));
|
||||||
stat_errno = errno;
|
stat_errno = errno;
|
||||||
|
|
||||||
if (only_existing && statret == -1 && errno == ENOENT) {
|
if (only_existing && statret == -1 && stat_errno == ENOENT) {
|
||||||
/* we only want to update existing files */
|
/* we only want to update existing files */
|
||||||
if (verbose > 1) {
|
if (verbose > 1) {
|
||||||
rprintf(FINFO, "not creating new file \"%s\"\n",
|
rprintf(FINFO, "not creating new file \"%s\"\n",
|
||||||
@@ -496,6 +497,16 @@ static void recv_generator(char *fname, struct file_struct *file, int i,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (partial_dir) {
|
||||||
|
STRUCT_STAT st2;
|
||||||
|
char *partialptr = partial_dir_fname(fname);
|
||||||
|
if (partialptr && link_stat(partialptr, &st2, 0) == 0
|
||||||
|
&& S_ISREG(st2.st_mode)) {
|
||||||
|
st = st2;
|
||||||
|
fnamecmp = partialptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* open the file */
|
/* open the file */
|
||||||
fd = do_open(fnamecmp, O_RDONLY, 0);
|
fd = do_open(fnamecmp, O_RDONLY, 0);
|
||||||
|
|
||||||
|
|||||||
19
options.c
19
options.c
@@ -118,6 +118,7 @@ unsigned int backup_dir_remainder;
|
|||||||
|
|
||||||
char *backup_suffix = NULL;
|
char *backup_suffix = NULL;
|
||||||
char *tmpdir = NULL;
|
char *tmpdir = NULL;
|
||||||
|
char *partial_dir = NULL;
|
||||||
char *compare_dest = NULL;
|
char *compare_dest = NULL;
|
||||||
char *config_file = NULL;
|
char *config_file = NULL;
|
||||||
char *shell_cmd = NULL;
|
char *shell_cmd = NULL;
|
||||||
@@ -268,6 +269,7 @@ void usage(enum logcode F)
|
|||||||
rprintf(F," --ignore-errors delete even if there are I/O errors\n");
|
rprintf(F," --ignore-errors delete even if there are I/O errors\n");
|
||||||
rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
|
rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
|
||||||
rprintf(F," --partial keep partially transferred files\n");
|
rprintf(F," --partial keep partially transferred files\n");
|
||||||
|
rprintf(F," --partial-dir=DIR put a partially transferred file into DIR\n");
|
||||||
rprintf(F," --force force deletion of directories even if not empty\n");
|
rprintf(F," --force force deletion of directories even if not empty\n");
|
||||||
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
|
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
|
||||||
rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
|
rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
|
||||||
@@ -383,6 +385,7 @@ static struct poptOption long_options[] = {
|
|||||||
{"stats", 0, POPT_ARG_NONE, &do_stats, 0, 0, 0 },
|
{"stats", 0, POPT_ARG_NONE, &do_stats, 0, 0, 0 },
|
||||||
{"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 },
|
{"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 },
|
||||||
{"partial", 0, POPT_ARG_NONE, &keep_partial, 0, 0, 0 },
|
{"partial", 0, POPT_ARG_NONE, &keep_partial, 0, 0, 0 },
|
||||||
|
{"partial-dir", 0, POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
|
||||||
{"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
|
{"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
|
||||||
{"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 },
|
{"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 },
|
||||||
{"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
|
{"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
|
||||||
@@ -718,6 +721,8 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
|||||||
(*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
|
(*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
|
||||||
if (tmpdir)
|
if (tmpdir)
|
||||||
tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
|
tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
|
||||||
|
if (partial_dir)
|
||||||
|
partial_dir = alloc_sanitize_path(partial_dir, curr_dir);
|
||||||
if (compare_dest)
|
if (compare_dest)
|
||||||
compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
|
compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
|
||||||
if (backup_dir)
|
if (backup_dir)
|
||||||
@@ -770,6 +775,11 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
|||||||
|
|
||||||
if (inplace) {
|
if (inplace) {
|
||||||
#if HAVE_FTRUNCATE
|
#if HAVE_FTRUNCATE
|
||||||
|
if (partial_dir) {
|
||||||
|
snprintf(err_buf, sizeof err_buf,
|
||||||
|
"--inplace cannot be used with --partial-dir\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
keep_partial = 0;
|
keep_partial = 0;
|
||||||
#else
|
#else
|
||||||
snprintf(err_buf, sizeof err_buf,
|
snprintf(err_buf, sizeof err_buf,
|
||||||
@@ -777,6 +787,10 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
|||||||
am_server ? "server" : "client");
|
am_server ? "server" : "client");
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
} else if (partial_dir) {
|
||||||
|
if (strcmp(partial_dir, ".") == 0)
|
||||||
|
partial_dir = NULL;
|
||||||
|
keep_partial = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files_from) {
|
if (files_from) {
|
||||||
@@ -969,7 +983,10 @@ void server_options(char **args,int *argc)
|
|||||||
args[ac++] = arg;
|
args[ac++] = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keep_partial)
|
if (partial_dir && am_sender) {
|
||||||
|
args[ac++] = "--partial-dir";
|
||||||
|
args[ac++] = partial_dir;
|
||||||
|
} else if (keep_partial)
|
||||||
args[ac++] = "--partial";
|
args[ac++] = "--partial";
|
||||||
|
|
||||||
if (force_delete)
|
if (force_delete)
|
||||||
|
|||||||
47
receiver.c
47
receiver.c
@@ -38,6 +38,7 @@ extern int preserve_perms;
|
|||||||
extern int cvs_exclude;
|
extern int cvs_exclude;
|
||||||
extern int io_error;
|
extern int io_error;
|
||||||
extern char *tmpdir;
|
extern char *tmpdir;
|
||||||
|
extern char *partial_dir;
|
||||||
extern char *compare_dest;
|
extern char *compare_dest;
|
||||||
extern int make_backups;
|
extern int make_backups;
|
||||||
extern int do_progress;
|
extern int do_progress;
|
||||||
@@ -340,7 +341,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
|
|||||||
char *fname, fbuf[MAXPATHLEN];
|
char *fname, fbuf[MAXPATHLEN];
|
||||||
char template[MAXPATHLEN];
|
char template[MAXPATHLEN];
|
||||||
char fnametmp[MAXPATHLEN];
|
char fnametmp[MAXPATHLEN];
|
||||||
char *fnamecmp;
|
char *fnamecmp, *partialptr;
|
||||||
char fnamecmpbuf[MAXPATHLEN];
|
char fnamecmpbuf[MAXPATHLEN];
|
||||||
struct file_struct *file;
|
struct file_struct *file;
|
||||||
struct stats initial_stats;
|
struct stats initial_stats;
|
||||||
@@ -408,8 +409,6 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
|
|||||||
if (verbose > 2)
|
if (verbose > 2)
|
||||||
rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname));
|
rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname));
|
||||||
|
|
||||||
fnamecmp = fname;
|
|
||||||
|
|
||||||
if (read_batch) {
|
if (read_batch) {
|
||||||
while (i > next_gen_i) {
|
while (i > next_gen_i) {
|
||||||
next_gen_i = read_int(batch_gen_fd);
|
next_gen_i = read_int(batch_gen_fd);
|
||||||
@@ -436,9 +435,22 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (partial_dir) {
|
||||||
|
if ((partialptr = partial_dir_fname(fname)) != NULL)
|
||||||
|
fnamecmp = partialptr;
|
||||||
|
else
|
||||||
|
fnamecmp = fname;
|
||||||
|
} else
|
||||||
|
fnamecmp = partialptr = fname;
|
||||||
|
|
||||||
/* open the file */
|
/* open the file */
|
||||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||||
|
|
||||||
|
if (fd1 == -1 && fnamecmp != fname) {
|
||||||
|
fnamecmp = fname;
|
||||||
|
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (fd1 == -1 && compare_dest != NULL) {
|
if (fd1 == -1 && compare_dest != NULL) {
|
||||||
/* try the file at compare_dest instead */
|
/* try the file at compare_dest instead */
|
||||||
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
|
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
|
||||||
@@ -526,7 +538,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup_set(fnametmp, fname, file, fd1, fd2);
|
if (partialptr)
|
||||||
|
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!am_server && verbose) /* log the transfer */
|
if (!am_server && verbose) /* log the transfer */
|
||||||
@@ -546,10 +559,20 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
|
|||||||
exit_cleanup(RERR_FILEIO);
|
exit_cleanup(RERR_FILEIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recv_ok || keep_partial || inplace)
|
if (recv_ok || inplace)
|
||||||
finish_transfer(fname, fnametmp, file, recv_ok);
|
finish_transfer(fname, fnametmp, file, recv_ok);
|
||||||
else
|
else if (keep_partial && partialptr
|
||||||
|
&& handle_partial_dir(partialptr, PDIR_CREATE))
|
||||||
|
finish_transfer(partialptr, fnametmp, file, 0);
|
||||||
|
else {
|
||||||
|
partialptr = NULL;
|
||||||
do_unlink(fnametmp);
|
do_unlink(fnametmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (partialptr != fname && fnamecmp == partialptr && recv_ok) {
|
||||||
|
do_unlink(partialptr);
|
||||||
|
handle_partial_dir(partialptr, PDIR_DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
cleanup_disable();
|
cleanup_disable();
|
||||||
|
|
||||||
@@ -557,9 +580,13 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
|
|||||||
int msgtype = csum_length == SUM_LENGTH || read_batch ?
|
int msgtype = csum_length == SUM_LENGTH || read_batch ?
|
||||||
FERROR : FINFO;
|
FERROR : FINFO;
|
||||||
if (msgtype == FERROR || verbose) {
|
if (msgtype == FERROR || verbose) {
|
||||||
char *errstr, *redostr;
|
char *errstr, *redostr, *keptstr;
|
||||||
char *keptstr = keep_partial || inplace ?
|
if (!(keep_partial && partialptr) && !inplace)
|
||||||
"retain" : "discard";
|
keptstr = "discarded";
|
||||||
|
else if (partial_dir)
|
||||||
|
keptstr = "put into partial-dir";
|
||||||
|
else
|
||||||
|
keptstr = "retained";
|
||||||
if (msgtype == FERROR) {
|
if (msgtype == FERROR) {
|
||||||
errstr = "ERROR";
|
errstr = "ERROR";
|
||||||
redostr = "";
|
redostr = "";
|
||||||
@@ -568,7 +595,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
|
|||||||
redostr = " (will try again)";
|
redostr = " (will try again)";
|
||||||
}
|
}
|
||||||
rprintf(msgtype,
|
rprintf(msgtype,
|
||||||
"%s: %s failed verification -- update %sed%s.\n",
|
"%s: %s failed verification -- update %s%s.\n",
|
||||||
errstr, safe_fname(fname),
|
errstr, safe_fname(fname),
|
||||||
keptstr, redostr);
|
keptstr, redostr);
|
||||||
}
|
}
|
||||||
|
|||||||
3
rsync.h
3
rsync.h
@@ -115,6 +115,9 @@
|
|||||||
#define FULL_FLUSH 1
|
#define FULL_FLUSH 1
|
||||||
#define NORMAL_FLUSH 0
|
#define NORMAL_FLUSH 0
|
||||||
|
|
||||||
|
#define PDIR_CREATE 1
|
||||||
|
#define PDIR_DELETE 0
|
||||||
|
|
||||||
|
|
||||||
/* Log-message categories. FLOG is only used on the daemon side to
|
/* Log-message categories. FLOG is only used on the daemon side to
|
||||||
* output messages to the log file. */
|
* output messages to the log file. */
|
||||||
|
|||||||
1
t_stub.c
1
t_stub.c
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
int modify_window = 0;
|
int modify_window = 0;
|
||||||
int module_id = -1;
|
int module_id = -1;
|
||||||
|
char *partial_dir;
|
||||||
struct exclude_list_struct server_exclude_list;
|
struct exclude_list_struct server_exclude_list;
|
||||||
|
|
||||||
void rprintf(UNUSED(enum logcode code), const char *format, ...)
|
void rprintf(UNUSED(enum logcode code), const char *format, ...)
|
||||||
|
|||||||
61
util.c
61
util.c
@@ -31,6 +31,7 @@ extern int verbose;
|
|||||||
extern int dry_run;
|
extern int dry_run;
|
||||||
extern int module_id;
|
extern int module_id;
|
||||||
extern int modify_window;
|
extern int modify_window;
|
||||||
|
extern char *partial_dir;
|
||||||
extern struct exclude_list_struct server_exclude_list;
|
extern struct exclude_list_struct server_exclude_list;
|
||||||
|
|
||||||
int sanitize_paths = 0;
|
int sanitize_paths = 0;
|
||||||
@@ -970,6 +971,66 @@ char *full_fname(const char *fn)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char partial_fname[MAXPATHLEN];
|
||||||
|
|
||||||
|
char *partial_dir_fname(const char *fname)
|
||||||
|
{
|
||||||
|
char *t = partial_fname;
|
||||||
|
int sz = sizeof partial_fname;
|
||||||
|
const char *fn;
|
||||||
|
|
||||||
|
if ((fn = strrchr(fname, '/')) != NULL) {
|
||||||
|
fn++;
|
||||||
|
if (*partial_dir != '/') {
|
||||||
|
int len = fn - fname;
|
||||||
|
strncpy(t, fname, len); /* safe */
|
||||||
|
t += len;
|
||||||
|
sz -= len;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
fn = fname;
|
||||||
|
if ((int)pathjoin(t, sz, partial_dir, fn) >= sz)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return partial_fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no --partial-dir option was specified, we don't need to do anything
|
||||||
|
* (the partial-dir is essentially '.'), so just return success. */
|
||||||
|
int handle_partial_dir(const char *fname, int create)
|
||||||
|
{
|
||||||
|
char *fn, *dir;
|
||||||
|
|
||||||
|
if (fname != partial_fname)
|
||||||
|
return 1;
|
||||||
|
if (!create && *partial_dir == '/')
|
||||||
|
return 1;
|
||||||
|
if (!(fn = strrchr(partial_fname, '/')))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
*fn = '\0';
|
||||||
|
dir = partial_fname;
|
||||||
|
if (create) {
|
||||||
|
STRUCT_STAT st;
|
||||||
|
#if SUPPORT_LINKS
|
||||||
|
int statret = do_lstat(dir, &st);
|
||||||
|
#else
|
||||||
|
int statret = do_stat(dir, &st);
|
||||||
|
#endif
|
||||||
|
if (statret == 0 && !S_ISDIR(st.st_mode)) {
|
||||||
|
if (do_unlink(dir) < 0)
|
||||||
|
return 0;
|
||||||
|
statret = -1;
|
||||||
|
}
|
||||||
|
if (statret < 0 && do_mkdir(dir, 0700) < 0)
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
do_rmdir(dir);
|
||||||
|
*fn = '/';
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/** We need to supply our own strcmp function for file list comparisons
|
/** We need to supply our own strcmp function for file list comparisons
|
||||||
to ensure that signed/unsigned usage is consistent between machines. */
|
to ensure that signed/unsigned usage is consistent between machines. */
|
||||||
int u_strcmp(const char *cs1, const char *cs2)
|
int u_strcmp(const char *cs1, const char *cs2)
|
||||||
|
|||||||
Reference in New Issue
Block a user