*** empty log message ***
[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 int csum_length;
25
26 extern int verbose;
27 extern int am_server;
28 extern int always_checksum;
29 extern off_t total_size;
30
31 extern int cvs_exclude;
32
33 extern int recurse;
34
35 extern int one_file_system;
36 extern int make_backups;
37 extern int preserve_links;
38 extern int preserve_hard_links;
39 extern int preserve_perms;
40 extern int preserve_devices;
41 extern int preserve_uid;
42 extern int preserve_gid;
43 extern int preserve_times;
44
45 static char **local_exclude_list = NULL;
46
47 static void clean_fname(char *name);
48
49
50 /*
51   This function is used to check if a file should be included/excluded
52   from the list of files based on its name and type etc
53  */
54 static int match_file_name(char *fname,struct stat *st)
55 {
56   if (check_exclude(fname,local_exclude_list)) {
57     if (verbose > 2)
58       fprintf(FERROR,"excluding file %s\n",fname);
59     return 0;
60   }
61   return 1;
62 }
63
64 /* used by the one_file_system code */
65 static dev_t filesystem_dev;
66
67 static void set_filesystem(char *fname)
68 {
69   struct stat st;
70   if (lstat(fname,&st) != 0) return;
71   filesystem_dev = st.st_dev;
72 }
73
74
75 static void send_directory(int f,struct file_list *flist,char *dir);
76
77 static char *flist_dir = NULL;
78
79 extern void (*send_file_entry)(struct file_struct *file,int f);
80 extern void (*receive_file_entry)(struct file_struct *file,
81                                   unsigned char flags,int f);
82
83
84 void send_file_entry_v11(struct file_struct *file,int f)
85 {
86   unsigned char flags;
87   static time_t last_time=0;
88   static mode_t last_mode=0;
89   static dev_t last_rdev=0;
90   static uid_t last_uid=0;
91   static gid_t last_gid=0;
92   static char lastname[MAXPATHLEN]="";
93   int l1,l2;
94
95   if (f == -1) return;
96
97   if (!file) {
98     write_byte(f,0);
99     return;
100   }
101
102   flags = FILE_VALID;
103
104   if (file->mode == last_mode) flags |= SAME_MODE;
105   if (file->rdev == last_rdev) flags |= SAME_RDEV;
106   if (file->uid == last_uid) flags |= SAME_UID;
107   if (file->gid == last_gid) flags |= SAME_GID;
108   if (file->modtime == last_time) flags |= SAME_TIME;
109
110   for (l1=0;lastname[l1] && file->name[l1] == lastname[l1];l1++) ;
111   l2 = strlen(file->name) - l1;
112
113   if (l1 > 0) flags |= SAME_NAME;
114   if (l2 > 255) flags |= LONG_NAME;
115
116   write_byte(f,flags);  
117   if (flags & SAME_NAME)
118     write_byte(f,l1);
119   if (flags & LONG_NAME)
120     write_int(f,l2);
121   else
122     write_byte(f,l2);
123   write_buf(f,file->name+l1,l2);
124
125   write_int(f,(int)file->length);
126   if (!(flags & SAME_TIME))
127     write_int(f,(int)file->modtime);
128   if (!(flags & SAME_MODE))
129     write_int(f,(int)file->mode);
130   if (preserve_uid && !(flags & SAME_UID))
131     write_int(f,(int)file->uid);
132   if (preserve_gid && !(flags & SAME_GID))
133     write_int(f,(int)file->gid);
134   if (preserve_devices && IS_DEVICE(file->mode) && !(flags & SAME_RDEV))
135     write_int(f,(int)file->rdev);
136
137 #if SUPPORT_LINKS
138   if (preserve_links && S_ISLNK(file->mode)) {
139     write_int(f,strlen(file->link));
140     write_buf(f,file->link,strlen(file->link));
141   }
142 #endif
143
144 #if SUPPORT_HARD_LINKS
145   if (preserve_hard_links && S_ISREG(file->mode)) {
146     write_int(f,file->dev);
147     write_int(f,file->inode);
148   }
149 #endif
150
151   if (always_checksum) {
152     write_buf(f,file->sum,csum_length);
153   }       
154
155   last_mode = file->mode;
156   last_rdev = file->rdev;
157   last_uid = file->uid;
158   last_gid = file->gid;
159   last_time = file->modtime;
160
161   strcpy(lastname,file->name);
162   lastname[255] = 0;
163 }
164
165
166
167 void receive_file_entry_v11(struct file_struct *file,
168                             unsigned char flags,int f)
169 {
170   static time_t last_time=0;
171   static mode_t last_mode=0;
172   static dev_t last_rdev=0;
173   static uid_t last_uid=0;
174   static gid_t last_gid=0;
175   static char lastname[MAXPATHLEN]="";
176   int l1=0,l2=0;
177
178   if (flags & SAME_NAME)
179     l1 = read_byte(f);
180   
181   if (flags & LONG_NAME)
182     l2 = read_int(f);
183   else
184     l2 = read_byte(f);
185
186   bzero((char *)file,sizeof(*file));
187
188   file->name = (char *)malloc(l1+l2+1);
189   if (!file->name) out_of_memory("receive_file_entry");
190
191   strncpy(file->name,lastname,l1);
192   read_buf(f,file->name+l1,l2);
193   file->name[l1+l2] = 0;
194
195   file->length = (off_t)read_int(f);
196   file->modtime = (flags & SAME_TIME) ? last_time : (time_t)read_int(f);
197   file->mode = (flags & SAME_MODE) ? last_mode : (mode_t)read_int(f);
198   if (preserve_uid)
199     file->uid = (flags & SAME_UID) ? last_uid : (uid_t)read_int(f);
200   if (preserve_gid)
201     file->gid = (flags & SAME_GID) ? last_gid : (gid_t)read_int(f);
202   if (preserve_devices && IS_DEVICE(file->mode))
203     file->rdev = (flags & SAME_RDEV) ? last_rdev : (dev_t)read_int(f);
204
205 #if SUPPORT_LINKS
206   if (preserve_links && S_ISLNK(file->mode)) {
207     int l = read_int(f);
208     file->link = (char *)malloc(l+1);
209     if (!file->link) out_of_memory("receive_file_entry");
210     read_buf(f,file->link,l);
211     file->link[l] = 0;
212   }
213 #endif
214
215 #if SUPPORT_HARD_LINKS
216   if (preserve_hard_links && S_ISREG(file->mode)) {
217     file->dev = read_int(f);
218     file->inode = read_int(f);
219   }
220 #endif
221   
222   if (always_checksum)
223     read_buf(f,file->sum,csum_length);
224   
225   last_mode = file->mode;
226   last_rdev = file->rdev;
227   last_uid = file->uid;
228   last_gid = file->gid;
229   last_time = file->modtime;
230
231   strcpy(lastname,file->name);
232   lastname[255] = 0;
233 }
234
235
236
237 static struct file_struct *make_file(char *fname)
238 {
239   static struct file_struct file;
240   struct stat st;
241   char sum[SUM_LENGTH];
242
243   bzero(sum,SUM_LENGTH);
244
245   if (lstat(fname,&st) != 0) {
246     fprintf(FERROR,"%s: %s\n",
247             fname,strerror(errno));
248     return NULL;
249   }
250
251   if (S_ISDIR(st.st_mode) && !recurse) {
252     fprintf(FERROR,"skipping directory %s\n",fname);
253     return NULL;
254   }
255
256   if (one_file_system && st.st_dev != filesystem_dev)
257     return NULL;
258
259   if (!match_file_name(fname,&st))
260     return NULL;
261
262   if (verbose > 2)
263     fprintf(FERROR,"make_file(%s)\n",fname);
264
265   bzero((char *)&file,sizeof(file));
266
267   file.name = strdup(fname);
268   file.modtime = st.st_mtime;
269   file.length = st.st_size;
270   file.mode = st.st_mode;
271   file.uid = st.st_uid;
272   file.gid = st.st_gid;
273   file.dev = st.st_dev;
274   file.inode = st.st_ino;
275 #ifdef HAVE_ST_RDEV
276   file.rdev = st.st_rdev;
277 #endif
278
279 #if SUPPORT_LINKS
280   if (S_ISLNK(st.st_mode)) {
281     int l;
282     char lnk[MAXPATHLEN];
283     if ((l=readlink(fname,lnk,MAXPATHLEN-1)) == -1) {
284       fprintf(FERROR,"readlink %s : %s\n",fname,strerror(errno));
285       return NULL;
286     }
287     lnk[l] = 0;
288     file.link = strdup(lnk);
289   }
290 #endif
291
292   if (always_checksum && S_ISREG(st.st_mode)) {
293     file_checksum(fname,file.sum,st.st_size);
294   }       
295
296   if (flist_dir)
297     file.dir = strdup(flist_dir);
298   else
299     file.dir = NULL;
300
301   if (!S_ISDIR(st.st_mode))
302     total_size += st.st_size;
303
304   return &file;
305 }
306
307
308
309 static void send_file_name(int f,struct file_list *flist,char *fname)
310 {
311   struct file_struct *file;
312
313   file = make_file(fname);
314
315   if (!file) return;  
316   
317   if (flist->count >= flist->malloced) {
318     flist->malloced += 100;
319     flist->files = (struct file_struct *)realloc(flist->files,
320                                                  sizeof(flist->files[0])*
321                                                  flist->malloced);
322     if (!flist->files)
323       out_of_memory("send_file_name");
324   }
325
326   if (strcmp(file->name,".") && strcmp(file->name,"/")) {
327     flist->files[flist->count++] = *file;    
328     send_file_entry(file,f);
329   }
330
331   if (S_ISDIR(file->mode) && recurse) {
332     char **last_exclude_list = local_exclude_list;
333     send_directory(f,flist,file->name);
334     local_exclude_list = last_exclude_list;
335     return;
336   }
337 }
338
339
340
341 static void send_directory(int f,struct file_list *flist,char *dir)
342 {
343   DIR *d;
344   struct dirent *di;
345   char fname[MAXPATHLEN];
346   int l;
347   char *p;
348
349   d = opendir(dir);
350   if (!d) {
351     fprintf(FERROR,"%s: %s\n",
352             dir,strerror(errno));
353     return;
354   }
355
356   strcpy(fname,dir);
357   l = strlen(fname);
358   if (fname[l-1] != '/')
359     strcat(fname,"/");
360   p = fname + strlen(fname);
361
362   if (cvs_exclude) {
363     strcpy(p,".cvsignore");
364     local_exclude_list = make_exclude_list(fname,NULL,0);
365   }  
366
367   for (di=readdir(d); di; di=readdir(d)) {
368     if (strcmp(di->d_name,".")==0 ||
369         strcmp(di->d_name,"..")==0)
370       continue;
371     strcpy(p,di->d_name);
372     send_file_name(f,flist,fname);
373   }
374
375   closedir(d);
376 }
377
378
379
380 struct file_list *send_file_list(int f,int argc,char *argv[])
381 {
382   int i,l;
383   struct stat st;
384   char *p,*dir;
385   char dbuf[MAXPATHLEN];
386   struct file_list *flist;
387
388   if (verbose && recurse && !am_server) {
389     fprintf(FINFO,"building file list ... ");
390     fflush(FINFO);
391   }
392
393   flist = (struct file_list *)malloc(sizeof(flist[0]));
394   if (!flist) out_of_memory("send_file_list");
395
396   flist->count=0;
397   flist->malloced = 100;
398   flist->files = (struct file_struct *)malloc(sizeof(flist->files[0])*
399                                               flist->malloced);
400   if (!flist->files) out_of_memory("send_file_list");
401
402   for (i=0;i<argc;i++) {
403     char fname2[MAXPATHLEN];
404     char *fname = fname2;
405
406     strcpy(fname,argv[i]);
407
408     l = strlen(fname);
409     if (l != 1 && fname[l-1] == '/') {
410       strcat(fname,".");
411     }
412
413     if (lstat(fname,&st) != 0) {
414       fprintf(FERROR,"%s : %s\n",fname,strerror(errno));
415       continue;
416     }
417
418     if (S_ISDIR(st.st_mode) && !recurse) {
419       fprintf(FERROR,"skipping directory %s\n",fname);
420       continue;
421     }
422
423     dir = NULL;
424     p = strrchr(fname,'/');
425     if (p) {
426       *p = 0;
427       dir = fname;
428       fname = p+1;      
429     }
430     if (!*fname)
431       fname = ".";
432
433     if (dir && *dir) {
434       if (getcwd(dbuf,MAXPATHLEN-1) == NULL) {
435         fprintf(FERROR,"getwd : %s\n",strerror(errno));
436         exit_cleanup(1);
437       }
438       if (chdir(dir) != 0) {
439         fprintf(FERROR,"chdir %s : %s\n",dir,strerror(errno));
440         continue;
441       }
442       flist_dir = dir;
443       if (one_file_system)
444         set_filesystem(fname);
445       send_file_name(f,flist,fname);
446       flist_dir = NULL;
447       if (chdir(dbuf) != 0) {
448         fprintf(FERROR,"chdir %s : %s\n",dbuf,strerror(errno));
449         exit_cleanup(1);
450       }
451       continue;
452     }
453
454     if (one_file_system)
455       set_filesystem(fname);
456     send_file_name(f,flist,fname);
457   }
458
459   if (f != -1) {
460     send_file_entry(NULL,f);
461     write_flush(f);
462   }
463
464   if (verbose && recurse && !am_server)
465     fprintf(FINFO,"done\n");
466
467   clean_flist(flist);
468
469   return flist;
470 }
471
472
473 struct file_list *recv_file_list(int f)
474 {
475   struct file_list *flist;
476   unsigned char flags;
477
478   if (verbose && recurse && !am_server) {
479     fprintf(FINFO,"receiving file list ... ");
480     fflush(FINFO);
481   }
482
483   flist = (struct file_list *)malloc(sizeof(flist[0]));
484   if (!flist)
485     goto oom;
486
487   flist->count=0;
488   flist->malloced=100;
489   flist->files = (struct file_struct *)malloc(sizeof(flist->files[0])*
490                                               flist->malloced);
491   if (!flist->files)
492     goto oom;
493
494
495   for (flags=read_byte(f); flags; flags=read_byte(f)) {
496     int i = flist->count;
497
498     if (i >= flist->malloced) {
499       flist->malloced += 100;
500       flist->files =(struct file_struct *)realloc(flist->files,
501                                                   sizeof(flist->files[0])*
502                                                   flist->malloced);
503       if (!flist->files)
504         goto oom;
505     }
506
507     receive_file_entry(&flist->files[i],flags,f);
508
509     if (S_ISREG(flist->files[i].mode))
510       total_size += flist->files[i].length;
511
512     flist->count++;
513
514     if (verbose > 2)
515       fprintf(FERROR,"recv_file_name(%s)\n",flist->files[i].name);
516   }
517
518
519   if (verbose > 2)
520     fprintf(FERROR,"received %d names\n",flist->count);
521
522   clean_flist(flist);
523
524   if (verbose && recurse && !am_server) {
525     fprintf(FINFO,"done\n");
526   }
527
528   return flist;
529
530 oom:
531     out_of_memory("recv_file_list");
532     return NULL; /* not reached */
533 }
534
535
536 int file_compare(struct file_struct *f1,struct file_struct *f2)
537 {
538   if (!f1->name && !f2->name) return 0;
539   if (!f1->name) return -1;
540   if (!f2->name) return 1;
541   return strcmp(f1->name,f2->name);
542 }
543
544
545 int flist_find(struct file_list *flist,struct file_struct *f)
546 {
547   int low=0,high=flist->count;
548
549   while (low != high) {
550     int mid = (low+high)/2;
551     int ret = file_compare(&flist->files[mid],f);
552     if (ret == 0) return mid;
553     if (ret > 0) 
554       high=mid;
555     else
556       low=mid+1;
557   }
558   if (file_compare(&flist->files[low],f) == 0)
559     return low;
560   return -1;
561 }
562
563
564 static void clean_fname(char *name)
565 {
566   char *p;
567   int l;
568   int modified = 1;
569
570   if (!name) return;
571
572   while (modified) {
573     modified = 0;
574
575     if ((p=strstr(name,"/./"))) {
576       modified = 1;
577       while (*p) {
578         p[0] = p[2];
579         p++;
580       }
581     }
582
583     if ((p=strstr(name,"//"))) {
584       modified = 1;
585       while (*p) {
586         p[0] = p[1];
587         p++;
588       }
589     }
590
591     if (strncmp(p=name,"./",2) == 0) {      
592       modified = 1;
593       while (*p) {
594         p[0] = p[2];
595         p++;
596       }
597     }
598
599     l = strlen(p=name);
600     if (l > 1 && p[l-1] == '/') {
601       modified = 1;
602       p[l-1] = 0;
603     }
604   }
605 }
606
607
608 /*
609  * This routine ensures we don't have any duplicate names in our file list.
610  * duplicate names can cause corruption because of the pipelining 
611  */
612 void clean_flist(struct file_list *flist)
613 {
614   int i;
615
616   if (!flist || flist->count == 0) 
617     return;
618   
619   for (i=0;i<flist->count;i++) {
620     clean_fname(flist->files[i].name);
621   }
622       
623   qsort(flist->files,flist->count,
624         sizeof(flist->files[0]),
625         (int (*)())file_compare);
626
627   for (i=1;i<flist->count;i++) {
628     if (flist->files[i].name &&
629         strcmp(flist->files[i].name,flist->files[i-1].name) == 0) {
630       if (verbose > 1 && !am_server)
631         fprintf(FERROR,"removing duplicate name %s from file list %d\n",
632                 flist->files[i-1].name,i-1);
633       free(flist->files[i-1].name);
634       bzero((char *)&flist->files[i-1],sizeof(flist->files[i-1]));
635     } 
636   }
637 }
638