replace calls to strcmp() with a u_strcmp() function that uses only
[rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index cf4015191040e4d705a9c990fefa5001ad8f7af9..759206909f0d8b8475d6a23f018d42b8dbba48a0 100644 (file)
--- a/flist.c
+++ b/flist.c
 
 #include "rsync.h"
 
+extern struct stats stats;
+
 extern int csum_length;
 
 extern int verbose;
 extern int am_server;
 extern int always_checksum;
-extern int64 total_size;
 
 extern int cvs_exclude;
 
@@ -46,7 +47,7 @@ extern int copy_links;
 extern int remote_version;
 extern int io_error;
 
-static char **local_exclude_list;
+static struct exclude_struct **local_exclude_list;
 
 int link_stat(const char *Path, STRUCT_STAT *Buffer) 
 {
@@ -67,7 +68,7 @@ int link_stat(const char *Path, STRUCT_STAT *Buffer)
  */
 static int match_file_name(char *fname,STRUCT_STAT *st)
 {
-  if (check_exclude(fname,local_exclude_list)) {
+  if (check_exclude(fname,local_exclude_list,st)) {
     if (verbose > 2)
       rprintf(FINFO,"excluding file %s\n",fname);
     return 0;
@@ -90,49 +91,6 @@ static void send_directory(int f,struct file_list *flist,char *dir);
 
 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)
 {
@@ -163,12 +121,17 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
   if (file->gid == last_gid) flags |= SAME_GID;
   if (file->modtime == last_time) flags |= SAME_TIME;
 
-  for (l1=0;lastname[l1] && fname[l1] == lastname[l1];l1++) ;
+  for (l1=0;lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);l1++) ;  
   l2 = strlen(fname) - l1;
 
   if (l1 > 0) flags |= SAME_NAME;
   if (l2 > 255) flags |= LONG_NAME;
 
+  /* we must make sure we don't send a zero flags byte or the other
+     end will terminate the flist transfer */
+  if (flags == 0 && !S_ISDIR(file->mode)) flags |= FLAG_DELETE;
+  if (flags == 0) flags |= LONG_NAME;
+
   write_byte(f,flags);  
   if (flags & SAME_NAME)
     write_byte(f,l1);
@@ -262,6 +225,12 @@ static void receive_file_entry(struct file_struct **fptr,
 
   clean_fname(thisname);
 
+  if (relative_paths && thisname[0] == '/') {
+         /* strip / off absolute paths in destination */
+         memmove(thisname, thisname+1, strlen(thisname));
+         if (!thisname[0]) strcpy(thisname,".");
+  }
+
   if ((p = strrchr(thisname,'/'))) {
          static char *lastdir;
          *p = 0;
@@ -453,7 +422,7 @@ static struct file_struct *make_file(char *fname)
        }
 
        if (!S_ISDIR(st.st_mode))
-               total_size += st.st_size;
+               stats.total_size += st.st_size;
 
        return file;
 }
@@ -487,10 +456,10 @@ static void send_file_name(int f,struct file_list *flist,char *fname,
   }
 
   if (S_ISDIR(file->mode) && recursive) {
-    char **last_exclude_list = local_exclude_list;
-    send_directory(f,flist,f_name(file));
-    local_exclude_list = last_exclude_list;
-    return;
+         struct exclude_struct **last_exclude_list = local_exclude_list;
+         send_directory(f,flist,f_name(file));
+         local_exclude_list = last_exclude_list;
+         return;
   }
 }
 
@@ -507,7 +476,7 @@ static void send_directory(int f,struct file_list *flist,char *dir)
        d = opendir(dir);
        if (!d) {
                io_error = 1;
-               rprintf(FERROR,"%s: %s\n",
+               rprintf(FERROR,"opendir(%s): %s\n",
                        dir,strerror(errno));
                return;
        }
@@ -529,7 +498,7 @@ static void send_directory(int f,struct file_list *flist,char *dir)
        if (cvs_exclude) {
                if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN-1) {
                        strcpy(p,".cvsignore");
-                       local_exclude_list = make_exclude_list(fname,NULL,0);
+                       local_exclude_list = make_exclude_list(fname,NULL,0,0);
                } else {
                        io_error = 1;
                        rprintf(FINFO,"cannot cvs-exclude in long-named directory %s\n",fname);
@@ -542,7 +511,7 @@ static void send_directory(int f,struct file_list *flist,char *dir)
                    strcmp(dname,"..")==0)
                        continue;
                strlcpy(p,dname,MAXPATHLEN-(l+1));
-               send_file_name(f,flist,fname,recurse,FLAG_DELETE);
+               send_file_name(f,flist,fname,recurse,0);
        }
 
        closedir(d);
@@ -555,15 +524,17 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
        int i,l;
        STRUCT_STAT st;
        char *p,*dir;
-       char dbuf[MAXPATHLEN];
        char lastpath[MAXPATHLEN]="";
        struct file_list *flist;
+       int64 start_write;
 
        if (verbose && recurse && !am_server && f != -1) {
                rprintf(FINFO,"building file list ... ");
                rflush(FINFO);
        }
 
+       start_write = stats.total_written;
+
        flist = (struct file_list *)malloc(sizeof(flist[0]));
        if (!flist) out_of_memory("send_file_list");
 
@@ -619,8 +590,11 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
                                strlcpy(lastpath, fname, sizeof(lastpath)-1);
                                *p = '/';
                                for (p=fname+1; (p=strchr(p,'/')); p++) {
+                                       int copy_links_saved = copy_links;
                                        *p = 0;
+                                       copy_links = 0;
                                        send_file_name(f, flist, fname, 0, 0);
+                                       copy_links = copy_links_saved;
                                        *p = '/';
                                }
                        } else {
@@ -632,24 +606,23 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
                        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;
@@ -682,7 +655,8 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
 
        if (f != -1) {
                io_end_buffering(f);
-               write_flush(f);
+               stats.flist_size = stats.total_written - start_write;
+               stats.num_files = flist->count;
        }
 
        if (verbose > 2)
@@ -696,12 +670,15 @@ struct file_list *recv_file_list(int f)
 {
   struct file_list *flist;
   unsigned char flags;
+  int64 start_read;
 
   if (verbose && recurse && !am_server) {
     rprintf(FINFO,"receiving file list ... ");
     rflush(FINFO);
   }
 
+  start_read = stats.total_read;
+
   flist = (struct file_list *)malloc(sizeof(flist[0]));
   if (!flist)
     goto oom;
@@ -732,7 +709,7 @@ struct file_list *recv_file_list(int f)
     receive_file_entry(&flist->files[i],flags,f);
 
     if (S_ISREG(flist->files[i]->mode))
-      total_size += flist->files[i]->length;
+           stats.total_size += flist->files[i]->length;
 
     flist->count++;
 
@@ -763,6 +740,9 @@ struct file_list *recv_file_list(int f)
   if (verbose > 2)
     rprintf(FINFO,"recv_file_list done\n");
 
+  stats.flist_size = stats.total_read - start_read;
+  stats.num_files = flist->count;
+
   return flist;
 
 oom:
@@ -777,8 +757,8 @@ int file_compare(struct file_struct **f1,struct file_struct **f2)
        if (!(*f1)->basename) return -1;
        if (!(*f2)->basename) return 1;
        if ((*f1)->dirname == (*f2)->dirname)
-               return strcmp((*f1)->basename, (*f2)->basename);
-       return strcmp(f_name(*f1),f_name(*f2));
+               return u_strcmp((*f1)->basename, (*f2)->basename);
+       return u_strcmp(f_name(*f1),f_name(*f2));
 }