X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/7796395a0aaa485ef4aa6e2dea1023ee3a273d36..5fb543d5879ec3ad8f3e68a92b1766ece1b8326a:/rsync.c diff --git a/rsync.c b/rsync.c index 16f80ed5..3b4ff1ba 100644 --- a/rsync.c +++ b/rsync.c @@ -60,6 +60,75 @@ static void free_sums(struct sum_struct *s) } +/* + * delete a file or directory. If force_delet is set then delete + * recursively + */ +static int delete_file(char *fname) +{ + DIR *d; + struct dirent *di; + char buf[MAXPATHLEN]; + extern int force_delete; + struct stat st; + int ret; + + if (do_unlink(fname) == 0 || errno == ENOENT) return 0; + +#if SUPPORT_LINKS + ret = lstat(fname, &st); +#else + ret = stat(fname, &st); +#endif + if (ret) { + fprintf(FERROR,"stat(%s) : %s\n", fname, strerror(errno)); + return -1; + } + + if (!S_ISDIR(st.st_mode)) { + fprintf(FERROR,"unlink(%s) : %s\n", fname, strerror(errno)); + return -1; + } + + if (do_rmdir(fname) == 0 || errno == ENOENT) return 0; + if (!force_delete || errno != ENOTEMPTY) { + fprintf(FERROR,"rmdir(%s) : %s\n", fname, strerror(errno)); + return -1; + } + + /* now we do a recsursive delete on the directory ... */ + d = opendir(fname); + if (!d) { + fprintf(FERROR,"opendir(%s): %s\n", + fname,strerror(errno)); + return -1; + } + + for (di=readdir(d); di; di=readdir(d)) { + if (strcmp(di->d_name,".")==0 || + strcmp(di->d_name,"..")==0) + continue; + strncpy(buf, fname, (MAXPATHLEN-strlen(di->d_name))-2); + strcat(buf, "/"); + strcat(buf, di->d_name); + buf[MAXPATHLEN-1] = 0; + if (verbose > 0) + fprintf(FINFO,"deleting %s\n", buf); + if (delete_file(buf) != 0) { + closedir(d); + return -1; + } + } + + closedir(d); + + if (do_rmdir(fname) != 0) { + fprintf(FERROR,"rmdir(%s) : %s\n", fname, strerror(errno)); + return -1; + } + + return 0; +} /* send a sums struct down a fd @@ -233,21 +302,24 @@ static int set_perms(char *fname,struct file_struct *file,struct stat *st, if ((am_root && preserve_uid && st->st_uid != file->uid) || (preserve_gid && st->st_gid != file->gid)) { - updated = 1; - if (do_lchown(fname, - (am_root&&preserve_uid)?file->uid:-1, - preserve_gid?file->gid:-1) != 0) { - if (verbose>1 || preserve_uid) - fprintf(FERROR,"chown %s : %s\n",fname,strerror(errno)); - return updated; - } + if (do_lchown(fname, + (am_root&&preserve_uid)?file->uid:-1, + preserve_gid?file->gid:-1) != 0) { + if (preserve_uid && st->st_uid != file->uid) + updated = 1; + if (verbose>1 || preserve_uid) + fprintf(FERROR,"chown %s : %s\n", + fname,strerror(errno)); + return updated; + } + updated = 1; } if (verbose > 1 && report) { - if (updated) - fprintf(FINFO,"%s\n",fname); - else - fprintf(FINFO,"%s is uptodate\n",fname); + if (updated) + fprintf(FINFO,"%s\n",fname); + else + fprintf(FINFO,"%s is uptodate\n",fname); } return updated; } @@ -337,7 +409,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out) } } } - do_unlink(fname); + delete_file(fname); if (do_symlink(file->link,fname) != 0) { fprintf(FERROR,"link %s -> %s : %s\n", fname,file->link,strerror(errno)); @@ -356,7 +428,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out) if (statret != 0 || st.st_mode != file->mode || st.st_rdev != file->rdev) { - do_unlink(fname); + delete_file(fname); if (verbose > 2) fprintf(FERROR,"mknod(%s,0%o,0x%x)\n", fname,(int)file->mode,(int)file->rdev); @@ -397,15 +469,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out) } if (!S_ISREG(st.st_mode)) { - /* its not a regular file on the receiving end, but it is on the - sending end. If its a directory then skip it (too dangerous to - do a recursive deletion??) otherwise try to unlink it */ - if (S_ISDIR(st.st_mode)) { - fprintf(FERROR,"ERROR: %s is a directory\n",fname); - return; - } - if (do_unlink(fname) != 0) { - fprintf(FERROR,"%s : not a regular file (generator)\n",fname); + if (delete_file(fname) != 0) { return; } @@ -868,14 +932,13 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) -off_t send_files(struct file_list *flist,int f_out,int f_in) +void send_files(struct file_list *flist,int f_out,int f_in) { int fd; struct sum_struct *s; struct map_struct *buf; struct stat st; char fname[MAXPATHLEN]; - off_t total=0; int i; struct file_struct *file; int phase = 0; @@ -910,7 +973,7 @@ off_t send_files(struct file_list *flist,int f_out,int f_in) if (strlen(fname) == MAXPATHLEN-1) { fprintf(FERROR, "send_files failed on long-named directory %s\n", fname); - return -1; + return; } strcat(fname,"/"); offset = strlen(file->basedir)+1; @@ -930,7 +993,7 @@ off_t send_files(struct file_list *flist,int f_out,int f_in) s = receive_sums(f_in); if (!s) { fprintf(FERROR,"receive_sums failed\n"); - return -1; + return; } fd = open(fname,O_RDONLY); @@ -946,7 +1009,7 @@ off_t send_files(struct file_list *flist,int f_out,int f_in) fprintf(FERROR,"fstat failed : %s\n",strerror(errno)); free_sums(s); close(fd); - return -1; + return; } if (st.st_size > 0) { @@ -981,8 +1044,6 @@ off_t send_files(struct file_list *flist,int f_out,int f_in) if (verbose > 2) fprintf(FERROR,"sender finished %s\n",fname); - - total += st.st_size; } if (verbose > 2) @@ -992,8 +1053,6 @@ off_t send_files(struct file_list *flist,int f_out,int f_in) write_int(f_out,-1); write_flush(f_out); - - return total; }