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
= new(struct file_list
);
190 out_of_memory("create_flist_from_batch");
192 batch_flist
->count
= 0;
193 batch_flist
->malloced
= 1000;
194 batch_flist
->files
= new_array(struct file_struct
*,
195 batch_flist
->malloced
);
196 if (!batch_flist
->files
) {
197 out_of_memory("create_flist_from_batch");
200 for (flags
= read_batch_flags(); flags
; flags
= read_batch_flags()) {
202 int i
= batch_flist
->count
;
204 if (i
>= batch_flist
->malloced
) {
205 if (batch_flist
->malloced
< 1000)
206 batch_flist
->malloced
+= 1000;
208 batch_flist
->malloced
*= 2;
210 = realloc_array(batch_flist
->files
,
211 struct file_struct
*,
212 batch_flist
->malloced
);
213 if (!batch_flist
->files
)
214 out_of_memory("create_flist_from_batch");
216 read_batch_flist_info(&batch_flist
->files
[i
]);
217 batch_flist
->files
[i
]->flags
= flags
;
219 batch_flist
->count
++;
225 int read_batch_flist_file(char *buff
, int len
)
228 char filename
[MAXPATHLEN
];
231 /* Set up file extension */
232 strlcpy(filename
, batch_prefix
, sizeof(filename
));
233 strlcat(filename
, rsync_flist_file
, sizeof(filename
));
235 /* Open batch flist file for reading */
236 fdb
= do_open(filename
, O_RDONLY
, 0);
238 rprintf(FERROR
, "Batch file %s open error: %s\n",
239 filename
, strerror(errno
));
246 /* Read flist batch file */
248 switch (bytes_read
= read(fdb
, buff
, len
)) {
250 rprintf(FERROR
, "Batch file %s read error: %s\n",
251 filename
, strerror(errno
));
262 unsigned char read_batch_flags(void)
266 if (read_batch_flist_file((char *) &flags
, 4)) {
273 void read_batch_flist_info(struct file_struct
**fptr
)
276 char char_str_len
[4];
278 struct file_struct
*file
;
280 file
= new(struct file_struct
);
282 out_of_memory("read_batch_flist_info");
283 memset((char *) file
, 0, sizeof(*file
));
288 * Keep these in sync with bytes_to_write assignment
289 * in write_batch_flist_info()
291 read_batch_flist_file((char *) &file
->modtime
, sizeof(time_t));
292 read_batch_flist_file((char *) &file
->length
, sizeof(OFF_T
));
293 read_batch_flist_file((char *) &file
->mode
, sizeof(mode_t
));
294 read_batch_flist_file((char *) &file
->inode
, sizeof(INO64_T
));
295 read_batch_flist_file((char *) &file
->dev
, sizeof(DEV64_T
));
296 read_batch_flist_file((char *) &file
->rdev
, sizeof(DEV64_T
));
297 read_batch_flist_file((char *) &file
->uid
, sizeof(uid_t
));
298 read_batch_flist_file((char *) &file
->gid
, sizeof(gid_t
));
299 read_batch_flist_file(char_str_len
, sizeof(char_str_len
));
300 int_str_len
= IVAL(char_str_len
, 0);
301 if (int_str_len
> 0) {
302 read_batch_flist_file(buff
, int_str_len
);
303 buff
[int_str_len
] = '\0';
304 file
->basename
= strdup(buff
);
306 file
->basename
= NULL
;
309 read_batch_flist_file(char_str_len
, sizeof(char_str_len
));
310 int_str_len
= IVAL(char_str_len
, 0);
311 if (int_str_len
> 0) {
312 read_batch_flist_file(buff
, int_str_len
);
313 buff
[int_str_len
] = '\0';
314 file
[0].dirname
= strdup(buff
);
316 file
[0].dirname
= NULL
;
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].basedir
= strdup(buff
);
326 file
[0].basedir
= NULL
;
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].link
= strdup(buff
);
339 read_batch_flist_file(char_str_len
, sizeof(char_str_len
));
340 int_str_len
= IVAL(char_str_len
, 0);
341 if (int_str_len
> 0) {
342 read_batch_flist_file(buff
, int_str_len
);
343 buff
[int_str_len
] = '\0';
344 file
[0].sum
= strdup(buff
);
350 void write_batch_csums_file(void *buff
, int bytes_to_write
)
352 static int fdb_open
= 1;
353 char filename
[MAXPATHLEN
];
356 /* Set up file extension */
357 strlcpy(filename
, batch_prefix
, sizeof(filename
));
358 strlcat(filename
, rsync_csums_file
, sizeof(filename
));
361 * Open batch csums file for writing;
362 * create it if it doesn't exist
364 fdb
= do_open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
,
367 rprintf(FERROR
, "Batch file %s open error: %s\n",
368 filename
, strerror(errno
));
375 /* Write buffer to batch csums file */
377 if (write(fdb
, buff
, bytes_to_write
) == -1) {
378 rprintf(FERROR
, "Batch file %s write error: %s\n",
379 filename
, strerror(errno
));
385 void close_batch_csums_file(void)
392 * Write csum info to batch file
394 * @todo This will break if s->count is ever larger than maxint. The
395 * batch code should probably be changed to consistently use the
396 * variable-length integer routines, which is probably a compatible
399 void write_batch_csum_info(int *flist_entry
, int flist_count
,
400 struct sum_struct
*s
)
404 extern int csum_length
;
408 write_batch_csums_file(flist_entry
, sizeof(int));
409 int_count
= s
? (int) s
->count
: 0;
410 write_batch_csums_file(&int_count
, sizeof int_count
);
413 for (i
= 0; i
< s
->count
; i
++) {
414 write_batch_csums_file(&s
->sums
[i
].sum1
, sizeof(uint32
));
415 if ((*flist_entry
== flist_count
- 1)
416 && (i
== s
->count
- 1)) {
419 write_batch_csums_file(s
->sums
[i
].sum2
, csum_length
);
424 int read_batch_csums_file(char *buff
, int len
)
426 static int fdb_open
= 1;
428 char filename
[MAXPATHLEN
];
431 /* Set up file extension */
432 strlcpy(filename
, batch_prefix
, sizeof(filename
));
433 strlcat(filename
, rsync_csums_file
, sizeof(filename
));
435 /* Open batch flist file for reading */
436 fdb
= do_open(filename
, O_RDONLY
, 0);
438 rprintf(FERROR
, "Batch file %s open error: %s\n",
439 filename
, strerror(errno
));
446 /* Read csums batch file */
448 bytes_read
= read(fdb
, buff
, len
);
450 if (bytes_read
== -1) {
451 rprintf(FERROR
, "Batch file %s read error: %s\n",
452 filename
, strerror(errno
));
460 void read_batch_csum_info(int flist_entry
, struct sum_struct
*s
,
461 int *checksums_match
)
464 int file_flist_entry
;
467 char file_sum2
[SUM_LENGTH
];
468 extern int csum_length
;
470 read_batch_csums_file((char *) &file_flist_entry
, sizeof(int));
471 if (file_flist_entry
!= flist_entry
) {
472 rprintf(FINFO
, "file_flist_entry (%d) != flist_entry (%d)\n",
473 file_flist_entry
, flist_entry
);
478 read_batch_csums_file((char *) &file_chunk_ct
,
480 *checksums_match
= 1;
481 for (i
= 0; i
< file_chunk_ct
; i
++) {
483 read_batch_csums_file((char *) &file_sum1
,
485 read_batch_csums_file(file_sum2
, csum_length
);
487 if ((s
->sums
[i
].sum1
!= file_sum1
) ||
488 (memcmp(s
->sums
[i
].sum2
, file_sum2
, csum_length
)
490 *checksums_match
= 0;
496 void write_batch_delta_file(char *buff
, int bytes_to_write
)
498 static int fdb_delta_open
= 1;
499 char filename
[MAXPATHLEN
];
501 if (fdb_delta_open
) {
502 /* Set up file extension */
503 strlcpy(filename
, batch_prefix
, sizeof(filename
));
504 strlcat(filename
, rsync_delta_file
, sizeof(filename
));
507 * Open batch delta file for writing;
508 * create it if it doesn't exist
510 fdb_delta
= do_open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
,
512 if (fdb_delta
== -1) {
513 rprintf(FERROR
, "Batch file %s open error: %s\n",
514 filename
, strerror(errno
));
521 /* Write buffer to batch delta file */
523 if (write(fdb_delta
, buff
, bytes_to_write
) == -1) {
524 rprintf(FERROR
, "Batch file %s write error: %s\n",
525 filename
, strerror(errno
));
531 void close_batch_delta_file(void)
536 int read_batch_delta_file(char *buff
, int len
)
538 static int fdb_delta_open
= 1;
540 char filename
[MAXPATHLEN
];
542 if (fdb_delta_open
) {
543 /* Set up file extension */
544 strlcpy(filename
, batch_prefix
, sizeof(filename
));
545 strlcat(filename
, rsync_delta_file
, sizeof(filename
));
547 /* Open batch flist file for reading */
548 fdb_delta
= do_open(filename
, O_RDONLY
, 0);
549 if (fdb_delta
== -1) {
550 rprintf(FERROR
, "Batch file %s open error: %s\n",
551 filename
, strerror(errno
));
558 /* Read delta batch file */
560 bytes_read
= read(fdb_delta
, buff
, len
);
562 if (bytes_read
== -1) {
563 rprintf(FERROR
, "Batch file %s read error: %s\n",
564 filename
, strerror(errno
));
572 void show_flist(int index
, struct file_struct
**fptr
)
574 /* for debugging show_flist(flist->count, flist->files * */
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",
588 if (fptr
[i
]->basedir
)
589 rprintf(FINFO
, "flist->basedir=%s\n",
594 void show_argvs(int argc
, char *argv
[])
596 /* for debugging * */
599 rprintf(FINFO
, "BATCH.C:show_argvs,argc=%d\n", argc
);
600 for (i
= 0; i
< argc
; i
++) {
602 rprintf(FINFO
, "i=%d,argv[i]=%s\n", i
, argv
[i
]);