📄 generator.c
字号:
rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(backupptr)); unmake_file(back_file); back_file = NULL; close(fd); goto cleanup; } if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) { int save_errno = errno ? errno : EINVAL; /* 0 paranoia */ if (errno == ENOENT && make_bak_dir(backupptr) == 0) { if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) save_errno = errno ? errno : save_errno; else save_errno = 0; } if (save_errno) { rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(backupptr)); unmake_file(back_file); back_file = NULL; close(fd); goto cleanup; } } fnamecmp_type = FNAMECMP_BACKUP; } if (verbose > 3) { rprintf(FINFO, "gen mapped %s of size %.0f\n", fnamecmp, (double)sx.st.st_size); } if (verbose > 2) rprintf(FINFO, "generating and sending sums for %d\n", ndx); notify_others: if (remove_source_files && !delay_updates && !phase && !dry_run) increment_active_files(ndx, itemizing, code); if (inc_recurse && !dry_run) cur_flist->in_progress++;#ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) file->flags |= FLAG_FILE_SENT;#endif write_ndx(f_out, ndx); if (itemizing) { int iflags = ITEM_TRANSFER; if (always_checksum > 0) iflags |= ITEM_REPORT_CHANGE; if (fnamecmp_type != FNAMECMP_FNAME) iflags |= ITEM_BASIS_TYPE_FOLLOWS; if (fnamecmp_type == FNAMECMP_FUZZY) iflags |= ITEM_XNAME_FOLLOWS; itemize(fnamecmp, file, -1, real_ret, &real_sx, iflags, fnamecmp_type, fuzzy_file ? fuzzy_file->basename : NULL);#ifdef SUPPORT_ACLS if (preserve_acls) free_acl(&real_sx);#endif#ifdef SUPPORT_XATTRS if (preserve_xattrs) free_xattr(&real_sx);#endif } if (!do_xfers) {#ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1);#endif goto cleanup; } if (read_batch) goto cleanup; if (statret != 0 || whole_file) write_sum_head(f_out, NULL); else if (sx.st.st_size <= 0) { write_sum_head(f_out, NULL); close(fd); } else { if (generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy) < 0) { rprintf(FWARNING, "WARNING: file is too large for checksum sending: %s\n", fnamecmp); write_sum_head(f_out, NULL); } close(fd); } cleanup: if (back_file) { int save_preserve_xattrs = preserve_xattrs; if (f_copy >= 0) close(f_copy);#ifdef SUPPORT_XATTRS if (preserve_xattrs) { copy_xattrs(fname, backupptr); preserve_xattrs = 0; }#endif set_file_attrs(backupptr, back_file, NULL, NULL, 0); preserve_xattrs = save_preserve_xattrs; if (verbose > 1) { rprintf(FINFO, "backed up %s to %s\n", fname, backupptr); } unmake_file(back_file); }#ifdef SUPPORT_ACLS if (preserve_acls) free_acl(&sx);#endif#ifdef SUPPORT_XATTRS if (preserve_xattrs) free_xattr(&sx);#endif return;}#ifdef SUPPORT_HARD_LINKSstatic void handle_skipped_hlink(struct file_struct *file, int itemizing, enum logcode code, int f_out){ char fbuf[MAXPATHLEN]; int new_last_ndx; struct file_list *save_flist = cur_flist; /* If we skip the last item in a chain of links and there was a * prior non-skipped hard-link waiting to finish, finish it now. */ if ((new_last_ndx = skip_hard_link(file, &cur_flist)) < 0) return; file = cur_flist->files[new_last_ndx - cur_flist->ndx_start]; cur_flist->in_progress--; /* undo prior increment */ f_name(file, fbuf); recv_generator(fbuf, file, new_last_ndx, itemizing, code, f_out); cur_flist = save_flist;}#endifstatic void touch_up_dirs(struct file_list *flist, int ndx){ static int counter = 0; struct file_struct *file; char *fname; int i, start, end; if (ndx < 0) { start = 0; end = flist->used - 1; } else start = end = ndx; /* Fix any directory permissions that were modified during the * transfer and/or re-set any tweaked modified-time values. */ for (i = start; i <= end; i++, counter++) { file = flist->files[i]; if (!S_ISDIR(file->mode) || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)) continue; if (verbose > 3) { fname = f_name(file, NULL); rprintf(FINFO, "touch_up_dirs: %s (%d)\n", NS(fname), i); } if (!F_IS_ACTIVE(file) || file->flags & FLAG_MISSING_DIR || (!need_retouch_dir_times && file->mode & S_IWUSR)) continue; fname = f_name(file, NULL); if (!(file->mode & S_IWUSR)) do_chmod(fname, file->mode); if (need_retouch_dir_times) { STRUCT_STAT st; if (link_stat(fname, &st, 0) == 0 && cmp_time(st.st_mtime, file->modtime) != 0) set_modtime(fname, file->modtime, file->mode); } if (counter >= loopchk_limit) { if (allowed_lull) maybe_send_keepalive(); else maybe_flush_socket(0); counter = 0; } }}void check_for_finished_files(int itemizing, enum logcode code, int check_redo){ struct file_struct *file; struct file_list *flist; char fbuf[MAXPATHLEN]; int ndx; while (1) {#ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && (ndx = get_hlink_num()) != -1) { flist = flist_for_ndx(ndx, "check_for_finished_files.1"); file = flist->files[ndx - flist->ndx_start]; assert(file->flags & FLAG_HLINKED); finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1); flist->in_progress--; continue; }#endif if (check_redo && (ndx = get_redo_num()) != -1) { csum_length = SUM_LENGTH; max_size = -max_size; min_size = -min_size; ignore_existing = -ignore_existing; ignore_non_existing = -ignore_non_existing; update_only = -update_only; always_checksum = -always_checksum; size_only = -size_only; append_mode = -append_mode; make_backups = -make_backups; /* avoid dup backup w/inplace */ ignore_times++; flist = cur_flist; cur_flist = flist_for_ndx(ndx, "check_for_finished_files.2"); file = cur_flist->files[ndx - cur_flist->ndx_start]; if (solo_file) strlcpy(fbuf, solo_file, sizeof fbuf); else f_name(file, fbuf); recv_generator(fbuf, file, ndx, itemizing, code, sock_f_out); cur_flist->to_redo--; cur_flist = flist; csum_length = SHORT_SUM_LENGTH; max_size = -max_size; min_size = -min_size; ignore_existing = -ignore_existing; ignore_non_existing = -ignore_non_existing; update_only = -update_only; always_checksum = -always_checksum; size_only = -size_only; append_mode = -append_mode; make_backups = -make_backups; ignore_times--; continue; } if (cur_flist == first_flist) break; /* We only get here if inc_recurse is enabled. */ if (first_flist->in_progress || first_flist->to_redo) break; if (!read_batch) { write_ndx(sock_f_out, NDX_DONE); maybe_flush_socket(1); } if (delete_during == 2 || !dir_tweaking) { /* Skip directory touch-up. */ } else if (first_flist->parent_ndx >= 0) touch_up_dirs(dir_flist, first_flist->parent_ndx); flist_free(first_flist); /* updates first_flist */ }}void generate_files(int f_out, const char *local_name){ int i, ndx, next_loopchk = 0; char fbuf[MAXPATHLEN]; int itemizing; enum logcode code; int save_do_progress = do_progress; if (protocol_version >= 29) { itemizing = 1; maybe_ATTRS_REPORT = stdout_format_has_i ? 0 : ATTRS_REPORT; code = logfile_format_has_i ? FNONE : FLOG; } else if (am_daemon) { itemizing = logfile_format_has_i && do_xfers; maybe_ATTRS_REPORT = ATTRS_REPORT; code = itemizing || !do_xfers ? FCLIENT : FINFO; } else if (!am_server) { itemizing = stdout_format_has_i; maybe_ATTRS_REPORT = stdout_format_has_i ? 0 : ATTRS_REPORT; code = itemizing ? FNONE : FINFO; } else { itemizing = 0; maybe_ATTRS_REPORT = ATTRS_REPORT; code = FINFO; } solo_file = local_name; dir_tweaking = !(list_only || solo_file || dry_run); need_retouch_dir_times = preserve_times > 1; loopchk_limit = allowed_lull ? allowed_lull * 5 : 200; symlink_timeset_failed_flags = ITEM_REPORT_TIME | (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0); implied_dirs_are_missing = relative_paths && !implied_dirs && protocol_version < 30; if (verbose > 2) rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid()); if (delete_before && !solo_file && cur_flist->used > 0) do_delete_pass(); if (delete_during == 2) { deldelay_size = BIGPATHBUFLEN * 4; deldelay_buf = new_array(char, deldelay_size); if (!deldelay_buf) out_of_memory("delete-delay"); } do_progress = 0; if (append_mode > 0 || whole_file < 0) whole_file = 0; if (verbose >= 2) { rprintf(FINFO, "delta-transmission %s\n", whole_file ? "disabled for local transfer or --whole-file" : "enabled"); } /* Since we often fill up the outgoing socket and then just sit around * waiting for the other 2 processes to do their thing, we don't want * to exit on a timeout. If the data stops flowing, the receiver will * notice that and let us know via the redo pipe (or its closing). */ ignore_timeout = 1; dflt_perms = (ACCESSPERMS & ~orig_umask); do {#ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && inc_recurse) { while (!flist_eof && file_total < FILECNT_LOOKAHEAD/2) wait_for_receiver(); }#endif if (inc_recurse && cur_flist->parent_ndx >= 0) { struct file_struct *fp = dir_flist->files[cur_flist->parent_ndx]; if (solo_file) strlcpy(fbuf, solo_file, sizeof fbuf); else f_name(fp, fbuf); ndx = cur_flist->ndx_start - 1; recv_generator(fbuf, fp, ndx, itemizing, code, f_out); if (delete_during && dry_run < 2 && !list_only && !(fp->flags & FLAG_MISSING_DIR)) { if (fp->flags & FLAG_CONTENT_DIR) { dev_t dirdev; if (one_file_system) { uint32 *devp = F_DIR_DEV_P(fp); dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); } else dirdev = MAKEDEV(0, 0); delete_in_dir(fbuf, fp, &dirdev); } else change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp)); } } for (i = cur_flist->low; i <= cur_flist->high; i++) { struct file_struct *file = cur_flist->sorted[i]; if (!F_IS_ACTIVE(file)) continue; if (unsort_ndx) ndx = F_NDX(file); else ndx = i + cur_flist->ndx_start; if (solo_file) strlcpy(fbuf, solo_file, sizeof fbuf); else f_name(file, fbuf); recv_generator(fbuf, file, ndx, itemizing, code, f_out); check_for_finished_files(itemizing, code, 0); if (i + cur_flist->ndx_start >= next_loopchk) { if (allowed_lull) maybe_send_keepalive(); else maybe_flush_socket(0); next_loopchk += loopchk_limit; } } if (!inc_recurse) { write_ndx(f_out, NDX_DONE); break; } while (1) { check_for_finished_files(itemizing, code, 1); if (cur_flist->next || flist_eof) break; wait_for_receiver(); } } while ((cur_flist = cur_flist->next) != NULL); if (read_batch && inc_recurse) write_ndx(f_out, NDX_DONE); if (delete_during) delete_in_dir(NULL, NULL, &dev_zero); phase++; if (verbose > 2) rprintf(FINFO, "generate_files phase=%d\n", phase); while (1) { check_for_finished_files(itemizing, code, 1); if (msgdone_cnt) break; wait_for_receiver(); } phase++; if (verbose > 2) rprintf(FINFO, "generate_files phase=%d\n", phase); write_ndx(f_out, NDX_DONE); /* Reduce round-trip lag-time for a useless delay-updates phase. */ if (protocol_version >= 29 && !delay_updates) write_ndx(f_out, NDX_DONE); /* Read MSG_DONE for the redo phase (and any prior messages). */ while (1) { check_for_finished_files(itemizing, code, 0); if (msgdone_cnt > 1) break; wait_for_receiver(); } if (protocol_version >= 29) { phase++; if (verbose > 2) rprintf(FINFO, "generate_files phase=%d\n", phase); if (delay_updates) write_ndx(f_out, NDX_DONE); /* Read MSG_DONE for delay-updates phase & prior messages. */ while (msgdone_cnt == 2) wait_for_receiver(); } do_progress = save_do_progress; if (delete_during == 2) do_delayed_deletions(fbuf); if (delete_after && !solo_file && file_total > 0) do_delete_pass(); if ((need_retouch_dir_perms || need_retouch_dir_times) && dir_tweaking && (!inc_recurse || delete_during == 2)) touch_up_dirs(dir_flist, -1); if (max_delete >= 0 && deletion_count > max_delete) { rprintf(FWARNING, "Deletions stopped due to --max-delete limit (%d skipped)\n", deletion_count - max_delete); io_error |= IOERR_DEL_LIMIT; } if (verbose > 2) rprintf(FINFO, "generate_files finished\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -