add the dummy file to .cvsignore
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index 8226b21..0aa1eea 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -26,7 +26,7 @@ extern int csum_length;
 extern int verbose;
 extern int am_server;
 extern int always_checksum;
-extern off_t total_size;
+extern int64 total_size;
 
 extern int cvs_exclude;
 
@@ -45,7 +45,7 @@ extern int relative_paths;
 extern int copy_links;
 extern int remote_version;
 
-static char **local_exclude_list = NULL;
+static char **local_exclude_list;
 
 int link_stat(const char *Path, struct stat *Buffer) 
 {
@@ -87,7 +87,7 @@ static void set_filesystem(char *fname)
 
 static void send_directory(int f,struct file_list *flist,char *dir);
 
-static char *flist_dir = NULL;
+static char *flist_dir;
 
 static void clean_fname(char *name)
 {
@@ -136,12 +136,12 @@ static void clean_fname(char *name)
 void send_file_entry(struct file_struct *file,int f)
 {
   unsigned char flags;
-  static time_t last_time=0;
-  static mode_t last_mode=0;
-  static dev_t last_rdev=0;
-  static uid_t last_uid=0;
-  static gid_t last_gid=0;
-  static char lastname[MAXPATHLEN]="";
+  static time_t last_time;
+  static mode_t last_mode;
+  static dev_t last_rdev;
+  static uid_t last_uid;
+  static gid_t last_gid;
+  static char lastname[MAXPATHLEN];
   char *fname;
   int l1,l2;
 
@@ -177,7 +177,7 @@ void send_file_entry(struct file_struct *file,int f)
     write_byte(f,l2);
   write_buf(f,fname+l1,l2);
 
-  write_int(f,(int)file->length);
+  write_longint(f,file->length);
   if (!(flags & SAME_TIME))
     write_int(f,(int)file->modtime);
   if (!(flags & SAME_MODE))
@@ -202,8 +202,8 @@ void send_file_entry(struct file_struct *file,int f)
 
 #if SUPPORT_HARD_LINKS
   if (preserve_hard_links && S_ISREG(file->mode)) {
-    write_int(f,file->dev);
-    write_int(f,file->inode);
+    write_int(f,(int)file->dev);
+    write_int(f,(int)file->inode);
   }
 #endif
 
@@ -226,11 +226,11 @@ void send_file_entry(struct file_struct *file,int f)
 void receive_file_entry(struct file_struct **fptr,
                        unsigned char flags,int f)
 {
-  static time_t last_time=0;
-  static mode_t last_mode=0;
-  static dev_t last_rdev=0;
-  static uid_t last_uid=0;
-  static gid_t last_gid=0;
+  static time_t last_time;
+  static mode_t last_mode;
+  static dev_t last_rdev;
+  static uid_t last_uid;
+  static gid_t last_gid;
   static char lastname[MAXPATHLEN];
   char thisname[MAXPATHLEN];
   int l1=0,l2=0;
@@ -277,7 +277,7 @@ void receive_file_entry(struct file_struct **fptr,
   if (!file->basename) out_of_memory("receive_file_entry 1");
 
 
-  file->length = (off_t)read_int(f);
+  file->length = read_longint(f);
   file->modtime = (flags & SAME_TIME) ? last_time : (time_t)read_int(f);
   file->mode = (flags & SAME_MODE) ? last_mode : (mode_t)read_int(f);
   if (preserve_uid)
@@ -423,7 +423,8 @@ static struct file_struct *make_file(char *fname)
 
 
 
-static void send_file_name(int f,struct file_list *flist,char *fname)
+static void send_file_name(int f,struct file_list *flist,char *fname,
+                          int recursive)
 {
   struct file_struct *file;
 
@@ -448,7 +449,7 @@ static void send_file_name(int f,struct file_list *flist,char *fname)
     send_file_entry(file,f);
   }
 
-  if (S_ISDIR(file->mode) && recurse) {
+  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;
@@ -501,7 +502,7 @@ static void send_directory(int f,struct file_list *flist,char *dir)
                    strcmp(di->d_name,"..")==0)
                        continue;
                strncpy(p,di->d_name,MAXPATHLEN-(l+1));
-               send_file_name(f,flist,fname);
+               send_file_name(f,flist,fname,recurse);
        }
 
        closedir(d);
@@ -511,107 +512,126 @@ static void send_directory(int f,struct file_list *flist,char *dir)
 
 struct file_list *send_file_list(int f,int argc,char *argv[])
 {
-  int i,l;
-  struct stat st;
-  char *p,*dir;
-  char dbuf[MAXPATHLEN];
-  struct file_list *flist;
-
-  if (verbose && recurse && !am_server && f != -1) {
-    fprintf(FINFO,"building file list ... ");
-    fflush(FINFO);
-  }
-
-  flist = (struct file_list *)malloc(sizeof(flist[0]));
-  if (!flist) out_of_memory("send_file_list");
-
-  flist->count=0;
-  flist->malloced = 1000;
-  flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])*
-                                              flist->malloced);
-  if (!flist->files) out_of_memory("send_file_list");
-
-  for (i=0;i<argc;i++) {
-    char fname2[MAXPATHLEN];
-    char *fname = fname2;
+       int i,l;
+       struct stat st;
+       char *p,*dir;
+       char dbuf[MAXPATHLEN];
+       char lastpath[MAXPATHLEN]="";
+       struct file_list *flist;
+
+       if (verbose && recurse && !am_server && f != -1) {
+               fprintf(FINFO,"building file list ... ");
+               fflush(FINFO);
+       }
 
-    strncpy(fname,argv[i],MAXPATHLEN-1);
-    fname[MAXPATHLEN-1] = 0;
+       flist = (struct file_list *)malloc(sizeof(flist[0]));
+       if (!flist) out_of_memory("send_file_list");
 
-    l = strlen(fname);
-    if (l != 1 && fname[l-1] == '/') {
-      strcat(fname,".");
-    }
+       flist->count=0;
+       flist->malloced = 1000;
+       flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])*
+                                                    flist->malloced);
+       if (!flist->files) out_of_memory("send_file_list");
 
-    if (link_stat(fname,&st) != 0) {
-      fprintf(FERROR,"%s : %s\n",fname,strerror(errno));
-      continue;
-    }
+       for (i=0;i<argc;i++) {
+               char fname2[MAXPATHLEN];
+               char *fname = fname2;
 
-    if (S_ISDIR(st.st_mode) && !recurse) {
-      fprintf(FERROR,"skipping directory %s\n",fname);
-      continue;
-    }
+               strncpy(fname,argv[i],MAXPATHLEN-1);
+               fname[MAXPATHLEN-1] = 0;
 
-    dir = NULL;
-
-    if (!relative_paths) {
-           p = strrchr(fname,'/');
-           if (p) {
-                   *p = 0;
-                   if (p == fname) 
-                           dir = "/";
-                   else
-                           dir = fname;      
-                   fname = p+1;      
-           }
-    }
-
-    if (!*fname)
-      fname = ".";
-
-    if (dir && *dir) {
-      if (getcwd(dbuf,MAXPATHLEN-1) == NULL) {
-       fprintf(FERROR,"getwd : %s\n",strerror(errno));
-       exit_cleanup(1);
-      }
-      if (chdir(dir) != 0) {
-       fprintf(FERROR,"chdir %s : %s\n",dir,strerror(errno));
-       continue;
-      }
-      flist_dir = dir;
-      if (one_file_system)
-       set_filesystem(fname);
-      send_file_name(f,flist,fname);
-      flist_dir = NULL;
-      if (chdir(dbuf) != 0) {
-       fprintf(FERROR,"chdir %s : %s\n",dbuf,strerror(errno));
-       exit_cleanup(1);
-      }
-      continue;
-    }
+               l = strlen(fname);
+               if (l != 1 && fname[l-1] == '/') {
+                       strcat(fname,".");
+               }
 
-    if (one_file_system)
-      set_filesystem(fname);
-    send_file_name(f,flist,fname);
-  }
+               if (link_stat(fname,&st) != 0) {
+                       fprintf(FERROR,"%s : %s\n",fname,strerror(errno));
+                       continue;
+               }
 
-  if (f != -1) {
-    send_file_entry(NULL,f);
-    write_flush(f);
-  }
+               if (S_ISDIR(st.st_mode) && !recurse) {
+                       fprintf(FERROR,"skipping directory %s\n",fname);
+                       continue;
+               }
 
-  if (verbose && recurse && !am_server && f != -1)
-    fprintf(FINFO,"done\n");
+               dir = NULL;
+
+               if (!relative_paths) {
+                       p = strrchr(fname,'/');
+                       if (p) {
+                               *p = 0;
+                               if (p == fname) 
+                                       dir = "/";
+                               else
+                                       dir = fname;      
+                               fname = p+1;      
+                       }
+               } else if (f != -1 && (p=strrchr(fname,'/'))) {
+                       /* this ensures we send the intermediate directories,
+                          thus getting their permissions right */
+                       *p = 0;
+                       if (strcmp(lastpath,fname)) {
+                               strcpy(lastpath, fname);
+                               *p = '/';
+                               for (p=fname+1; (p=strchr(p,'/')); p++) {
+                                       *p = 0;
+                                       send_file_name(f, flist, fname, 0);
+                                       *p = '/';
+                               }
+                       } else {
+                               *p = '/';
+                       }
+               }
+               
+               if (!*fname)
+                       fname = ".";
+               
+               if (dir && *dir) {
+                       if (getcwd(dbuf,MAXPATHLEN-1) == NULL) {
+                               fprintf(FERROR,"getwd : %s\n",strerror(errno));
+                               exit_cleanup(1);
+                       }
+                       if (chdir(dir) != 0) {
+                               fprintf(FERROR,"chdir %s : %s\n",
+                                       dir,strerror(errno));
+                               continue;
+                       }
+                       flist_dir = dir;
+                       if (one_file_system)
+                               set_filesystem(fname);
+                       send_file_name(f,flist,fname,recurse);
+                       flist_dir = NULL;
+                       if (chdir(dbuf) != 0) {
+                               fprintf(FERROR,"chdir %s : %s\n",
+                                       dbuf,strerror(errno));
+                               exit_cleanup(1);
+                       }
+                       continue;
+               }
+               
+               if (one_file_system)
+                       set_filesystem(fname);
+               send_file_name(f,flist,fname,recurse);
+       }
 
-  clean_flist(flist);
+       if (f != -1) {
+               send_file_entry(NULL,f);
+               write_flush(f);
+       }
 
-  /* now send the uid/gid list. This was introduced in protocol version 15 */
-  if (f != -1 && remote_version >= 15) {
-         send_uid_list(f);
-  }
+       if (verbose && recurse && !am_server && f != -1)
+               fprintf(FINFO,"done\n");
+       
+       clean_flist(flist);
+       
+       /* now send the uid/gid list. This was introduced in protocol
+           version 15 */
+       if (f != -1 && remote_version >= 15) {
+               send_uid_list(f);
+       }
 
-  return flist;
+       return flist;
 }
 
 
@@ -728,8 +748,8 @@ static void free_file(struct file_struct *file)
        if (!file) return;
        if (file->basename) free(file->basename);
        if (file->link) free(file->link);
+       if (file->sum) free(file->sum);
        bzero((char *)file, sizeof(*file));
-       free(file);
 }
 
 
@@ -741,6 +761,7 @@ void flist_free(struct file_list *flist)
        int i;
        for (i=1;i<flist->count;i++) {
                free_file(flist->files[i]);
+               free(flist->files[i]);
        }       
        bzero((char *)flist->files, sizeof(flist->files[0])*flist->count);
        free(flist->files);
@@ -766,13 +787,13 @@ void clean_flist(struct file_list *flist)
 
        for (i=1;i<flist->count;i++) {
                if (flist->files[i]->basename &&
+                   flist->files[i-1]->basename &&
                    strcmp(f_name(flist->files[i]),
                           f_name(flist->files[i-1])) == 0) {
                        if (verbose > 1 && !am_server)
                                fprintf(FERROR,"removing duplicate name %s from file list %d\n",
                                        f_name(flist->files[i-1]),i-1);
                        free_file(flist->files[i]);
-                       flist->files[i] = NULL;
                } 
        }
 }
@@ -787,7 +808,7 @@ char *f_name(struct file_struct *f)
        static int n;
        char *p = names[n];
 
-       if (!f) return NULL;
+       if (!f || !f->basename) return NULL;
 
        n = (n+1)%10;