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