source: trunk/dports/net/rsync/files/patch-fileflags.diff @ 80017

Last change on this file since 80017 was 80017, checked in by blair@…, 9 years ago

rsync: update to 3.0.8.

File size: 57.6 KB
  • Makefile.in

    This patch provides --fileflags, which preserves the st_flags stat() field.
    Modified from a patch that was written by Rolf Grossmann.
    
    To use this patch, run these commands for a successful build:
    
        patch -p1 <patches/fileflags.diff
        ./prepare-source
        ./configure
        make
    
    based-on: 1ddcdaf3f6808ba53aef9e19f630a18808de22ac
    diff --git a/Makefile.in b/Makefile.in
    a b popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ 
    4242        popt/popthelp.o popt/poptparse.o
    4343OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
    4444
    45 TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
     45TLS_OBJ = tls.o syscall.o t_stub.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
    4646
    4747# Programs we must have to run the test cases
    4848CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
    getgroups$(EXEEXT): getgroups.o 
    107107getfsdev$(EXEEXT): getfsdev.o
    108108        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
    109109
    110 TRIMSLASH_OBJ = trimslash.o syscall.o lib/compat.o lib/snprintf.o
     110TRIMSLASH_OBJ = trimslash.o syscall.o t_stub.o lib/compat.o lib/snprintf.o
    111111trimslash$(EXEEXT): $(TRIMSLASH_OBJ)
    112112        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
    113113
  • compat.c

    diff --git a/compat.c b/compat.c
    a b extern int checksum_seed; 
    4343extern int basis_dir_cnt;
    4444extern int prune_empty_dirs;
    4545extern int protocol_version;
     46extern int force_change;
    4647extern int protect_args;
    4748extern int preserve_uid;
    4849extern int preserve_gid;
     50extern int preserve_fileflags;
    4951extern int preserve_acls;
    5052extern int preserve_xattrs;
    5153extern int need_messages_from_generator;
    extern char *iconv_opt; 
    6365#endif
    6466
    6567/* These index values are for the file-list's extra-attribute array. */
    66 int uid_ndx, gid_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
     68int uid_ndx, gid_ndx, fileflags_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
    6769
    6870int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
    6971int sender_symlink_iconv = 0;   /* sender should convert symlink content */
    void setup_protocol(int f_out,int f_in) 
    140142                uid_ndx = ++file_extra_cnt;
    141143        if (preserve_gid)
    142144                gid_ndx = ++file_extra_cnt;
     145        if (preserve_fileflags || (force_change && !am_sender))
     146                fileflags_ndx = ++file_extra_cnt;
    143147        if (preserve_acls && !am_sender)
    144148                acls_ndx = ++file_extra_cnt;
    145149        if (preserve_xattrs)
  • configure.ac

    diff --git a/configure.ac b/configure.ac
    a b AC_FUNC_UTIME_NULL 
    569569AC_FUNC_ALLOCA
    570570AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
    571571    fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
     572    chflags \
    572573    memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \
    573574    strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
    574575    setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
  • flist.c

    diff --git a/flist.c b/flist.c
    a b extern int preserve_links; 
    5151extern int preserve_hard_links;
    5252extern int preserve_devices;
    5353extern int preserve_specials;
     54extern int preserve_fileflags;
    5455extern int delete_during;
    5556extern int eol_nulls;
    5657extern int relative_paths;
    static void send_file_entry(int f, const char *fname, struct file_struct *file, 
    394395{
    395396        static time_t modtime;
    396397        static mode_t mode;
     398#ifdef SUPPORT_FILEFLAGS
     399        static uint32 fileflags;
     400#endif
    397401#ifdef SUPPORT_HARD_LINKS
    398402        static int64 dev;
    399403#endif
    static void send_file_entry(int f, const char *fname, struct file_struct *file, 
    423427                xflags |= XMIT_SAME_MODE;
    424428        else
    425429                mode = file->mode;
     430#ifdef SUPPORT_FILEFLAGS
     431        if (preserve_fileflags) {
     432                if (F_FFLAGS(file) == fileflags)
     433                        xflags |= XMIT_SAME_FLAGS;
     434                else
     435                        fileflags = F_FFLAGS(file);
     436        }
     437#endif
    426438
    427439        if (preserve_devices && IS_DEVICE(mode)) {
    428440                if (protocol_version < 28) {
    static void send_file_entry(int f, const char *fname, struct file_struct *file, 
    547559        }
    548560        if (!(xflags & XMIT_SAME_MODE))
    549561                write_int(f, to_wire_mode(mode));
     562#ifdef SUPPORT_FILEFLAGS
     563        if (preserve_fileflags && !(xflags & XMIT_SAME_FLAGS))
     564                write_int(f, (int)fileflags);
     565#endif
    550566        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
    551567                if (protocol_version < 30)
    552568                        write_int(f, uid);
    static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 
    634650{
    635651        static int64 modtime;
    636652        static mode_t mode;
     653#ifdef SUPPORT_FILEFLAGS
     654        static uint32 fileflags;
     655#endif
    637656#ifdef SUPPORT_HARD_LINKS
    638657        static int64 dev;
    639658#endif
    static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 
    731750                        file_length = F_LENGTH(first);
    732751                        modtime = first->modtime;
    733752                        mode = first->mode;
     753#ifdef SUPPORT_FILEFLAGS
     754                        if (preserve_fileflags)
     755                                fileflags = F_FFLAGS(first);
     756#endif
    734757                        if (preserve_uid)
    735758                                uid = F_OWNER(first);
    736759                        if (preserve_gid)
    static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 
    768791
    769792        if (chmod_modes && !S_ISLNK(mode))
    770793                mode = tweak_mode(mode, chmod_modes);
     794#ifdef SUPPORT_FILEFLAGS
     795        if (preserve_fileflags && !(xflags & XMIT_SAME_FLAGS))
     796                fileflags = (uint32)read_int(f);
     797#endif
    771798
    772799        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
    773800                if (protocol_version < 30)
    static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 
    909936        }
    910937#endif
    911938        file->mode = mode;
     939#ifdef SUPPORT_FILEFLAGS
     940        if (fileflags_ndx) /* check the ndx for force_change w/o preserve_fileflags */
     941                F_FFLAGS(file) = fileflags;
     942#endif
    912943        if (preserve_uid)
    913944                F_OWNER(file) = uid;
    914945        if (preserve_gid) {
    struct file_struct *make_file(const char *fname, struct file_list *flist, 
    12831314        }
    12841315#endif
    12851316        file->mode = st.st_mode;
     1317#if defined SUPPORT_FILEFLAGS || defined SUPPORT_FORCE_CHANGE
     1318        if (fileflags_ndx)
     1319                F_FFLAGS(file) = st.st_flags;
     1320#endif
    12861321        if (preserve_uid)
    12871322                F_OWNER(file) = st.st_uid;
    12881323        if (preserve_gid)
    static struct file_struct *send_file_name(int f, struct file_list *flist, 
    14291464#ifdef SUPPORT_XATTRS
    14301465                if (preserve_xattrs) {
    14311466                        sx.st.st_mode = file->mode;
     1467#ifdef SUPPORT_FILEFLAGS
     1468                        sx.st.st_flags = preserve_fileflags ? F_FFLAGS(file) : 0;
     1469#endif
    14321470                        sx.xattr = NULL;
    14331471                        if (get_xattr(fname, &sx) < 0) {
    14341472                                io_error |= IOERR_GENERAL;
  • generator.c

    diff --git a/generator.c b/generator.c
    a b extern int do_progress; 
    3535extern int relative_paths;
    3636extern int implied_dirs;
    3737extern int keep_dirlinks;
     38extern int force_change;
    3839extern int preserve_acls;
    3940extern int preserve_xattrs;
    4041extern int preserve_links;
    extern int preserve_devices; 
    4243extern int preserve_specials;
    4344extern int preserve_hard_links;
    4445extern int preserve_executability;
     46extern int preserve_fileflags;
    4547extern int preserve_perms;
    4648extern int preserve_times;
    4749extern int delete_mode;
    static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags) 
    164166        }
    165167
    166168        if (flags & DEL_NO_UID_WRITE)
    167                 do_chmod(fbuf, mode | S_IWUSR);
     169                do_chmod(fbuf, mode | S_IWUSR, NO_FFLAGS);
    168170
    169171        if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
    170172                /* This only happens on the first call to delete_item() since
    171173                 * delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */
     174#ifdef SUPPORT_FORCE_CHANGE
     175                if (force_change)
     176                        make_mutable(fbuf, NULL, NO_FFLAGS, force_change);
     177#endif
    172178                ignore_perishable = 1;
    173179                /* If DEL_RECURSE is not set, this just reports emptiness. */
    174180                ret = delete_dir_contents(fbuf, flags);
    static enum delret delete_dir_contents(char *fname, uint16 flags) 
    285291                }
    286292
    287293                strlcpy(p, fp->basename, remainder);
     294#ifdef SUPPORT_FORCE_CHANGE
     295                if (force_change) {
     296                        mode_t mode = fp->mode;
     297                        make_mutable(fname, &mode, F_FFLAGS(fp), force_change);
     298                }
     299#endif
    288300                if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)
    289                         do_chmod(fname, fp->mode | S_IWUSR);
     301                        do_chmod(fname, fp->mode | S_IWUSR, NO_FFLAGS);
    290302                /* Save stack by recursing to ourself directly. */
    291303                if (S_ISDIR(fp->mode)) {
    292304                        if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
    int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp) 
    647659                        return 0;
    648660                if (perms_differ(file, sxp))
    649661                        return 0;
     662#ifdef SUPPORT_FILEFLAGS
     663                if (preserve_fileflags && sxp->st.st_flags != F_FFLAGS(file))
     664                        return 0;
     665#endif
    650666                if (ownership_differs(file, sxp))
    651667                        return 0;
    652668#ifdef SUPPORT_ACLS
    void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre 
    698714                if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
    699715                    && sxp->st.st_gid != (gid_t)F_GROUP(file))
    700716                        iflags |= ITEM_REPORT_GROUP;
     717#ifdef SUPPORT_FILEFLAGS
     718                if (preserve_fileflags && !S_ISLNK(file->mode)
     719                 && sxp->st.st_flags != F_FFLAGS(file))
     720                        iflags |= ITEM_REPORT_FFLAGS;
     721#endif
    701722#ifdef SUPPORT_ACLS
    702723                if (preserve_acls && !S_ISLNK(file->mode)) {
    703724                        if (!ACL_READY(*sxp))
    static void recv_generator(char *fname, struct file_struct *file, int ndx, 
    14911512                        file->mode = dest_mode(file->mode, sx.st.st_mode,
    14921513                                               dflt_perms, statret == 0);
    14931514                }
     1515#ifdef SUPPORT_FORCE_CHANGE
     1516                if (force_change && !preserve_fileflags)
     1517                        F_FFLAGS(file) = sx.st.st_flags;
     1518#endif
    14941519                if (statret != 0 && basis_dir[0] != NULL) {
    14951520                        int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
    14961521                                              itemizing, code);
    static void recv_generator(char *fname, struct file_struct *file, int ndx, 
    15261551                /* We need to ensure that the dirs in the transfer have writable
    15271552                 * permissions during the time we are putting files within them.
    15281553                 * This is then fixed after the transfer is done. */
     1554#ifdef SUPPORT_FORCE_CHANGE
     1555                if (force_change && F_FFLAGS(file) & force_change) {
     1556                        mode_t mode = file->mode;
     1557                        if (make_mutable(fname, &mode, F_FFLAGS(file), force_change))
     1558                                need_retouch_dir_perms = 1;
     1559                }
     1560#endif
    15291561#ifdef HAVE_CHMOD
    15301562                if (!am_root && !(file->mode & S_IWUSR) && dir_tweaking) {
    15311563                        mode_t mode = file->mode | S_IWUSR;
    1532                         if (do_chmod(fname, mode) < 0) {
     1564                        if (do_chmod(fname, mode, 0) < 0) {
    15331565                                rsyserr(FERROR_XFER, errno,
    15341566                                        "failed to modify permissions on %s",
    15351567                                        full_fname(fname));
    static void recv_generator(char *fname, struct file_struct *file, int ndx, 
    15721604                file->mode = dest_mode(file->mode, sx.st.st_mode, dflt_perms,
    15731605                                       exists);
    15741606        }
     1607#ifdef SUPPORT_FORCE_CHANGE
     1608        if (force_change && !preserve_fileflags)
     1609                F_FFLAGS(file) = sx.st.st_flags;
     1610#endif
    15751611
    15761612#ifdef SUPPORT_HARD_LINKS
    15771613        if (preserve_hard_links && F_HLINK_NOT_FIRST(file)
    static void touch_up_dirs(struct file_list *flist, int ndx) 
    21152151                        continue;
    21162152                fname = f_name(file, NULL);
    21172153                if (fix_dir_perms)
    2118                         do_chmod(fname, file->mode);
     2154                        do_chmod(fname, file->mode, 0);
    21192155                if (need_retouch_dir_times) {
    21202156                        STRUCT_STAT st;
    21212157                        if (link_stat(fname, &st, 0) == 0
    21222158                         && cmp_time(st.st_mtime, file->modtime) != 0)
    2123                                 set_modtime(fname, file->modtime, file->mode);
     2159                                set_modtime(fname, file->modtime, file->mode, 0);
    21242160                }
     2161#ifdef SUPPORT_FORCE_CHANGE
     2162                if (force_change && F_FFLAGS(file) & force_change)
     2163                        undo_make_mutable(fname, F_FFLAGS(file));
     2164#endif
    21252165                if (counter >= loopchk_limit) {
    21262166                        if (allowed_lull)
    21272167                                maybe_send_keepalive();
  • log.c

    diff --git a/log.c b/log.c
    a b static void log_formatted(enum logcode code, const char *format, const char *op, 
    658658                        c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
    659659                        c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
    660660                        c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
    661                         c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.' : 'u';
     661                        c[8] = !(iflags & ITEM_REPORT_FFLAGS) ? '.' : 'f';
    662662                        c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
    663663                        c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
    664664                        c[11] = '\0';
  • main.c

    diff --git a/main.c b/main.c
    a b  
    2626#if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
    2727#include <locale.h>
    2828#endif
     29#ifdef SUPPORT_FORCE_CHANGE
     30#include <sys/sysctl.h>
     31#endif
    2932
    3033extern int verbose;
    3134extern int dry_run;
    extern int protocol_version; 
    5154extern int file_total;
    5255extern int recurse;
    5356extern int xfer_dirs;
     57extern int force_change;
    5458extern int protect_args;
    5559extern int relative_paths;
    5660extern int sanitize_paths;
    static int do_recv(int f_in, int f_out, char *local_name) 
    753757         * points to an identical file won't be replaced by the referent. */
    754758        copy_links = copy_dirlinks = copy_unsafe_links = 0;
    755759
     760#ifdef SUPPORT_FORCE_CHANGE
     761        if (force_change & SYS_IMMUTABLE) {
     762                /* Determine whether we'll be able to unlock a system immutable item. */
     763                int mib[2];
     764                int securityLevel = 0;
     765                size_t len = sizeof securityLevel;
     766
     767                mib[0] = CTL_KERN;
     768                mib[1] = KERN_SECURELVL;
     769                if (sysctl(mib, 2, &securityLevel, &len, NULL, 0) == 0 && securityLevel > 0) {
     770                        rprintf(FERROR, "System security level is too high to force mutability on system immutable files and directories.\n");
     771                        exit_cleanup(RERR_UNSUPPORTED);
     772                }
     773        }
     774#endif
     775
    756776#ifdef SUPPORT_HARD_LINKS
    757777        if (preserve_hard_links && !inc_recurse)
    758778                match_hard_links(first_flist);
  • options.c

    diff --git a/options.c b/options.c
    a b int preserve_hard_links = 0; 
    5353int preserve_acls = 0;
    5454int preserve_xattrs = 0;
    5555int preserve_perms = 0;
     56int preserve_fileflags = 0;
    5657int preserve_executability = 0;
    5758int preserve_devices = 0;
    5859int preserve_specials = 0;
    int implied_dirs = 1; 
    8485int numeric_ids = 0;
    8586int allow_8bit_chars = 0;
    8687int force_delete = 0;
     88int force_change = 0;
    8789int io_timeout = 0;
    8890int prune_empty_dirs = 0;
    8991int use_qsort = 0;
    static void print_rsync_version(enum logcode f) 
    223225        char const *links = "no ";
    224226        char const *iconv = "no ";
    225227        char const *ipv6 = "no ";
     228        char const *fileflags = "no ";
    226229        STRUCT_STAT *dumstat;
    227230
    228231#if SUBPROTOCOL_VERSION != 0
    static void print_rsync_version(enum logcode f) 
    256259#ifdef CAN_SET_SYMLINK_TIMES
    257260        symtimes = "";
    258261#endif
     262#ifdef SUPPORT_FILEFLAGS
     263        fileflags = "";
     264#endif
    259265
    260266        rprintf(f, "%s  version %s  protocol version %d%s\n",
    261267                RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
    static void print_rsync_version(enum logcode f) 
    269275                (int)(sizeof (int64) * 8));
    270276        rprintf(f, "    %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
    271277                got_socketpair, hardlinks, links, ipv6, have_inplace);
    272         rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes\n",
    273                 have_inplace, acls, xattrs, iconv, symtimes);
     278        rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sfile-flags\n",
     279                have_inplace, acls, xattrs, iconv, symtimes, fileflags);
    274280
    275281#ifdef MAINTAINER_MODE
    276282        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
    void usage(enum logcode F) 
    337343  rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
    338344  rprintf(F," -H, --hard-links            preserve hard links\n");
    339345  rprintf(F," -p, --perms                 preserve permissions\n");
     346#ifdef SUPPORT_FILEFLAGS
     347  rprintf(F,"     --fileflags             preserve file-flags (aka chflags)\n");
     348#endif
    340349  rprintf(F," -E, --executability         preserve the file's executability\n");
    341350  rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
    342351#ifdef SUPPORT_ACLS
    void usage(enum logcode F) 
    374383  rprintf(F,"     --delete-after          receiver deletes after transfer, not during\n");
    375384  rprintf(F,"     --delete-excluded       also delete excluded files from destination dirs\n");
    376385  rprintf(F,"     --ignore-errors         delete even if there are I/O errors\n");
    377   rprintf(F,"     --force                 force deletion of directories even if not empty\n");
     386  rprintf(F,"     --force-delete          force deletion of directories even if not empty\n");
     387#ifdef SUPPORT_FORCE_CHANGE
     388  rprintf(F,"     --force-change          affect user-/system-immutable files/dirs\n");
     389  rprintf(F,"     --force-uchange         affect user-immutable files/dirs\n");
     390  rprintf(F,"     --force-schange         affect system-immutable files/dirs\n");
     391#endif
    378392  rprintf(F,"     --max-delete=NUM        don't delete more than NUM files\n");
    379393  rprintf(F,"     --max-size=SIZE         don't transfer any file larger than SIZE\n");
    380394  rprintf(F,"     --min-size=SIZE         don't transfer any file smaller than SIZE\n");
    static struct poptOption long_options[] = { 
    479493  {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
    480494  {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
    481495  {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
     496#ifdef SUPPORT_FILEFLAGS
     497  {"fileflags",        0,  POPT_ARG_VAL,    &preserve_fileflags, 1, 0, 0 },
     498  {"no-fileflags",     0,  POPT_ARG_VAL,    &preserve_fileflags, 0, 0, 0 },
     499#endif
    482500  {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
    483501  {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
    484502  {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
    static struct poptOption long_options[] = { 
    557575  {"remove-source-files",0,POPT_ARG_VAL,    &remove_source_files, 1, 0, 0 },
    558576  {"force",            0,  POPT_ARG_VAL,    &force_delete, 1, 0, 0 },
    559577  {"no-force",         0,  POPT_ARG_VAL,    &force_delete, 0, 0, 0 },
     578  {"force-delete",     0,  POPT_ARG_VAL,    &force_delete, 1, 0, 0 },
     579  {"no-force-delete",  0,  POPT_ARG_VAL,    &force_delete, 0, 0, 0 },
     580#ifdef SUPPORT_FORCE_CHANGE
     581  {"force-change",     0,  POPT_ARG_VAL,    &force_change, ALL_IMMUTABLE, 0, 0 },
     582  {"no-force-change",  0,  POPT_ARG_VAL,    &force_change, 0, 0, 0 },
     583  {"force-uchange",    0,  POPT_ARG_VAL,    &force_change, USR_IMMUTABLE, 0, 0 },
     584  {"force-schange",    0,  POPT_ARG_VAL,    &force_change, SYS_IMMUTABLE, 0, 0 },
     585#endif
    560586  {"ignore-errors",    0,  POPT_ARG_VAL,    &ignore_errors, 1, 0, 0 },
    561587  {"no-ignore-errors", 0,  POPT_ARG_VAL,    &ignore_errors, 0, 0, 0 },
    562588  {"max-delete",       0,  POPT_ARG_INT,    &max_delete, 0, 0, 0 },
    void server_options(char **args, int *argc_p) 
    18791905        if (xfer_dirs && !recurse && delete_mode && am_sender)
    18801906                args[ac++] = "--no-r";
    18811907
     1908        if (preserve_fileflags)
     1909                args[ac++] = "--fileflags";
     1910
    18821911        if (do_compression && def_compress_level != Z_DEFAULT_COMPRESSION) {
    18831912                if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0)
    18841913                        goto oom;
    void server_options(char **args, int *argc_p) 
    19661995                        args[ac++] = "--delete-excluded";
    19671996                if (force_delete)
    19681997                        args[ac++] = "--force";
     1998#ifdef SUPPORT_FORCE_CHANGE
     1999                if (force_change) {
     2000                        if (force_change == ALL_IMMUTABLE)
     2001                                args[ac++] = "--force-change";
     2002                        else if (force_change == USR_IMMUTABLE)
     2003                                args[ac++] = "--force-uchange";
     2004                        else if (force_change == SYS_IMMUTABLE)
     2005                                args[ac++] = "--force-schange";
     2006                }
     2007#endif
    19692008                if (write_batch < 0)
    19702009                        args[ac++] = "--only-write-batch=X";
    19712010                if (am_root > 1)
  • rsync.c

    diff --git a/rsync.c b/rsync.c
    a b  
    2929
    3030extern int verbose;
    3131extern int dry_run;
     32extern int force_change;
    3233extern int preserve_acls;
    3334extern int preserve_xattrs;
    3435extern int preserve_perms;
     36extern int preserve_fileflags;
    3537extern int preserve_executability;
    3638extern int preserve_times;
    3739extern int am_root;
    mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms, 
    374376        return new_mode;
    375377}
    376378
     379#if defined SUPPORT_FILEFLAGS || defined SUPPORT_FORCE_CHANGE
     380/* Set a file's st_flags. */
     381static int set_fileflags(const char *fname, uint32 fileflags)
     382{
     383        if (do_chflags(fname, fileflags) != 0) {
     384                rsyserr(FERROR_XFER, errno,
     385                        "failed to set fileflags (%x) on %s",
     386                        fileflags, full_fname(fname));
     387                return 0;
     388        }
     389
     390        return 1;
     391}
     392
     393/* Remove immutable flags from an object, so it can be altered/removed.
     394 * Returns the fileflags if flags were removed, otherwise 0.  If the
     395 * fileflags value is NO_FFLAGS, we will stat the fname to figure out
     396 * what the flags are, and return the mode via *mode_ptr (if non-NULL). */
     397uint32 make_mutable(const char *fname, mode_t *mode_ptr, uint32 fileflags, uint32 iflags)
     398{
     399        if (fileflags == NO_FFLAGS) {
     400                STRUCT_STAT st;
     401                if (x_lstat(fname, &st, NULL) < 0)
     402                        return 0;
     403                fileflags = st.st_flags;
     404                if (mode_ptr)
     405                        *mode_ptr = st.st_mode;
     406                else
     407                        mode_ptr = &st.st_mode;
     408        }
     409
     410        if ((mode_ptr && S_ISLNK(*mode_ptr)) || !(fileflags & iflags))
     411                return 0;
     412
     413        if (!set_fileflags(fname, fileflags & ~iflags))
     414                return 0;
     415
     416        return fileflags;
     417}
     418
     419/* Undo a prior make_mutable() call that returned a 1. */
     420int undo_make_mutable(const char *fname, uint32 fileflags)
     421{
     422        if (!set_fileflags(fname, fileflags)) {
     423                rsyserr(FINFO, errno, "failed to relock %s", full_fname(fname));
     424                return -1;
     425        }
     426        return 1;
     427}
     428
     429/* This returns the st_flags value if the parent directory was made mutable, otherwise 0.
     430 * It stores the parent directory path into parent_dirbuf. */
     431int make_parentdir_mutable(const char *fname, uint32 iflags, char *parent_dirbuf, int parent_dirbuf_size)
     432{
     433        char *slash = strrchr(fname, '/');
     434
     435        if (slash) {
     436                int len = slash - fname;
     437                if (len >= parent_dirbuf_size)
     438                        return 0;
     439                strlcpy(parent_dirbuf, fname, len+1);
     440        } else
     441                strlcpy(parent_dirbuf, ".", parent_dirbuf_size);
     442
     443        return make_mutable(parent_dirbuf, NULL, NO_FFLAGS, iflags);
     444}
     445#endif
     446
    377447int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    378448                   const char *fnamecmp, int flags)
    379449{
    int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 
    382452        int change_uid, change_gid;
    383453        mode_t new_mode = file->mode;
    384454        int inherit;
     455#ifdef SUPPORT_FORCE_CHANGE
     456        int became_mutable = 0;
     457#endif
    385458
    386459        if (!sxp) {
    387460                if (dry_run)
    int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 
    411484        if (daemon_chmod_modes && !S_ISLNK(new_mode))
    412485                new_mode = tweak_mode(new_mode, daemon_chmod_modes);
    413486
     487#ifdef SUPPORT_FORCE_CHANGE
     488        if (force_change)
     489                became_mutable = make_mutable(fname, &sxp->st.st_mode, sxp->st.st_flags, force_change);
     490#endif
     491
    414492#ifdef SUPPORT_ACLS
    415493        if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
    416494                get_acl(fname, sxp);
    int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 
    429507                flags |= ATTRS_SKIP_MTIME;
    430508        if (!(flags & ATTRS_SKIP_MTIME)
    431509            && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
    432                 int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
     510                int ret = set_modtime(fname, file->modtime, sxp->st.st_mode, ST_FLAGS(sxp->st));
    433511                if (ret < 0) {
    434512                        rsyserr(FERROR_XFER, errno, "failed to set times on %s",
    435513                                full_fname(fname));
    int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 
    465543                if (am_root >= 0) {
    466544                        uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
    467545                        gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid;
    468                         if (do_lchown(fname, uid, gid) != 0) {
     546                        if (do_lchown(fname, uid, gid, sxp->st.st_mode, ST_FLAGS(sxp->st)) != 0) {
    469547                                /* We shouldn't have attempted to change uid
    470548                                 * or gid unless have the privilege. */
    471549                                rsyserr(FERROR_XFER, errno, "%s %s failed",
    int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 
    503581
    504582#ifdef HAVE_CHMOD
    505583        if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
    506                 int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode);
     584                int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode, ST_FLAGS(sxp->st));
    507585                if (ret < 0) {
    508586                        rsyserr(FERROR_XFER, errno,
    509587                                "failed to set permissions on %s",
    int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 
    515593        }
    516594#endif
    517595
     596#ifdef SUPPORT_FORCE_CHANGE
     597        if (became_mutable)
     598                undo_make_mutable(fname, sxp->st.st_flags);
     599#endif
     600
     601#ifdef SUPPORT_FILEFLAGS
     602        if (preserve_fileflags && !S_ISLNK(sxp->st.st_mode)
     603         && sxp->st.st_flags != F_FFLAGS(file)) {
     604                uint32 fileflags = F_FFLAGS(file);
     605                if (flags & ATTRS_DELAY_IMMUTABLE)
     606                        fileflags &= ~ALL_IMMUTABLE;
     607                if (sxp->st.st_flags != fileflags
     608                 && !set_fileflags(fname, fileflags))
     609                        goto cleanup;
     610                updated = 1;
     611        }
     612#endif
     613
    518614        if (verbose > 1 && flags & ATTRS_REPORT) {
    519615                if (updated)
    520616                        rprintf(FCLIENT, "%s\n", fname);
    int finish_transfer(const char *fname, const char *fnametmp, 
    578674
    579675        /* Change permissions before putting the file into place. */
    580676        set_file_attrs(fnametmp, file, NULL, fnamecmp,
    581                        ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
     677                       ATTRS_DELAY_IMMUTABLE
     678                       | (ok_to_set_time ? 0 : ATTRS_SKIP_MTIME));
    582679
    583680        /* move tmp file over real file */
    584681        if (verbose > 2)
    int finish_transfer(const char *fname, const char *fnametmp, 
    597694        }
    598695        if (ret == 0) {
    599696                /* The file was moved into place (not copied), so it's done. */
     697#ifdef SUPPORT_FILEFLAGS
     698                if (preserve_fileflags && F_FFLAGS(file) & ALL_IMMUTABLE)
     699                        set_fileflags(fname, F_FFLAGS(file));
     700#endif
    600701                return 1;
    601702        }
    602703        /* The file was copied, so tweak the perms of the copied file.  If it
  • rsync.h

    diff --git a/rsync.h b/rsync.h
    a b  
    6161#define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
    6262#define XMIT_HLINK_FIRST (1<<12)        /* protocols 30 - now (HLINKED files only) */
    6363#define XMIT_IO_ERROR_ENDLIST (1<<12)   /* protocols 31*- now (w/XMIT_EXTENDED_FLAGS) (also protocol 30 w/'f' compat flag) */
     64#define XMIT_SAME_FLAGS (1<<14)         /* protocols ?? - now */
    6465
    6566/* These flags are used in the live flist data. */
    6667
     
    160161
    161162#define ATTRS_REPORT            (1<<0)
    162163#define ATTRS_SKIP_MTIME        (1<<1)
     164#define ATTRS_DELAY_IMMUTABLE   (1<<2)
    163165
    164166#define FULL_FLUSH      1
    165167#define NORMAL_FLUSH    0
     
    186188#define ITEM_REPORT_GROUP (1<<6)
    187189#define ITEM_REPORT_ACL (1<<7)
    188190#define ITEM_REPORT_XATTR (1<<8)
     191#define ITEM_REPORT_FFLAGS (1<<9)
    189192#define ITEM_BASIS_TYPE_FOLLOWS (1<<11)
    190193#define ITEM_XNAME_FOLLOWS (1<<12)
    191194#define ITEM_IS_NEW (1<<13)
    typedef unsigned int size_t; 
    482485#endif
    483486#endif
    484487
     488#define NO_FFLAGS ((uint32)-1)
     489
     490#ifdef HAVE_CHFLAGS
     491#define SUPPORT_FILEFLAGS 1
     492#define SUPPORT_FORCE_CHANGE 1
     493#endif
     494
     495#if defined SUPPORT_FILEFLAGS || defined SUPPORT_FORCE_CHANGE
     496#ifndef UF_NOUNLINK
     497#define UF_NOUNLINK 0
     498#endif
     499#ifndef SF_NOUNLINK
     500#define SF_NOUNLINK 0
     501#endif
     502#define USR_IMMUTABLE (UF_IMMUTABLE|UF_NOUNLINK|UF_APPEND)
     503#define SYS_IMMUTABLE (SF_IMMUTABLE|SF_NOUNLINK|SF_APPEND)
     504#define ALL_IMMUTABLE (USR_IMMUTABLE|SYS_IMMUTABLE)
     505#define ST_FLAGS(st) (st.st_flags)
     506#else
     507#define ST_FLAGS(st) NO_FFLAGS
     508#endif
     509
    485510/* Find a variable that is either exactly 32-bits or longer.
    486511 * If some code depends on 32-bit truncation, it will need to
    487512 * take special action in a "#if SIZEOF_INT32 > 4" section. */
    extern int file_extra_cnt; 
    652677extern int inc_recurse;
    653678extern int uid_ndx;
    654679extern int gid_ndx;
     680extern int fileflags_ndx;
    655681extern int acls_ndx;
    656682extern int xattrs_ndx;
    657683
    extern int xattrs_ndx; 
    689715/* When the associated option is on, all entries will have these present: */
    690716#define F_OWNER(f) REQ_EXTRA(f, uid_ndx)->unum
    691717#define F_GROUP(f) REQ_EXTRA(f, gid_ndx)->unum
     718#if defined SUPPORT_FILEFLAGS || defined SUPPORT_FORCE_CHANGE
     719#define F_FFLAGS(f) REQ_EXTRA(f, fileflags_ndx)->unum
     720#else
     721#define F_FFLAGS(f) NO_FFLAGS
     722#endif
    692723#define F_ACL(f) REQ_EXTRA(f, acls_ndx)->num
    693724#define F_XATTR(f) REQ_EXTRA(f, xattrs_ndx)->num
    694725#define F_NDX(f) REQ_EXTRA(f, unsort_ndx)->num
  • rsync.yo

    diff --git a/rsync.yo b/rsync.yo
    a b to the detailed description below for a complete description. verb( 
    342342 -K, --keep-dirlinks         treat symlinked dir on receiver as dir
    343343 -H, --hard-links            preserve hard links
    344344 -p, --perms                 preserve permissions
     345     --fileflags             preserve file-flags (aka chflags)
    345346 -E, --executability         preserve executability
    346347     --chmod=CHMOD           affect file and/or directory permissions
    347348 -A, --acls                  preserve ACLs (implies -p)
    to the detailed description below for a complete description. verb( 
    373374     --delete-after          receiver deletes after transfer, not before
    374375     --delete-excluded       also delete excluded files from dest dirs
    375376     --ignore-errors         delete even if there are I/O errors
    376      --force                 force deletion of dirs even if not empty
     377     --force-delete          force deletion of dirs even if not empty
     378     --force-change          affect user/system immutable files/dirs
     379     --force-uchange         affect user-immutable files/dirs
     380     --force-schange         affect system-immutable files/dirs
    377381     --max-delete=NUM        don't delete more than NUM files
    378382     --max-size=SIZE         don't transfer any file larger than SIZE
    379383     --min-size=SIZE         don't transfer any file smaller than SIZE
    specified, in which case bf(-r) is not implied. 
    547551
    548552Note that bf(-a) bf(does not preserve hardlinks), because
    549553finding multiply-linked files is expensive.  You must separately
    550 specify bf(-H).
     554specify bf(-H).  Note also that for backward compatibility, bf(-a)
     555currently does bf(not) imply the bf(--fileflags) option.
    551556
    552557dit(--no-OPTION) You may turn off one or more implied options by prefixing
    553558the option name with "no-".  Not all options may be prefixed with a "no-":
    they would be using bf(--copy-links). 
    827832Without this option, if the sending side has replaced a directory with a
    828833symlink to a directory, the receiving side will delete anything that is in
    829834the way of the new symlink, including a directory hierarchy (as long as
    830 bf(--force) or bf(--delete) is in effect).
     835bf(--force-delete) or bf(--delete) is in effect).
    831836
    832837See also bf(--keep-dirlinks) for an analogous option for the receiving
    833838side.
    Note that this option does not copy rsyncs special xattr values (e.g. those 
    990995used by bf(--fake-super)) unless you repeat the option (e.g. -XX).  This
    991996"copy all xattrs" mode cannot be used with bf(--fake-super).
    992997
     998dit(bf(--fileflags)) This option causes rsync to update the file-flags to be
     999the same as the source files and directories (if your OS supports the
     1000bf(chflags)(2) system call).   Some flags can only be altered by the super-user
     1001and some might only be unset below a certain secure-level (usually single-user
     1002mode). It will not make files alterable that are set to immutable on the
     1003receiver.  To do that, see bf(--force-change), bf(--force-uchange), and
     1004bf(--force-schange).
     1005
     1006dit(bf(--force-change)) This option causes rsync to disable both user-immutable
     1007and system-immutable flags on files and directories that are being updated or
     1008deleted on the receiving side.  This option overrides bf(--force-uchange) and
     1009bf(--force-schange).
     1010
     1011dit(bf(--force-uchange)) This option causes rsync to disable user-immutable
     1012flags on files and directories that are being updated or deleted on the
     1013receiving side.  It does not try to affect system flags.  This option overrides
     1014bf(--force-change) and bf(--force-schange).
     1015
     1016dit(bf(--force-schange)) This option causes rsync to disable system-immutable
     1017flags on files and directories that are being updated or deleted on the
     1018receiving side.  It does not try to affect user flags.  This option overrides
     1019bf(--force-change) and bf(--force-schange).
     1020
    9931021dit(bf(--chmod)) This option tells rsync to apply one or more
    9941022comma-separated "chmod" strings to the permission of the files in the
    9951023transfer.  The resulting value is treated as though it were the permissions
    See bf(--delete) (which is implied) for more details on file-deletion. 
    12601288dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files
    12611289even when there are I/O errors.
    12621290
    1263 dit(bf(--force)) This option tells rsync to delete a non-empty directory
     1291dit(bf(--force-delete)) This option tells rsync to delete a non-empty directory
    12641292when it is to be replaced by a non-directory.  This is only relevant if
    12651293deletions are not active (see bf(--delete) for details).
    12661294
    1267 Note for older rsync versions: bf(--force) used to still be required when
    1268 using bf(--delete-after), and it used to be non-functional unless the
     1295This option can be abbreviated bf(--force) for backward compatibility.
     1296Note that some older rsync versions used to still require bf(--force)
     1297when using bf(--delete-after), and it used to be non-functional unless the
    12691298bf(--recursive) option was also enabled.
    12701299
    12711300dit(bf(--max-delete=NUM)) This tells rsync not to delete more than NUM
    with older versions of rsync, but that also turns on the output of other 
    17531782verbose messages).
    17541783
    17551784The "%i" escape has a cryptic output that is 11 letters long.  The general
    1756 format is like the string bf(YXcstpoguax), where bf(Y) is replaced by the
     1785format is like the string bf(YXcstpogfax), where bf(Y) is replaced by the
    17571786type of update being done, bf(X) is replaced by the file-type, and the
    17581787other letters represent attributes that may be output if they are being
    17591788modified.
    quote(itemization( 
    18091838  sender's value (requires bf(--owner) and super-user privileges).
    18101839  it() A bf(g) means the group is different and is being updated to the
    18111840  sender's value (requires bf(--group) and the authority to set the group).
    1812   it() The bf(u) slot is reserved for future use.
     1841  it() The bf(f) means that the fileflags information changed.
    18131842  it() The bf(a) means that the ACL information changed.
    18141843  it() The bf(x) means that the extended attribute information changed.
    18151844))
  • syscall.c

    diff --git a/syscall.c b/syscall.c
    a b extern int dry_run; 
    3333extern int am_root;
    3434extern int read_only;
    3535extern int list_only;
     36extern int force_change;
    3637extern int preserve_perms;
    3738extern int preserve_executability;
    3839
    int do_unlink(const char *fname) 
    5051{
    5152        if (dry_run) return 0;
    5253        RETURN_ERROR_IF_RO_OR_LO;
    53         return unlink(fname);
     54        if (unlink(fname) == 0)
     55                return 0;
     56
     57#ifdef SUPPORT_FORCE_CHANGE
     58        if (force_change && (errno == EPERM || errno == EACCES)) {
     59                char parent[MAXPATHLEN];
     60                int parent_flags;
     61                int saved_errno = errno;
     62                int file_flags = make_mutable(fname, NULL, NO_FFLAGS, force_change);
     63                if (file_flags && unlink(fname) == 0)
     64                        return 0;
     65                parent_flags = make_parentdir_mutable(fname, force_change, parent, sizeof parent);
     66                if (parent_flags) {
     67                        int ret = unlink(fname);
     68                        undo_make_mutable(parent, parent_flags);
     69                        if (ret == 0)
     70                                return 0;
     71                }
     72                if (file_flags)
     73                        undo_make_mutable(fname, file_flags);
     74                errno = saved_errno;
     75        }
     76#endif
     77
     78        return -1;
    5479}
    5580
    5681int do_symlink(const char *fname1, const char *fname2)
    5782{
    5883        if (dry_run) return 0;
    5984        RETURN_ERROR_IF_RO_OR_LO;
    60         return symlink(fname1, fname2);
     85        if (symlink(fname1, fname2) == 0)
     86                return 0;
     87
     88#ifdef SUPPORT_FORCE_CHANGE
     89        if (force_change && (errno == EPERM || errno == EACCES)) {
     90                char parent[MAXPATHLEN];
     91                int saved_errno = errno;
     92                int parent_flags = make_parentdir_mutable(fname2, force_change, parent, sizeof parent);
     93                if (parent_flags) {
     94                        int ret = symlink(fname1, fname2);
     95                        undo_make_mutable(parent, parent_flags);
     96                        if (ret == 0)
     97                                return 0;
     98                }
     99                errno = saved_errno;
     100        }
     101#endif
     102
     103        return -1;
    61104}
    62105
    63106#ifdef HAVE_LINK
    int do_link(const char *fname1, const char *fname2) 
    65108{
    66109        if (dry_run) return 0;
    67110        RETURN_ERROR_IF_RO_OR_LO;
    68         return link(fname1, fname2);
     111        if (link(fname1, fname2) == 0)
     112                return 0;
     113
     114#ifdef SUPPORT_FORCE_CHANGE
     115        if (force_change && (errno == EPERM || errno == EACCES)) {
     116                char parent[MAXPATHLEN];
     117                int saved_errno = errno;
     118                int parent_flags = make_parentdir_mutable(fname2, force_change, parent, sizeof parent);
     119                if (parent_flags) {
     120                        int ret = link(fname1, fname2);
     121                        undo_make_mutable(parent, parent_flags);
     122                        if (ret == 0)
     123                                return 0;
     124                }
     125                errno = saved_errno;
     126        }
     127#endif
     128
     129        return -1;
    69130}
    70131#endif
    71132
    72 int do_lchown(const char *path, uid_t owner, gid_t group)
     133int do_lchown(const char *path, uid_t owner, gid_t group, mode_t mode, uint32 fileflags)
    73134{
    74135        if (dry_run) return 0;
    75136        RETURN_ERROR_IF_RO_OR_LO;
    76137#ifndef HAVE_LCHOWN
    77138#define lchown chown
    78139#endif
    79         return lchown(path, owner, group);
     140        if (lchown(path, owner, group) == 0)
     141                return 0;
     142
     143#ifdef SUPPORT_FORCE_CHANGE
     144        if (force_change && (errno == EPERM || errno == EACCES)) {
     145                int saved_errno = errno;
     146                fileflags = make_mutable(path, &mode, fileflags, force_change);
     147                if (fileflags) {
     148                        int ret = lchown(path, owner, group);
     149                        undo_make_mutable(path, fileflags);
     150                        if (ret == 0)
     151                                return 0;
     152                }
     153                errno = saved_errno;
     154        }
     155#else
     156        mode = fileflags = 0; /* avoid compiler warning */
     157#endif
     158
     159        return -1;
    80160}
    81161
    82162int do_mknod(const char *pathname, mode_t mode, dev_t dev)
    int do_mknod(const char *pathname, mode_t mode, dev_t dev) 
    116196                        return -1;
    117197                close(sock);
    118198#ifdef HAVE_CHMOD
    119                 return do_chmod(pathname, mode);
     199                return do_chmod(pathname, mode, 0);
    120200#else
    121201                return 0;
    122202#endif
    int do_rmdir(const char *pathname) 
    133213{
    134214        if (dry_run) return 0;
    135215        RETURN_ERROR_IF_RO_OR_LO;
    136         return rmdir(pathname);
     216        if (rmdir(pathname) == 0)
     217                return 0;
     218
     219#ifdef SUPPORT_FORCE_CHANGE
     220        if (force_change && (errno == EPERM || errno == EACCES)) {
     221                char parent[MAXPATHLEN];
     222                int parent_flags;
     223                int saved_errno = errno;
     224                int file_flags = make_mutable(pathname, NULL, NO_FFLAGS, force_change);
     225                if (file_flags && rmdir(pathname) == 0)
     226                        return 0;
     227                parent_flags = make_parentdir_mutable(pathname, force_change, parent, sizeof parent);
     228                if (parent_flags) {
     229                        int ret = rmdir(pathname);
     230                        undo_make_mutable(parent, parent_flags);
     231                        if (ret == 0)
     232                                return 0;
     233                }
     234                if (file_flags)
     235                        undo_make_mutable(pathname, file_flags);
     236                errno = saved_errno;
     237        }
     238#endif
     239
     240        return -1;
    137241}
    138242
    139243int do_open(const char *pathname, int flags, mode_t mode)
    140244{
     245        int fd;
    141246        if (flags != O_RDONLY) {
    142247                RETURN_ERROR_IF(dry_run, 0);
    143248                RETURN_ERROR_IF_RO_OR_LO;
    144249        }
     250        if ((fd = open(pathname, flags | O_BINARY, mode)) >= 0)
     251                return fd;
     252
     253#ifdef SUPPORT_FORCE_CHANGE
     254        if (force_change && (errno == EPERM || errno == EACCES)) {
     255                char parent[MAXPATHLEN];
     256                int saved_errno = errno;
     257                int parent_flags = make_parentdir_mutable(pathname, force_change, parent, sizeof parent);
     258                if (parent_flags) {
     259                        fd = open(pathname, flags | O_BINARY, mode);
     260                        undo_make_mutable(parent, parent_flags);
     261                        if (fd >= 0)
     262                                return fd;
     263                }
     264                errno = saved_errno;
     265        }
     266#endif
    145267
    146         return open(pathname, flags | O_BINARY, mode);
     268        return -1;
    147269}
    148270
    149271#ifdef HAVE_CHMOD
    150 int do_chmod(const char *path, mode_t mode)
     272int do_chmod(const char *path, mode_t mode, uint32 fileflags)
    151273{
    152274        int code;
    153275        if (dry_run) return 0;
    int do_chmod(const char *path, mode_t mode) 
    170292        } else
    171293                code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
    172294#endif /* !HAVE_LCHMOD */
     295#ifdef SUPPORT_FORCE_CHANGE
     296        if (code < 0 && force_change && (errno == EPERM || errno == EACCES) && !S_ISLNK(mode)) {
     297                int saved_errno = errno;
     298                fileflags = make_mutable(path, &mode, fileflags, force_change);
     299                if (fileflags) {
     300#ifdef HAVE_LCHMOD
     301                        code = lchmod(path, mode & CHMOD_BITS);
     302#else
     303                        code = chmod(path, mode & CHMOD_BITS);
     304#endif
     305                        undo_make_mutable(path, fileflags);
     306                        if (code == 0)
     307                                return 0;
     308                }
     309                errno = saved_errno;
     310        }
     311#else
     312        fileflags = 0; /* avoid compiler warning */
     313#endif
    173314        if (code != 0 && (preserve_perms || preserve_executability))
    174315                return code;
    175316        return 0;
    176317}
    177318#endif
    178319
     320#ifdef HAVE_CHFLAGS
     321int do_chflags(const char *path, uint32 fileflags)
     322{
     323        if (dry_run) return 0;
     324        RETURN_ERROR_IF_RO_OR_LO;
     325        return chflags(path, fileflags);
     326}
     327#endif
     328
    179329int do_rename(const char *fname1, const char *fname2)
    180330{
    181331        if (dry_run) return 0;
    182332        RETURN_ERROR_IF_RO_OR_LO;
    183         return rename(fname1, fname2);
     333        if (rename(fname1, fname2) == 0)
     334                return 0;
     335
     336#ifdef SUPPORT_FORCE_CHANGE
     337        if (force_change && (errno == EPERM || errno == EACCES)) {
     338                int saved_errno = errno;
     339                int ret = -1, file2_flags = 0;
     340                int file1_flags = make_mutable(fname1, NULL, NO_FFLAGS, force_change);
     341                if (file1_flags && rename(fname1, fname2) == 0)
     342                        ret = 0;
     343                else {
     344                        file2_flags = make_mutable(fname2, NULL, NO_FFLAGS, force_change);
     345                        if (file2_flags && rename(fname1, fname2) == 0)
     346                                ret = 0;
     347                        else {
     348                                char parent1[MAXPATHLEN];
     349                                int parent1_flags = make_parentdir_mutable(fname1, force_change,
     350                                                        parent1, sizeof parent1);
     351                                if (parent1_flags && rename(fname1, fname2) == 0)
     352                                        ret = 0;
     353                                else {
     354                                        char parent2[MAXPATHLEN];
     355                                        int parent2_flags = make_parentdir_mutable(fname2, force_change,
     356                                                                parent2, sizeof parent2);
     357                                        if (parent2_flags) {
     358                                                if (rename(fname1, fname2) == 0)
     359                                                        ret = 0;
     360                                                undo_make_mutable(parent2, parent2_flags);
     361                                        }
     362                                }
     363                                if (parent1_flags)
     364                                        undo_make_mutable(parent1, parent1_flags);
     365                        }
     366                }
     367
     368                if (ret == 0)
     369                        file2_flags = file1_flags; /* file1 is now file2 */
     370                else if (file1_flags)
     371                        undo_make_mutable(fname1, file1_flags);
     372                if (file2_flags)
     373                        undo_make_mutable(fname2, file2_flags);
     374                if (ret == 0)
     375                        return 0;
     376
     377                errno = saved_errno;
     378        }
     379#endif
     380
     381        return -1;
    184382}
    185383
    186384#ifdef HAVE_FTRUNCATE
    int do_mkdir(char *fname, mode_t mode) 
    222420        if (dry_run) return 0;
    223421        RETURN_ERROR_IF_RO_OR_LO;
    224422        trim_trailing_slashes(fname);
    225         return mkdir(fname, mode);
     423        if (mkdir(fname, mode) == 0)
     424                return 0;
     425
     426#ifdef SUPPORT_FORCE_CHANGE
     427        if (force_change && (errno == EPERM || errno == EACCES)) {
     428                char parent[MAXPATHLEN];
     429                int saved_errno = errno;
     430                int parent_flags = make_parentdir_mutable(fname, force_change, parent, sizeof parent);
     431                if (parent_flags) {
     432                        int ret = mkdir(fname, mode);
     433                        undo_make_mutable(parent, parent_flags);
     434                        if (ret == 0)
     435                                return 0;
     436                }
     437                errno = saved_errno;
     438        }
     439#endif
     440
     441        return -1;
    226442}
    227443
    228444/* like mkstemp but forces permissions */
    int do_mkstemp(char *template, mode_t perms) 
    235451#if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
    236452        {
    237453                int fd = mkstemp(template);
    238                 if (fd == -1)
     454#ifdef SUPPORT_FORCE_CHANGE
     455                if (fd < 0 && force_change) {
     456                        char parent[MAXPATHLEN];
     457                        int saved_errno = errno;
     458                        int parent_flags = make_parentdir_mutable(template, force_change, parent, sizeof parent);
     459                        if (parent_flags) {
     460                                fd = mkstemp(template);
     461                                undo_make_mutable(parent, parent_flags);
     462                        }
     463                        errno = saved_errno;
     464                }
     465#endif
     466                if (fd < 0)
    239467                        return -1;
    240468                if (fchmod(fd, perms) != 0 && preserve_perms) {
    241469                        int errno_save = errno;
    OFF_T do_lseek(int fd, OFF_T offset, int whence) 
    302530}
    303531
    304532#ifdef HAVE_UTIMENSAT
    305 int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec)
     533int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags)
    306534{
    307535        struct timespec t[2];
    308536
    int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec) 
    313541        t[0].tv_nsec = UTIME_NOW;
    314542        t[1].tv_sec = modtime;
    315543        t[1].tv_nsec = mod_nsec;
    316         return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW);
     544        if (utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW) == 0)
     545                return 0;
     546
     547#ifdef SUPPORT_FORCE_CHANGE
     548        fileflags = make_mutable(fname, &mode, fileflags, force_change);
     549        if (fileflags) {
     550                if (utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW) == 0)
     551                        return 0;
     552                undo_make_mutable(fname, fileflags);
     553        }
     554#else
     555        mode = fileflags; /* avoid compiler warning */
     556#endif
     557
     558        return -1;
    317559}
    318560#endif
    319561
    320562#ifdef HAVE_LUTIMES
    321 int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec)
     563int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags)
    322564{
    323565        struct timeval t[2];
    324566
    int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec) 
    329571        t[0].tv_usec = 0;
    330572        t[1].tv_sec = modtime;
    331573        t[1].tv_usec = mod_nsec / 1000;
    332         return lutimes(fname, t);
     574        if (lutimes(fname, t) == 0)
     575                return 0;
     576
     577#ifdef SUPPORT_FORCE_CHANGE
     578        fileflags = make_mutable(fname, &mode, fileflags, force_change);
     579        if (fileflags) {
     580                if (lutimes(fname, t) == 0)
     581                        return 0;
     582                undo_make_mutable(fname, fileflags);
     583        }
     584#else
     585        mode = fileflags; /* avoid compiler warning */
     586#endif
     587
     588        return -1;
    333589}
    334590#endif
    335591
    336592#ifdef HAVE_UTIMES
    337 int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec)
     593int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags)
    338594{
    339595        struct timeval t[2];
    340596
    int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec) 
    345601        t[0].tv_usec = 0;
    346602        t[1].tv_sec = modtime;
    347603        t[1].tv_usec = mod_nsec / 1000;
    348         return utimes(fname, t);
     604        if (utimes(fname, t) == 0)
     605                return 0;
     606
     607#ifdef SUPPORT_FORCE_CHANGE
     608        fileflags = make_mutable(fname, &mode, fileflags, force_change);
     609        if (fileflags) {
     610                if (utimes(fname, t) == 0)
     611                        return 0;
     612                undo_make_mutable(fname, fileflags);
     613        }
     614#else
     615        mode = fileflags; /* avoid compiler warning */
     616#endif
     617
     618        return -1;
    349619}
    350620
    351621#elif defined HAVE_UTIME
    352 int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec))
     622int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec), mode_t mode, uint32 fileflags)
    353623{
    354624#ifdef HAVE_STRUCT_UTIMBUF
    355         struct utimbuf tbuf;
     625        struct utimbuf tbuf, *t = &tbuf;
    356626#else
    357627        time_t t[2];
    358628#endif
    int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec)) 
    360630        if (dry_run) return 0;
    361631        RETURN_ERROR_IF_RO_OR_LO;
    362632
    363 # ifdef HAVE_STRUCT_UTIMBUF
     633#ifdef HAVE_STRUCT_UTIMBUF
    364634        tbuf.actime = time(NULL);
    365635        tbuf.modtime = modtime;
    366         return utime(fname, &tbuf);
    367 # else
     636#else
    368637        t[0] = time(NULL);
    369638        t[1] = modtime;
    370         return utime(fname, t);
    371 # endif
     639#endif
     640        if (utime(fname, t) == 0)
     641                return 0;
     642
     643#ifdef SUPPORT_FORCE_CHANGE
     644        fileflags = make_mutable(fname, &mode, fileflags, force_change);
     645        if (fileflags) {
     646                if (utime(fname, t) == 0)
     647                        return 0;
     648                undo_make_mutable(fname, fileflags);
     649        }
     650#else
     651        mode = fileflags; /* avoid compiler warning */
     652#endif
     653
     654        return -1;
    372655}
    373656
    374657#else
  • t_stub.c

    diff --git a/t_stub.c b/t_stub.c
    a b int module_id = -1; 
    2626int relative_paths = 0;
    2727int human_readable = 0;
    2828int module_dirlen = 0;
     29int force_change = 0;
    2930int preserve_times = 0;
    3031int preserve_xattrs = 0;
    3132mode_t orig_umask = 002;
    struct filter_list_struct daemon_filter_list; 
    9091{
    9192        return "tester";
    9293}
     94
     95#if defined SUPPORT_FILEFLAGS || defined SUPPORT_FORCE_CHANGE
     96 uint32 make_mutable(UNUSED(const char *fname), UNUSED(mode_t *mode), UNUSED(uint32 fileflags), UNUSED(uint32 iflags))
     97{
     98        return 0;
     99}
     100
     101 int undo_make_mutable(UNUSED(const char *fname), UNUSED(uint32 fileflags))
     102{
     103        return 0;
     104}
     105
     106 int make_parentdir_mutable(UNUSED(const char *fname), UNUSED(uint32 iflags), UNUSED(char *parent_dirbuf), UNUSED(int parent_dirbuf_size))
     107{
     108        return 0;
     109}
     110#endif
     111
     112#ifdef SUPPORT_XATTRS
     113 int x_lstat(UNUSED(const char *fname), UNUSED(STRUCT_STAT *fst), UNUSED(STRUCT_STAT *xst))
     114{
     115        return -1;
     116}
     117#endif
  • util.c

    diff --git a/util.c b/util.c
    a b NORETURN void overflow_exit(const char *str) 
    125125
    126126/* This returns 0 for success, 1 for a symlink if symlink time-setting
    127127 * is not possible, or -1 for any other error. */
    128 int set_modtime(const char *fname, time_t modtime, mode_t mode)
     128int set_modtime(const char *fname, time_t modtime, mode_t mode, uint32 fileflags)
    129129{
    130130        static int switch_step = 0;
    131131
    int set_modtime(const char *fname, time_t modtime, mode_t mode) 
    138138        switch (switch_step) {
    139139#ifdef HAVE_UTIMENSAT
    140140#include "case_N.h"
    141                 if (do_utimensat(fname, modtime, 0) == 0)
     141                if (do_utimensat(fname, modtime, 0, mode, fileflags) == 0)
    142142                        break;
    143143                if (errno != ENOSYS)
    144144                        return -1;
    int set_modtime(const char *fname, time_t modtime, mode_t mode) 
    148148
    149149#ifdef HAVE_LUTIMES
    150150#include "case_N.h"
    151                 if (do_lutimes(fname, modtime, 0) == 0)
     151                if (do_lutimes(fname, modtime, 0, mode, fileflags) == 0)
    152152                        break;
    153153                if (errno != ENOSYS)
    154154                        return -1;
    int set_modtime(const char *fname, time_t modtime, mode_t mode) 
    167167
    168168#include "case_N.h"
    169169#ifdef HAVE_UTIMES
    170                 if (do_utimes(fname, modtime, 0) == 0)
     170                if (do_utimes(fname, modtime, 0, mode, fileflags) == 0)
    171171                        break;
    172172#else
    173                 if (do_utime(fname, modtime, 0) == 0)
     173                if (do_utime(fname, modtime, 0, mode, fileflags) == 0)
    174174                        break;
    175175#endif
    176176
  • xattrs.c

    diff --git a/xattrs.c b/xattrs.c
    a b int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode) 
    10411041        mode = (fst.st_mode & _S_IFMT) | (fmode & ACCESSPERMS)
    10421042             | (S_ISDIR(fst.st_mode) ? 0700 : 0600);
    10431043        if (fst.st_mode != mode)
    1044                 do_chmod(fname, mode);
     1044                do_chmod(fname, mode, ST_FLAGS(fst));
    10451045        if (!IS_DEVICE(fst.st_mode))
    10461046                fst.st_rdev = 0; /* just in case */
    10471047
  • config.h.in

    diff -up a/config.h.in b/config.h.in
    a b  
    7070/* Define to 1 if vsprintf has a C99-compatible return value */
    7171#undef HAVE_C99_VSNPRINTF
    7272
     73/* Define to 1 if you have the `chflags' function. */
     74#undef HAVE_CHFLAGS
     75
    7376/* Define to 1 if you have the `chmod' function. */
    7477#undef HAVE_CHMOD
    7578
  • configure.sh

    diff -up a/configure.sh b/configure.sh
    a b fi 
    74257425
    74267426for ac_func in waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
    74277427    fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
     7428    chflags \
    74287429    memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \
    74297430    strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
    74307431    setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
  • proto.h

    diff -up a/proto.h b/proto.h
    a b int read_ndx_and_attrs(int f_in, int *if 
    274274void free_sums(struct sum_struct *s);
    275275mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
    276276                 int exists);
     277uint32 make_mutable(const char *fname, mode_t *mode_ptr, uint32 fileflags, uint32 iflags);
     278int undo_make_mutable(const char *fname, uint32 fileflags);
     279int make_parentdir_mutable(const char *fname, uint32 iflags, char *parent_dirbuf, int parent_dirbuf_size);
    277280int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    278281                   const char *fnamecmp, int flags);
    279282RETSIGTYPE sig_int(UNUSED(int val));
    void set_socket_options(int fd, char *op 
    297300int do_unlink(const char *fname);
    298301int do_symlink(const char *fname1, const char *fname2);
    299302int do_link(const char *fname1, const char *fname2);
    300 int do_lchown(const char *path, uid_t owner, gid_t group);
     303int do_lchown(const char *path, uid_t owner, gid_t group, mode_t mode, uint32 fileflags);
    301304int do_mknod(const char *pathname, mode_t mode, dev_t dev);
    302305int do_rmdir(const char *pathname);
    303306int do_open(const char *pathname, int flags, mode_t mode);
    304 int do_chmod(const char *path, mode_t mode);
     307int do_chmod(const char *path, mode_t mode, uint32 fileflags);
     308int do_chflags(const char *path, uint32 fileflags);
    305309int do_rename(const char *fname1, const char *fname2);
    306310int do_ftruncate(int fd, OFF_T size);
    307311void trim_trailing_slashes(char *name);
    int do_stat(const char *fname, STRUCT_ST 
    311315int do_lstat(const char *fname, STRUCT_STAT *st);
    312316int do_fstat(int fd, STRUCT_STAT *st);
    313317OFF_T do_lseek(int fd, OFF_T offset, int whence);
    314 int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec);
    315 int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec);
    316 int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec);
    317 int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec));
     318int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
     319int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
     320int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
     321int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec), mode_t mode, uint32 fileflags);
    318322void set_compression(const char *fname);
    319323void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
    320324                int32 n, int32 toklen);
    int fd_pair(int fd[2]); 
    334338void print_child_argv(const char *prefix, char **cmd);
    335339NORETURN void out_of_memory(const char *str);
    336340NORETURN void overflow_exit(const char *str);
    337 int set_modtime(const char *fname, time_t modtime, mode_t mode);
     341int set_modtime(const char *fname, time_t modtime, mode_t mode, uint32 fileflags);
    338342int mkdir_defmode(char *fname);
    339343int create_directory_path(char *fname);
    340344int full_write(int desc, const char *ptr, size_t len);
  • rsync.1

    diff -up a/rsync.1 b/rsync.1
    a b to the detailed description below for a 
    417417 \-K, \-\-keep\-dirlinks         treat symlinked dir on receiver as dir
    418418 \-H, \-\-hard\-links            preserve hard links
    419419 \-p, \-\-perms                 preserve permissions
     420     \-\-fileflags             preserve file\-flags (aka chflags)
    420421 \-E, \-\-executability         preserve executability
    421422     \-\-chmod=CHMOD           affect file and/or directory permissions
    422423 \-A, \-\-acls                  preserve ACLs (implies \-p)
    to the detailed description below for a 
    448449     \-\-delete\-after          receiver deletes after transfer, not before
    449450     \-\-delete\-excluded       also delete excluded files from dest dirs
    450451     \-\-ignore\-errors         delete even if there are I/O errors
    451      \-\-force                 force deletion of dirs even if not empty
     452     \-\-force\-delete          force deletion of dirs even if not empty
     453     \-\-force\-change          affect user/system immutable files/dirs
     454     \-\-force\-uchange         affect user\-immutable files/dirs
     455     \-\-force\-schange         affect system\-immutable files/dirs
    452456     \-\-max\-delete=NUM        don'\&t delete more than NUM files
    453457     \-\-max\-size=SIZE         don'\&t transfer any file larger than SIZE
    454458     \-\-min\-size=SIZE         don'\&t transfer any file smaller than SIZE
    specified, in which case \fB\-r\fP is no 
    638642.IP
    639643Note that \fB\-a\fP \fBdoes not preserve hardlinks\fP, because
    640644finding multiply\-linked files is expensive.  You must separately
    641 specify \fB\-H\fP.
     645specify \fB\-H\fP.  Note also that for backward compatibility, \fB\-a\fP
     646currently does \fBnot\fP imply the \fB\-\-fileflags\fP option.
    642647.IP
    643648.IP "\-\-no\-OPTION"
    644649You may turn off one or more implied options by prefixing
    they would be using \fB\-\-copy\-links\f 
    955960Without this option, if the sending side has replaced a directory with a
    956961symlink to a directory, the receiving side will delete anything that is in
    957962the way of the new symlink, including a directory hierarchy (as long as
    958 \fB\-\-force\fP or \fB\-\-delete\fP is in effect).
     963\fB\-\-force\-delete\fP or \fB\-\-delete\fP is in effect).
    959964.IP
    960965See also \fB\-\-keep\-dirlinks\fP for an analogous option for the receiving
    961966side.
    Note that this option does not copy rsyn 
    11421147used by \fB\-\-fake\-super\fP) unless you repeat the option (e.g. \-XX).  This
    11431148\(dq\&copy all xattrs\(dq\& mode cannot be used with \fB\-\-fake\-super\fP.
    11441149.IP
     1150.IP "\fB\-\-fileflags\fP"
     1151This option causes rsync to update the file\-flags to be
     1152the same as the source files and directories (if your OS supports the
     1153\fBchflags\fP(2) system call).   Some flags can only be altered by the super\-user
     1154and some might only be unset below a certain secure\-level (usually single\-user
     1155mode). It will not make files alterable that are set to immutable on the
     1156receiver.  To do that, see \fB\-\-force\-change\fP, \fB\-\-force\-uchange\fP, and
     1157\fB\-\-force\-schange\fP.
     1158.IP
     1159.IP "\fB\-\-force\-change\fP"
     1160This option causes rsync to disable both user\-immutable
     1161and system\-immutable flags on files and directories that are being updated or
     1162deleted on the receiving side.  This option overrides \fB\-\-force\-uchange\fP and
     1163\fB\-\-force\-schange\fP.
     1164.IP
     1165.IP "\fB\-\-force\-uchange\fP"
     1166This option causes rsync to disable user\-immutable
     1167flags on files and directories that are being updated or deleted on the
     1168receiving side.  It does not try to affect system flags.  This option overrides
     1169\fB\-\-force\-change\fP and \fB\-\-force\-schange\fP.
     1170.IP
     1171.IP "\fB\-\-force\-schange\fP"
     1172This option causes rsync to disable system\-immutable
     1173flags on files and directories that are being updated or deleted on the
     1174receiving side.  It does not try to affect user flags.  This option overrides
     1175\fB\-\-force\-change\fP and \fB\-\-force\-schange\fP.
     1176.IP
    11451177.IP "\fB\-\-chmod\fP"
    11461178This option tells rsync to apply one or more
    11471179comma\-separated \(dq\&chmod\(dq\& strings to the permission of the files in the
    See \fB\-\-delete\fP (which is implied) 
    14421474Tells \fB\-\-delete\fP to go ahead and delete files
    14431475even when there are I/O errors.
    14441476.IP
    1445 .IP "\fB\-\-force\fP"
     1477.IP "\fB\-\-force\-delete\fP"
    14461478This option tells rsync to delete a non\-empty directory
    14471479when it is to be replaced by a non\-directory.  This is only relevant if
    14481480deletions are not active (see \fB\-\-delete\fP for details).
    14491481.IP
    1450 Note for older rsync versions: \fB\-\-force\fP used to still be required when
    1451 using \fB\-\-delete\-after\fP, and it used to be non\-functional unless the
     1482This option can be abbreviated \fB\-\-force\fP for backward compatibility.
     1483Note that some older rsync versions used to still require \fB\-\-force\fP
     1484when using \fB\-\-delete\-after\fP, and it used to be non\-functional unless the
    14521485\fB\-\-recursive\fP option was also enabled.
    14531486.IP
    14541487.IP "\fB\-\-max\-delete=NUM\fP"
    with older versions of rsync, but that a 
    20042037verbose messages).
    20052038.IP
    20062039The \(dq\&%i\(dq\& escape has a cryptic output that is 11 letters long.  The general
    2007 format is like the string \fBYXcstpoguax\fP, where \fBY\fP is replaced by the
     2040format is like the string \fBYXcstpogfax\fP, where \fBY\fP is replaced by the
    20082041type of update being done, \fBX\fP is replaced by the file\-type, and the
    20092042other letters represent attributes that may be output if they are being
    20102043modified.
    sender\(cq\&s value (requires \fB\-\-own 
    20742107A \fBg\fP means the group is different and is being updated to the
    20752108sender\(cq\&s value (requires \fB\-\-group\fP and the authority to set the group).
    20762109.IP o
    2077 The \fBu\fP slot is reserved for future use.
     2110The \fBf\fP means that the fileflags information changed.
    20782111.IP o
    20792112The \fBa\fP means that the ACL information changed.
    20802113.IP o
Note: See TracBrowser for help on using the repository browser.