home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / OPENSTEP / UNIX / Utilities / rsync-1.6.3-MIH / src / flist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-27  |  13.7 KB  |  642 lines

  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.       if (p == fname) 
  428.     dir = "/";
  429.       else
  430.     dir = fname;      
  431.       fname = p+1;      
  432.     }
  433.     if (!*fname)
  434.       fname = ".";
  435.  
  436.     if (dir && *dir) {
  437.       if (getwd(dbuf) == NULL) {
  438.     fprintf(FERROR,"getwd : %s\n",strerror(errno));
  439.     exit_cleanup(1);
  440.       }
  441.       if (chdir(dir) != 0) {
  442.     fprintf(FERROR,"chdir %s : %s\n",dir,strerror(errno));
  443.     continue;
  444.       }
  445.       flist_dir = dir;
  446.       if (one_file_system)
  447.     set_filesystem(fname);
  448.       send_file_name(f,flist,fname);
  449.       flist_dir = NULL;
  450.       if (chdir(dbuf) != 0) {
  451.     fprintf(FERROR,"chdir %s : %s\n",dbuf,strerror(errno));
  452.     exit_cleanup(1);
  453.       }
  454.       continue;
  455.     }
  456.  
  457.     if (one_file_system)
  458.       set_filesystem(fname);
  459.     send_file_name(f,flist,fname);
  460.   }
  461.  
  462.   if (f != -1) {
  463.     send_file_entry(NULL,f);
  464.     write_flush(f);
  465.   }
  466.  
  467.   if (verbose && recurse && !am_server)
  468.     fprintf(FINFO,"done\n");
  469.  
  470.   clean_flist(flist);
  471.  
  472.   return flist;
  473. }
  474.  
  475.  
  476. struct file_list *recv_file_list(int f)
  477. {
  478.   struct file_list *flist;
  479.   unsigned char flags;
  480.  
  481.   if (verbose && recurse && !am_server) {
  482.     fprintf(FINFO,"receiving file list ... ");
  483.     fflush(FINFO);
  484.   }
  485.  
  486.   flist = (struct file_list *)malloc(sizeof(flist[0]));
  487.   if (!flist)
  488.     goto oom;
  489.  
  490.   flist->count=0;
  491.   flist->malloced=100;
  492.   flist->files = (struct file_struct *)malloc(sizeof(flist->files[0])*
  493.                           flist->malloced);
  494.   if (!flist->files)
  495.     goto oom;
  496.  
  497.  
  498.   for (flags=read_byte(f); flags; flags=read_byte(f)) {
  499.     int i = flist->count;
  500.  
  501.     if (i >= flist->malloced) {
  502.       flist->malloced += 100;
  503.       flist->files =(struct file_struct *)realloc(flist->files,
  504.                           sizeof(flist->files[0])*
  505.                           flist->malloced);
  506.       if (!flist->files)
  507.     goto oom;
  508.     }
  509.  
  510.     receive_file_entry(&flist->files[i],flags,f);
  511.  
  512.     if (S_ISREG(flist->files[i].mode))
  513.       total_size += flist->files[i].length;
  514.  
  515.     flist->count++;
  516.  
  517.     if (verbose > 2)
  518.       fprintf(FERROR,"recv_file_name(%s)\n",flist->files[i].name);
  519.   }
  520.  
  521.  
  522.   if (verbose > 2)
  523.     fprintf(FERROR,"received %d names\n",flist->count);
  524.  
  525.   clean_flist(flist);
  526.  
  527.   if (verbose && recurse && !am_server) {
  528.     fprintf(FINFO,"done\n");
  529.   }
  530.  
  531.   return flist;
  532.  
  533. oom:
  534.     out_of_memory("recv_file_list");
  535.     return NULL; /* not reached */
  536. }
  537.  
  538.  
  539. int file_compare(struct file_struct *f1,struct file_struct *f2)
  540. {
  541.   if (!f1->name && !f2->name) return 0;
  542.   if (!f1->name) return -1;
  543.   if (!f2->name) return 1;
  544.   return strcmp(f1->name,f2->name);
  545. }
  546.  
  547.  
  548. int flist_find(struct file_list *flist,struct file_struct *f)
  549. {
  550.   int low=0,high=flist->count;
  551.  
  552.   while (low != high) {
  553.     int mid = (low+high)/2;
  554.     int ret = file_compare(&flist->files[mid],f);
  555.     if (ret == 0) return mid;
  556.     if (ret > 0) 
  557.       high=mid;
  558.     else
  559.       low=mid+1;
  560.   }
  561.   if (file_compare(&flist->files[low],f) == 0)
  562.     return low;
  563.   return -1;
  564. }
  565.  
  566.  
  567. static void clean_fname(char *name)
  568. {
  569.   char *p;
  570.   int l;
  571.   int modified = 1;
  572.  
  573.   if (!name) return;
  574.  
  575.   while (modified) {
  576.     modified = 0;
  577.  
  578.     if ((p=strstr(name,"/./"))) {
  579.       modified = 1;
  580.       while (*p) {
  581.     p[0] = p[2];
  582.     p++;
  583.       }
  584.     }
  585.  
  586.     if ((p=strstr(name,"//"))) {
  587.       modified = 1;
  588.       while (*p) {
  589.     p[0] = p[1];
  590.     p++;
  591.       }
  592.     }
  593.  
  594.     if (strncmp(p=name,"./",2) == 0) {      
  595.       modified = 1;
  596.       while (*p) {
  597.     p[0] = p[2];
  598.     p++;
  599.       }
  600.     }
  601.  
  602.     l = strlen(p=name);
  603.     if (l > 1 && p[l-1] == '/') {
  604.       modified = 1;
  605.       p[l-1] = 0;
  606.     }
  607.   }
  608. }
  609.  
  610.  
  611. /*
  612.  * This routine ensures we don't have any duplicate names in our file list.
  613.  * duplicate names can cause corruption because of the pipelining 
  614.  */
  615. void clean_flist(struct file_list *flist)
  616. {
  617.   int i;
  618.  
  619.   if (!flist || flist->count == 0) 
  620.     return;
  621.   
  622.   for (i=0;i<flist->count;i++) {
  623.     clean_fname(flist->files[i].name);
  624.   }
  625.       
  626.   qsort(flist->files,flist->count,
  627.     sizeof(flist->files[0]),
  628.     (int (*)())file_compare);
  629.  
  630.   for (i=1;i<flist->count;i++) {
  631.     if (flist->files[i].name &&
  632.     strcmp(flist->files[i].name,flist->files[i-1].name) == 0) {
  633.       if (verbose > 1 && !am_server)
  634.     fprintf(FERROR,"removing duplicate name %s from file list %d\n",
  635.         flist->files[i-1].name,i-1);
  636.       free(flist->files[i-1].name);
  637.       bzero((char *)&flist->files[i-1],sizeof(flist->files[i-1]));
  638.     } 
  639.   }
  640. }
  641.  
  642.