Modified file stored as well
[rsync.git] / batch.c
1 /* -*- c-file-style: "linux" -*-
2    
3    Weiss 1/1999
4    Batch utilities for rsync.
5
6 */ 
7
8 #include "rsync.h"
9 #include <time.h>
10
11 char rsync_flist_file[27] = "rsync_flist.";    
12 char rsync_csums_file[27] = "rsync_csums.";     
13 char rsync_delta_file[27] = "rsync_delta.";    
14 char rsync_argvs_file[27] = "rsync_argvs.";    
15
16 char batch_file_ext[15];
17  
18 int fdb;
19 int fdb_delta;
20 int fdb_open;   
21 int fdb_close;  
22
23 struct file_list *batch_flist;
24
25 void create_batch_file_ext()
26 {
27     struct tm *timeptr;
28     time_t elapsed_seconds;
29     
30     /* Save run date and time to use for batch file extensions */
31     time(&elapsed_seconds);
32     timeptr = localtime(&elapsed_seconds);
33
34     sprintf(batch_file_ext, "%4d%02d%02d%02d%02d%02d",
35              timeptr->tm_year+1900, timeptr->tm_mon+1, timeptr->tm_mday,
36              timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
37 }
38
39 void set_batch_file_ext(char *ext)
40 {
41     strcpy(batch_file_ext, ext);  
42 }
43
44 void write_batch_flist_file(char *buff, int bytes_to_write)
45 {
46
47     if (fdb_open) {
48        /* Set up file extension */
49        strcat(rsync_flist_file, batch_file_ext); 
50
51        /* Open batch flist file for writing; create it if it doesn't exist */
52        fdb = do_open(rsync_flist_file, O_WRONLY|O_CREAT|O_TRUNC,
53                                               S_IREAD|S_IWRITE);
54        if (fdb == -1) {
55           rprintf(FERROR, "Batch file %s open error: %s\n",
56           rsync_flist_file, strerror(errno));
57           close(fdb);
58           exit_cleanup(1);
59        }
60        fdb_open = 0;
61     }
62
63     /* Write buffer to batch flist file */
64
65     if ( write(fdb, buff, bytes_to_write) == -1 ) { 
66             rprintf(FERROR, "Batch file %s write error: %s\n",
67           rsync_flist_file, strerror(errno));
68           close(fdb);
69           exit_cleanup(1);
70     }
71
72
73     if (fdb_close) {
74        close(fdb);
75     }
76 }
77
78 void write_batch_flist_info(int flist_count, struct file_struct **fptr)
79 {
80     int i;
81     int bytes_to_write;   
82
83     /* Write flist info to batch file */
84
85     bytes_to_write = sizeof(unsigned) +
86                      sizeof(time_t) +
87                      sizeof(OFF_T) +
88                      sizeof(mode_t) +
89                      sizeof(INO_T) +
90                      (2 * sizeof(dev_t)) +
91                      sizeof(uid_t) +
92                      sizeof(gid_t);   
93
94     fdb_open = 1;
95     fdb_close = 0;
96
97     for (i=0; i<flist_count; i++) {
98        write_batch_flist_file( (char *) fptr[i], bytes_to_write);
99        write_char_bufs(fptr[i]->basename);
100        write_char_bufs(fptr[i]->dirname);
101        write_char_bufs(fptr[i]->basedir);
102        write_char_bufs(fptr[i]->link);
103        if (i==flist_count - 1) {
104           fdb_close = 1;
105        }
106        write_char_bufs(fptr[i]->sum);
107     }  
108
109 }
110
111 void write_char_bufs(char *buf)
112 {
113    /* Write the size of the string which will follow  */ 
114
115    char b[4];
116    if (buf != NULL)
117       SIVAL(b,0,strlen(buf));  
118    else {
119       SIVAL(b,0,0);
120    }
121
122    write_batch_flist_file(b, sizeof(int));  
123
124    /*  Write the string if there is one */
125
126    if (buf != NULL) {
127       write_batch_flist_file(buf, strlen(buf)); 
128    }
129 }
130
131 void write_batch_argvs_file(int orig_argc, int argc, char **argv)
132 {
133     int fdb;
134     int i;
135     char buff[256];
136
137     strcat(rsync_argvs_file, batch_file_ext);
138     
139
140     /* Open batch argvs file for writing; create it if it doesn't exist */
141     fdb = do_open(rsync_argvs_file, O_WRONLY|O_CREAT|O_TRUNC,
142                                            S_IREAD|S_IWRITE|S_IEXEC);
143     if (fdb == -1) {
144        rprintf(FERROR, "Batch file %s open error: %s\n", rsync_argvs_file,
145          strerror(errno));
146           close(fdb);
147           exit_cleanup(1);
148     }
149     buff[0] = '\0';
150     /* Write argvs info to batch file */
151    
152     for (i=argc - orig_argc;i<argc;i++) {
153        if ( !strcmp(argv[i],"-F") ){  /* safer to change it here than script*/ 
154           strncat(buff,"-f ",3);  /* chg to -f + ext to get ready for remote */
155           strncat(buff,batch_file_ext,strlen(batch_file_ext));
156        }
157        else {
158           strncat(buff,argv[i],strlen(argv[i]));
159        }
160     
161        if (i < (argc - 1)) {
162           strncat(buff," ",1);
163        }
164     }
165     if (!write(fdb, buff, strlen(buff))) { 
166           rprintf(FERROR, "Batch file %s write error: %s\n",
167             rsync_argvs_file, strerror(errno));
168           close(fdb);
169           exit_cleanup(1);
170     }
171     close(fdb);
172 }
173
174 struct file_list *create_flist_from_batch()
175 {
176    unsigned char flags;
177
178    fdb_open = 1;
179    fdb_close = 0;  
180
181    batch_flist = (struct file_list *)malloc(sizeof(batch_flist[0]));
182    if (!batch_flist) {
183      out_of_memory("create_flist_from_batch"); 
184    }
185    batch_flist->count=0;
186    batch_flist->malloced=1000;
187    batch_flist->files = (struct file_struct **)malloc(sizeof(batch_flist->files[0])* batch_flist->malloced);
188    if (!batch_flist->files) {
189      out_of_memory("create_flist_from_batch");   /* dw -- will exit */
190    }
191
192    for ( flags=read_batch_flags() ; flags; flags=read_batch_flags() ) {
193
194      int i = batch_flist->count;
195  
196      if (i >= batch_flist->malloced) {
197           if (batch_flist->malloced < 1000)
198                   batch_flist->malloced += 1000;
199           else
200                   batch_flist->malloced *= 2;
201           batch_flist->files =(struct file_struct **)realloc(batch_flist->files,
202                                                sizeof(batch_flist->files[0])*
203                                                batch_flist->malloced);
204           if (!batch_flist->files)
205                   out_of_memory("create_flist_from_batch");
206     }
207     read_batch_flist_info(&batch_flist->files[i]);
208     batch_flist->files[i]->flags = flags;   
209
210     batch_flist->count++;
211   }
212
213   return batch_flist;
214
215 }
216
217 int read_batch_flist_file(char *buff, int len)
218 {
219     int bytes_read;
220       
221     if (fdb_open) {
222
223        /*  Set up file extension  */
224        strcat(rsync_flist_file, batch_file_ext);
225
226        /* Open batch flist file for reading */
227        fdb = do_open(rsync_flist_file, O_RDONLY, 0);
228        if (fdb == -1) {
229           rprintf(FERROR, "Batch file %s open error: %s\n", rsync_flist_file,
230             strerror(errno));
231           close(fdb);
232           exit_cleanup(1);
233        }
234        fdb_open = 0;
235     }
236
237     /* Read flist batch file */
238
239     bytes_read = read(fdb, buff, len); 
240
241     if (bytes_read == -1) { 
242        rprintf(FERROR, "Batch file %s read error: %s\n",
243           rsync_flist_file, strerror(errno));
244        close(fdb);
245        exit_cleanup(1);
246     }
247     if (bytes_read == 0) {    /* EOF */
248        close(fdb);
249     }
250     return bytes_read;
251 }
252
253 unsigned char read_batch_flags()
254 {
255     int flags; 
256
257     if (read_batch_flist_file((char *)&flags, 4) ) { 
258        return 1;
259     }
260     else {
261        return 0; 
262     }
263 }
264
265 void read_batch_flist_info(struct file_struct **fptr)
266 {
267     int int_str_len;   
268     char char_str_len[4];   
269     char buff[256];   
270     struct file_struct *file;
271
272     file = (struct file_struct *)malloc(sizeof(*file));
273     if (!file) out_of_memory("read_batch_flist_info");
274     memset((char *)file, 0, sizeof(*file));
275
276     (*fptr) = file;
277
278     read_batch_flist_file((char *)&file->modtime, sizeof(time_t)); 
279     read_batch_flist_file((char *)&file->length, sizeof(OFF_T)); 
280     read_batch_flist_file((char *)&file->mode, sizeof(mode_t)); 
281     read_batch_flist_file((char *)&file->inode, sizeof(INO_T)); 
282     read_batch_flist_file((char *)&file->dev, sizeof(dev_t)); 
283     read_batch_flist_file((char *)&file->rdev, sizeof(dev_t)); 
284     read_batch_flist_file((char *)&file->uid, sizeof(uid_t)); 
285     read_batch_flist_file((char *)&file->gid, sizeof(gid_t)); 
286     read_batch_flist_file(char_str_len, sizeof(char_str_len)); 
287     int_str_len = IVAL(char_str_len,0);
288     if (int_str_len > 0) {
289        read_batch_flist_file(buff, int_str_len); 
290        buff[int_str_len] = '\0';
291        file->basename = strdup(buff); 
292     }
293     else {
294        file->basename = NULL;
295     }
296
297     read_batch_flist_file(char_str_len, sizeof(char_str_len)); 
298     int_str_len = IVAL(char_str_len,0);
299     if (int_str_len > 0) {
300        read_batch_flist_file(buff, int_str_len); 
301        buff[int_str_len] = '\0';
302        file[0].dirname = strdup(buff); 
303     }
304     else {
305        file[0].dirname = NULL;
306     }
307
308     read_batch_flist_file(char_str_len, sizeof(char_str_len)); 
309     int_str_len = IVAL(char_str_len,0);
310     if (int_str_len > 0) {
311        read_batch_flist_file(buff, int_str_len); 
312        buff[int_str_len] = '\0';
313        file[0].basedir = strdup(buff); 
314     }
315     else {
316        file[0].basedir = NULL;
317     }
318
319     read_batch_flist_file(char_str_len, sizeof(char_str_len)); 
320     int_str_len = IVAL(char_str_len,0);
321     if (int_str_len > 0) {
322        read_batch_flist_file(buff, int_str_len); 
323        buff[int_str_len] = '\0';
324        file[0].link = strdup(buff); 
325     }
326     else {
327        file[0].link = NULL;
328     }
329
330     read_batch_flist_file(char_str_len, sizeof(char_str_len)); 
331     int_str_len = IVAL(char_str_len,0);
332     if (int_str_len > 0) {
333        read_batch_flist_file(buff, int_str_len); 
334        buff[int_str_len] = '\0';
335        file[0].sum = strdup(buff); 
336     }
337     else {
338        file[0].sum = NULL;
339     }
340 }
341
342 void write_batch_csums_file(char *buff, int bytes_to_write)
343 {
344
345     static int fdb_open = 1;
346
347     if (fdb_open) {
348        /* Set up file extension */
349        strcat(rsync_csums_file, batch_file_ext); 
350
351        /* Open batch csums file for writing; create it if it doesn't exist */
352        fdb = do_open(rsync_csums_file, O_WRONLY|O_CREAT|O_TRUNC,
353                                               S_IREAD|S_IWRITE);
354        if (fdb == -1) {
355           rprintf(FERROR, "Batch file %s open error: %s\n",
356           rsync_csums_file, strerror(errno));
357           close(fdb);
358           exit_cleanup(1);
359        }
360        fdb_open = 0; 
361     }
362
363     /* Write buffer to batch csums file */
364
365     if ( write(fdb, buff, bytes_to_write) == -1 ) { 
366             rprintf(FERROR, "Batch file %s write error: %s\n",
367           rsync_csums_file, strerror(errno));
368           close(fdb);
369           exit_cleanup(1);
370     }
371 }
372
373 void close_batch_csums_file() 
374 {
375     close(fdb);
376
377 }
378
379 void write_batch_csum_info(int *flist_entry, int flist_count, struct sum_struct *s)
380 {
381     int i;
382     int int_zero = 0;
383     extern int csum_length;
384
385     fdb_open = 1;
386
387     /* Write csum info to batch file */
388
389     write_batch_csums_file ( (char *) flist_entry, sizeof(int) );
390     write_batch_csums_file ( (char *) (s?&s->count:&int_zero), sizeof(int) );
391     if (s) {
392        for (i=0; i < s->count; i++) {
393           write_batch_csums_file( (char *) &s->sums[i].sum1, sizeof(uint32));
394           if ( (*flist_entry == flist_count - 1) && (i == s->count - 1) ) {
395              fdb_close = 1;
396           }
397           write_batch_csums_file( s->sums[i].sum2, csum_length);
398        } 
399     }  
400 }
401
402 int read_batch_csums_file(char *buff, int len)
403 {
404     static int fdb_open = 1; 
405     int bytes_read;
406       
407     if (fdb_open) {
408
409        /*  Set up file extension  */
410        strcat(rsync_csums_file, batch_file_ext);
411
412        /* Open batch flist file for reading */
413        fdb = do_open(rsync_csums_file, O_RDONLY, 0);
414        if (fdb == -1) {
415           rprintf(FERROR, "Batch file %s open error: %s\n", rsync_csums_file,
416             strerror(errno));
417           close(fdb);
418           exit_cleanup(1);
419        }
420        fdb_open = 0;
421     }
422
423     /* Read csums batch file */
424
425     bytes_read = read(fdb, buff, len); 
426
427     if (bytes_read == -1) { 
428        rprintf(FERROR, "Batch file %s read error: %s\n",
429           rsync_csums_file, strerror(errno));
430        close(fdb);
431        exit_cleanup(1);
432     }
433     return bytes_read;
434 }
435
436
437 void read_batch_csum_info(int flist_entry, struct sum_struct *s, int *checksums_match)
438 {
439     int i;
440     int file_flist_entry;
441     int file_chunk_ct;
442     uint32 file_sum1;
443     char file_sum2[SUM_LENGTH]; 
444     extern int csum_length;
445  
446
447     read_batch_csums_file((char *)&file_flist_entry, sizeof(int)); 
448     if (file_flist_entry != flist_entry) {
449        rprintf(FINFO,"file_list_entry NE flist_entry\n");
450        rprintf(FINFO,"file_flist_entry = %d  flist_entry = %d\n", file_flist_entry, flist_entry);
451        close(fdb);
452        exit_cleanup(1);
453     
454     }
455     else {
456        read_batch_csums_file((char *)&file_chunk_ct, sizeof(int)); 
457        *checksums_match = 1;
458        for (i = 0;i < file_chunk_ct;i++) {
459           
460           read_batch_csums_file((char *)&file_sum1, sizeof(uint32)); 
461           read_batch_csums_file(file_sum2, csum_length); 
462
463           if ( (s->sums[i].sum1 != file_sum1) ||  
464                ( memcmp(s->sums[i].sum2,file_sum2, csum_length)!=0) ) {
465                    *checksums_match = 0;
466           }
467        }  /*  end for  */
468     }
469
470 }
471
472 void write_batch_delta_file(char *buff, int bytes_to_write)
473 {
474     static int fdb_delta_open = 1;
475
476     if (fdb_delta_open) {
477        /* Set up file extension */
478        strcat(rsync_delta_file, batch_file_ext); 
479
480        /* Open batch delta file for writing; create it if it doesn't exist */
481        fdb_delta = do_open(rsync_delta_file, O_WRONLY|O_CREAT|O_TRUNC,
482                                               S_IREAD|S_IWRITE);
483        if (fdb_delta == -1) {
484           rprintf(FERROR, "Batch file %s open error: %s\n",
485           rsync_delta_file, strerror(errno));
486           close(fdb_delta);
487           exit_cleanup(1);
488        }
489        fdb_delta_open = 0; 
490     }
491
492     /* Write buffer to batch delta file */
493
494     if ( write(fdb_delta, buff, bytes_to_write) == -1 ) { 
495             rprintf(FERROR, "Batch file %s write error: %s\n",
496           rsync_delta_file, strerror(errno));
497           close(fdb_delta);
498           exit_cleanup(1);
499     }
500 }
501 void close_batch_delta_file()
502 {
503    close(fdb_delta);
504
505 }
506
507 int read_batch_delta_file(char *buff, int len)
508 {
509     static int fdb_delta_open = 1;
510     int bytes_read;
511       
512     if (fdb_delta_open) {
513
514        /*  Set up file extension  */
515        strcat(rsync_delta_file, batch_file_ext);
516
517        /* Open batch flist file for reading */
518        fdb_delta = do_open(rsync_delta_file, O_RDONLY, 0);
519        if (fdb_delta == -1) {
520           rprintf(FERROR, "Batch file %s open error: %s\n", rsync_delta_file,
521             strerror(errno));
522           close(fdb_delta);
523           exit_cleanup(1);
524        }
525        fdb_delta_open = 0;
526     }
527
528     /* Read delta batch file */
529
530     bytes_read = read(fdb_delta, buff, len); 
531
532     if (bytes_read == -1) { 
533        rprintf(FERROR, "Batch file %s read error: %s\n",
534           rsync_delta_file, strerror(errno));
535        close(fdb_delta);
536        exit_cleanup(1);
537     }
538     return bytes_read;
539 }
540
541
542 void show_flist(int index, struct file_struct **fptr)
543 {
544    /*  for debugging    show_flist(flist->count, flist->files **/ 
545
546     int i;
547     for (i=0;i<index;i++) {
548             rprintf(FINFO, "flist->flags=%#x\n",fptr[i]->flags);  
549             rprintf(FINFO, "flist->modtime=%#lx\n",
550                     (long unsigned) fptr[i]->modtime);  
551             rprintf(FINFO, "flist->length=%.0f\n", (double) fptr[i]->length);  
552             rprintf(FINFO, "flist->mode=%#o\n", (int) fptr[i]->mode);  
553             rprintf(FINFO, "flist->basename=%s\n",fptr[i]->basename);
554             if (fptr[i]->dirname) 
555                     rprintf(FINFO, "flist->dirname=%s\n",fptr[i]->dirname);
556             if (fptr[i]->basedir) 
557                     rprintf(FINFO, "flist->basedir=%s\n",fptr[i]->basedir);
558     }
559 }
560
561 void show_argvs(int argc, char *argv[])
562 {
563    /*  for debugging  **/ 
564
565     int i;
566     rprintf(FINFO,"BATCH.C:show_argvs,argc=%d\n",argc);
567     for (i=0;i<argc;i++) {
568    /*    if (argv[i])   */
569        rprintf(FINFO,"i=%d,argv[i]=%s\n",i,argv[i]);  
570
571     }
572 }
573