diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/acls.c rsync-3.0.5/acls.c --- rsync-3.0.5_base/acls.c 2008-03-01 14:01:41.000000000 -0600 +++ rsync-3.0.5/acls.c 2009-01-01 21:23:42.000000000 -0600 @@ -595,6 +595,11 @@ rsync_acl *new_racl = EXPAND_ITEM_LIST(racl_list, rsync_acl, 1000); uchar flags = 0; +// fprintf(stderr, "ndx: %d, user: %d, group: %d, mask: %d, other: %d, name-cnt: %d\n", +// racl_list->count-1, racl->user_obj, racl->group_obj, +// racl->mask_obj, racl->other_obj, +// racl->names.count); + if (racl->user_obj != NO_ENTRY) flags |= XMIT_USER_OBJ; if (racl->group_obj != NO_ENTRY) @@ -732,6 +737,11 @@ duo_item = EXPAND_ITEM_LIST(racl_list, acl_duo, 1000); duo_item->racl = empty_rsync_acl; +// fprintf(stderr, "ndx: %d, user: %d, group: %d, mask: %d, other: %d, name-cnt: %d\n", +// racl_list->count-1, duo_item->racl.user_obj, duo_item->racl.mask_obj, +// duo_item->racl.mask_obj, duo_item->racl.other_obj, +// duo_item->racl.names.count); + flags = read_byte(f); if (flags & XMIT_USER_OBJ) @@ -929,8 +939,11 @@ } else { mode_t cur_mode = sxp->st.st_mode; if (!duo_item->sacl - && !pack_smb_acl(&duo_item->sacl, &duo_item->racl)) + && !pack_smb_acl(&duo_item->sacl, &duo_item->racl)) { + // BOMBICH + rprintf(FERROR, "Failed to set ACL for: %s (user: %d, group: %d, mask: %d, other: %d)\n", fname, duo_item->racl.user_obj, duo_item->racl.group_obj, duo_item->racl.mask_obj, duo_item->racl.other_obj); return -1; + } #ifdef HAVE_OSX_ACLS mode = 0; /* eliminate compiler warning */ #else diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/backup.c rsync-3.0.5/backup.c --- rsync-3.0.5_base/backup.c 2009-01-01 21:08:02.000000000 -0600 +++ rsync-3.0.5/backup.c 2009-01-01 21:10:07.000000000 -0600 @@ -293,26 +293,11 @@ do_unlink(fname); } + // BOMBICH if (!kept && S_ISDIR(file->mode)) { - /* make an empty directory */ - if (do_mkdir(buf, file->mode) < 0) { - int save_errno = errno ? errno : EINVAL; /* 0 paranoia */ - if (errno == ENOENT && make_bak_dir(buf) == 0) { - if (do_mkdir(buf, file->mode) < 0) - save_errno = errno ? errno : save_errno; - else - save_errno = 0; - } - if (save_errno) { - rsyserr(FINFO, save_errno, "mkdir %s failed", - full_fname(buf)); - } - } - - ret_code = do_rmdir(fname); - if (verbose > 2) { - rprintf(FINFO, "make_backup: RMDIR %s returns %i\n", - full_fname(fname), ret_code); + if (robust_move(fname, buf) != 0) { + rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"", + full_fname(fname), full_fname(buf)); } kept = 1; } diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/byteorder.h rsync-3.0.5/byteorder.h --- rsync-3.0.5_base/byteorder.h 2008-03-01 14:01:41.000000000 -0600 +++ rsync-3.0.5/byteorder.h 2009-01-01 21:10:07.000000000 -0600 @@ -18,10 +18,9 @@ * with this program; if not, visit the http://fsf.org website. */ -#undef CAREFUL_ALIGNMENT - /* We know that the x86 can handle misalignment and has the same * byte order (LSB-first) as the 32-bit numbers we transmit. */ +/* #ifdef __i386__ #define CAREFUL_ALIGNMENT 0 #endif @@ -29,6 +28,9 @@ #ifndef CAREFUL_ALIGNMENT #define CAREFUL_ALIGNMENT 1 #endif +*/ + +#define CAREFUL_ALIGNMENT 1 #define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) #define UVAL(buf,pos) ((uint32)CVAL(buf,pos)) diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/config.h rsync-3.0.5/config.h --- rsync-3.0.5_base/config.h 2009-01-01 21:08:30.000000000 -0600 +++ rsync-3.0.5/config.h 2009-01-01 21:10:07.000000000 -0600 @@ -169,7 +169,7 @@ #define HAVE_LANGINFO_H 1 /* Define to 1 if you have the `lchmod' function. */ -#define HAVE_LCHMOD 1 +/* #undef HAVE_LCHMOD */ /* Define to 1 if you have the `lchown' function. */ #define HAVE_LCHOWN 1 @@ -228,7 +228,7 @@ /* #undef HAVE_LSEEK64 */ /* Define to 1 if you have the `lutimes' function. */ -#define HAVE_LUTIMES 1 +/* #undef HAVE_LUTIMES */ /* Define to 1 if you have the `mallinfo' function. */ /* #undef HAVE_MALLINFO */ @@ -672,3 +672,6 @@ /* Define to `int' if doesn't define. */ /* #undef uid_t */ + +// BOMBICH +#define PARSEABLE_OUTPUT 1 \ No newline at end of file diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/flist.c rsync-3.0.5/flist.c --- rsync-3.0.5_base/flist.c 2009-01-01 21:07:52.000000000 -0600 +++ rsync-3.0.5/flist.c 2009-01-01 21:10:07.000000000 -0600 @@ -161,18 +161,30 @@ static void maybe_emit_filelist_progress(int count) { +// BOMBICH +#ifdef PARSEABLE_OUTPUT + if (!inc_recurse && xfer_dirs && !am_server && (count % 100) == 0 && count > 0) + rprintf(FINFO, "S;;;BFL;;;NOF;;;%d\n", count); +#else if (do_progress && show_filelist_p() && (count % 100) == 0) emit_filelist_progress(count); +#endif } static void finish_filelist_progress(const struct file_list *flist) { +// BOMBICH +#ifdef PARSEABLE_OUTPUT + if (!inc_recurse) + rprintf(FINFO, "S;;;FTC;;;NOF;;;%d;;;BT;;;%.3f\n", flist->used, (double)stats.flist_buildtime/1000); +#else if (do_progress) { /* This overwrites the progress line */ rprintf(FINFO, "%d file%sto consider\n", flist->used, flist->used == 1 ? " " : "s "); } else rprintf(FINFO, "done\n"); +#endif } void show_flist_stats(void) @@ -545,8 +557,11 @@ if (first_hlink_ndx >= 0) { write_varint(f, first_hlink_ndx); - if (first_hlink_ndx >= first_ndx) - goto the_end; + if (first_hlink_ndx >= first_ndx) { + // BOMBICH + stats.hard_links_not_copied++; + goto the_end; + } } write_varlong30(f, F_LENGTH(file), 3); @@ -643,6 +658,20 @@ if (S_ISREG(mode) || S_ISLNK(mode)) stats.total_size += F_LENGTH(file); + + // BOMBICH + // Maintain stats on the sender side + if (S_ISDIR(mode)) + stats.num_dirs++; + else if (S_ISREG(mode)) + stats.num_reg_files++; + else if (S_ISLNK(mode)) + stats.num_symlinks++; + else if (IS_DEVICE(mode)) + stats.num_devices++; + else if (IS_SPECIAL(mode)) + stats.num_special++; + } static struct file_struct *recv_file_entry(struct file_list *flist, @@ -749,6 +778,7 @@ struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start]; file_length = F_LENGTH(first); modtime = first->modtime; + if (crtimes_ndx) crtime=f_crtime(first); mode = first->mode; if (preserve_uid) uid = F_OWNER(first); @@ -1105,6 +1135,16 @@ if (S_ISREG(mode) || S_ISLNK(mode)) stats.total_size += file_length; + if (who_am_i() == "generator") { + // Maintain stats on the receiver side. This is for the benefit of the + // generator -- the receive generator prints out non-transfer related + // progress info several times a second. Having the number of reg_files + // is helpful for progess indication + // BOMBICH + if (S_ISDIR(mode)) + stats.num_dirs++; + } + return file; } @@ -1382,6 +1422,19 @@ if (!file) return NULL; +// rprintf(FINFO, "make_file (%s): %s\n", who_am_i()); +// // BOMBICH +// if (S_ISDIR(file->mode)) +// stats.num_dirs++; +// else if (S_ISREG(file->mode)) +// stats.num_reg_files++; +// else if (S_ISLNK(file->mode)) +// stats.num_symlinks++; +// else if (IS_DEVICE(file->mode)) +// stats.num_devices++; +// else if (IS_SPECIAL(file->mode)) +// stats.num_special++; +// if (chmod_modes && !S_ISLNK(file->mode)) file->mode = tweak_mode(file->mode, chmod_modes); @@ -2003,6 +2056,14 @@ else if (inc_recurse && verbose && !am_server) rprintf(FCLIENT, "sending incremental file list\n"); + // BOMBICH + stats.num_dirs = 0; + stats.num_reg_files = 0; + stats.num_symlinks = 0; + stats.num_devices = 0; + stats.num_special = 0; + stats.hard_links_not_copied = 0; + start_write = stats.total_written; gettimeofday(&start_tv, NULL); @@ -2235,7 +2296,10 @@ idev_destroy(); #endif +// BOMBICH +#ifndef PARSEABLE_OUTPUT if (show_filelist_p()) +#endif finish_filelist_progress(flist); gettimeofday(&end_tv, NULL); @@ -2316,6 +2380,10 @@ else if (inc_recurse && verbose && !am_server && !first_flist) rprintf(FCLIENT, "receiving incremental file list\n"); + // BOMBICH + if (!first_flist) + stats.num_dirs = 0; + start_read = stats.total_read; #ifdef SUPPORT_HARD_LINKS diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/generator.c rsync-3.0.5/generator.c --- rsync-3.0.5_base/generator.c 2009-01-01 21:08:03.000000000 -0600 +++ rsync-3.0.5/generator.c 2009-03-05 09:19:27.000000000 -0600 @@ -121,6 +121,14 @@ static int need_retouch_dir_times; static int need_retouch_dir_perms; static const char *solo_file = NULL; + +// BOMBICH +struct timeval last_update; +static unsigned long msdiff(struct timeval *t1, struct timeval *t2) +{ + return (t2->tv_sec - t1->tv_sec) * 1000L + + (t2->tv_usec - t1->tv_usec) / 1000; +} /* For calling delete_item() and delete_dir_contents(). */ #define DEL_NO_UID_WRITE (1<<0) /* file/dir has our uid w/o write perm */ @@ -177,6 +185,12 @@ fbuf, (int)mode, (int)flags); } + // BOMBICH + if (S_ISDIR(mode) && make_backups > 0) { + ret = make_backup(fbuf); + goto check_ret; + } + if (flags & DEL_NO_UID_WRITE) do_chmod(fbuf, mode | S_IWUSR, NO_FFLAGS); @@ -534,7 +548,8 @@ /* If an item in dirlist is not found in flist, delete it * from the filesystem. */ - for (i = dirlist->used; i--; ) { + // BOMBICH + for (i = 0; i < dirlist->used; i++ ) { struct file_struct *fp = dirlist->files[i]; if (!F_IS_ACTIVE(fp)) continue; @@ -1525,13 +1540,6 @@ goto cleanup; } } -#ifdef SUPPORT_XATTRS - if (preserve_xattrs && statret == 1) - copy_xattrs(fnamecmpbuf, fname); -#endif - if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0) - && verbose && code != FNONE && f_out != -1) - rprintf(code, "%s/\n", fname); /* We need to ensure that the dirs in the transfer have writable * permissions during the time we are putting files within them. @@ -1541,6 +1549,15 @@ && make_mutable(fname, file->mode, F_FFLAGS(file), force_change)) need_retouch_dir_perms = 1; #endif + +#ifdef SUPPORT_XATTRS + if (preserve_xattrs && statret == 1) + copy_xattrs(fnamecmpbuf, fname); +#endif + if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0) + && verbose && code != FNONE && f_out != -1) + rprintf(code, "%s/\n", fname); + #ifdef HAVE_CHMOD if (!am_root && !(file->mode & S_IWUSR) && dir_tweaking) { mode_t mode = file->mode | S_IWUSR; @@ -1792,6 +1809,28 @@ fnamecmp = fname; fnamecmp_type = FNAMECMP_FNAME; +// BOMBICH +#ifdef PARSEABLE_OUTPUT + struct timeval now; + gettimeofday(&now, NULL); + + // The Recv generator gets a list of every single file sent by the sender whether it will + // eventually be copied or not. Here we optionally print out the current file that is being + // received for consideration to give the user a general idea of where rsync is within their fs + + // Print update information every fifth of a second. If a file changed, print update + // information as long as the file is larger than 32K or time since last update > tenth of a second + unsigned long time_diff = msdiff(&last_update, &now); + int fileUnchanged = unchanged_file(fnamecmpbuf, file, &sx.st); + if ((fileUnchanged && time_diff > 200) || (!fileUnchanged && (file->len32 > 32768 || time_diff > 100))) { + last_update = now; + if (inc_recurse) + rprintf(FINFO, "S;;;CP;;;NOI;;;%d;;;CF;;;%s\n", stats.num_files - stats.num_dirs, fname); + else + rprintf(FINFO, "S;;;CP;;;PROG;;;%d;;;CF;;;%s\n", (ndx * 100) / stats.num_files, fname); + } +#endif + if (statret == 0 && !S_ISREG(sx.st.st_mode)) { if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_FILE) != 0) goto cleanup; diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/main.c rsync-3.0.5/main.c --- rsync-3.0.5_base/main.c 2008-10-11 13:14:43.000000000 -0500 +++ rsync-3.0.5/main.c 2009-01-01 21:10:07.000000000 -0600 @@ -242,6 +242,13 @@ if (do_stats) { rprintf(FCLIENT, "\n"); rprintf(FINFO,"Number of files: %d\n", stats.num_files); + // BOMBICH + rprintf(FINFO,"Number of directories: %d\n", stats.num_dirs); + rprintf(FINFO,"Number of regular files: %d\n", stats.num_reg_files); + rprintf(FINFO,"Number of symlinks: %d\n", stats.num_symlinks); + rprintf(FINFO,"Number of devices: %d\n", stats.num_devices); + rprintf(FINFO,"Number of special files: %d\n", stats.num_special); + rprintf(FINFO,"Number of re-linked hard links: %d\n", stats.hard_links_not_copied); rprintf(FINFO,"Number of files transferred: %d\n", stats.num_transferred_files); rprintf(FINFO,"Total file size: %s bytes\n", diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/match.c rsync-3.0.5/match.c --- rsync-3.0.5_base/match.c 2008-03-01 14:01:41.000000000 -0600 +++ rsync-3.0.5/match.c 2009-03-05 10:14:22.000000000 -0600 @@ -39,6 +39,15 @@ extern struct stats stats; +// BOMBICH +struct timeval last_update; +static unsigned long msdiff(struct timeval *t1, struct timeval *t2) +{ + return (t2->tv_sec - t1->tv_sec) * 1000L + + (t2->tv_usec - t1->tv_usec) / 1000; +} + + #define TRADITIONAL_TABLESIZE (1<<16) static uint32 tablesize; @@ -135,6 +144,20 @@ if (buf && do_progress) show_progress(last_match, buf->file_size); + +// BOMBICH +#ifdef PARSEABLE_OUTPUT + // This provides updates when we're in the middle of copying a single file + if (buf) { + struct timeval now; + gettimeofday(&now, NULL); + unsigned long time_diff = msdiff(&last_update, &now); + if (time_diff > 1000) { + last_update = now; + rprintf(FINFO, "S;;;STATS;;;TTS;;;%.0llu\n", stats.total_transferred_size - buf->file_size + offset); + } + } +#endif } diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/receiver.c rsync-3.0.5/receiver.c --- rsync-3.0.5_base/receiver.c 2008-11-15 16:49:28.000000000 -0600 +++ rsync-3.0.5/receiver.c 2009-03-10 22:45:30.000000000 -0500 @@ -20,6 +20,9 @@ */ #include "rsync.h" +// For statfs(): +#include +#include extern int verbose; extern int dry_run; @@ -39,6 +42,7 @@ extern int preserve_hard_links; extern int preserve_perms; extern int preserve_xattrs; +extern int force_change; extern int basis_dir_cnt; extern int make_backups; extern int cleanup_got_literal; @@ -153,6 +157,20 @@ } #endif +#ifdef SUPPORT_FORCE_CHANGE + if (fd == -1) { + stat_x sx; + if (do_stat(file->dirname, &sx.st) < 0) + rprintf(FINFO, "Failed to stat %s!\n", full_fname(file->dirname)); + else { + if (force_change && make_mutable(file->dirname, sx.st.st_mode, sx.st.st_flags, force_change) > 0) { + fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); + undo_make_mutable(file->dirname, sx.st.st_flags); + } + } + } +#endif + if (fd == -1) { rsyserr(FERROR_XFER, errno, "mkstemp %s failed", full_fname(fnametmp)); @@ -297,6 +315,16 @@ if (fd != -1 && offset > 0 && sparse_end(fd) != 0) { report_write_error: + // This next line is a temporary hack. It looks like receiver and generator messages sent to rsyserr aren't getting displayed: + /* +receive_data(x): 10A270.dmg [No space left on device] +rsyserr(x): write failed on %s [No space left on device] +rsyserr(x): writefd_unbuffered failed to write %ld bytes [%s] [Broken pipe] +rsync: writefd_unbuffered failed to write 4 bytes [sender]: Broken pipe (32) + + + */ + fprintf(stderr, "rsync: write failed on %s: %s\n", full_fname(fname), strerror(errno)); rsyserr(FERROR_XFER, errno, "write failed on %s", full_fname(fname)); exit_cleanup(RERR_FILEIO); @@ -626,9 +654,6 @@ } } - updating_basis_or_equiv = inplace - && (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP); - if (fd1 == -1) { st.st_mode = 0; st.st_size = 0; @@ -642,6 +667,22 @@ continue; } + // Switch to inplace if the target is getting tight on space and we're dealing with large files + if (!inplace && (double)st.st_size > 512*1024*1024) { + struct statfs fsb; + if (statfs(normalize_path(fname, 0, NULL), &fsb) == 0) { + double fs = (double)fsb.f_bavail * (double)fsb.f_bsize; + if (fs < (double)st.st_size) { + rprintf(FINFO, "Switching from \"atomic\" to \"in place\" transfer to accommodate large files and dwindling free space on the target.\n"); + inplace = 1; + } + } else + rprintf(FINFO, "Failed to statfs %s: %s\n", full_fname(fname), strerror(errno)); + } + + updating_basis_or_equiv = inplace + && (fnamecmp == fname || fnamecmp_type == FNAMECMP_BACKUP); + if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) { /* this special handling for directories * wouldn't be necessary if robust_rename() diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/rounding.h rsync-3.0.5/rounding.h --- rsync-3.0.5_base/rounding.h 1969-12-31 18:00:00.000000000 -0600 +++ rsync-3.0.5/rounding.h 2008-11-27 21:09:25.000000000 -0600 @@ -0,0 +1 @@ +#define EXTRA_ROUNDING 0 diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/rsync.c rsync-3.0.5/rsync.c --- rsync-3.0.5_base/rsync.c 2009-01-01 21:07:52.000000000 -0600 +++ rsync-3.0.5/rsync.c 2009-03-05 17:01:29.000000000 -0600 @@ -31,6 +31,7 @@ extern int dry_run; extern int preserve_acls; extern int preserve_xattrs; +extern int force_change; extern int preserve_perms; extern int preserve_fileflags; extern int preserve_executability; @@ -397,16 +398,20 @@ { if (S_ISLNK(mode) || !(fileflags & iflags)) return 0; - if (!set_fileflags(fname, fileflags & ~iflags)) + if (!set_fileflags(fname, fileflags & ~iflags)) { + rsyserr(FINFO, errno, "failed to unlock %s", full_fname(fname)); return -1; + } return 1; } /* Undo a prior make_mutable() call that returned a 1. */ int undo_make_mutable(const char *fname, uint32 fileflags) { - if (!set_fileflags(fname, fileflags)) + if (!set_fileflags(fname, fileflags)) { + rsyserr(FINFO, errno, "failed to relock %s", full_fname(fname)); return -1; + } return 1; } #endif @@ -419,6 +424,7 @@ int change_uid, change_gid; mode_t new_mode = file->mode; int inherit; + int became_mutable; if (!sxp) { if (dry_run) @@ -449,6 +455,11 @@ if (daemon_chmod_modes && !S_ISLNK(new_mode)) new_mode = tweak_mode(new_mode, daemon_chmod_modes); +#ifdef SUPPORT_FORCE_CHANGE + if (force_change) + became_mutable = make_mutable(fname, sxp->st.st_mode, sxp->st.st_flags, force_change) > 0; +#endif + #ifdef SUPPORT_ACLS if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp)) get_acl(fname, sxp); @@ -554,6 +565,11 @@ } #endif +#ifdef SUPPORT_FORCE_CHANGE + if (became_mutable) + undo_make_mutable(fname, sxp->st.st_flags); +#endif + #ifdef SUPPORT_FILEFLAGS if (preserve_fileflags && !S_ISLNK(sxp->st.st_mode) && sxp->st.st_flags != F_FFLAGS(file)) { diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/rsync.h rsync-3.0.5/rsync.h --- rsync-3.0.5_base/rsync.h 2009-01-01 21:07:52.000000000 -0600 +++ rsync-3.0.5/rsync.h 2009-01-01 21:10:07.000000000 -0600 @@ -863,6 +863,13 @@ int64 flist_size; int num_files; int num_transferred_files; + // BOMBICH + int num_dirs; + int num_reg_files; + int num_symlinks; + int num_devices; + int num_special; + int hard_links_not_copied; }; struct chmod_mode_struct; diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/sender.c rsync-3.0.5/sender.c --- rsync-3.0.5_base/sender.c 2008-08-14 09:32:18.000000000 -0500 +++ rsync-3.0.5/sender.c 2009-01-01 21:10:07.000000000 -0600 @@ -46,6 +46,16 @@ extern struct stats stats; extern struct file_list *cur_flist, *first_flist, *dir_flist; +// BOMBICH +#ifdef PARSEABLE_OUTPUT +struct timeval last_update; +static unsigned long msdiff(struct timeval *t1, struct timeval *t2) +{ + return (t2->tv_sec - t1->tv_sec) * 1000L + + (t2->tv_usec - t1->tv_usec) / 1000; +} +#endif + /** * @file * @@ -263,6 +273,21 @@ set_current_file_index(file, ndx); stats.num_transferred_files++; stats.total_transferred_size += F_LENGTH(file); +// BOMBICH +// Update the user on total transfer size, number of files copied, number of non-folder "items" discovered, and the name +// of the file we're currently copying. To limit CPU usage, do this only 10 times per second +#ifdef PARSEABLE_OUTPUT + if (inc_recurse) { + struct timeval now; + gettimeofday(&now, NULL); + unsigned long time_diff = msdiff(&last_update, &now); + if (time_diff > 100) { + last_update = now; +// rprintf(FINFO, "S;;;STATS;;;TTS;;;%.0llu;;;FC;;;%d;;;CF;;;%s\n", stats.total_transferred_size, stats.num_transferred_files, fname); + rprintf(FINFO, "S;;;STATS;;;TTS;;;%.0llu;;;CF;;;%s\n", stats.total_transferred_size, fname); + } + } +#endif if (!do_xfers) { /* log the transfer */ log_item(FCLIENT, file, &stats, iflags, NULL); @@ -367,5 +392,11 @@ match_report(); +// BOMBICH +#ifdef PARSEABLE_OUTPUT + // Print the grand total + rprintf(FINFO, "S;;;SUM_STATS;;;TTS;;;%.0llu;;;FC;;;%d;;;DIRS;;;%d;;;REG;;;%d;;;SYM;;;%d;;;DEV;;;%d;;;SPEC;;;%d;;;HLNK;;;%d\n", stats.total_transferred_size, stats.num_transferred_files, stats.num_dirs, stats.num_reg_files, stats.num_symlinks, stats.num_devices, stats.num_special, stats.hard_links_not_copied); +#endif + write_ndx(f_out, NDX_DONE); } diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/syscall.c rsync-3.0.5/syscall.c --- rsync-3.0.5_base/syscall.c 2009-01-01 21:07:52.000000000 -0600 +++ rsync-3.0.5/syscall.c 2009-03-29 20:27:48.000000000 -0500 @@ -59,17 +59,32 @@ if (unlink(fname) == 0) return 0; #ifdef SUPPORT_FORCE_CHANGE - if (force_change && errno == EPERM) { - STRUCT_STAT st; + if (force_change && (errno == EPERM || errno == EACCES)) { + STRUCT_STAT st, pst; + char *parent; + int became_mutable; + int saved_errno = errno; - if (x_lstat(fname, &st, NULL) == 0 - && make_mutable(fname, st.st_mode, st.st_flags, force_change) > 0) { - if (unlink(fname) == 0) + if (x_lstat(fname, &st, NULL) == 0) { + became_mutable = make_mutable(fname, st.st_mode, st.st_flags, force_change) > 0; + if (became_mutable && unlink(fname) == 0) return 0; - undo_make_mutable(fname, st.st_flags); + + if ((parent = (char *)dirname(fname)) != NULL + && x_lstat(parent, &pst, NULL) == 0) { + if (make_mutable(parent, pst.st_mode, pst.st_flags, force_change) > 0) { + if (unlink(fname) == 0) { + undo_make_mutable(parent, pst.st_flags); + return 0; + } else { + undo_make_mutable(parent, pst.st_flags); + if (became_mutable) + undo_make_mutable(fname, st.st_flags); + } + } + } } - /* TODO: handle immutable directories */ - errno = EPERM; + errno = saved_errno; } #endif return -1; @@ -77,17 +92,65 @@ int do_symlink(const char *fname1, const char *fname2) { + int ret; if (dry_run) return 0; RETURN_ERROR_IF_RO_OR_LO; - return symlink(fname1, fname2); + ret = symlink(fname1, fname2); + +#ifdef SUPPORT_FORCE_CHANGE + if (force_change && (errno == EPERM || errno == EACCES)) { + STRUCT_STAT pst; + char *parent; + int saved_errno = errno; + + // Attempt to make the parent directory mutable + if ((parent = (char *)dirname(fname2)) != NULL + && x_lstat(parent, &pst, NULL) == 0) { + if (make_mutable(parent, pst.st_mode, pst.st_flags, force_change) > 0) { + if (symlink(fname1, fname2) == 0) { + undo_make_mutable(parent, pst.st_flags); + return 0; + } else + undo_make_mutable(parent, pst.st_flags); + } + errno = saved_errno; + } + } +#endif + + return ret; } #ifdef HAVE_LINK int do_link(const char *fname1, const char *fname2) { + int ret; if (dry_run) return 0; RETURN_ERROR_IF_RO_OR_LO; - return link(fname1, fname2); + ret = link(fname1, fname2); + +#ifdef SUPPORT_FORCE_CHANGE + if (force_change && (errno == EPERM || errno == EACCES)) { + STRUCT_STAT pst; + char *parent; + int saved_errno = errno; + + // Attempt to make the parent directory mutable + if ((parent = (char *)dirname(fname2)) != NULL + && x_lstat(parent, &pst, NULL) == 0) { + if (make_mutable(parent, pst.st_mode, pst.st_flags, force_change) > 0) { + if (link(fname1, fname2) == 0) { + undo_make_mutable(parent, pst.st_flags); + return 0; + } else + undo_make_mutable(parent, pst.st_flags); + } + errno = saved_errno; + } + } +#endif + + return ret; } #endif @@ -101,7 +164,8 @@ if (lchown(path, owner, group) == 0) return 0; #ifdef SUPPORT_FORCE_CHANGE - if (force_change && errno == EPERM) { + if (force_change && (errno == EPERM || errno == EACCES)) { + int saved_errno = errno; if (fileflags == NO_FFLAGS) { STRUCT_STAT st; if (x_lstat(path, &st, NULL) == 0) { @@ -116,7 +180,7 @@ if (ret == 0) return 0; } - errno = EPERM; + errno = saved_errno; } #else mode = fileflags = 0; /* avoid compiler warning */ @@ -181,16 +245,35 @@ if (rmdir(pathname) == 0) return 0; #ifdef SUPPORT_FORCE_CHANGE - if (force_change && errno == EPERM) { - STRUCT_STAT st; + if (force_change && (errno == EPERM || errno == EACCES)) { + STRUCT_STAT st, pst; + char *parent; + int became_mutable; + int saved_errno = errno; - if (x_lstat(pathname, &st, NULL) == 0 - && make_mutable(pathname, st.st_mode, st.st_flags, force_change) > 0) { - if (rmdir(pathname) == 0) - return 0; - undo_make_mutable(pathname, st.st_flags); + if (x_lstat(pathname, &st, NULL) == 0) { + became_mutable = make_mutable(pathname, st.st_mode, st.st_flags, force_change); + if (became_mutable >= 0) { // even if this item is not immutable, the parent may be + if (rmdir(pathname) == 0) + return 0; + else { + // Attempt to make the parent directory mutable + if ((parent = (char *)dirname(pathname)) != NULL + && x_lstat(parent, &pst, NULL) == 0) { + if (make_mutable(parent, pst.st_mode, pst.st_flags, force_change) > 0) { + if (rmdir(pathname) == 0) { + undo_make_mutable(parent, pst.st_flags); + return 0; + } else + undo_make_mutable(parent, pst.st_flags); + } + } + } + if (became_mutable) + undo_make_mutable(pathname, st.st_flags); + } } - errno = EPERM; + errno = saved_errno; } #endif return -1; @@ -229,7 +312,8 @@ } else code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */ #ifdef SUPPORT_FORCE_CHANGE - if (code < 0 && force_change && errno == EPERM && !S_ISLNK(mode)) { + if (code < 0 && force_change && (errno == EPERM || errno == EACCES) && !S_ISLNK(mode)) { + int saved_errno = errno; if (fileflags == NO_FFLAGS) { STRUCT_STAT st; if (x_lstat(path, &st, NULL) == 0) @@ -242,7 +326,7 @@ if (code == 0) return 0; } - errno = EPERM; + errno = saved_errno; } #else fileflags = 0; /* avoid compiler warning */ @@ -269,9 +353,11 @@ if (rename(fname1, fname2) == 0) return 0; #ifdef SUPPORT_FORCE_CHANGE - if (force_change && errno == EPERM) { - STRUCT_STAT st1, st2; - int became_mutable; + if (force_change && (errno == EPERM || errno == EACCES)) { + STRUCT_STAT st1, st2, pst1, pst2; + int became_mutable, p1_mutable = 0, p2_mutable = 0; + char *p1, *p2; + int saved_errno = errno; if (x_lstat(fname1, &st1, NULL) != 0) goto failed; @@ -280,19 +366,50 @@ goto success; if (x_lstat(fname2, &st2, NULL) == 0 && make_mutable(fname2, st2.st_mode, st2.st_flags, force_change) > 0) { - if (rename(fname1, fname2) == 0) { - success: - if (became_mutable) /* Yes, use fname2 and st1! */ - undo_make_mutable(fname2, st1.st_flags); - return 0; - } - undo_make_mutable(fname2, st2.st_flags); + if (rename(fname1, fname2) == 0) + goto success; } - /* TODO: handle immutable directories */ - if (became_mutable) - undo_make_mutable(fname1, st1.st_flags); + + // Now try making the parent directories mutable + if ((p1 = (char *)dirname(fname1)) == NULL || (p2 = (char *)dirname(fname2)) == NULL) + goto failed; + + if (x_lstat(p1, &pst1, NULL) != 0) + goto failed; + p1_mutable = make_mutable(p1, pst1.st_mode, pst1.st_flags, force_change) > 0; + if (p1_mutable && rename(fname1, fname2) == 0) + goto success; + + if (strcmp(p1, p2) != 0) { + if (x_lstat(p2, &pst2, NULL) != 0) + goto failed; + p2_mutable = make_mutable(p2, pst2.st_mode, pst2.st_flags, force_change) > 0; + if (p2_mutable && rename(fname1, fname2) == 0) + goto success; + } + failed: - errno = EPERM; + errno = saved_errno; + if (became_mutable) { + undo_make_mutable(fname1, st1.st_flags); + undo_make_mutable(fname2, st2.st_flags); + } + if (p1_mutable) + undo_make_mutable(p1, pst1.st_flags); + if (p2_mutable) + undo_make_mutable(p2, pst2.st_flags); + return -1; + + success: + if (became_mutable) /* Yes, use fname2 and st1! */ + undo_make_mutable(fname2, st1.st_flags); + if (p1_mutable) + undo_make_mutable(p1, pst1.st_flags); + if (p2_mutable) + undo_make_mutable(p2, pst2.st_flags); + return 0; + + } #endif return -1; @@ -318,10 +435,34 @@ int do_mkdir(char *fname, mode_t mode) { + int ret; if (dry_run) return 0; RETURN_ERROR_IF_RO_OR_LO; trim_trailing_slashes(fname); - return mkdir(fname, mode); + ret = mkdir(fname, mode); + +#ifdef SUPPORT_FORCE_CHANGE + if (force_change && (errno == EPERM || errno == EACCES)) { + STRUCT_STAT pst; + char *parent; + int saved_errno = errno; + + // Attempt to make the parent directory mutable + if ((parent = (char *)dirname(fname)) != NULL + && x_lstat(parent, &pst, NULL) == 0) { + if (make_mutable(parent, pst.st_mode, pst.st_flags, force_change) > 0) { + if (mkdir(fname, mode) == 0) { + undo_make_mutable(parent, pst.st_flags); + return 0; + } else + undo_make_mutable(parent, pst.st_flags); + } + errno = saved_errno; + } + } +#endif + + return ret; } /* like mkstemp but forces permissions */ diff -Naur -X rsync3/_build/diff_ignore rsync-3.0.5_base/xattrs.c rsync-3.0.5/xattrs.c --- rsync-3.0.5_base/xattrs.c 2009-01-01 21:07:50.000000000 -0600 +++ rsync-3.0.5/xattrs.c 2009-03-23 09:14:54.000000000 -0500 @@ -129,7 +129,7 @@ if (list_len >= 0) { if ((size_t)list_len <= namebuf_len) break; - } else if (errno == ENOTSUP) + } else if (errno == ENOTSUP || errno == ENOENT || errno == EINVAL) return 0; else if (errno != ERANGE) { arg = (double)namebuf_len; @@ -168,7 +168,7 @@ *len_ptr = datum_len; if (datum_len == (size_t)-1) { - if (errno == ENOTSUP || no_missing_error) + if (errno == ENOTSUP || errno == ENOATTR || no_missing_error) return NULL; rsyserr(FERROR_XFER, errno, "get_xattr_data: lgetxattr(\"%s\",\"%s\",0) failed", @@ -323,7 +323,7 @@ if (sys_lsetxattr(dest, name, ptr, datum_len) < 0) { int save_errno = errno ? errno : EINVAL; rsyserr(FERROR_XFER, errno, - "rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed", + "copy_xattrs: lsetxattr(\"%s\",\"%s\") failed", dest, name); errno = save_errno; return -1; @@ -548,7 +548,8 @@ /* Re-read the long datum. */ if (!(ptr = get_xattr_data(fname, rxa->name, &len, 0))) { - rprintf(FERROR_XFER, "failed to re-read xattr %s for %s\n", rxa->name, fname); + if (errno != ENOTSUP && errno != ENOATTR) + rprintf(FERROR_XFER, "failed to re-read xattr %s for %s\n", rxa->name, fname); write_varint(f_out, 0); continue; } @@ -813,7 +814,7 @@ if (sys_lsetxattr(fname, name, rxas[i].datum, rxas[i].datum_len) < 0) { rsyserr(FERROR_XFER, errno, "rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed", - fname, name); + full_fname(fname), name); ret = -1; } else /* make sure caller sets mtime */ sxp->st.st_mtime = (time_t)-1; @@ -841,10 +842,12 @@ } if (i == xalp->count) { if (sys_lremovexattr(fname, name) < 0) { - rsyserr(FERROR_XFER, errno, - "rsync_xal_clear: lremovexattr(\"%s\",\"%s\") failed", - fname, name); - ret = -1; + if (errno != ENOATTR) { + rsyserr(FERROR_XFER, errno, + "rsync_xal_clear: lremovexattr(\"%s\",\"%s\") failed", + full_fname(fname), name); + ret = -1; + } } else /* make sure caller sets mtime */ sxp->st.st_mtime = (time_t)-1; }