Merge across rsync+ patch; add a little documentation to the manpage. More documenta...
[rsync/rsync.git] / batch.c
1 /* 
2    Weiss 1/1999
3    Batch utilities 
4
5 */ 
6
7 #include "rsync.h"
8 #include <time.h>
9
10 char rsync_flist_file[27] = "rsync_flist.";    
11 char rsync_csums_file[27] = "rsync_csums.";     
12 char rsync_delta_file[27] = "rsync_delta.";    
13 char rsync_argvs_file[27] = "rsync_argvs.";    
14
15 char batch_file_ext[15];
16  
17 int fdb;
18 int fdb_delta;
19 int fdb_open;   
20 int fdb_close;  
21
22 struct file_list *batch_flist;
23
24 void create_batch_file_ext()
25 {
26     struct tm *timeptr;
27     time_t elapsed_seconds;
28     
29     /* Save run date and time to use for batch file extensions */
30     time(&elapsed_seconds);
31     timeptr = localtime(&elapsed_seconds);
32
33     sprintf(batch_file_ext, "%4d%02d%02d%02d%02d%02d",
34              timeptr->tm_year+1900, timeptr->tm_mon+1, timeptr->tm_mday,
35              timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
36 }
37
38 void set_batch_file_ext(char *ext)
39 {
40     strcpy(batch_file_ext, ext);  
41 }
42
43 void write_batch_flist_file(char *buff, int bytes_to_write)
44 {
45
46     if (fdb_open) {
47        /* Set up file extension */
48        strcat(rsync_flist_file, batch_file_ext); 
49
50        /* Open batch flist file for writing; create it if it doesn't exist */
51        fdb = do_open(rsync_flist_file, O_WRONLY|O_CREAT|O_TRUNC,
52                                               S_IREAD|S_IWRITE);
53        if (fdb == -1) {
54           rprintf(FERROR, "Batch file %s open error: %s\n",
55           rsync_flist_file, strerror(errno));
56           close(fdb);
57           exit_cleanup(1);
58        }
59        fdb_open = 0;
60     }
61
62     /* Write buffer to batch flist file */
63
64     if ( write(fdb, buff, bytes_to_write) == -1 ) { 
65             rprintf(FERROR, "Batch file %s write error: %s\n",
66           rsync_flist_file, strerror(errno));
67           close(fdb);
68           exit_cleanup(1);
69     }
70
71
72     if (fdb_close) {
73        close(fdb);
74     }
75 }
76
77 void write_batch_flist_info(int flist_count, struct file_struct **fptr)
78 {
79     int i;
80     int bytes_to_write;   
81
82     /* Write flist info to batch file */
83
84     bytes_to_write = sizeof(unsigned) +
85                      sizeof(time_t) +
86                      sizeof(OFF_T) +
87                      sizeof(mode_t) +
88                      sizeof(INO_T) +
89                      (2 * sizeof(dev_t)) +
90                      sizeof(uid_t) +
91                      sizeof(gid_t);   
92
93     fdb_open = 1;
94     fdb_close = 0;
95
96     for (i=0; i<flist_count; i++) {
97        write_batch_flist_file( (char *) fptr[i], bytes_to_write);
98        write_char_bufs(fptr[i]->basename);
99        write_char_bufs(fptr[i]->dirname);
100        write_char_bufs(fptr[i]->basedir);
101        write_char_bufs(fptr[i]->link);
102        if (i==flist_count - 1) {
103           fdb_close = 1;
104        }
105        write_char_bufs(fptr[i]->sum);
106     }  
107
108 }
109
110 void write_char_bufs(char *buf)
111 {
112    /* Write the size of the string which will follow  */ 
113
114    char b[4];
115    if (buf != NULL)
116       SIVAL(b,0,strlen(buf));  
117    else {
118       SIVAL(b,0,0);
119    }
120
121    write_batch_flist_file(b, sizeof(int));  
122
123    /*  Write the string if there is one */
124
125    if (buf != NULL) {
126       write_batch_flist_file(buf, strlen(buf)); 
127    }
128 }
129
130 void write_batch_argvs_file(int orig_argc, int argc, char **argv)
131 {
132     int fdb;
133     int i;
134     char buff[256];
135
136     strcat(rsync_argvs_file, batch_file_ext);
137     
138
139     /* Open batch argvs file for writing; create it if it doesn't exist */
140     fdb = do_open(rsync_argvs_file, O_WRONLY|O_CREAT|O_TRUNC,
141                                            S_IREAD|S_IWRITE|S_IEXEC);
142     if (fdb == -1) {
143        rprintf(FERROR, "Batch file %s open error: %s\n", rsync_argvs_file,
144          strerror(errno));
145           close(fdb);
146           exit_cleanup(1);
147     }
148     buff[0] = '\0';
149     /* Write argvs info to batch file */
150    
151     for (i=argc - orig_argc;i<argc;i++) {
152        if ( !strcmp(argv[i],"-F") ){  /* safer to change it here than script*/ 
153           strncat(buff,"-f ",3);  /* chg to -f + ext to get ready for remote */
154           strncat(buff,batch_file_ext,strlen(batch_file_ext));
155        }
156        else {
157           strncat(buff,argv[i],strlen(argv[i]));
158        }
159     
160        if (i < (argc - 1)) {
161           strncat(buff," ",1);
162        }
163     }
164     if (!write(fdb, buff, strlen(buff))) { 
165           rprintf(FERROR, "Batch file %s write error: %s\n",
166             rsync_argvs_file, strerror(errno));
167           close(fdb);
168           exit_cleanup(1);
169     }
170     close(fdb);
171 }
172
173 struct file_list *create_flist_from_batch()
174 {
175    unsigned char flags;
176
177    fdb_open = 1;
178    fdb_close = 0;  
179
180    batch_flist = (struct file_list *)malloc(sizeof(batch_flist[0]));
181    if (!batch_flist) {
182      out_of_memory("create_flist_from_batch"); 
183    }
184    batch_flist->count=0;
185    batch_flist->malloced=1000;
186    batch_flist->files = (struct file_struct **)malloc(sizeof(batch_flist->files[0])* batch_flist->malloced);
187    if (!batch_flist->files) {
188      out_of_memory("create_flist_from_batch");   /* dw -- will exit */
189    }
190
191    for ( flags=read_batch_flags() ; flags; flags=read_batch_flags() ) {
192
193      int i = batch_flist->count;
194  
195      if (i >= batch_flist->malloced) {
196           if (batch_flist->malloced < 1000)
197                   batch_flist->malloced += 1000;
198           else
199                   batch_flist->malloced *= 2;
200           batch_flist->files =(struct file_struct **)realloc(batch_flist->files,
201                                                sizeof(batch_flist->files[0])*
202                                                batch_flist->malloced);
203           if (!batch_flist->files)
204                   out_of_memory("create_flist_from_batch");
205     }
206     read_batch_flist_info(&batch_flist->files[i]);
207     batch_flist->files[i]->flags = flags;   
208
209     batch_flist->count++;
210   }
211
212   return batch_flist;
213
214 }
215
216 int read_batch_flist_file(char *buff, int len)
217 {
218     int bytes_read;
219       
220     if (fdb_open) {
221
222        /*  Set up file extension  */
223        strcat(rsync_flist_file, batch_file_ext);
224
225        /* Open batch flist file for reading */
226        fdb = do_open(rsync_flist_file, O_RDONLY, 0);
227        if (fdb == -1) {
228           rprintf(FERROR, "Batch file %s open error: %s\n", rsync_flist_file,
229             strerror(errno));
230           close(fdb);
231           exit_cleanup(1);
232        }
233        fdb_open = 0;
234     }
235
236     /* Read flist batch file */
237
238     bytes_read = read(fdb, buff, len); 
239
240     if (bytes_read == -1) { 
241        rprintf(FERROR, "Batch file %s read error: %s\n",
242           rsync_flist_file, strerror(errno));
243        close(fdb);
244        exit_cleanup(1);
245     }
246     if (bytes_read == 0) {    /* EOF */
247        close(fdb);
248     }
249     return bytes_read;
250 }
251
252 unsigned char read_batch_flags()
253 {
254     int flags; 
255
256     if (read_batch_flist_file((char *)&flags, 4) ) { 
257        return 1;
258     }
259     else {
260        return 0; 
261     }
262 }
263
264 void read_batch_flist_info(struct file_struct **fptr)
265 {
266     int int_str_len;   
267     char char_str_len[4];   
268     char buff[256];   
269     struct file_struct *file;
270
271     file = (struct file_struct *)malloc(sizeof(*file));
272     if (!file) out_of_memory("read_batch_flist_info");
273     memset((char *)file, 0, sizeof(*file));
274
275     (*fptr) = file;
276
277     read_batch_flist_file((char *)&file->modtime, sizeof(time_t)); 
278     read_batch_flist_file((char *)&file->length, sizeof(OFF_T)); 
279     read_batch_flist_file((char *)&file->mode, sizeof(mode_t)); 
280     read_batch_flist_file((char *)&file->inode, sizeof(INO_T)); 
281     read_batch_flist_file((char *)&file->dev, sizeof(dev_t)); 
282     read_batch_flist_file((char *)&file->rdev, sizeof(dev_t)); 
283     read_batch_flist_file((char *)&file->uid, sizeof(uid_t)); 
284     read_batch_flist_file((char *)&file->gid, sizeof(gid_t)); 
285     read_batch_flist_file(char_str_len, sizeof(char_str_len)); 
286     int_str_len = IVAL(char_str_len,0);
287     if (int_str_len > 0) {
288        read_batch_flist_file(buff, int_str_len); 
289        buff[int_str_len] = '\0';
290        file->basename = strdup(buff); 
291     }
292     else {
293        file->basename = NULL;
294     }
295
296     read_batch_flist_file(char_str_len, sizeof(char_str_len)); 
297     int_str_len = IVAL(char_str_len,0);
298     if (int_str_len > 0) {
299        read_batch_flist_file(buff, int_str_len); 
300        buff[int_str_len] = '\0';
301        file[0].dirname = strdup(buff); 
302     }
303     else {
304        file[0].dirname = NULL;
305     }
306
307     read_batch_flist_file(char_str_len, sizeof(char_str_len)); 
308     int_str_len = IVAL(char_str_len,0);
309     if (int_str_len > 0) {
310        read_batch_flist_file(buff, int_str_len); 
311        buff[int_str_len] = '\0';
312        file[0].basedir = strdup(buff); 
313     }
314     else {
315        file[0].basedir = NULL;
316     }
317
318     read_batch_flist_file(char_str_len, sizeof(char_str_len)); 
319     int_str_len = IVAL(char_str_len,0);
320     if (int_str_len > 0) {
321        read_batch_flist_file(buff, int_str_len); 
322        buff[int_str_len] = '\0';
323        file[0].link = strdup(buff); 
324     }
325     else {
326        file[0].link = NULL;
327     }
328
329     read_batch_flist_file(char_str_len, sizeof(char_str_len)); 
330     int_str_len = IVAL(char_str_len,0);
331     if (int_str_len > 0) {
332        read_batch_flist_file(buff, int_str_len); 
333        buff[int_str_len] = '\0';
334        file[0].sum = strdup(buff); 
335     }
336     else {
337        file[0].sum = NULL;
338     }
339 }
340
341 void write_batch_csums_file(char *buff, int bytes_to_write)
342 {
343
344     static int fdb_open = 1;
345
346     if (fdb_open) {
347        /* Set up file extension */
348        strcat(rsync_csums_file, batch_file_ext); 
349
350        /* Open batch csums file for writing; create it if it doesn't exist */
351        fdb = do_open(rsync_csums_file, O_WRONLY|O_CREAT|O_TRUNC,
352                                               S_IREAD|S_IWRITE);
353        if (fdb == -1) {
354           rprintf(FERROR, "Batch file %s open error: %s\n",
355           rsync_csums_file, strerror(errno));
356           close(fdb);
357           exit_cleanup(1);
358        }
359        fdb_open = 0; 
360     }
361
362     /* Write buffer to batch csums file */
363
364     if ( write(fdb, buff, bytes_to_write) == -1 ) { 
365             rprintf(FERROR, "Batch file %s write error: %s\n",
366           rsync_csums_file, strerror(errno));
367           close(fdb);
368           exit_cleanup(1);
369     }
370 }
371
372 void close_batch_csums_file() 
373 {
374     close(fdb);
375
376 }
377
378 void write_batch_csum_info(int *flist_entry, int flist_count, struct sum_struct *s)
379 {
380     int i;
381     int int_zero = 0;
382     extern int block_size;
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=%x\n",fptr[i]->modtime);  
550        rprintf(FINFO,"flist->length=%x\n",fptr[i]->length);  
551        rprintf(FINFO,"flist->mode=%x\n",fptr[i]->mode);  
552        rprintf(FINFO,"flist->basename=%s\n",fptr[i]->basename);
553        if (fptr[i]->dirname) 
554        rprintf(FINFO,"flist->dirname=%s\n",fptr[i]->dirname);
555        if (fptr[i]->basedir) 
556        rprintf(FINFO,"flist->basedir=%s\n",fptr[i]->basedir);
557     }
558 }
559
560 void show_argvs(int argc, char *argv[])
561 {
562    /*  for debugging  **/ 
563
564     int i;
565     rprintf(FINFO,"BATCH.C:show_argvs,argc=%d\n",argc);
566     for (i=0;i<argc;i++) {
567    /*    if (argv[i])   */
568        rprintf(FINFO,"i=%d,argv[i]=%s\n",i,argv[i]);  
569
570     }
571 }
572