*** empty log message ***
authorAndrew Tridgell <tridge@samba.org>
Tue, 6 Jan 1998 16:53:52 +0000 (16:53 +0000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 6 Jan 1998 16:53:52 +0000 (16:53 +0000)
flist.c
rsync.c
rsync.h

diff --git a/flist.c b/flist.c
index 894cf16..40158fa 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -581,16 +581,6 @@ int file_compare(struct file_struct *f1,struct file_struct *f2)
 }
 
 
-/* we need this function because of the silly way in which duplicate
-   entries are handled in the file lists - we can't change this
-   without breaking existing versions */
-static int flist_up(struct file_list *flist, int i)
-{
-       while (!flist->files[i].name) i++;
-       return i;
-}
-
-
 int flist_find(struct file_list *flist,struct file_struct *f)
 {
        int low=0,high=flist->count-1;
diff --git a/rsync.c b/rsync.c
index 78022fb..673f141 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -551,6 +551,61 @@ static void delete_one(struct file_struct *f)
 }
 
 
+/* yuck! This function wouldn't have been necessary if I had the sorting
+   algorithm right. Unfortunately fixing the sorting algorithm would introduce
+   a backward incompatibility as file list indexes are sent over the link.
+
+   The aim is to see if a directory has already had the deletion algorithm applied
+   to it (due to recursion), and if so to skip it. The bisection is to 
+   prevent this being an n^2 algorithm */
+static int delete_already_done(struct file_list *flist,int j)
+{
+       int low=0,high=j-1;
+       char *name;
+       char *p;
+
+       if (j == 0) return 0;
+
+       name = strdup(flist->files[j].name);
+
+       if (!name) {
+               fprintf(FERROR,"out of memory in delete_already_done");
+               exit_cleanup(1);
+       }
+
+       p = strrchr(name,'/');
+       if (!p) {
+               free(name);
+               return 0;
+       }
+       *p = 0;
+
+       while (low != high) {
+               int mid = (low+high)/2;
+               int ret = strcmp(flist->files[flist_up(flist, mid)].name,name);
+               if (ret == 0) {
+                       free(name);
+                       return 1;
+               }
+               if (ret > 0) {
+                       high=mid;
+               } else {
+                       low=mid+1;
+               }
+       }
+
+       low = flist_up(flist, low);
+
+       if (strcmp(flist->files[low].name,name) == 0) {
+               free(name);
+               return 1;
+       }
+
+       free(name);
+       return 0;
+}
+
+
 /* this deletes any files on the receiving side that are not present
    on the sending side. For version 1.6.4 I have changed the behaviour
    to match more closely what most people seem to expect of this option */
@@ -558,23 +613,22 @@ static void delete_files(struct file_list *flist)
 {
   struct file_list *local_file_list;
   int i, j;
-  char *last_name=NULL;
 
   if (cvs_exclude)
     add_cvs_excludes();
 
   for (j=0;j<flist->count;j++) {
+         char *name = flist->files[j].name;
+
          if (!S_ISDIR(flist->files[j].mode)) continue;
-         if (strcmp(flist->files[j].name,".")==0) continue;
-         if (last_name &&
-             flist->files[j].name[strlen(last_name)] == '/' &&
-             strncmp(flist->files[j].name,last_name, strlen(last_name))==0)
-                 continue;
-         last_name = flist->files[j].name;
-         if (!(local_file_list = send_file_list(-1,1,&last_name)))
+
+         if (delete_already_done(flist, j)) continue;
+
+         if (!(local_file_list = send_file_list(-1,1,&name)))
                  continue;
+
          if (verbose > 1)
-                 fprintf(FINFO,"deleting in %s\n", last_name);
+                 fprintf(FINFO,"deleting in %s\n", name);
 
          for (i=local_file_list->count-1;i>=0;i--) {
                  if (!local_file_list->files[i].name) continue;
diff --git a/rsync.h b/rsync.h
index b9bca21..0b88103 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -248,6 +248,16 @@ struct map_struct {
   int fd,size,p_size,p_offset,p_len;
 };
 
+/* we need this function because of the silly way in which duplicate
+   entries are handled in the file lists - we can't change this
+   without breaking existing versions */
+static int flist_up(struct file_list *flist, int i)
+{
+       while (!flist->files[i].name) i++;
+       return i;
+}
+
+
 #include "byteorder.h"
 #include "version.h"
 #include "proto.h"