759206909f0d8b8475d6a23f018d42b8dbba48a0
[rsync/rsync.git] / flist.c
1 /* 
2    Copyright (C) Andrew Tridgell 1996
3    Copyright (C) Paul Mackerras 1996
4    
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14    
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /* generate and receive file lists */
21
22 #include "rsync.h"
23
24 extern struct stats stats;
25
26 extern int csum_length;
27
28 extern int verbose;
29 extern int am_server;
30 extern int always_checksum;
31
32 extern int cvs_exclude;
33
34 extern int recurse;
35
36 extern int one_file_system;
37 extern int make_backups;
38 extern int preserve_links;
39 extern int preserve_hard_links;
40 extern int preserve_perms;
41 extern int preserve_devices;
42 extern int preserve_uid;
43 extern int preserve_gid;
44 extern int preserve_times;
45 extern int relative_paths;
46 extern int copy_links;
47 extern int remote_version;
48 extern int io_error;
49
50 static struct exclude_struct **local_exclude_list;
51
52 int link_stat(const char *Path, STRUCT_STAT *Buffer) 
53 {
54 #if SUPPORT_LINKS
55     if (copy_links) {
56         return do_stat(Path, Buffer);
57     } else {
58         return do_lstat(Path, Buffer);
59     }
60 #else
61     return do_stat(Path, Buffer);
62 #endif
63 }
64
65 /*
66   This function is used to check if a file should be included/excluded
67   from the list of files based on its name and type etc
68  */
69 static int match_file_name(char *fname,STRUCT_STAT *st)
70 {
71   if (check_exclude(fname,local_exclude_list,st)) {
72     if (verbose > 2)
73       rprintf(FINFO,"excluding file %s\n",fname);
74     return 0;
75   }
76   return 1;
77 }
78
79 /* used by the one_file_system code */
80 static dev_t filesystem_dev;
81
82 static void set_filesystem(char *fname)
83 {
84   STRUCT_STAT st;
85   if (link_stat(fname,&st) != 0) return;
86   filesystem_dev = st.st_dev;
87 }
88
89
90 static void send_directory(int f,struct file_list *flist,char *dir);
91
92 static char *flist_dir;
93
94
95 void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
96 {
97   unsigned char flags;
98   static time_t last_time;
99   static mode_t last_mode;
100   static dev_t last_rdev;
101   static uid_t last_uid;
102   static gid_t last_gid;
103   static char lastname[MAXPATHLEN];
104   char *fname;
105   int l1,l2;
106
107   if (f == -1) return;
108
109   if (!file) {
110     write_byte(f,0);
111     return;
112   }
113
114   fname = f_name(file);
115
116   flags = base_flags;
117
118   if (file->mode == last_mode) flags |= SAME_MODE;
119   if (file->rdev == last_rdev) flags |= SAME_RDEV;
120   if (file->uid == last_uid) flags |= SAME_UID;
121   if (file->gid == last_gid) flags |= SAME_GID;
122   if (file->modtime == last_time) flags |= SAME_TIME;
123
124   for (l1=0;lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);l1++) ;  
125   l2 = strlen(fname) - l1;
126
127   if (l1 > 0) flags |= SAME_NAME;
128   if (l2 > 255) flags |= LONG_NAME;
129
130   /* we must make sure we don't send a zero flags byte or the other
131      end will terminate the flist transfer */
132   if (flags == 0 && !S_ISDIR(file->mode)) flags |= FLAG_DELETE;
133   if (flags == 0) flags |= LONG_NAME;
134
135   write_byte(f,flags);  
136   if (flags & SAME_NAME)
137     write_byte(f,l1);
138   if (flags & LONG_NAME)
139     write_int(f,l2);
140   else
141     write_byte(f,l2);
142   write_buf(f,fname+l1,l2);
143
144   write_longint(f,file->length);
145   if (!(flags & SAME_TIME))
146     write_int(f,(int)file->modtime);
147   if (!(flags & SAME_MODE))
148     write_int(f,(int)file->mode);
149   if (preserve_uid && !(flags & SAME_UID)) {
150           add_uid(file->uid);
151           write_int(f,(int)file->uid);
152   }
153   if (preserve_gid && !(flags & SAME_GID)) {
154           add_gid(file->gid);
155           write_int(f,(int)file->gid);
156   }
157   if (preserve_devices && IS_DEVICE(file->mode) && !(flags & SAME_RDEV))
158     write_int(f,(int)file->rdev);
159
160 #if SUPPORT_LINKS
161   if (preserve_links && S_ISLNK(file->mode)) {
162     write_int(f,strlen(file->link));
163     write_buf(f,file->link,strlen(file->link));
164   }
165 #endif
166
167 #if SUPPORT_HARD_LINKS
168   if (preserve_hard_links && S_ISREG(file->mode)) {
169     write_int(f,(int)file->dev);
170     write_int(f,(int)file->inode);
171   }
172 #endif
173
174   if (always_checksum) {
175           write_buf(f,file->sum,csum_length);
176   }       
177
178   last_mode = file->mode;
179   last_rdev = file->rdev;
180   last_uid = file->uid;
181   last_gid = file->gid;
182   last_time = file->modtime;
183
184   strlcpy(lastname,fname,MAXPATHLEN-1);
185   lastname[MAXPATHLEN-1] = 0;
186 }
187
188
189
190 static void receive_file_entry(struct file_struct **fptr,
191                                unsigned flags,int f)
192 {
193   static time_t last_time;
194   static mode_t last_mode;
195   static dev_t last_rdev;
196   static uid_t last_uid;
197   static gid_t last_gid;
198   static char lastname[MAXPATHLEN];
199   char thisname[MAXPATHLEN];
200   int l1=0,l2=0;
201   char *p;
202   struct file_struct *file;
203
204   if (flags & SAME_NAME)
205     l1 = read_byte(f);
206   
207   if (flags & LONG_NAME)
208     l2 = read_int(f);
209   else
210     l2 = read_byte(f);
211
212   file = (struct file_struct *)malloc(sizeof(*file));
213   if (!file) out_of_memory("receive_file_entry");
214   bzero((char *)file,sizeof(*file));
215   (*fptr) = file;
216
217   if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry");
218
219   strlcpy(thisname,lastname,l1);
220   read_sbuf(f,&thisname[l1],l2);
221   thisname[l1+l2] = 0;
222
223   strlcpy(lastname,thisname,MAXPATHLEN-1);
224   lastname[MAXPATHLEN-1] = 0;
225
226   clean_fname(thisname);
227
228   if (relative_paths && thisname[0] == '/') {
229           /* strip / off absolute paths in destination */
230           memmove(thisname, thisname+1, strlen(thisname));
231           if (!thisname[0]) strcpy(thisname,".");
232   }
233
234   if ((p = strrchr(thisname,'/'))) {
235           static char *lastdir;
236           *p = 0;
237           if (lastdir && strcmp(thisname, lastdir)==0) {
238                   file->dirname = lastdir;
239           } else {
240                   file->dirname = strdup(thisname);
241                   lastdir = file->dirname;
242           }
243           file->basename = strdup(p+1);
244   } else {
245           file->dirname = NULL;
246           file->basename = strdup(thisname);
247   }
248
249   if (!file->basename) out_of_memory("receive_file_entry 1");
250
251
252   file->flags = flags;
253   file->length = read_longint(f);
254   file->modtime = (flags & SAME_TIME) ? last_time : (time_t)read_int(f);
255   file->mode = (flags & SAME_MODE) ? last_mode : (mode_t)read_int(f);
256   if (preserve_uid)
257     file->uid = (flags & SAME_UID) ? last_uid : (uid_t)read_int(f);
258   if (preserve_gid)
259     file->gid = (flags & SAME_GID) ? last_gid : (gid_t)read_int(f);
260   if (preserve_devices && IS_DEVICE(file->mode))
261     file->rdev = (flags & SAME_RDEV) ? last_rdev : (dev_t)read_int(f);
262
263   if (preserve_links && S_ISLNK(file->mode)) {
264     int l = read_int(f);
265     file->link = (char *)malloc(l+1);
266     if (!file->link) out_of_memory("receive_file_entry 2");
267     read_sbuf(f,file->link,l);
268   }
269
270 #if SUPPORT_HARD_LINKS
271   if (preserve_hard_links && S_ISREG(file->mode)) {
272     file->dev = read_int(f);
273     file->inode = read_int(f);
274   }
275 #endif
276   
277   if (always_checksum) {
278           file->sum = (char *)malloc(MD4_SUM_LENGTH);
279           if (!file->sum) out_of_memory("md4 sum");
280           read_buf(f,file->sum,csum_length);
281   }
282   
283   last_mode = file->mode;
284   last_rdev = file->rdev;
285   last_uid = file->uid;
286   last_gid = file->gid;
287   last_time = file->modtime;
288 }
289
290
291 /* determine if a file in a different filesstem should be skipped
292    when one_file_system is set. We bascally only want to include
293    the mount points - but they can be hard to find! */
294 static int skip_filesystem(char *fname, STRUCT_STAT *st)
295 {
296         STRUCT_STAT st2;
297         char *p = strrchr(fname, '/');
298
299         /* skip all but directories */
300         if (!S_ISDIR(st->st_mode)) return 1;
301
302         /* if its not a subdirectory then allow */
303         if (!p) return 0;
304
305         *p = 0;
306         if (link_stat(fname, &st2)) {
307                 *p = '/';
308                 return 0;
309         }
310         *p = '/';
311         
312         return (st2.st_dev != filesystem_dev);
313 }
314
315 static struct file_struct *make_file(char *fname)
316 {
317         struct file_struct *file;
318         STRUCT_STAT st;
319         char sum[SUM_LENGTH];
320         char *p;
321         char cleaned_name[MAXPATHLEN];
322
323         strlcpy(cleaned_name, fname, MAXPATHLEN-1);
324         cleaned_name[MAXPATHLEN-1] = 0;
325         clean_fname(cleaned_name);
326         fname = cleaned_name;
327
328         bzero(sum,SUM_LENGTH);
329
330         if (link_stat(fname,&st) != 0) {
331                 io_error = 1;
332                 rprintf(FERROR,"%s: %s\n",
333                         fname,strerror(errno));
334                 return NULL;
335         }
336
337         if (S_ISDIR(st.st_mode) && !recurse) {
338                 rprintf(FINFO,"skipping directory %s\n",fname);
339                 return NULL;
340         }
341         
342         if (one_file_system && st.st_dev != filesystem_dev) {
343                 if (skip_filesystem(fname, &st))
344                         return NULL;
345         }
346         
347         if (!match_file_name(fname,&st))
348                 return NULL;
349         
350         if (verbose > 2)
351                 rprintf(FINFO,"make_file(%s)\n",fname);
352         
353         file = (struct file_struct *)malloc(sizeof(*file));
354         if (!file) out_of_memory("make_file");
355         bzero((char *)file,sizeof(*file));
356
357         if ((p = strrchr(fname,'/'))) {
358                 static char *lastdir;
359                 *p = 0;
360                 if (lastdir && strcmp(fname, lastdir)==0) {
361                         file->dirname = lastdir;
362                 } else {
363                         file->dirname = strdup(fname);
364                         lastdir = file->dirname;
365                 }
366                 file->basename = strdup(p+1);
367                 *p = '/';
368         } else {
369                 file->dirname = NULL;
370                 file->basename = strdup(fname);
371         }
372
373         file->modtime = st.st_mtime;
374         file->length = st.st_size;
375         file->mode = st.st_mode;
376         file->uid = st.st_uid;
377         file->gid = st.st_gid;
378         file->dev = st.st_dev;
379         file->inode = st.st_ino;
380 #ifdef HAVE_ST_RDEV
381         file->rdev = st.st_rdev;
382 #endif
383
384 #if SUPPORT_LINKS
385         if (S_ISLNK(st.st_mode)) {
386                 int l;
387                 char lnk[MAXPATHLEN];
388                 if ((l=readlink(fname,lnk,MAXPATHLEN-1)) == -1) {
389                         io_error=1;
390                         rprintf(FERROR,"readlink %s : %s\n",
391                                 fname,strerror(errno));
392                         return NULL;
393                 }
394                 lnk[l] = 0;
395                 file->link = strdup(lnk);
396         }
397 #endif
398
399         if (always_checksum) {
400                 file->sum = (char *)malloc(MD4_SUM_LENGTH);
401                 if (!file->sum) out_of_memory("md4 sum");
402                 /* drat. we have to provide a null checksum for non-regular
403                    files in order to be compatible with earlier versions
404                    of rsync */
405                 if (S_ISREG(st.st_mode)) {
406                         file_checksum(fname,file->sum,st.st_size);
407                 } else {
408                         memset(file->sum, 0, MD4_SUM_LENGTH);
409                 }
410         }       
411
412         if (flist_dir) {
413                 static char *lastdir;
414                 if (lastdir && strcmp(lastdir, flist_dir)==0) {
415                         file->basedir = lastdir;
416                 } else {
417                         file->basedir = strdup(flist_dir);
418                         lastdir = file->basedir;
419                 }
420         } else {
421                 file->basedir = NULL;
422         }
423
424         if (!S_ISDIR(st.st_mode))
425                 stats.total_size += st.st_size;
426
427         return file;
428 }
429
430
431
432 static void send_file_name(int f,struct file_list *flist,char *fname,
433                            int recursive, unsigned base_flags)
434 {
435   struct file_struct *file;
436
437   file = make_file(fname);
438
439   if (!file) return;  
440   
441   if (flist->count >= flist->malloced) {
442           if (flist->malloced < 1000)
443                   flist->malloced += 1000;
444           else
445                   flist->malloced *= 2;
446           flist->files = (struct file_struct **)realloc(flist->files,
447                                                         sizeof(flist->files[0])*
448                                                         flist->malloced);
449           if (!flist->files)
450                   out_of_memory("send_file_name");
451   }
452
453   if (strcmp(file->basename,"")) {
454     flist->files[flist->count++] = file;
455     send_file_entry(file,f,base_flags);
456   }
457
458   if (S_ISDIR(file->mode) && recursive) {
459           struct exclude_struct **last_exclude_list = local_exclude_list;
460           send_directory(f,flist,f_name(file));
461           local_exclude_list = last_exclude_list;
462           return;
463   }
464 }
465
466
467
468 static void send_directory(int f,struct file_list *flist,char *dir)
469 {
470         DIR *d;
471         struct dirent *di;
472         char fname[MAXPATHLEN];
473         int l;
474         char *p;
475
476         d = opendir(dir);
477         if (!d) {
478                 io_error = 1;
479                 rprintf(FERROR,"opendir(%s): %s\n",
480                         dir,strerror(errno));
481                 return;
482         }
483
484         strlcpy(fname,dir,MAXPATHLEN-1);
485         l = strlen(fname);
486         if (fname[l-1] != '/') {
487                 if (l == MAXPATHLEN-1) {
488                         io_error = 1;
489                         rprintf(FERROR,"skipping long-named directory %s\n",fname);
490                         closedir(d);
491                         return;
492                 }
493                 strlcat(fname,"/", MAXPATHLEN-1);
494                 l++;
495         }
496         p = fname + strlen(fname);
497
498         if (cvs_exclude) {
499                 if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN-1) {
500                         strcpy(p,".cvsignore");
501                         local_exclude_list = make_exclude_list(fname,NULL,0,0);
502                 } else {
503                         io_error = 1;
504                         rprintf(FINFO,"cannot cvs-exclude in long-named directory %s\n",fname);
505                 }
506         }  
507         
508         for (di=readdir(d); di; di=readdir(d)) {
509                 char *dname = d_name(di);
510                 if (strcmp(dname,".")==0 ||
511                     strcmp(dname,"..")==0)
512                         continue;
513                 strlcpy(p,dname,MAXPATHLEN-(l+1));
514                 send_file_name(f,flist,fname,recurse,0);
515         }
516
517         closedir(d);
518 }
519
520
521
522 struct file_list *send_file_list(int f,int argc,char *argv[])
523 {
524         int i,l;
525         STRUCT_STAT st;
526         char *p,*dir;
527         char lastpath[MAXPATHLEN]="";
528         struct file_list *flist;
529         int64 start_write;
530
531         if (verbose && recurse && !am_server && f != -1) {
532                 rprintf(FINFO,"building file list ... ");
533                 rflush(FINFO);
534         }
535
536         start_write = stats.total_written;
537
538         flist = (struct file_list *)malloc(sizeof(flist[0]));
539         if (!flist) out_of_memory("send_file_list");
540
541         flist->count=0;
542         flist->malloced = 1000;
543         flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])*
544                                                      flist->malloced);
545         if (!flist->files) out_of_memory("send_file_list");
546
547         if (f != -1) {
548                 io_start_buffering(f);
549         }
550
551         for (i=0;i<argc;i++) {
552                 char fname2[MAXPATHLEN];
553                 char *fname = fname2;
554
555                 strlcpy(fname,argv[i],MAXPATHLEN-1);
556
557                 l = strlen(fname);
558                 if (l != 1 && fname[l-1] == '/') {
559                         strlcat(fname,".",MAXPATHLEN-1);
560                 }
561
562                 if (link_stat(fname,&st) != 0) {
563                         io_error=1;
564                         rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
565                         continue;
566                 }
567
568                 if (S_ISDIR(st.st_mode) && !recurse) {
569                         rprintf(FINFO,"skipping directory %s\n",fname);
570                         continue;
571                 }
572
573                 dir = NULL;
574
575                 if (!relative_paths) {
576                         p = strrchr(fname,'/');
577                         if (p) {
578                                 *p = 0;
579                                 if (p == fname) 
580                                         dir = "/";
581                                 else
582                                         dir = fname;      
583                                 fname = p+1;      
584                         }
585                 } else if (f != -1 && (p=strrchr(fname,'/'))) {
586                         /* this ensures we send the intermediate directories,
587                            thus getting their permissions right */
588                         *p = 0;
589                         if (strcmp(lastpath,fname)) {
590                                 strlcpy(lastpath, fname, sizeof(lastpath)-1);
591                                 *p = '/';
592                                 for (p=fname+1; (p=strchr(p,'/')); p++) {
593                                         int copy_links_saved = copy_links;
594                                         *p = 0;
595                                         copy_links = 0;
596                                         send_file_name(f, flist, fname, 0, 0);
597                                         copy_links = copy_links_saved;
598                                         *p = '/';
599                                 }
600                         } else {
601                                 *p = '/';
602                         }
603                 }
604                 
605                 if (!*fname)
606                         fname = ".";
607                 
608                 if (dir && *dir) {
609                         char *olddir = push_dir(dir, 1);
610
611                         if (!olddir) {
612                                 io_error=1;
613                                 rprintf(FERROR,"push_dir %s : %s\n",
614                                         dir,strerror(errno));
615                                 continue;
616                         }
617
618                         flist_dir = dir;
619                         if (one_file_system)
620                                 set_filesystem(fname);
621                         send_file_name(f,flist,fname,recurse,FLAG_DELETE);
622                         flist_dir = NULL;
623                         if (pop_dir(olddir) != 0) {
624                                 rprintf(FERROR,"pop_dir %s : %s\n",
625                                         dir,strerror(errno));
626                                 exit_cleanup(1);
627                         }
628                         continue;
629                 }
630                 
631                 if (one_file_system)
632                         set_filesystem(fname);
633                 send_file_name(f,flist,fname,recurse,FLAG_DELETE);
634         }
635
636         if (f != -1) {
637                 send_file_entry(NULL,f,0);
638         }
639
640         if (verbose && recurse && !am_server && f != -1)
641                 rprintf(FINFO,"done\n");
642         
643         clean_flist(flist);
644         
645         /* now send the uid/gid list. This was introduced in protocol
646            version 15 */
647         if (f != -1 && remote_version >= 15) {
648                 send_uid_list(f);
649         }
650
651         /* if protocol version is >= 17 then send the io_error flag */
652         if (f != -1 && remote_version >= 17) {
653                 write_int(f, io_error);
654         }
655
656         if (f != -1) {
657                 io_end_buffering(f);
658                 stats.flist_size = stats.total_written - start_write;
659                 stats.num_files = flist->count;
660         }
661
662         if (verbose > 2)
663                 rprintf(FINFO,"send_file_list done\n");
664
665         return flist;
666 }
667
668
669 struct file_list *recv_file_list(int f)
670 {
671   struct file_list *flist;
672   unsigned char flags;
673   int64 start_read;
674
675   if (verbose && recurse && !am_server) {
676     rprintf(FINFO,"receiving file list ... ");
677     rflush(FINFO);
678   }
679
680   start_read = stats.total_read;
681
682   flist = (struct file_list *)malloc(sizeof(flist[0]));
683   if (!flist)
684     goto oom;
685
686   flist->count=0;
687   flist->malloced=1000;
688   flist->files = (struct file_struct **)malloc(sizeof(flist->files[0])*
689                                                flist->malloced);
690   if (!flist->files)
691     goto oom;
692
693
694   for (flags=read_byte(f); flags; flags=read_byte(f)) {
695     int i = flist->count;
696
697     if (i >= flist->malloced) {
698           if (flist->malloced < 1000)
699                   flist->malloced += 1000;
700           else
701                   flist->malloced *= 2;
702           flist->files =(struct file_struct **)realloc(flist->files,
703                                                        sizeof(flist->files[0])*
704                                                        flist->malloced);
705           if (!flist->files)
706                   goto oom;
707     }
708
709     receive_file_entry(&flist->files[i],flags,f);
710
711     if (S_ISREG(flist->files[i]->mode))
712             stats.total_size += flist->files[i]->length;
713
714     flist->count++;
715
716     if (verbose > 2)
717       rprintf(FINFO,"recv_file_name(%s)\n",f_name(flist->files[i]));
718   }
719
720
721   if (verbose > 2)
722     rprintf(FINFO,"received %d names\n",flist->count);
723
724   clean_flist(flist);
725
726   if (verbose && recurse && !am_server) {
727     rprintf(FINFO,"done\n");
728   }
729
730   /* now recv the uid/gid list. This was introduced in protocol version 15 */
731   if (f != -1 && remote_version >= 15) {
732           recv_uid_list(f, flist);
733   }
734
735   /* if protocol version is >= 17 then recv the io_error flag */
736   if (f != -1 && remote_version >= 17) {
737           io_error |= read_int(f);
738   }
739
740   if (verbose > 2)
741     rprintf(FINFO,"recv_file_list done\n");
742
743   stats.flist_size = stats.total_read - start_read;
744   stats.num_files = flist->count;
745
746   return flist;
747
748 oom:
749     out_of_memory("recv_file_list");
750     return NULL; /* not reached */
751 }
752
753
754 int file_compare(struct file_struct **f1,struct file_struct **f2)
755 {
756         if (!(*f1)->basename && !(*f2)->basename) return 0;
757         if (!(*f1)->basename) return -1;
758         if (!(*f2)->basename) return 1;
759         if ((*f1)->dirname == (*f2)->dirname)
760                 return u_strcmp((*f1)->basename, (*f2)->basename);
761         return u_strcmp(f_name(*f1),f_name(*f2));
762 }
763
764
765 int flist_find(struct file_list *flist,struct file_struct *f)
766 {
767         int low=0,high=flist->count-1;
768
769         if (flist->count <= 0) return -1;
770
771         while (low != high) {
772                 int mid = (low+high)/2;
773                 int ret = file_compare(&flist->files[flist_up(flist, mid)],&f);
774                 if (ret == 0) return flist_up(flist, mid);
775                 if (ret > 0) {
776                         high=mid;
777                 } else {
778                         low=mid+1;
779                 }
780         }
781
782         if (file_compare(&flist->files[flist_up(flist,low)],&f) == 0)
783                 return flist_up(flist,low);
784         return -1;
785 }
786
787
788 /*
789  * free up one file
790  */
791 static void free_file(struct file_struct *file)
792 {
793         if (!file) return;
794         if (file->basename) free(file->basename);
795         if (file->link) free(file->link);
796         if (file->sum) free(file->sum);
797         bzero((char *)file, sizeof(*file));
798 }
799
800
801 /*
802  * free up all elements in a flist
803  */
804 void flist_free(struct file_list *flist)
805 {
806         int i;
807         for (i=1;i<flist->count;i++) {
808                 free_file(flist->files[i]);
809                 free(flist->files[i]);
810         }       
811         bzero((char *)flist->files, sizeof(flist->files[0])*flist->count);
812         free(flist->files);
813         bzero((char *)flist, sizeof(*flist));
814         free(flist);
815 }
816
817
818 /*
819  * This routine ensures we don't have any duplicate names in our file list.
820  * duplicate names can cause corruption because of the pipelining 
821  */
822 void clean_flist(struct file_list *flist)
823 {
824         int i;
825
826         if (!flist || flist->count == 0) 
827                 return;
828   
829         qsort(flist->files,flist->count,
830               sizeof(flist->files[0]),
831               (int (*)())file_compare);
832
833         for (i=1;i<flist->count;i++) {
834                 if (flist->files[i]->basename &&
835                     flist->files[i-1]->basename &&
836                     strcmp(f_name(flist->files[i]),
837                            f_name(flist->files[i-1])) == 0) {
838                         if (verbose > 1 && !am_server)
839                                 rprintf(FINFO,"removing duplicate name %s from file list %d\n",
840                                         f_name(flist->files[i-1]),i-1);
841                         free_file(flist->files[i]);
842                 } 
843         }
844 }
845
846
847 /*
848  * return the full filename of a flist entry
849  */
850 char *f_name(struct file_struct *f)
851 {
852         static char names[10][MAXPATHLEN];
853         static int n;
854         char *p = names[n];
855
856         if (!f || !f->basename) return NULL;
857
858         n = (n+1)%10;
859
860         if (f->dirname) {
861                 slprintf(p, MAXPATHLEN-1, "%s/%s", f->dirname, f->basename);
862         } else {
863                 strlcpy(p, f->basename, MAXPATHLEN-1);
864         }
865
866         return p;
867 }
868