home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / rsync221.zip / receiver.c < prev    next >
C/C++ Source or Header  |  1999-03-04  |  12KB  |  485 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. #include "rsync.h"
  21.  
  22. extern int verbose;
  23. extern int recurse;
  24. extern int delete_mode;
  25. extern int remote_version;
  26. extern int csum_length;
  27. extern struct stats stats;
  28. extern int dry_run;
  29. extern int am_server;
  30. extern int relative_paths;
  31. extern int preserve_hard_links;
  32. extern int cvs_exclude;
  33. extern int io_error;
  34. extern char *tmpdir;
  35. extern char *compare_dest;
  36. extern int make_backups;
  37. extern char *backup_suffix;
  38.  
  39.  
  40. static struct delete_list {
  41.     dev_t dev;
  42.     INO_T inode;
  43. } *delete_list;
  44. static int dlist_len, dlist_alloc_len;
  45.  
  46.  
  47. /* yuck! This function wouldn't have been necessary if I had the sorting
  48.    algorithm right. Unfortunately fixing the sorting algorithm would introduce
  49.    a backward incompatibility as file list indexes are sent over the link.
  50. */
  51. static int delete_already_done(struct file_list *flist,int j)
  52. {
  53.     int i;
  54.     STRUCT_STAT st;
  55.  
  56.     if (link_stat(f_name(flist->files[j]), &st)) return 1;
  57.  
  58.     for (i=0;i<dlist_len;i++) {
  59.         if (st.st_ino == delete_list[i].inode &&
  60.             st.st_dev == delete_list[i].dev)
  61.             return 1;
  62.     }
  63.  
  64.     return 0;
  65. }
  66.  
  67. static void add_delete_entry(struct file_struct *file)
  68. {
  69.     if (dlist_len == dlist_alloc_len) {
  70.         dlist_alloc_len += 1024;
  71.         delete_list = (struct delete_list *)Realloc(delete_list, sizeof(delete_list[0])*dlist_alloc_len);
  72.         if (!delete_list) out_of_memory("add_delete_entry");
  73.     }
  74.  
  75.     delete_list[dlist_len].dev = file->dev;
  76.     delete_list[dlist_len].inode = file->inode;
  77.     dlist_len++;
  78.  
  79.     if (verbose > 3)
  80.         rprintf(FINFO,"added %s to delete list\n", f_name(file));
  81. }
  82.  
  83. static void delete_one(struct file_struct *f)
  84. {
  85.     if (!S_ISDIR(f->mode)) {
  86.         if (do_unlink(f_name(f)) != 0) {
  87.             rprintf(FERROR,"unlink %s : %s\n",f_name(f),strerror(errno));
  88.         } else if (verbose) {
  89.             rprintf(FINFO,"deleting %s\n",f_name(f));
  90.         }
  91.     } else {    
  92.         if (do_rmdir(f_name(f)) != 0) {
  93.             if (errno != ENOTEMPTY && errno != EEXIST)
  94.                 rprintf(FERROR,"rmdir %s : %s\n",f_name(f),strerror(errno));
  95.         } else if (verbose) {
  96.             rprintf(FINFO,"deleting directory %s\n",f_name(f));      
  97.         }
  98.     }
  99. }
  100.  
  101.  
  102.  
  103.  
  104. /* this deletes any files on the receiving side that are not present
  105.    on the sending side. For version 1.6.4 I have changed the behaviour
  106.    to match more closely what most people seem to expect of this option */
  107. static void delete_files(struct file_list *flist)
  108. {
  109.     struct file_list *local_file_list;
  110.     int i, j;
  111.     char *name;
  112.  
  113.     if (cvs_exclude)
  114.         add_cvs_excludes();
  115.  
  116.     if (io_error) {
  117.         rprintf(FINFO,"IO error encountered - skipping file deletion\n");
  118.         return;
  119.     }
  120.  
  121.     for (j=0;j<flist->count;j++) {
  122.         if (!S_ISDIR(flist->files[j]->mode) || 
  123.             !(flist->files[j]->flags & FLAG_DELETE)) continue;
  124.  
  125.         if (remote_version < 19 &&
  126.             delete_already_done(flist, j)) continue;
  127.  
  128.         name = strdup(f_name(flist->files[j]));
  129.  
  130.         if (!(local_file_list = send_file_list(-1,1,&name))) {
  131.             free(name);
  132.             continue;
  133.         }
  134.  
  135.         if (verbose > 1)
  136.             rprintf(FINFO,"deleting in %s\n", name);
  137.  
  138.         for (i=local_file_list->count-1;i>=0;i--) {
  139.             if (!local_file_list->files[i]->basename) continue;
  140.             if (remote_version < 19 &&
  141.                 S_ISDIR(local_file_list->files[i]->mode))
  142.                 add_delete_entry(local_file_list->files[i]);
  143.             if (-1 == flist_find(flist,local_file_list->files[i])) {
  144.                 char *f = f_name(local_file_list->files[i]);
  145.                 int k = strlen(f) - strlen(backup_suffix);
  146.                 if (make_backups && ((k <= 0) ||
  147.                         (strcmp(f+k,backup_suffix) != 0))) {
  148.                     (void) make_backup(f);
  149.                 } else {
  150.                     delete_one(local_file_list->files[i]);
  151.                 }
  152.             }
  153.         }
  154.         flist_free(local_file_list);
  155.         free(name);
  156.     }
  157. }
  158.  
  159.  
  160. static int get_tmpname(char *fnametmp, char *fname)
  161. {
  162.     char *f;
  163.  
  164.     /* open tmp file */
  165.     if (tmpdir) {
  166.         f = strrchr(fname,'/');
  167.         if (f == NULL) 
  168.             f = fname;
  169.         else 
  170.             f++;
  171.         if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
  172.             rprintf(FERROR,"filename too long\n");
  173.             return 0;
  174.         }
  175.         slprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
  176.         return 1;
  177.     } 
  178.  
  179.     f = strrchr(fname,'/');
  180.  
  181.     if (strlen(fname)+9 > MAXPATHLEN) {
  182.         rprintf(FERROR,"filename too long\n");
  183.         return 0;
  184.     }
  185.  
  186.     if (f) {
  187.         *f = 0;
  188.         slprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
  189.              fname,f+1);
  190.         *f = '/';
  191.     } else {
  192.         slprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
  193.     }
  194.  
  195.     return 1;
  196. }
  197.  
  198.  
  199. static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
  200.             OFF_T total_size)
  201. {
  202.     int i,n,remainder,len,count;
  203.     OFF_T offset = 0;
  204.     OFF_T offset2;
  205.     char *data;
  206.     static char file_sum1[MD4_SUM_LENGTH];
  207.     static char file_sum2[MD4_SUM_LENGTH];
  208.     char *map=NULL;
  209.     
  210.     count = read_int(f_in);
  211.     n = read_int(f_in);
  212.     remainder = read_int(f_in);
  213.     
  214.     sum_init();
  215.     
  216.     for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
  217.  
  218.         show_progress(offset, total_size);
  219.  
  220.         if (i > 0) {
  221.             extern int cleanup_got_literal;
  222.  
  223.             if (verbose > 3) {
  224.                 rprintf(FINFO,"data recv %d at %d\n",
  225.                     i,(int)offset);
  226.             }
  227.  
  228.             stats.literal_data += i;
  229.             cleanup_got_literal = 1;
  230.       
  231.             sum_update(data,i);
  232.  
  233.             if (fd != -1 && write_file(fd,data,i) != i) {
  234.                 rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
  235.                 exit_cleanup(RERR_FILEIO);
  236.             }
  237.             offset += i;
  238.             continue;
  239.         } 
  240.  
  241.         i = -(i+1);
  242.         offset2 = i*n;
  243.         len = n;
  244.         if (i == count-1 && remainder != 0)
  245.             len = remainder;
  246.         
  247.         stats.matched_data += len;
  248.         
  249.         if (verbose > 3)
  250.             rprintf(FINFO,"chunk[%d] of size %d at %d offset=%d\n",
  251.                 i,len,(int)offset2,(int)offset);
  252.         
  253.         map = map_ptr(buf,offset2,len);
  254.         
  255.         see_token(map, len);
  256.         sum_update(map,len);
  257.         
  258.         if (fd != -1 && write_file(fd,map,len) != len) {
  259.             rprintf(FERROR,"write failed on %s : %s\n",
  260.                 fname,strerror(errno));
  261.             exit_cleanup(RERR_FILEIO);
  262.         }
  263.         offset += len;
  264.     }
  265.  
  266.     end_progress();
  267.  
  268.     if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
  269.         rprintf(FERROR,"write failed on %s : %s\n",
  270.             fname,strerror(errno));
  271.         exit_cleanup(RERR_FILEIO);
  272.     }
  273.  
  274.     sum_end(file_sum1);
  275.  
  276.     if (remote_version >= 14) {
  277.         read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
  278.         if (verbose > 2) {
  279.             rprintf(FINFO,"got file_sum\n");
  280.         }
  281.         if (fd != -1 && 
  282.             memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
  283.             return 0;
  284.         }
  285.     }
  286.     return 1;
  287. }
  288.  
  289.  
  290.  
  291. int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
  292. {  
  293.     int fd1,fd2;
  294.     STRUCT_STAT st;
  295.     char *fname;
  296.     char fnametmp[MAXPATHLEN];
  297.     char *fnamecmp;
  298.     char fnamecmpbuf[MAXPATHLEN];
  299.     struct map_struct *buf;
  300.     int i;
  301.     struct file_struct *file;
  302.     int phase=0;
  303.     int recv_ok;
  304.     extern struct stats stats;        
  305.     struct stats initial_stats;
  306.  
  307.     if (verbose > 2) {
  308.         rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
  309.     }
  310.  
  311.     if (recurse && delete_mode && !local_name && flist->count>0) {
  312.         delete_files(flist);
  313.     }
  314.  
  315.     while (1) {      
  316.         cleanup_disable();
  317.  
  318.         i = read_int(f_in);
  319.         if (i == -1) {
  320.             if (phase==0 && remote_version >= 13) {
  321.                 phase++;
  322.                 csum_length = SUM_LENGTH;
  323.                 if (verbose > 2)
  324.                     rprintf(FINFO,"recv_files phase=%d\n",phase);
  325.                 write_int(f_gen,-1);
  326.                 continue;
  327.             }
  328.             break;
  329.         }
  330.  
  331.         if (i < 0 || i >= flist->count) {
  332.             rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n", 
  333.                 i, flist->count);
  334.             exit_cleanup(RERR_PROTOCOL);
  335.         }
  336.  
  337.         file = flist->files[i];
  338.         fname = f_name(file);
  339.  
  340.         stats.num_transferred_files++;
  341.         stats.total_transferred_size += file->length;
  342.  
  343.         if (local_name)
  344.             fname = local_name;
  345.  
  346.         if (dry_run) {
  347.             if (!am_server) {
  348.                 log_transfer(file, fname);
  349.             }
  350.             continue;
  351.         }
  352.  
  353.         initial_stats = stats;
  354.  
  355.         if (verbose > 2)
  356.             rprintf(FINFO,"recv_files(%s)\n",fname);
  357.  
  358.         fnamecmp = fname;
  359.  
  360.         /* open the file */  
  361.         fd1 = open(fnamecmp,O_RDONLY);
  362.  
  363.         if ((fd1 == -1) && (compare_dest != NULL)) {
  364.             /* try the file at compare_dest instead */
  365.             slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
  366.                         compare_dest,fname);
  367.             fnamecmp = fnamecmpbuf;
  368.             fd1 = open(fnamecmp,O_RDONLY);
  369.         }
  370.  
  371.         if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
  372.             rprintf(FERROR,"fstat %s : %s\n",fnamecmp,strerror(errno));
  373.             receive_data(f_in,NULL,-1,NULL,file->length);
  374.             close(fd1);
  375.             continue;
  376.         }
  377.  
  378.         if (fd1 != -1 && !S_ISREG(st.st_mode)) {
  379.             rprintf(FERROR,"%s : not a regular file (recv_files)\n",fnamecmp);
  380.             receive_data(f_in,NULL,-1,NULL,file->length);
  381.             close(fd1);
  382.             continue;
  383.         }
  384.  
  385.         if (fd1 != -1 && st.st_size > 0) {
  386.             buf = map_file(fd1,st.st_size);
  387.             if (verbose > 2)
  388.                 rprintf(FINFO,"recv mapped %s of size %d\n",fnamecmp,(int)st.st_size);
  389.         } else {
  390.             buf = NULL;
  391.         }
  392.  
  393.         if (!get_tmpname(fnametmp,fname)) {
  394.             if (buf) unmap_file(buf);
  395.             if (fd1 != -1) close(fd1);
  396.             continue;
  397.         }
  398.  
  399.         /* mktemp is deliberately used here instead of mkstemp.
  400.            because O_EXCL is used on the open, the race condition
  401.            is not a problem or a security hole, and we want to
  402.            control the access permissions on the created file. */
  403.         if (NULL == do_mktemp(fnametmp)) {
  404.             rprintf(FERROR,"mktemp %s failed\n",fnametmp);
  405.             receive_data(f_in,buf,-1,NULL,file->length);
  406.             if (buf) unmap_file(buf);
  407.             if (fd1 != -1) close(fd1);
  408.             continue;
  409.         }
  410.  
  411.         /* we initially set the perms without the
  412.            setuid/setgid bits to ensure that there is no race
  413.            condition. They are then correctly updated after
  414.            the lchown. Thanks to snabb@epipe.fi for pointing
  415.            this out */
  416.         fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
  417.                   file->mode & ACCESSPERMS);
  418.  
  419.         if (fd2 == -1 && relative_paths && errno == ENOENT && 
  420.             create_directory_path(fnametmp) == 0) {
  421.             fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
  422.                       file->mode & ACCESSPERMS);
  423.         }
  424.         if (fd2 == -1) {
  425.             rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
  426.             receive_data(f_in,buf,-1,NULL,file->length);
  427.             if (buf) unmap_file(buf);
  428.             if (fd1 != -1) close(fd1);
  429.             continue;
  430.         }
  431.       
  432.         cleanup_set(fnametmp, fname, file, buf, fd1, fd2);
  433.  
  434.         if (!am_server) {
  435.             log_transfer(file, fname);
  436.         }
  437.  
  438.         /* recv file data */
  439.         recv_ok = receive_data(f_in,buf,fd2,fname,file->length);
  440.  
  441.         log_recv(file, &initial_stats);
  442.         
  443.         if (buf) unmap_file(buf);
  444.         if (fd1 != -1) {
  445.             close(fd1);
  446.         }
  447.         close(fd2);
  448.         
  449.         if (verbose > 2)
  450.             rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
  451.  
  452.         finish_transfer(fname, fnametmp, file);
  453.  
  454.         cleanup_disable();
  455.                 
  456.         if (!recv_ok) {
  457.             if (csum_length == SUM_LENGTH) {
  458.                 rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
  459.                     fname);
  460.             } else {
  461.                 if (verbose > 1)
  462.                     rprintf(FINFO,"redoing %s(%d)\n",fname,i);
  463.                 write_int(f_gen,i);
  464.             }
  465.         }
  466.     }
  467.  
  468.     if (preserve_hard_links)
  469.         do_hard_links(flist);
  470.  
  471.     /* now we need to fix any directory permissions that were 
  472.        modified during the transfer */
  473.     for (i = 0; i < flist->count; i++) {
  474.         file = flist->files[i];
  475.         if (!file->basename || !S_ISDIR(file->mode)) continue;
  476.         recv_generator(f_name(file),flist,i,-1);
  477.     }
  478.  
  479.     if (verbose > 2)
  480.         rprintf(FINFO,"recv_files finished\n");
  481.     
  482.     return 0;
  483. }
  484.  
  485.