{
extern char *config_file;
+ /* this ensures that we don't call getcwd after the chroot,
+ which doesn't work on platforms that use popen("pwd","r")
+ for getcwd */
+ push_dir("/", 0);
+
if (is_a_socket(STDIN_FILENO)) {
/* we are running via inetd */
return start_daemon(STDIN_FILENO);
static char *flist_dir;
-static void clean_fname(char *name)
-{
- char *p;
- int l;
- int modified = 1;
-
- if (!name) return;
-
- while (modified) {
- modified = 0;
-
- if ((p=strstr(name,"/./"))) {
- modified = 1;
- while (*p) {
- p[0] = p[2];
- p++;
- }
- }
-
- if ((p=strstr(name,"//"))) {
- modified = 1;
- while (*p) {
- p[0] = p[1];
- p++;
- }
- }
-
- if (strncmp(p=name,"./",2) == 0) {
- modified = 1;
- do {
- p[0] = p[2];
- } while (*p++);
- }
-
- l = strlen(p=name);
- if (l > 1 && p[l-1] == '/') {
- modified = 1;
- p[l-1] = 0;
- }
- }
-}
-
-
void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
{
int i,l;
STRUCT_STAT st;
char *p,*dir;
- char dbuf[MAXPATHLEN];
char lastpath[MAXPATHLEN]="";
struct file_list *flist;
fname = ".";
if (dir && *dir) {
- if (getcwd(dbuf,MAXPATHLEN-1) == NULL) {
- rprintf(FERROR,"getwd : %s\n",strerror(errno));
- exit_cleanup(1);
- }
- if (chdir(dir) != 0) {
+ char *olddir = push_dir(dir, 1);
+
+ if (!olddir) {
io_error=1;
- rprintf(FERROR,"chdir %s : %s\n",
+ rprintf(FERROR,"push_dir %s : %s\n",
dir,strerror(errno));
continue;
}
+
flist_dir = dir;
if (one_file_system)
set_filesystem(fname);
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
flist_dir = NULL;
- if (chdir(dbuf) != 0) {
- rprintf(FERROR,"chdir %s : %s\n",
- dbuf,strerror(errno));
+ if (pop_dir(olddir) != 0) {
+ rprintf(FERROR,"pop_dir %s : %s\n",
+ dir,strerror(errno));
exit_cleanup(1);
}
continue;
if (do_stat(name,&st) == 0) {
if (S_ISDIR(st.st_mode)) {
- if (chdir(name) != 0) {
- rprintf(FERROR,"chdir %s : %s (1)\n",
+ if (!push_dir(name, 0)) {
+ rprintf(FERROR,"push_dir %s : %s (1)\n",
name,strerror(errno));
exit_cleanup(1);
}
rprintf(FINFO,"created directory %s\n",name);
}
- if (chdir(name) != 0) {
- rprintf(FERROR,"chdir %s : %s (2)\n",name,strerror(errno));
+ if (!push_dir(name, 0)) {
+ rprintf(FERROR,"push_dir %s : %s (2)\n",
+ name,strerror(errno));
exit_cleanup(1);
}
if (verbose > 2)
rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
- if (!relative_paths && chdir(dir) != 0) {
- rprintf(FERROR,"chdir %s: %s (3)\n",dir,strerror(errno));
+ if (!relative_paths && !push_dir(dir, 0)) {
+ rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
exit_cleanup(1);
}
argc--;
dir = argv[0];
argc--;
argv++;
- if (!am_daemon && chdir(dir) != 0) {
- rprintf(FERROR,"chdir %s : %s (4)\n",
+ if (!am_daemon && !push_dir(dir, 0)) {
+ rprintf(FERROR,"push_dir %s : %s (4)\n",
dir,strerror(errno));
exit_cleanup(1);
}
rprintf(F,"Options:\n");
rprintf(F,"-v, --verbose increase verbosity\n");
rprintf(F,"-c, --checksum always checksum\n");
- rprintf(F,"-a, --archive archive mode (same as -rlptDog)\n");
+ rprintf(F,"-a, --archive archive mode\n");
rprintf(F,"-r, --recursive recurse into directories\n");
rprintf(F,"-R, --relative use relative path names\n");
rprintf(F,"-b, --backup make backups (default ~ extension)\n");
which already exist and have the same checksum and size on the
receiver are skipped. This option can be quite slow.
-dit(bf(-a, --archive)) This is equivalent to -rlptDog. It is a quick way
+dit(bf(-a, --archive)) This is equivalent to -rlptDg. It is a quick way
of saying I want recursion and want to preserve everything.
+Note: if the user launching rsync is root then the -o option (preserve
+uid) is also implied.
+
dit(bf(-r, --recursive)) This tells rsync to copy directories recursively
dit(bf(-R, --relative)) Use relative paths. This means that the full path
if (!p) return (void *)malloc(size);
return (void *)realloc(p, size);
}
+
+
+void clean_fname(char *name)
+{
+ char *p;
+ int l;
+ int modified = 1;
+
+ if (!name) return;
+
+ while (modified) {
+ modified = 0;
+
+ if ((p=strstr(name,"/./"))) {
+ modified = 1;
+ while (*p) {
+ p[0] = p[2];
+ p++;
+ }
+ }
+
+ if ((p=strstr(name,"//"))) {
+ modified = 1;
+ while (*p) {
+ p[0] = p[1];
+ p++;
+ }
+ }
+
+ if (strncmp(p=name,"./",2) == 0) {
+ modified = 1;
+ do {
+ p[0] = p[2];
+ } while (*p++);
+ }
+
+ l = strlen(p=name);
+ if (l > 1 && p[l-1] == '/') {
+ modified = 1;
+ p[l-1] = 0;
+ }
+ }
+}
+
+
+static char curr_dir[MAXPATHLEN];
+
+/* like chdir() but can be reversed with pop_dir() if save is set. It
+ is also much faster as it remembers where we have been */
+char *push_dir(char *dir, int save)
+{
+ char *ret = curr_dir;
+ static int initialised;
+
+ if (!initialised) {
+ initialised = 1;
+ getcwd(curr_dir, sizeof(curr_dir)-1);
+ }
+
+ if (chdir(dir)) return NULL;
+
+ if (save) {
+ ret = strdup(curr_dir);
+ }
+
+ if (*dir == '/') {
+ strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
+ } else {
+ strlcat(curr_dir,"/", sizeof(curr_dir)-1);
+ strlcat(curr_dir,dir, sizeof(curr_dir)-1);
+ }
+
+ clean_fname(curr_dir);
+
+ return ret;
+}
+
+/* reverse a push_dir call */
+int pop_dir(char *dir)
+{
+ int ret;
+
+ ret = chdir(dir);
+ if (ret) {
+ free(dir);
+ return ret;
+ }
+
+ strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
+
+ free(dir);
+
+ return 0;
+}