summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
0cfcfa2)
suggested on the list recently. See the man page entry for details but
basically it changes the behaviour so that paths are not stripped,
thus allowing you to specify a single rsync command to sync lots of
directories/files while preserving the full path name of each file.
also fixed a bug in the handling of umasks when both the source and
destination machines are local. We need to reset the umask before the
exec to ensure that the child gets a correct umask.
extern int preserve_uid;
extern int preserve_gid;
extern int preserve_times;
extern int preserve_uid;
extern int preserve_gid;
extern int preserve_times;
+extern int relative_paths;
static char **local_exclude_list = NULL;
static char **local_exclude_list = NULL;
- p = strrchr(fname,'/');
- if (p) {
- *p = 0;
- if (p == fname)
- dir = "/";
- else
- dir = fname;
- fname = p+1;
+
+ if (!relative_paths) {
+ p = strrchr(fname,'/');
+ if (p) {
+ *p = 0;
+ if (p == fname)
+ dir = "/";
+ else
+ dir = fname;
+ fname = p+1;
+ }
if (!*fname)
fname = ".";
if (!*fname)
fname = ".";
int do_compression=0;
int am_root=0;
int orig_umask=0;
int do_compression=0;
int am_root=0;
int orig_umask=0;
argstr[x++] = 'C';
if (ignore_times)
argstr[x++] = 'I';
argstr[x++] = 'C';
if (ignore_times)
argstr[x++] = 'I';
+ if (relative_paths)
+ argstr[x++] = 'R';
if (one_file_system)
argstr[x++] = 'x';
if (sparse_files)
if (one_file_system)
argstr[x++] = 'x';
if (sparse_files)
if (path && *path) {
char *dir = strdup(path);
p = strrchr(dir,'/');
if (path && *path) {
char *dir = strdup(path);
p = strrchr(dir,'/');
+ if (p && !relative_paths) {
*p = 0;
if (!dir[0])
args[argc++] = "/";
*p = 0;
if (!dir[0])
args[argc++] = "/";
if (stat(name,&st) == 0) {
if (S_ISDIR(st.st_mode)) {
if (chdir(name) != 0) {
if (stat(name,&st) == 0) {
if (S_ISDIR(st.st_mode)) {
if (chdir(name) != 0) {
- fprintf(FERROR,"chdir %s : %s\n",name,strerror(errno));
+ fprintf(FERROR,"chdir %s : %s (1)\n",name,strerror(errno));
exit_cleanup(1);
}
return NULL;
exit_cleanup(1);
}
return NULL;
return NULL;
if (mkdir(name,0777 & ~orig_umask) != 0) {
return NULL;
if (mkdir(name,0777 & ~orig_umask) != 0) {
- fprintf(FERROR,"mkdir %s : %s\n",name,strerror(errno));
+ fprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
exit_cleanup(1);
} else {
fprintf(FINFO,"created directory %s\n",name);
}
if (chdir(name) != 0) {
exit_cleanup(1);
} else {
fprintf(FINFO,"created directory %s\n",name);
}
if (chdir(name) != 0) {
- fprintf(FERROR,"chdir %s : %s\n",name,strerror(errno));
+ fprintf(FERROR,"chdir %s : %s (2)\n",name,strerror(errno));
if (verbose > 2)
fprintf(FERROR,"server_sender starting pid=%d\n",(int)getpid());
if (verbose > 2)
fprintf(FERROR,"server_sender starting pid=%d\n",(int)getpid());
- if (chdir(dir) != 0) {
- fprintf(FERROR,"chdir %s: %s\n",dir,strerror(errno));
+ if (!relative_paths && chdir(dir) != 0) {
+ fprintf(FERROR,"chdir %s: %s (3)\n",dir,strerror(errno));
exit_cleanup(1);
}
argc--;
exit_cleanup(1);
}
argc--;
argc--;
argv++;
if (chdir(dir) != 0) {
argc--;
argv++;
if (chdir(dir) != 0) {
- fprintf(FERROR,"chdir %s : %s\n",dir,strerror(errno));
+ fprintf(FERROR,"chdir %s : %s (4)\n",dir,strerror(errno));
fprintf(f,"-c, --checksum always checksum\n");
fprintf(f,"-a, --archive archive mode (same as -rlptDog)\n");
fprintf(f,"-r, --recursive recurse into directories\n");
fprintf(f,"-c, --checksum always checksum\n");
fprintf(f,"-a, --archive archive mode (same as -rlptDog)\n");
fprintf(f,"-r, --recursive recurse into directories\n");
+ fprintf(f,"-R, --relative use relative path names\n");
fprintf(f,"-b, --backup make backups (default ~ extension)\n");
fprintf(f,"-u, --update update only (don't overwrite newer files)\n");
fprintf(f,"-l, --links preserve soft links\n");
fprintf(f,"-b, --backup make backups (default ~ extension)\n");
fprintf(f,"-u, --update update only (don't overwrite newer files)\n");
fprintf(f,"-l, --links preserve soft links\n");
enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_RSYNC_PATH};
enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_RSYNC_PATH};
-static char *short_options = "oblHpguDCtcahvrIxnSe:B:z";
+static char *short_options = "oblHpguDCtcahvrRIxnSe:B:z";
static struct option long_options[] = {
{"version", 0, 0, OPT_VERSION},
static struct option long_options[] = {
{"version", 0, 0, OPT_VERSION},
{"update", 0, 0, 'u'},
{"verbose", 0, 0, 'v'},
{"recursive", 0, 0, 'r'},
{"update", 0, 0, 'u'},
{"verbose", 0, 0, 'v'},
{"recursive", 0, 0, 'r'},
+ {"relative", 0, 0, 'R'},
{"devices", 0, 0, 'D'},
{"perms", 0, 0, 'p'},
{"links", 0, 0, 'l'},
{"devices", 0, 0, 'D'},
{"perms", 0, 0, 'p'},
{"links", 0, 0, 'l'},
+ case 'R':
+ relative_paths = 1;
+ break;
+
case 'e':
shell_cmd = optarg;
break;
case 'e':
shell_cmd = optarg;
break;
extern int delete_mode;
extern int cvs_exclude;
extern int am_root;
extern int delete_mode;
extern int cvs_exclude;
extern int am_root;
+extern int relative_paths;
- if (statret != 0 && mkdir(fname,file->mode) != 0 && errno != EEXIST)
- fprintf(FERROR,"mkdir %s : %s\n",fname,strerror(errno));
+ if (statret != 0 && mkdir(fname,file->mode) != 0 && errno != EEXIST) {
+ if (!(relative_paths && errno==ENOENT &&
+ create_directory_path(fname)==0 &&
+ mkdir(fname,file->mode)==0)) {
+ fprintf(FERROR,"mkdir %s : %s (2)\n",
+ fname,strerror(errno));
+ }
+ }
if (set_perms(fname,file,NULL,0) && verbose)
fprintf(FINFO,"%s/\n",fname);
return;
if (set_perms(fname,file,NULL,0) && verbose)
fprintf(FINFO,"%s/\n",fname);
return;
continue;
}
fd2 = open(fnametmp,O_WRONLY|O_CREAT,file->mode);
continue;
}
fd2 = open(fnametmp,O_WRONLY|O_CREAT,file->mode);
+ if (relative_paths && errno == ENOENT &&
+ create_directory_path(fnametmp) == 0) {
+ fd2 = open(fnametmp,O_WRONLY|O_CREAT,file->mode);
+ }
if (fd2 == -1) {
fprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
receive_data(f_in,buf,-1,NULL);
if (fd2 == -1) {
fprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
receive_data(f_in,buf,-1,NULL);
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
}
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
}
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
execvp(command[0], command);
fprintf(FERROR,"Failed to exec %s : %s\n",
command[0],strerror(errno));
execvp(command[0], command);
fprintf(FERROR,"Failed to exec %s : %s\n",
command[0],strerror(errno));
return fcntl( fd, F_SETFL, val);
#undef FLAG_TO_SET
}
return fcntl( fd, F_SETFL, val);
#undef FLAG_TO_SET
}
+
+/****************************************************************************
+create any necessary directories in fname. Unfortunately we don't know
+what perms to give the directory when this is called so we need to rely
+on the umask
+****************************************************************************/
+int create_directory_path(char *fname)
+{
+ extern int orig_umask;
+ char *p;
+
+ while (*fname == '/') fname++;
+ while (strncmp(fname,"./",2)==0) fname += 2;
+
+ p = fname;
+ while ((p=strchr(p,'/'))) {
+ *p = 0;
+ mkdir(fname,0777 & ~orig_umask);
+ *p = '/';
+ p++;
+ }
+ return 0;
+}