|
version 1.1, 2012/02/17 15:09:30
|
version 1.1.1.1.2.1, 2013/07/22 00:20:20
|
|
Line 78 extern char *basis_dir[MAX_BASIS_DIRS+1];
|
Line 78 extern char *basis_dir[MAX_BASIS_DIRS+1];
|
| extern int compare_dest; |
extern int compare_dest; |
| extern int copy_dest; |
extern int copy_dest; |
| extern int link_dest; |
extern int link_dest; |
| |
extern int detect_renamed; |
| extern int whole_file; |
extern int whole_file; |
| extern int list_only; |
extern int list_only; |
| extern int read_batch; |
extern int read_batch; |
|
Line 96 extern char *backup_suffix;
|
Line 97 extern char *backup_suffix;
|
| extern int backup_suffix_len; |
extern int backup_suffix_len; |
| extern struct file_list *cur_flist, *first_flist, *dir_flist; |
extern struct file_list *cur_flist, *first_flist, *dir_flist; |
| extern struct filter_list_struct daemon_filter_list; |
extern struct filter_list_struct daemon_filter_list; |
| |
extern struct file_list the_fattr_list; |
| |
|
| int ignore_perishable = 0; |
int ignore_perishable = 0; |
| int non_perishable_cnt = 0; |
int non_perishable_cnt = 0; |
|
Line 103 int maybe_ATTRS_REPORT = 0;
|
Line 105 int maybe_ATTRS_REPORT = 0;
|
| |
|
| static dev_t dev_zero; |
static dev_t dev_zero; |
| static int deletion_count = 0; /* used to implement --max-delete */ |
static int deletion_count = 0; /* used to implement --max-delete */ |
| |
static int unexplored_dirs = 1; |
| static int deldelay_size = 0, deldelay_cnt = 0; |
static int deldelay_size = 0, deldelay_cnt = 0; |
| static char *deldelay_buf = NULL; |
static char *deldelay_buf = NULL; |
| static int deldelay_fd = -1; |
static int deldelay_fd = -1; |
|
Line 113 static int need_retouch_dir_times;
|
Line 116 static int need_retouch_dir_times;
|
| static int need_retouch_dir_perms; |
static int need_retouch_dir_perms; |
| static const char *solo_file = NULL; |
static const char *solo_file = NULL; |
| |
|
| /* For calling delete_item() and delete_dir_contents(). */ | /* For calling delete_item(), delete_dir_contents(), and delete_in_dir(). */ |
| #define DEL_NO_UID_WRITE (1<<0) /* file/dir has our uid w/o write perm */ |
#define DEL_NO_UID_WRITE (1<<0) /* file/dir has our uid w/o write perm */ |
| #define DEL_RECURSE (1<<1) /* if dir, delete all contents */ |
#define DEL_RECURSE (1<<1) /* if dir, delete all contents */ |
| #define DEL_DIR_IS_EMPTY (1<<2) /* internal delete_FUNCTIONS use only */ |
#define DEL_DIR_IS_EMPTY (1<<2) /* internal delete_FUNCTIONS use only */ |
|
Line 122 static const char *solo_file = NULL;
|
Line 125 static const char *solo_file = NULL;
|
| #define DEL_FOR_SYMLINK (1<<5) /* making room for a replacement symlink */ |
#define DEL_FOR_SYMLINK (1<<5) /* making room for a replacement symlink */ |
| #define DEL_FOR_DEVICE (1<<6) /* making room for a replacement device */ |
#define DEL_FOR_DEVICE (1<<6) /* making room for a replacement device */ |
| #define DEL_FOR_SPECIAL (1<<7) /* making room for a replacement special */ |
#define DEL_FOR_SPECIAL (1<<7) /* making room for a replacement special */ |
| |
#define DEL_NO_DELETIONS (1<<9) /* just check for renames w/o deleting */ |
| |
|
| #define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL) |
#define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL) |
| |
|
|
Line 146 static int is_backup_file(char *fn)
|
Line 150 static int is_backup_file(char *fn)
|
| return k > 0 && strcmp(fn+k, backup_suffix) == 0; |
return k > 0 && strcmp(fn+k, backup_suffix) == 0; |
| } |
} |
| |
|
| |
/* Search for a regular file that matches either (1) the size & modified |
| |
* time (plus the basename, if possible) or (2) the size & checksum. If |
| |
* we find an exact match down to the dirname, return -1 because we found |
| |
* an up-to-date file in the transfer, not a renamed file. */ |
| |
static int fattr_find(struct file_struct *f, char *fname) |
| |
{ |
| |
int low = the_fattr_list.low, high = the_fattr_list.high; |
| |
int mid, ok_match = -1, good_match = -1; |
| |
struct file_struct *fmid; |
| |
int diff; |
| |
|
| |
while (low <= high) { |
| |
mid = (low + high) / 2; |
| |
fmid = the_fattr_list.files[mid]; |
| |
if (F_LENGTH(fmid) != F_LENGTH(f)) { |
| |
if (F_LENGTH(fmid) < F_LENGTH(f)) |
| |
low = mid + 1; |
| |
else |
| |
high = mid - 1; |
| |
continue; |
| |
} |
| |
if (always_checksum) { |
| |
/* We use the FLAG_FILE_SENT flag to indicate when we |
| |
* have computed the checksum for an entry. */ |
| |
if (!(f->flags & FLAG_FILE_SENT)) { |
| |
if (fmid->modtime == f->modtime |
| |
&& f_name_cmp(fmid, f) == 0) |
| |
return -1; /* assume we can't help */ |
| |
file_checksum(fname, F_SUM(f), F_LENGTH(f)); |
| |
f->flags |= FLAG_FILE_SENT; |
| |
} |
| |
diff = u_memcmp(F_SUM(fmid), F_SUM(f), checksum_len); |
| |
if (diff) { |
| |
if (diff < 0) |
| |
low = mid + 1; |
| |
else |
| |
high = mid - 1; |
| |
continue; |
| |
} |
| |
} else { |
| |
if (fmid->modtime != f->modtime) { |
| |
if (fmid->modtime < f->modtime) |
| |
low = mid + 1; |
| |
else |
| |
high = mid - 1; |
| |
continue; |
| |
} |
| |
} |
| |
ok_match = mid; |
| |
diff = u_strcmp(fmid->basename, f->basename); |
| |
if (diff == 0) { |
| |
good_match = mid; |
| |
if (fmid->dirname == f->dirname) |
| |
return -1; /* file is up-to-date */ |
| |
if (!fmid->dirname) { |
| |
low = mid + 1; |
| |
continue; |
| |
} |
| |
if (!f->dirname) { |
| |
high = mid - 1; |
| |
continue; |
| |
} |
| |
diff = u_strcmp(fmid->dirname, f->dirname); |
| |
if (diff == 0) |
| |
return -1; /* file is up-to-date */ |
| |
} |
| |
if (diff < 0) |
| |
low = mid + 1; |
| |
else |
| |
high = mid - 1; |
| |
} |
| |
|
| |
return good_match >= 0 ? good_match : ok_match; |
| |
} |
| |
|
| |
static void look_for_rename(struct file_struct *file, char *fname) |
| |
{ |
| |
struct file_struct *fp; |
| |
char *partialptr, *fn; |
| |
STRUCT_STAT st; |
| |
int ndx; |
| |
|
| |
if (!partial_dir || (ndx = fattr_find(file, fname)) < 0) |
| |
return; |
| |
|
| |
fp = the_fattr_list.files[ndx]; |
| |
fn = f_name(fp, NULL); |
| |
/* We don't provide an alternate-basis file if there is a basis file. */ |
| |
if (link_stat(fn, &st, 0) == 0) |
| |
return; |
| |
|
| |
if (!dry_run) { |
| |
if ((partialptr = partial_dir_fname(fn)) == NULL |
| |
|| !handle_partial_dir(partialptr, PDIR_CREATE)) |
| |
return; |
| |
/* We only use the file if we can hard-link it into our tmp dir. */ |
| |
if (link(fname, partialptr) != 0) { |
| |
if (errno != EEXIST) |
| |
handle_partial_dir(partialptr, PDIR_DELETE); |
| |
return; |
| |
} |
| |
} |
| |
|
| |
/* I think this falls into the -vv category with "%s is uptodate", etc. */ |
| |
if (verbose > 1) |
| |
rprintf(FINFO, "found renamed: %s => %s\n", fname, fn); |
| |
} |
| |
|
| /* Delete a file or directory. If DEL_RECURSE is set in the flags, this will |
/* Delete a file or directory. If DEL_RECURSE is set in the flags, this will |
| * delete recursively. |
* delete recursively. |
| * |
* |
| * Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's |
* Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's |
| * a directory! (The buffer is used for recursion, but returned unchanged.) |
* a directory! (The buffer is used for recursion, but returned unchanged.) |
| |
* |
| |
* Also note: --detect-rename may use this routine with DEL_NO_DELETIONS set! |
| */ |
*/ |
| static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags) |
static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags) |
| { |
{ |
|
Line 177 static enum delret delete_item(char *fbuf, uint16 mode
|
Line 291 static enum delret delete_item(char *fbuf, uint16 mode
|
| goto check_ret; |
goto check_ret; |
| /* OK: try to delete the directory. */ |
/* OK: try to delete the directory. */ |
| } |
} |
| |
if (flags & DEL_NO_DELETIONS) |
| |
return DR_SUCCESS; |
| |
|
| if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && ++deletion_count > max_delete) |
if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && ++deletion_count > max_delete) |
| return DR_AT_LIMIT; |
return DR_AT_LIMIT; |
|
Line 232 static enum delret delete_item(char *fbuf, uint16 mode
|
Line 348 static enum delret delete_item(char *fbuf, uint16 mode
|
| * its contents, otherwise just checks for content. Returns DR_SUCCESS or |
* its contents, otherwise just checks for content. Returns DR_SUCCESS or |
| * DR_NOT_EMPTY. Note that fname must point to a MAXPATHLEN buffer! (The |
* DR_NOT_EMPTY. Note that fname must point to a MAXPATHLEN buffer! (The |
| * buffer is used for recursion, but returned unchanged.) |
* buffer is used for recursion, but returned unchanged.) |
| |
* |
| |
* Note: --detect-rename may use this routine with DEL_NO_DELETIONS set! |
| */ |
*/ |
| static enum delret delete_dir_contents(char *fname, uint16 flags) |
static enum delret delete_dir_contents(char *fname, uint16 flags) |
| { |
{ |
|
Line 251 static enum delret delete_dir_contents(char *fname, ui
|
Line 369 static enum delret delete_dir_contents(char *fname, ui
|
| save_filters = push_local_filters(fname, dlen); |
save_filters = push_local_filters(fname, dlen); |
| |
|
| non_perishable_cnt = 0; |
non_perishable_cnt = 0; |
| |
file_extra_cnt += SUM_EXTRA_CNT; |
| dirlist = get_dirlist(fname, dlen, 0); |
dirlist = get_dirlist(fname, dlen, 0); |
| |
file_extra_cnt -= SUM_EXTRA_CNT; |
| ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS; |
ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS; |
| |
|
| if (!dirlist->used) |
if (!dirlist->used) |
|
Line 291 static enum delret delete_dir_contents(char *fname, ui
|
Line 411 static enum delret delete_dir_contents(char *fname, ui
|
| if (S_ISDIR(fp->mode)) { |
if (S_ISDIR(fp->mode)) { |
| if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS) |
if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS) |
| ret = DR_NOT_EMPTY; |
ret = DR_NOT_EMPTY; |
| } | } else if (detect_renamed && S_ISREG(fp->mode)) |
| | look_for_rename(fp, fname); |
| if (delete_item(fname, fp->mode, flags) != DR_SUCCESS) |
if (delete_item(fname, fp->mode, flags) != DR_SUCCESS) |
| ret = DR_NOT_EMPTY; |
ret = DR_NOT_EMPTY; |
| } |
} |
|
Line 456 static void do_delayed_deletions(char *delbuf)
|
Line 577 static void do_delayed_deletions(char *delbuf)
|
| * all the --delete-WHEN options. Note that the fbuf pointer must point to a |
* all the --delete-WHEN options. Note that the fbuf pointer must point to a |
| * MAXPATHLEN buffer with the name of the directory in it (the functions we |
* MAXPATHLEN buffer with the name of the directory in it (the functions we |
| * call will append names onto the end, but the old dir value will be restored |
* call will append names onto the end, but the old dir value will be restored |
| * on exit). */ | * on exit). |
| static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev) | * |
| | * Note: --detect-rename may use this routine with DEL_NO_DELETIONS set! |
| | */ |
| | static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev, |
| | int del_flags) |
| { |
{ |
| static int already_warned = 0; |
static int already_warned = 0; |
| struct file_list *dirlist; |
struct file_list *dirlist; |
| char delbuf[MAXPATHLEN]; | char *p, delbuf[MAXPATHLEN]; |
| int dlen, i; | unsigned remainder; |
| | int dlen, i, restore_dot = 0; |
| |
|
| if (!fbuf) { |
if (!fbuf) { |
| change_local_filter_dir(NULL, 0, 0); |
change_local_filter_dir(NULL, 0, 0); |
|
Line 476 static void delete_in_dir(char *fbuf, struct file_stru
|
Line 602 static void delete_in_dir(char *fbuf, struct file_stru
|
| maybe_send_keepalive(); |
maybe_send_keepalive(); |
| |
|
| if (io_error && !ignore_errors) { |
if (io_error && !ignore_errors) { |
| if (already_warned) | if (!already_warned) { |
| | rprintf(FINFO, |
| | "IO error encountered -- skipping file deletion\n"); |
| | already_warned = 1; |
| | } |
| | if (!detect_renamed) |
| return; |
return; |
| rprintf(FINFO, | del_flags |= DEL_NO_DELETIONS; |
| "IO error encountered -- skipping file deletion\n"); | |
| already_warned = 1; | |
| return; | |
| } |
} |
| |
|
| dlen = strlen(fbuf); |
dlen = strlen(fbuf); |
| change_local_filter_dir(fbuf, dlen, F_DEPTH(file)); |
change_local_filter_dir(fbuf, dlen, F_DEPTH(file)); |
| |
|
| |
if (detect_renamed) |
| |
unexplored_dirs--; |
| |
|
| if (one_file_system) { |
if (one_file_system) { |
| if (file->flags & FLAG_TOP_DIR) |
if (file->flags & FLAG_TOP_DIR) |
| filesystem_dev = *fs_dev; |
filesystem_dev = *fs_dev; |
|
Line 496 static void delete_in_dir(char *fbuf, struct file_stru
|
Line 627 static void delete_in_dir(char *fbuf, struct file_stru
|
| |
|
| dirlist = get_dirlist(fbuf, dlen, 0); |
dirlist = get_dirlist(fbuf, dlen, 0); |
| |
|
| |
p = fbuf + dlen; |
| |
if (dlen == 1 && *fbuf == '.') { |
| |
restore_dot = 1; |
| |
p = fbuf; |
| |
} else if (dlen != 1 || *fbuf != '/') |
| |
*p++ = '/'; |
| |
remainder = MAXPATHLEN - (p - fbuf); |
| |
|
| /* If an item in dirlist is not found in flist, delete it |
/* If an item in dirlist is not found in flist, delete it |
| * from the filesystem. */ |
* from the filesystem. */ |
| for (i = dirlist->used; i--; ) { |
for (i = dirlist->used; i--; ) { |
|
Line 508 static void delete_in_dir(char *fbuf, struct file_stru
|
Line 647 static void delete_in_dir(char *fbuf, struct file_stru
|
| f_name(fp, NULL)); |
f_name(fp, NULL)); |
| continue; |
continue; |
| } |
} |
| |
if (detect_renamed && S_ISREG(fp->mode)) { |
| |
strlcpy(p, fp->basename, remainder); |
| |
look_for_rename(fp, fbuf); |
| |
} |
| /* Here we want to match regardless of file type. Replacement |
/* Here we want to match regardless of file type. Replacement |
| * of a file with one of another type is handled separately by |
* of a file with one of another type is handled separately by |
| * a delete_item call with a DEL_MAKE_ROOM flag. */ |
* a delete_item call with a DEL_MAKE_ROOM flag. */ |
|
Line 516 static void delete_in_dir(char *fbuf, struct file_stru
|
Line 659 static void delete_in_dir(char *fbuf, struct file_stru
|
| if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US) |
if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US) |
| flags |= DEL_NO_UID_WRITE; |
flags |= DEL_NO_UID_WRITE; |
| f_name(fp, delbuf); |
f_name(fp, delbuf); |
| if (delete_during == 2) { | if (delete_during == 2 && !(del_flags & DEL_NO_DELETIONS)) { |
| if (!remember_delete(fp, delbuf, flags)) | if (!remember_delete(fp, delbuf, del_flags | flags)) |
| break; |
break; |
| } else |
} else |
| delete_item(delbuf, fp->mode, flags); | delete_item(delbuf, fp->mode, del_flags | flags); |
| } | } else if (detect_renamed && S_ISDIR(fp->mode)) |
| | unexplored_dirs++; |
| } |
} |
| |
|
| |
if (restore_dot) |
| |
fbuf[0] = '.'; |
| |
fbuf[dlen] = '\0'; |
| |
|
| flist_free(dirlist); |
flist_free(dirlist); |
| } |
} |
| |
|
|
Line 556 static void do_delete_pass(void)
|
Line 704 static void do_delete_pass(void)
|
| || !S_ISDIR(st.st_mode)) |
|| !S_ISDIR(st.st_mode)) |
| continue; |
continue; |
| |
|
| delete_in_dir(fbuf, file, &st.st_dev); | delete_in_dir(fbuf, file, &st.st_dev, 0); |
| } |
} |
| delete_in_dir(NULL, NULL, &dev_zero); | delete_in_dir(NULL, NULL, &dev_zero, 0); |
| |
|
| if (do_progress && !am_server) |
if (do_progress && !am_server) |
| rprintf(FINFO, " \r"); |
rprintf(FINFO, " \r"); |
|
Line 1269 static void list_file_entry(struct file_struct *f)
|
Line 1417 static void list_file_entry(struct file_struct *f)
|
| } |
} |
| } |
} |
| |
|
| |
static struct bitbag *delayed_bits = NULL; |
| static int phase = 0; |
static int phase = 0; |
| static int dflt_perms; |
static int dflt_perms; |
| |
|
|
Line 1558 static void recv_generator(char *fname, struct file_st
|
Line 1707 static void recv_generator(char *fname, struct file_st
|
| } |
} |
| else if (delete_during && f_out != -1 && !phase |
else if (delete_during && f_out != -1 && !phase |
| && !(file->flags & FLAG_MISSING_DIR)) { |
&& !(file->flags & FLAG_MISSING_DIR)) { |
| if (file->flags & FLAG_CONTENT_DIR) | if (file->flags & FLAG_CONTENT_DIR) { |
| delete_in_dir(fname, file, &real_sx.st.st_dev); | if (detect_renamed && real_ret != 0) |
| else | unexplored_dirs++; |
| | delete_in_dir(fname, file, &real_sx.st.st_dev, |
| | delete_during < 0 ? DEL_NO_DELETIONS : 0); |
| | } else |
| change_local_filter_dir(fname, strlen(fname), F_DEPTH(file)); |
change_local_filter_dir(fname, strlen(fname), F_DEPTH(file)); |
| } |
} |
| goto cleanup; |
goto cleanup; |
|
Line 1844 static void recv_generator(char *fname, struct file_st
|
Line 1996 static void recv_generator(char *fname, struct file_st
|
| goto cleanup; |
goto cleanup; |
| } |
} |
| #endif |
#endif |
| if (stat_errno == ENOENT) | if (stat_errno == ENOENT) { |
| | if (detect_renamed && unexplored_dirs > 0 |
| | && F_LENGTH(file)) { |
| | bitbag_set_bit(delayed_bits, ndx); |
| | return; |
| | } |
| goto notify_others; |
goto notify_others; |
| |
} |
| rsyserr(FERROR_XFER, stat_errno, "recv_generator: failed to stat %s", |
rsyserr(FERROR_XFER, stat_errno, "recv_generator: failed to stat %s", |
| full_fname(fname)); |
full_fname(fname)); |
| goto cleanup; |
goto cleanup; |
|
Line 2254 void generate_files(int f_out, const char *local_name)
|
Line 2412 void generate_files(int f_out, const char *local_name)
|
| if (verbose > 2) |
if (verbose > 2) |
| rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid()); |
rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid()); |
| |
|
| |
if (detect_renamed) { |
| |
delayed_bits = bitbag_create(cur_flist->used); |
| |
if (!delete_before && !delete_during) |
| |
delete_during = -1; |
| |
} |
| |
|
| if (delete_before && !solo_file && cur_flist->used > 0) |
if (delete_before && !solo_file && cur_flist->used > 0) |
| do_delete_pass(); |
do_delete_pass(); |
| if (delete_during == 2) { |
if (delete_during == 2) { |
|
Line 2264 void generate_files(int f_out, const char *local_name)
|
Line 2428 void generate_files(int f_out, const char *local_name)
|
| } |
} |
| do_progress = 0; |
do_progress = 0; |
| |
|
| if (append_mode > 0 || whole_file < 0) | if (append_mode > 0 || detect_renamed || whole_file < 0) |
| whole_file = 0; |
whole_file = 0; |
| if (verbose >= 2) { |
if (verbose >= 2) { |
| rprintf(FINFO, "delta-transmission %s\n", |
rprintf(FINFO, "delta-transmission %s\n", |
|
Line 2306 void generate_files(int f_out, const char *local_name)
|
Line 2470 void generate_files(int f_out, const char *local_name)
|
| dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); |
dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); |
| } else |
} else |
| dirdev = MAKEDEV(0, 0); |
dirdev = MAKEDEV(0, 0); |
| delete_in_dir(fbuf, fp, &dirdev); | delete_in_dir(fbuf, fp, &dirdev, 0); |
| } else |
} else |
| change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp)); |
change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp)); |
| } |
} |
|
Line 2353 void generate_files(int f_out, const char *local_name)
|
Line 2517 void generate_files(int f_out, const char *local_name)
|
| } while ((cur_flist = cur_flist->next) != NULL); |
} while ((cur_flist = cur_flist->next) != NULL); |
| |
|
| if (delete_during) |
if (delete_during) |
| delete_in_dir(NULL, NULL, &dev_zero); | delete_in_dir(NULL, NULL, &dev_zero, 0); |
| | if (detect_renamed) { |
| | if (delete_during < 0) |
| | delete_during = 0; |
| | detect_renamed = 0; |
| | |
| | for (i = -1; (i = bitbag_next_bit(delayed_bits, i)) >= 0; ) { |
| | struct file_struct *file = cur_flist->files[i]; |
| | if (local_name) |
| | strlcpy(fbuf, local_name, sizeof fbuf); |
| | else |
| | f_name(file, fbuf); |
| | recv_generator(fbuf, file, i, itemizing, code, f_out); |
| | } |
| | } |
| phase++; |
phase++; |
| if (verbose > 2) |
if (verbose > 2) |
| rprintf(FINFO, "generate_files phase=%d\n", phase); |
rprintf(FINFO, "generate_files phase=%d\n", phase); |