1 /* -*- c-file-style: "linux" -*-
4 Batch utilities for rsync.
11 extern char *batch_prefix
;
13 struct file_list
*batch_flist
;
15 static char rsync_flist_file
[] = ".rsync_flist";
16 static char rsync_csums_file
[] = ".rsync_csums";
17 static char rsync_delta_file
[] = ".rsync_delta";
18 static char rsync_argvs_file
[] = ".rsync_argvs";
25 void write_batch_flist_file(char *buff
, int bytes_to_write
)
27 char filename
[MAXPATHLEN
];
30 /* Set up file extension */
31 strlcpy(filename
, batch_prefix
, sizeof(filename
));
32 strlcat(filename
, rsync_flist_file
, sizeof(filename
));
35 * Open batch flist file for writing;
36 * create it if it doesn't exist
38 fdb
= do_open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
,
41 rprintf(FERROR
, "Batch file %s open error: %s\n",
42 filename
, strerror(errno
));
49 /* Write buffer to batch flist file */
51 if (write(fdb
, buff
, bytes_to_write
) == -1) {
52 rprintf(FERROR
, "Batch file %s write error: %s\n",
53 filename
, strerror(errno
));
63 void write_batch_flist_info(int flist_count
, struct file_struct
**fptr
)
68 /* Write flist info to batch file */
84 for (i
= 0; i
< flist_count
; i
++) {
85 write_batch_flist_file((char *) fptr
[i
], bytes_to_write
);
86 write_char_bufs(fptr
[i
]->basename
);
87 write_char_bufs(fptr
[i
]->dirname
);
88 write_char_bufs(fptr
[i
]->basedir
);
89 write_char_bufs(fptr
[i
]->link
);
90 if (i
== flist_count
- 1) {
93 write_char_bufs(fptr
[i
]->sum
);
97 void write_char_bufs(char *buf
)
99 /* Write the size of the string which will follow */
103 SIVAL(b
, 0, buf
!= NULL
? strlen(buf
) : 0);
105 write_batch_flist_file(b
, sizeof(int));
107 /* Write the string if there is one */
110 write_batch_flist_file(buf
, strlen(buf
));
114 void write_batch_argvs_file(int argc
, char *argv
[])
118 char buff
[256]; /* XXX */
119 char buff2
[MAXPATHLEN
+ 6];
120 char filename
[MAXPATHLEN
];
122 /* Set up file extension */
123 strlcpy(filename
, batch_prefix
, sizeof(filename
));
124 strlcat(filename
, rsync_argvs_file
, sizeof(filename
));
127 * Open batch argvs file for writing;
128 * create it if it doesn't exist
130 fdb
= do_open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
,
131 S_IREAD
| S_IWRITE
| S_IEXEC
);
133 rprintf(FERROR
, "Batch file %s open error: %s\n",
134 filename
, strerror(errno
));
140 /* Write argvs info to batch file */
142 for (i
= 0; i
< argc
; ++i
) {
143 if (i
== argc
- 2) /* Skip source directory on cmdline */
147 * I think directly manipulating argv[] is probably bogus
149 if (!strncmp(argv
[i
], "--write-batch",
150 strlen("--write-batch"))) {
151 /* Safer to change it here than script */
153 * Change to --read-batch=prefix
154 * to get ready for remote
156 strlcat(buff
, "--read-batch=", sizeof(buff
));
157 strlcat(buff
, batch_prefix
, sizeof(buff
));
160 snprintf(buff2
, sizeof(buff2
), "${1:-%s}", argv
[i
]);
161 strlcat(buff
, buff2
, sizeof(buff
));
164 strlcat(buff
, argv
[i
], sizeof(buff
));
167 if (i
< (argc
- 1)) {
168 strlcat(buff
, " ", sizeof(buff
));
171 strlcat(buff
, "\n", sizeof(buff
));
172 if (!write(fdb
, buff
, strlen(buff
))) {
173 rprintf(FERROR
, "Batch file %s write error: %s\n",
174 filename
, strerror(errno
));
181 struct file_list
*create_flist_from_batch(void)
188 batch_flist
= (struct file_list
*) malloc(sizeof(batch_flist
[0]));
190 out_of_memory("create_flist_from_batch");
192 batch_flist
->count
= 0;
193 batch_flist
->malloced
= 1000;
195 (struct file_struct
**) malloc(sizeof(batch_flist
->files
[0]) *
196 batch_flist
->malloced
);
197 if (!batch_flist
->files
) {
198 out_of_memory("create_flist_from_batch");
201 for (flags
= read_batch_flags(); flags
; flags
= read_batch_flags()) {
203 int i
= batch_flist
->count
;
205 if (i
>= batch_flist
->malloced
) {
206 if (batch_flist
->malloced
< 1000)
207 batch_flist
->malloced
+= 1000;
209 batch_flist
->malloced
*= 2;
211 (struct file_struct
**) realloc(batch_flist
->
218 if (!batch_flist
->files
)
219 out_of_memory("create_flist_from_batch");
221 read_batch_flist_info(&batch_flist
->files
[i
]);
222 batch_flist
->files
[i
]->flags
= flags
;
224 batch_flist
->count
++;
230 int read_batch_flist_file(char *buff
, int len
)
233 char filename
[MAXPATHLEN
];
236 /* Set up file extension */
237 strlcpy(filename
, batch_prefix
, sizeof(filename
));
238 strlcat(filename
, rsync_flist_file
, sizeof(filename
));
240 /* Open batch flist file for reading */
241 fdb
= do_open(filename
, O_RDONLY
, 0);
243 rprintf(FERROR
, "Batch file %s open error: %s\n",
244 filename
, strerror(errno
));
251 /* Read flist batch file */
253 switch (bytes_read
= read(fdb
, buff
, len
)) {
255 rprintf(FERROR
, "Batch file %s read error: %s\n",
256 filename
, strerror(errno
));
267 unsigned char read_batch_flags(void)
271 if (read_batch_flist_file((char *) &flags
, 4)) {
278 void read_batch_flist_info(struct file_struct
**fptr
)
281 char char_str_len
[4];
283 struct file_struct
*file
;
285 file
= (struct file_struct
*) malloc(sizeof(*file
));
287 out_of_memory("read_batch_flist_info");
288 memset((char *) file
, 0, sizeof(*file
));
293 * Keep these in sync with bytes_to_write assignment
294 * in write_batch_flist_info()
296 read_batch_flist_file((char *) &file
->modtime
, sizeof(time_t));
297 read_batch_flist_file((char *) &file
->length
, sizeof(OFF_T
));
298 read_batch_flist_file((char *) &file
->mode
, sizeof(mode_t
));
299 read_batch_flist_file((char *) &file
->inode
, sizeof(INO64_T
));
300 read_batch_flist_file((char *) &file
->dev
, sizeof(DEV64_T
));
301 read_batch_flist_file((char *) &file
->rdev
, sizeof(DEV64_T
));
302 read_batch_flist_file((char *) &file
->uid
, sizeof(uid_t
));
303 read_batch_flist_file((char *) &file
->gid
, sizeof(gid_t
));
304 read_batch_flist_file(char_str_len
, sizeof(char_str_len
));
305 int_str_len
= IVAL(char_str_len
, 0);
306 if (int_str_len
> 0) {
307 read_batch_flist_file(buff
, int_str_len
);
308 buff
[int_str_len
] = '\0';
309 file
->basename
= strdup(buff
);
311 file
->basename
= NULL
;
314 read_batch_flist_file(char_str_len
, sizeof(char_str_len
));
315 int_str_len
= IVAL(char_str_len
, 0);
316 if (int_str_len
> 0) {
317 read_batch_flist_file(buff
, int_str_len
);
318 buff
[int_str_len
] = '\0';
319 file
[0].dirname
= strdup(buff
);
321 file
[0].dirname
= NULL
;
324 read_batch_flist_file(char_str_len
, sizeof(char_str_len
));
325 int_str_len
= IVAL(char_str_len
, 0);
326 if (int_str_len
> 0) {
327 read_batch_flist_file(buff
, int_str_len
);
328 buff
[int_str_len
] = '\0';
329 file
[0].basedir
= strdup(buff
);
331 file
[0].basedir
= NULL
;
334 read_batch_flist_file(char_str_len
, sizeof(char_str_len
));
335 int_str_len
= IVAL(char_str_len
, 0);
336 if (int_str_len
> 0) {
337 read_batch_flist_file(buff
, int_str_len
);
338 buff
[int_str_len
] = '\0';
339 file
[0].link
= strdup(buff
);
344 read_batch_flist_file(char_str_len
, sizeof(char_str_len
));
345 int_str_len
= IVAL(char_str_len
, 0);
346 if (int_str_len
> 0) {
347 read_batch_flist_file(buff
, int_str_len
);
348 buff
[int_str_len
] = '\0';
349 file
[0].sum
= strdup(buff
);
355 void write_batch_csums_file(void *buff
, int bytes_to_write
)
357 static int fdb_open
= 1;
358 char filename
[MAXPATHLEN
];
361 /* Set up file extension */
362 strlcpy(filename
, batch_prefix
, sizeof(filename
));
363 strlcat(filename
, rsync_csums_file
, sizeof(filename
));
366 * Open batch csums file for writing;
367 * create it if it doesn't exist
369 fdb
= do_open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
,
372 rprintf(FERROR
, "Batch file %s open error: %s\n",
373 filename
, strerror(errno
));
380 /* Write buffer to batch csums file */
382 if (write(fdb
, buff
, bytes_to_write
) == -1) {
383 rprintf(FERROR
, "Batch file %s write error: %s\n",
384 filename
, strerror(errno
));
390 void close_batch_csums_file(void)
397 * Write csum info to batch file
399 * @todo This will break if s->count is ever larger than maxint. The
400 * batch code should probably be changed to consistently use the
401 * variable-length integer routines, which is probably a compatible
404 void write_batch_csum_info(int *flist_entry
, int flist_count
,
405 struct sum_struct
*s
)
409 extern int csum_length
;
413 write_batch_csums_file(flist_entry
, sizeof(int));
414 int_count
= s
? (int) s
->count
: 0;
415 write_batch_csums_file(&int_count
, sizeof int_count
);
418 for (i
= 0; i
< s
->count
; i
++) {
419 write_batch_csums_file(&s
->sums
[i
].sum1
, sizeof(uint32
));
420 if ((*flist_entry
== flist_count
- 1)
421 && (i
== s
->count
- 1)) {
424 write_batch_csums_file(s
->sums
[i
].sum2
, csum_length
);
429 int read_batch_csums_file(char *buff
, int len
)
431 static int fdb_open
= 1;
433 char filename
[MAXPATHLEN
];
436 /* Set up file extension */
437 strlcpy(filename
, batch_prefix
, sizeof(filename
));
438 strlcat(filename
, rsync_csums_file
, sizeof(filename
));
440 /* Open batch flist file for reading */
441 fdb
= do_open(filename
, O_RDONLY
, 0);
443 rprintf(FERROR
, "Batch file %s open error: %s\n",
444 filename
, strerror(errno
));
451 /* Read csums batch file */
453 bytes_read
= read(fdb
, buff
, len
);
455 if (bytes_read
== -1) {
456 rprintf(FERROR
, "Batch file %s read error: %s\n",
457 filename
, strerror(errno
));
465 void read_batch_csum_info(int flist_entry
, struct sum_struct
*s
,
466 int *checksums_match
)
469 int file_flist_entry
;
472 char file_sum2
[SUM_LENGTH
];
473 extern int csum_length
;
475 read_batch_csums_file((char *) &file_flist_entry
, sizeof(int));
476 if (file_flist_entry
!= flist_entry
) {
477 rprintf(FINFO
, "file_flist_entry (%d) != flist_entry (%d)\n",
478 file_flist_entry
, flist_entry
);
483 read_batch_csums_file((char *) &file_chunk_ct
,
485 *checksums_match
= 1;
486 for (i
= 0; i
< file_chunk_ct
; i
++) {
488 read_batch_csums_file((char *) &file_sum1
,
490 read_batch_csums_file(file_sum2
, csum_length
);
492 if ((s
->sums
[i
].sum1
!= file_sum1
) ||
493 (memcmp(s
->sums
[i
].sum2
, file_sum2
, csum_length
)
495 *checksums_match
= 0;
501 void write_batch_delta_file(char *buff
, int bytes_to_write
)
503 static int fdb_delta_open
= 1;
504 char filename
[MAXPATHLEN
];
506 if (fdb_delta_open
) {
507 /* Set up file extension */
508 strlcpy(filename
, batch_prefix
, sizeof(filename
));
509 strlcat(filename
, rsync_delta_file
, sizeof(filename
));
512 * Open batch delta file for writing;
513 * create it if it doesn't exist
515 fdb_delta
= do_open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
,
517 if (fdb_delta
== -1) {
518 rprintf(FERROR
, "Batch file %s open error: %s\n",
519 filename
, strerror(errno
));
526 /* Write buffer to batch delta file */
528 if (write(fdb_delta
, buff
, bytes_to_write
) == -1) {
529 rprintf(FERROR
, "Batch file %s write error: %s\n",
530 filename
, strerror(errno
));
536 void close_batch_delta_file(void)
541 int read_batch_delta_file(char *buff
, int len
)
543 static int fdb_delta_open
= 1;
545 char filename
[MAXPATHLEN
];
547 if (fdb_delta_open
) {
548 /* Set up file extension */
549 strlcpy(filename
, batch_prefix
, sizeof(filename
));
550 strlcat(filename
, rsync_delta_file
, sizeof(filename
));
552 /* Open batch flist file for reading */
553 fdb_delta
= do_open(filename
, O_RDONLY
, 0);
554 if (fdb_delta
== -1) {
555 rprintf(FERROR
, "Batch file %s open error: %s\n",
556 filename
, strerror(errno
));
563 /* Read delta batch file */
565 bytes_read
= read(fdb_delta
, buff
, len
);
567 if (bytes_read
== -1) {
568 rprintf(FERROR
, "Batch file %s read error: %s\n",
569 filename
, strerror(errno
));
577 void show_flist(int index
, struct file_struct
**fptr
)
579 /* for debugging show_flist(flist->count, flist->files * */
582 for (i
= 0; i
< index
; i
++) {
583 rprintf(FINFO
, "flist->flags=%#x\n", fptr
[i
]->flags
);
584 rprintf(FINFO
, "flist->modtime=%#lx\n",
585 (long unsigned) fptr
[i
]->modtime
);
586 rprintf(FINFO
, "flist->length=%.0f\n",
587 (double) fptr
[i
]->length
);
588 rprintf(FINFO
, "flist->mode=%#o\n", (int) fptr
[i
]->mode
);
589 rprintf(FINFO
, "flist->basename=%s\n", fptr
[i
]->basename
);
590 if (fptr
[i
]->dirname
)
591 rprintf(FINFO
, "flist->dirname=%s\n",
593 if (fptr
[i
]->basedir
)
594 rprintf(FINFO
, "flist->basedir=%s\n",
599 void show_argvs(int argc
, char *argv
[])
601 /* for debugging * */
604 rprintf(FINFO
, "BATCH.C:show_argvs,argc=%d\n", argc
);
605 for (i
= 0; i
< argc
; i
++) {
607 rprintf(FINFO
, "i=%d,argv[i]=%s\n", i
, argv
[i
]);