X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/609e6dda6b3e3f7fa8cee01fdd0d79b670b7cd10..3f0211b63a6cdc4a2cecfd2a0dffeba172c86a47:/generator.c diff --git a/generator.c b/generator.c index 2cb6c7b9..046ad95d 100644 --- a/generator.c +++ b/generator.c @@ -84,6 +84,7 @@ extern int list_only; extern int read_batch; extern int safe_symlinks; extern long block_size; /* "long" because popt can't set an int32. */ +extern int unsort_ndx; extern int max_delete; extern int force_delete; extern int one_file_system; @@ -95,9 +96,6 @@ extern char *backup_suffix; extern int backup_suffix_len; extern struct file_list *cur_flist, *first_flist, *dir_flist; extern struct filter_list_struct server_filter_list; -#ifdef ICONV_OPTION -extern int ic_ndx; -#endif int ignore_perishable = 0; int non_perishable_cnt = 0; @@ -198,7 +196,7 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags) check_ret: if (replace && ret != DR_SUCCESS) { - rprintf(FERROR, "could not make way for new %s: %s\n", + rprintf(FERROR_XFER, "could not make way for new %s: %s\n", replace, fbuf); } return ret; @@ -317,7 +315,7 @@ static int flush_delete_delay(void) static int remember_delete(struct file_struct *file, const char *fname) { int len; - + while (1) { len = snprintf(deldelay_buf + deldelay_cnt, deldelay_size - deldelay_cnt, @@ -517,6 +515,14 @@ static void do_delete_pass(void) int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp) { +#ifndef HAVE_LUTIMES + if (S_ISLNK(file->mode)) { + ; + } else +#endif + if (preserve_times && cmp_time(sxp->st.st_mtime, file->modtime) != 0) + return 0; + if (preserve_perms && !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) return 0; @@ -562,6 +568,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0)) iflags |= ITEM_REPORT_TIME; +#if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST + if (S_ISLNK(file->mode)) { + ; + } else +#endif if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS)) iflags |= ITEM_REPORT_PERMS; if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid) @@ -825,6 +836,42 @@ static int find_fuzzy(struct file_struct *file, struct file_list *dirlist) return lowest_j; } +/* Copy a file found in our --copy-dest handling. */ +static int copy_altdest_file(const char *src, const char *dest, struct file_struct *file) +{ + char buf[MAXPATHLEN]; + const char *copy_to, *partialptr; + int fd_w; + + if (inplace) { + /* Let copy_file open the destination in place. */ + fd_w = -1; + copy_to = dest; + } else { + fd_w = open_tmpfile(buf, dest, file); + if (fd_w < 0) + return -1; + copy_to = buf; + } + cleanup_set(copy_to, NULL, NULL, -1, -1); + if (copy_file(src, copy_to, fd_w, file->mode, 0) < 0) { + if (verbose) { + rsyserr(FINFO, errno, "copy_file %s => %s", + full_fname(src), copy_to); + } + /* Try to clean up. */ + unlink(copy_to); + cleanup_disable(); + return -1; + } + partialptr = partial_dir ? partial_dir_fname(dest) : NULL; + if (partialptr && *partialptr == '/') + partialptr = NULL; + finish_transfer(dest, copy_to, src, partialptr, file, 1, 0); + cleanup_disable(); + return 0; +} + /* This is only called for regular files. We return -2 if we've finished * handling the file, -1 if no dest-linking occurred, or a non-negative * value if we found an alternate basis file. */ @@ -854,9 +901,6 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, case 2: if (!unchanged_attrs(cmpbuf, file, sxp)) continue; - if (always_checksum > 0 && preserve_times - && cmp_time(sxp->st.st_mtime, file->modtime)) - continue; best_match = j; match_level = 3; break; @@ -899,14 +943,8 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, #ifdef SUPPORT_HARD_LINKS try_a_copy: /* Copy the file locally. */ #endif - if (copy_file(cmpbuf, fname, file->mode, 0) < 0) { - if (verbose) { - rsyserr(FINFO, errno, "copy_file %s => %s", - full_fname(cmpbuf), fname); - } + if (!dry_run && copy_altdest_file(cmpbuf, fname, file) < 0) return -1; - } - set_file_attrs(fname, file, NULL, cmpbuf, 0); if (itemizing) itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL); #ifdef SUPPORT_XATTRS @@ -1044,7 +1082,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx, #endif && !S_ISDIR(file->mode)) { if (do_link(cmpbuf, fname) < 0) { - rsyserr(FERROR, errno, + rsyserr(FERROR_XFER, errno, "failed to hard-link %s with %s", cmpbuf, fname); return j; @@ -1201,7 +1239,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (relative_paths && !implied_dirs && do_stat(dn, &sx.st) < 0 && create_directory_path(fname) < 0) { - rsyserr(FERROR, errno, + rsyserr(FERROR_XFER, errno, "recv_generator: mkdir %s failed", full_fname(dn)); } @@ -1251,7 +1289,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR) goto cleanup; if (inc_recurse && ndx != cur_flist->ndx_start - 1) { - /* In inc_recurse mode we want ot make sure any missing + /* In inc_recurse mode we want to make sure any missing * directories get created while we're still processing * the parent dir (which allows us to touch the parent * dir's mtime right away). We will handle the dir in @@ -1304,7 +1342,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (!relative_paths || errno != ENOENT || create_directory_path(fname) < 0 || (do_mkdir(fname, file->mode) < 0 && errno != EEXIST)) { - rsyserr(FERROR, errno, + rsyserr(FERROR_XFER, errno, "recv_generator: mkdir %s failed", full_fname(fname)); skipping_dir_contents: @@ -1327,7 +1365,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (!am_root && !(file->mode & S_IWUSR) && dir_tweaking) { mode_t mode = file->mode | S_IWUSR; if (do_chmod(fname, mode) < 0) { - rsyserr(FERROR, errno, + rsyserr(FERROR_XFER, errno, "failed to modify permissions on %s", full_fname(fname)); } @@ -1389,7 +1427,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); if (itemizing) itemize(fname, file, ndx, 0, &sx, 0, 0, NULL); -#ifdef SUPPORT_HARD_LINKS +#if defined SUPPORT_HARD_LINKS && defined CAN_HARDLINK_SYMLINK if (preserve_hard_links && F_IS_HLINKED(file)) finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1); #endif @@ -1424,7 +1462,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, } #endif if (do_symlink(sl, fname) != 0) { - rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed", + rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed", full_fname(fname), sl); } else { set_file_attrs(fname, file, NULL, NULL, 0); @@ -1508,7 +1546,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, (long)major(rdev), (long)minor(rdev)); } if (do_mknod(fname, file->mode, rdev) < 0) { - rsyserr(FERROR, errno, "mknod %s failed", + rsyserr(FERROR_XFER, errno, "mknod %s failed", full_fname(fname)); } else { set_file_attrs(fname, file, NULL, NULL, 0); @@ -1626,7 +1664,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, #endif if (stat_errno == ENOENT) goto notify_others; - rsyserr(FERROR, stat_errno, "recv_generator: failed to stat %s", + rsyserr(FERROR_XFER, stat_errno, "recv_generator: failed to stat %s", full_fname(fname)); goto cleanup; } @@ -1675,7 +1713,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, goto cleanup; if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) goto pretend_missing; - if (copy_file(fname, backupptr, back_file->mode, 1) < 0) { + if (copy_file(fname, backupptr, -1, back_file->mode, 1) < 0) { unmake_file(back_file); back_file = NULL; goto cleanup; @@ -1716,7 +1754,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, goto pretend_missing; } if (robust_unlink(backupptr) && errno != ENOENT) { - rsyserr(FERROR, errno, "unlink %s", + rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(backupptr)); unmake_file(back_file); back_file = NULL; @@ -1726,7 +1764,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0 && (errno != ENOENT || make_bak_dir(backupptr) < 0 || (f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)) { - rsyserr(FERROR, errno, "open %s", + rsyserr(FERROR_XFER, errno, "open %s", full_fname(backupptr)); unmake_file(back_file); back_file = NULL; @@ -1868,6 +1906,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo) 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--; } #endif @@ -1921,7 +1960,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo) if (delete_during == 2 || !dir_tweaking) { /* Skip directory touch-up. */ - } else if (first_flist->ndx_start != 0) + } else if (first_flist->parent_ndx >= 0) touch_up_dirs(dir_flist, first_flist->parent_ndx); flist_free(first_flist); /* updates first_flist */ @@ -1996,12 +2035,12 @@ void generate_files(int f_out, const char *local_name) } #endif - if (inc_recurse && cur_flist->ndx_start) { + if (inc_recurse && cur_flist->parent_ndx >= 0) { struct file_struct *fp = dir_flist->files[cur_flist->parent_ndx]; 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) { + if (delete_during && dry_run < 2 && !list_only) { if (BITS_SETnUNSET(fp->flags, FLAG_CONTENT_DIR, FLAG_MISSING_DIR)) { dev_t dirdev; if (one_file_system) { @@ -2019,11 +2058,9 @@ void generate_files(int f_out, const char *local_name) if (!F_IS_ACTIVE(file)) continue; -#ifdef ICONV_OPTION - if (ic_ndx) + if (unsort_ndx) ndx = F_NDX(file); else -#endif ndx = i + cur_flist->ndx_start; if (solo_file)