Changeset 121462


Ignore:
Timestamp:
Jun 26, 2014, 1:16:27 AM (5 years ago)
Author:
mojca@…
Message:

rsync: upgrade to 3.1.1 (maintainer, #44117)

Location:
trunk/dports/net/rsync
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/dports/net/rsync/Portfile

    r97835 r121462  
    55
    66name                rsync
    7 version             3.0.9
    8 revision            2
     7version             3.1.1
     8revision            0
    99categories          net
    1010license             GPL-3+
     
    2222                    http://rsync.samba.org/ftp/rsync/src/
    2323
    24 checksums           md5     5ee72266fe2c1822333c407e1761b92b \
    25                     sha1    c64c8341984aea647506eb504496999fd968ddfc \
    26                     rmd160  e5ee8d786defb0d8f937c8d027466f418c63c97e \
    27                     sha256  30f10f8dd5490d28240d4271bb652b1da7a60b22ed2b9ae28090668de9247c05
     24checksums           md5     43bd6676f0b404326eee2d63be3cdcfe \
     25                    sha1    c84faba04f721d393feccfa0476bfeed9b5b5250 \
     26                    rmd160  de7ad955cb05d481a963aa30423790f3d82efe7b \
     27                    sha256  7de4364fcf5fe42f3bdb514417f1c40d10bbca896abe7e7f2c581c6ea08a2621
    2828
    2929depends_lib         port:popt port:libiconv
    3030
    31 # these come from http://rsync.samba.org/ftp/rsync/rsync-patches-3.0.9.tar.gz
     31# these come from http://rsync.samba.org/ftp/rsync/rsync-patches-3.1.1.tar.gz
    3232# and need to be updated with each release
    3333patchfiles          patch-fileflags.diff \
     
    3939
    4040configure.args      --with-rsyncd-conf=${prefix}/etc/rsyncd.conf
    41 configure.cflags   "-Os -I${prefix}/include"
    4241
    4342pre-configure {
  • trunk/dports/net/rsync/files/patch-crtimes.diff

    r96189 r121462  
    1010    make
    1111
    12 based-on: patch/b3.0.x/fileflags
     12based-on: patch/master/fileflags
    1313diff --git a/compat.c b/compat.c
    1414--- a/compat.c
    1515+++ b/compat.c
    16 @@ -47,6 +47,7 @@ extern int force_change;
     16@@ -48,6 +48,7 @@ extern int force_change;
    1717 extern int protect_args;
    1818 extern int preserve_uid;
     
    2222 extern int preserve_acls;
    2323 extern int preserve_xattrs;
    24 @@ -65,7 +66,7 @@ extern char *iconv_opt;
     24@@ -66,7 +67,7 @@ extern char *iconv_opt;
    2525 #endif
    2626 
     
    3131 int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
    3232 int sender_symlink_iconv = 0;  /* sender should convert symlink content */
    33 @@ -142,6 +143,8 @@ void setup_protocol(int f_out,int f_in)
     33@@ -144,6 +145,8 @@ void setup_protocol(int f_out,int f_in)
    3434                uid_ndx = ++file_extra_cnt;
    3535        if (preserve_gid)
     
    4343--- a/flist.c
    4444+++ b/flist.c
    45 @@ -54,6 +54,7 @@ extern int preserve_specials;
    46  extern int preserve_fileflags;
     45@@ -54,6 +54,7 @@ extern int preserve_fileflags;
    4746 extern int delete_during;
     47 extern int missing_args;
    4848 extern int eol_nulls;
    4949+extern int crtimes_ndx;
     
    5151 extern int implied_dirs;
    5252 extern int ignore_perishable;
    53 @@ -393,7 +394,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
     53@@ -398,7 +399,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
    5454 #endif
    5555                            int ndx, int first_ndx)
     
    6060 #ifdef SUPPORT_FILEFLAGS
    6161        static uint32 fileflags;
    62 @@ -488,6 +489,13 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
    63                 xflags |= XMIT_SAME_TIME;
    64         else
     62@@ -509,6 +510,13 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
    6563                modtime = file->modtime;
     64        if (NSEC_BUMP(file) && protocol_version >= 31)
     65                xflags |= XMIT_MOD_NSEC;
    6666+       if (crtimes_ndx) {
    6767+               time_t file_crtime = f_crtime(file);
     
    7474 #ifdef SUPPORT_HARD_LINKS
    7575        if (tmp_dev != -1) {
    76 @@ -557,6 +565,8 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
    77                 else
    78                         write_int(f, modtime);
     76@@ -593,6 +601,8 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
    7977        }
     78        if (xflags & XMIT_MOD_NSEC)
     79                write_varint(f, F_MOD_NSEC(file));
    8080+       if (crtimes_ndx && !(xflags & XMIT_CRTIME_EQ_MTIME))
    8181+               write_varlong(f, crtime, 4);
     
    8383                write_int(f, to_wire_mode(mode));
    8484 #ifdef SUPPORT_FILEFLAGS
    85 @@ -648,7 +658,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
     85@@ -686,7 +696,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
    8686 
    8787 static struct file_struct *recv_file_entry(int f, struct file_list *flist, int xflags)
     
    9292 #ifdef SUPPORT_FILEFLAGS
    9393        static uint32 fileflags;
    94 @@ -758,6 +768,8 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
    95                                 uid = F_OWNER(first);
    96                         if (preserve_gid)
    97                                 gid = F_GROUP(first);
    98 +                       if (crtimes_ndx)
    99 +                               crtime = f_crtime(first);
    100                         if (preserve_devices && IS_DEVICE(mode)) {
    101                                 uint32 *devp = F_RDEV_P(first);
    102                                 rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
    103 @@ -786,6 +798,19 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
    104                 } else
    105                         modtime = read_int(f);
    106         }
     94@@ -838,6 +848,19 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
     95                modtime_nsec = read_varint(f);
     96        else
     97                modtime_nsec = 0;
    10798+       if (crtimes_ndx) {
    10899+               if (!(xflags & XMIT_CRTIME_EQ_MTIME)) {
     
    121112                mode = from_wire_mode(read_int(f));
    122113 
    123 @@ -946,6 +971,8 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
     114@@ -1015,6 +1038,8 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
    124115                F_GROUP(file) = gid;
    125116                file->flags |= gid_flags;
     
    130121                F_NDX(file) = flist->used + flist->ndx_start;
    131122 
    132 @@ -1324,6 +1351,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
     123@@ -1416,6 +1441,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
    133124                F_GROUP(file) = st.st_gid;
    134125        if (am_generator && st.st_uid == our_uid)
     
    142133--- a/generator.c
    143134+++ b/generator.c
    144 @@ -21,6 +21,7 @@
    145   */
    146  
    147  #include "rsync.h"
    148 +#include "ifuncs.h"
    149  
    150  extern int verbose;
    151  extern int dry_run;
    152 @@ -41,6 +42,7 @@ extern int preserve_xattrs;
     135@@ -40,6 +40,7 @@ extern int preserve_xattrs;
    153136 extern int preserve_links;
    154137 extern int preserve_devices;
     
    158141 extern int preserve_executability;
    159142 extern int preserve_fileflags;
    160 @@ -576,8 +578,15 @@ static void do_delete_pass(void)
     143@@ -384,8 +385,15 @@ static void do_delete_pass(void)
    161144                rprintf(FINFO, "                    \r");
    162145 }
     
    175158 }
    176159 
    177 @@ -635,7 +644,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
     160@@ -443,7 +451,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
    178161 {
    179162        if (S_ISLNK(file->mode)) {
     
    184167 #endif
    185168 #ifdef CAN_CHMOD_SYMLINK
    186 @@ -655,7 +664,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
     169@@ -463,7 +471,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
    187170                        return 0;
    188171 #endif
     
    193176                if (perms_differ(file, sxp))
    194177                        return 0;
    195 @@ -698,6 +707,12 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
     178@@ -506,6 +514,12 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
    196179                 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
    197180                  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
     
    206189                if (S_ISLNK(file->mode)) {
    207190                        ;
    208 @@ -1263,7 +1278,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
    209  
     191@@ -1130,6 +1144,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
    210192 static void list_file_entry(struct file_struct *f)
    211193 {
    212 -       char permbuf[PERMSTRING_SIZE];
    213 +       char permbuf[PERMSTRING_SIZE], crtime_buf[32];
    214         double len;
    215  
    216         if (!F_IS_ACTIVE(f)) {
    217 @@ -1274,19 +1289,24 @@ static void list_file_entry(struct file_struct *f)
    218         permstring(permbuf, f->mode);
    219         len = F_LENGTH(f);
    220  
    221 +       if (crtimes_ndx)
    222 +               snprintf(crtime_buf, sizeof crtime_buf, " %s", timestring(f_crtime(f)));
    223 +       else
    224 +               *crtime_buf = '\0';
    225 +
    226         /* TODO: indicate '+' if the entry has an ACL. */
     194        char permbuf[PERMSTRING_SIZE];
     195+       time_t crtime = crtimes_ndx ? f_crtime(f) : 0;
     196        int64 len;
     197        int colwidth = human_readable ? 14 : 11;
     198 
     199@@ -1145,10 +1160,12 @@ static void list_file_entry(struct file_struct *f)
    227200 
    228201 #ifdef SUPPORT_LINKS
    229202        if (preserve_links && S_ISLNK(f->mode)) {
    230 -               rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
    231 +               rprintf(FINFO, "%s %11.0f %s%s %s -> %s\n",
    232                         permbuf, len, timestring(f->modtime),
    233 -                       f_name(f, NULL), F_SYMLINK(f));
    234 +                       crtime_buf, f_name(f, NULL), F_SYMLINK(f));
     203-               rprintf(FINFO, "%s %*s %s %s -> %s\n",
     204+               rprintf(FINFO, "%s %*s %s%s%s %s -> %s\n",
     205                        permbuf, colwidth, human_num(len),
     206-                       timestring(f->modtime), f_name(f, NULL),
     207-                       F_SYMLINK(f));
     208+                       timestring(f->modtime),
     209+                       crtimes_ndx ? " " : "",
     210+                       crtimes_ndx ? timestring(crtime) : "",
     211+                       f_name(f, NULL), F_SYMLINK(f));
    235212        } else
    236213 #endif
    237         {
    238 -               rprintf(FINFO, "%s %11.0f %s %s\n",
    239 +               rprintf(FINFO, "%s %11.0f %s%s %s\n",
    240                         permbuf, len, timestring(f->modtime),
    241 -                       f_name(f, NULL));
    242 +                       crtime_buf, f_name(f, NULL));
     214        if (missing_args == 2 && f->mode == 0) {
     215@@ -1156,9 +1173,12 @@ static void list_file_entry(struct file_struct *f)
     216                        colwidth + 31, "*missing",
     217                        f_name(f, NULL));
     218        } else {
     219-               rprintf(FINFO, "%s %*s %s %s\n",
     220+               rprintf(FINFO, "%s %*s %s%s%s %s\n",
     221                        permbuf, colwidth, human_num(len),
     222-                       timestring(f->modtime), f_name(f, NULL));
     223+                       timestring(f->modtime),
     224+                       crtimes_ndx ? " " : "",
     225+                       crtimes_ndx ? timestring(crtime) : "",
     226+                       f_name(f, NULL));
    243227        }
    244228 }
    245229 
    246 @@ -1383,6 +1403,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
     230@@ -1250,6 +1270,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
    247231                        return;
    248232                }
     
    251235 
    252236        if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
    253           parent_is_dry_missing:
    254 diff --git a/hlink.c b/hlink.c
    255 --- a/hlink.c
    256 +++ b/hlink.c
    257 @@ -371,6 +371,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
    258                 char cmpbuf[MAXPATHLEN];
    259                 stat_x alt_sx;
    260                 int j = 0;
    261 +               alt_sx.crtime = 0;
    262  #ifdef SUPPORT_ACLS
    263                 alt_sx.acc_acl = alt_sx.def_acl = NULL;
    264  #endif
    265 @@ -499,6 +500,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
    266         } else
    267                 our_name = fname;
    268  
    269 +       prev_sx.crtime = 0;
    270  #ifdef SUPPORT_ACLS
    271         prev_sx.acc_acl = prev_sx.def_acl = NULL;
    272  #endif
     237                int i;
    273238diff --git a/ifuncs.h b/ifuncs.h
    274239--- a/ifuncs.h
    275240+++ b/ifuncs.h
    276 @@ -67,6 +67,28 @@ d_name(struct dirent *di)
    277  #endif
     241@@ -43,6 +43,28 @@ free_xbuf(xbuf *xb)
     242        memset(xb, 0, sizeof (xbuf));
    278243 }
    279244 
     
    301266+
    302267 static inline int
    303  isDigit(const char *ptr)
     268 to_wire_mode(mode_t mode)
    304269 {
    305270diff --git a/log.c b/log.c
    306271--- a/log.c
    307272+++ b/log.c
    308 @@ -661,7 +661,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
     273@@ -723,7 +723,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
    309274                        c[8] = !(iflags & ITEM_REPORT_FFLAGS) ? '.' : 'f';
    310275                        c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
     
    319284--- a/options.c
    320285+++ b/options.c
    321 @@ -60,6 +60,7 @@ int preserve_specials = 0;
     286@@ -62,6 +62,7 @@ int preserve_specials = 0;
    322287 int preserve_uid = 0;
    323288 int preserve_gid = 0;
     
    327292 int cvs_exclude = 0;
    328293 int dry_run = 0;
    329 @@ -361,6 +362,7 @@ void usage(enum logcode F)
     294@@ -718,6 +719,7 @@ void usage(enum logcode F)
     295   rprintf(F,"     --specials              preserve special files\n");
    330296   rprintf(F," -D                          same as --devices --specials\n");
    331297   rprintf(F," -t, --times                 preserve modification times\n");
     298+  rprintf(F," -N, --crtimes               preserve create times (newness)\n");
    332299   rprintf(F," -O, --omit-dir-times        omit directories from --times\n");
    333 +  rprintf(F," -N, --crtimes               preserve create times (newness)\n");
     300   rprintf(F," -J, --omit-link-times       omit symlinks from --times\n");
    334301   rprintf(F,"     --super                 receiver attempts super-user activities\n");
    335  #ifdef SUPPORT_XATTRS
    336    rprintf(F,"     --fake-super            store/recover privileged attrs using xattrs\n");
    337 @@ -507,6 +509,9 @@ static struct poptOption long_options[] = {
     302@@ -885,6 +887,9 @@ static struct poptOption long_options[] = {
    338303   {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
    339304   {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
     
    345310   {"no-omit-dir-times",0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
    346311   {"no-O",             0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
    347 @@ -1810,6 +1815,8 @@ void server_options(char **args, int *argc_p)
     312@@ -2465,6 +2470,8 @@ void server_options(char **args, int *argc_p)
    348313                argstr[x++] = 'D';
    349314        if (preserve_times)
     
    357322--- a/rsync.c
    358323+++ b/rsync.c
    359 @@ -464,6 +464,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    360                                 full_fname(fname));
    361                         return 0;
    362                 }
    363 +               sx2.crtime = 0;
    364  #ifdef SUPPORT_ACLS
    365                 sx2.acc_acl = sx2.def_acl = NULL;
    366  #endif
    367 @@ -505,6 +506,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
     324@@ -581,6 +581,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    368325         || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
    369326         || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
     
    374331        if (!(flags & ATTRS_SKIP_MTIME)
    375332            && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
    376                 int ret = set_modtime(fname, file->modtime, sxp->st.st_mode, ST_FLAGS(sxp->st));
    377 @@ -518,6 +522,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
     333                int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode, ST_FLAGS(sxp->st));
     334@@ -594,6 +597,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    378335                else
    379336                        file->flags |= FLAG_TIME_FAILED;
     
    388345+       }
    389346 
    390         change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
    391         change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
    392 @@ -675,7 +687,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
     347 #ifdef SUPPORT_ACLS
     348        /* It's OK to call set_acl() now, even for a dir, as the generator
     349@@ -710,7 +721,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
    393350        /* Change permissions before putting the file into place. */
    394351        set_file_attrs(fnametmp, file, NULL, fnamecmp,
     
    398355 
    399356        /* move tmp file over real file */
    400         if (verbose > 2)
    401 @@ -706,7 +718,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
     357        if (DEBUG_GTE(RECV, 1))
     358@@ -739,7 +750,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
    402359 
    403360   do_set_file_attrs:
     
    411368--- a/rsync.h
    412369+++ b/rsync.h
    413 @@ -61,6 +61,7 @@
    414  #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
     370@@ -62,7 +62,8 @@
    415371 #define XMIT_HLINK_FIRST (1<<12)       /* protocols 30 - now (HLINKED files only) */
    416372 #define XMIT_IO_ERROR_ENDLIST (1<<12)  /* protocols 31*- now (w/XMIT_EXTENDED_FLAGS) (also protocol 30 w/'f' compat flag) */
    417 +#define XMIT_CRTIME_EQ_MTIME (1<<13)   /* protocols ?? - now */
    418  #define XMIT_SAME_FLAGS (1<<14)                /* protocols ?? - now */
     373 #define XMIT_MOD_NSEC (1<<13)          /* protocols 31 - now */
     374-#define XMIT_SAME_FLAGS (1<<14)                /* protocols ?? - now */
     375+#define XMIT_CRTIME_EQ_MTIME (1<<14)   /* protocols ?? - now */
     376+#define XMIT_SAME_FLAGS (1<<15)                /* protocols ?? - now */
    419377 
    420378 /* These flags are used in the live flist data. */
    421 @@ -162,6 +163,7 @@
     379 
     380@@ -167,6 +168,7 @@
    422381 #define ATTRS_REPORT           (1<<0)
    423382 #define ATTRS_SKIP_MTIME       (1<<1)
     
    427386 #define FULL_FLUSH     1
    428387 #define NORMAL_FLUSH   0
    429 @@ -178,7 +180,7 @@
     388@@ -183,7 +185,7 @@
    430389 #define FNAMECMP_FUZZY         0x83
    431390 
     
    436395 #define ITEM_REPORT_SIZE (1<<2)     /* regular files only */
    437396 #define ITEM_REPORT_TIMEFAIL (1<<2) /* symlinks only */
    438 @@ -677,6 +679,7 @@ extern int file_extra_cnt;
     397@@ -734,6 +736,7 @@ extern int file_extra_cnt;
    439398 extern int inc_recurse;
    440399 extern int uid_ndx;
     
    444403 extern int acls_ndx;
    445404 extern int xattrs_ndx;
    446 @@ -684,6 +687,7 @@ extern int xattrs_ndx;
     405@@ -741,6 +744,7 @@ extern int xattrs_ndx;
    447406 #define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
    448407 #define EXTRA_LEN (sizeof (union file_extras))
     
    452411 #define DIRNODE_EXTRA_CNT 3
    453412 #define SUM_EXTRA_CNT ((MAX_DIGEST_LEN + EXTRA_LEN - 1) / EXTRA_LEN)
    454 @@ -951,6 +955,7 @@ typedef struct {
     413@@ -1022,6 +1026,7 @@ typedef struct {
    455414 
    456415 typedef struct {
     
    463422--- a/rsync.yo
    464423+++ b/rsync.yo
    465 @@ -367,6 +367,7 @@ to the detailed description below for a complete description.  verb(
     424@@ -373,6 +373,7 @@ to the detailed description below for a complete description.  verb(
     425      --specials              preserve special files
    466426  -D                          same as --devices --specials
    467427  -t, --times                 preserve modification times
     428+ -N, --crtimes               preserve create times (newness)
    468429  -O, --omit-dir-times        omit directories from --times
    469 + -N, --crtimes               preserve create times (newness)
     430  -J, --omit-link-times       omit symlinks from --times
    470431      --super                 receiver attempts super-user activities
    471       --fake-super            store/recover privileged attrs using xattrs
    472   -S, --sparse                handle sparse files efficiently
    473 @@ -1105,6 +1106,9 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
    474  the directories on the receiving side, it is a good idea to use bf(-O).
    475  This option is inferred if you use bf(--backup) without bf(--backup-dir).
     432@@ -1201,6 +1202,9 @@ cause the next transfer to behave as if it used bf(-I), causing all files to be
     433 updated (though rsync's delta-transfer algorithm will make the update fairly efficient
     434 if the files haven't actually changed, you're much better off using bf(-t)).
    476435 
    477436+dit(bf(-N, --crtimes)) This tells rsync to set the create times (newness) of
    478437+the destination files to the same value as the source files.
    479438+
    480  dit(bf(--super)) This tells the receiving side to attempt super-user
    481  activities even if the receiving rsync wasn't run by the super-user.  These
    482  activities include: preserving users via the bf(--owner) option, preserving
    483 @@ -1811,7 +1815,7 @@ with older versions of rsync, but that also turns on the output of other
     439 dit(bf(-O, --omit-dir-times)) This tells rsync to omit directories when
     440 it is preserving modification times (see bf(--times)).  If NFS is sharing
     441 the directories on the receiving side, it is a good idea to use bf(-O).
     442@@ -2103,7 +2107,7 @@ with older versions of rsync, but that also turns on the output of other
    484443 verbose messages).
    485444 
     
    490449 other letters represent attributes that may be output if they are being
    491450 modified.
    492 @@ -1870,6 +1874,8 @@ quote(itemization(
     451@@ -2162,6 +2166,8 @@ quote(itemization(
    493452   it() The bf(f) means that the fileflags information changed.
    494453   it() The bf(a) means that the ACL information changed.
     
    502461--- a/syscall.c
    503462+++ b/syscall.c
    504 @@ -37,6 +37,13 @@ extern int force_change;
     463@@ -42,6 +42,13 @@ extern int force_change;
    505464 extern int preserve_perms;
    506465 extern int preserve_executability;
     
    516475        do { \
    517476                if (x) { \
    518 @@ -529,6 +536,36 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
     477@@ -460,6 +467,36 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
    519478 #endif
    520479 }
     
    551510+
    552511 #ifdef HAVE_UTIMENSAT
    553  int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags)
     512 int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec)
    554513 {
    555514diff --git a/testsuite/crtimes.test b/testsuite/crtimes.test
     
    585544--- a/testsuite/rsync.fns
    586545+++ b/testsuite/rsync.fns
    587 @@ -24,9 +24,9 @@ todir="$tmpdir/to"
     546@@ -23,9 +23,9 @@ todir="$tmpdir/to"
    588547 chkdir="$tmpdir/chk"
    589548 
     
    601560--- a/tls.c
    602561+++ b/tls.c
    603 @@ -107,6 +107,8 @@ static int stat_xattr(const char *fname, STRUCT_STAT *fst)
     562@@ -109,6 +109,8 @@ static int stat_xattr(const char *fname, STRUCT_STAT *fst)
    604563 
    605564 #endif
     
    610569 {
    611570        fprintf(stderr, PROGRAM ": %s %s: %s\n",
    612 @@ -114,16 +116,36 @@ static void failed(char const *what, char const *where)
     571@@ -116,16 +118,44 @@ static void failed(char const *what, char const *where)
    613572        exit(1);
    614573 }
    615574 
    616 +static void storetime(char *dest, time_t t, size_t destsize)
     575+static void storetime(char *dest, size_t destsize, time_t t, int nsecs)
    617576+{
    618577+       if (t) {
     578+               int len;
    619579+               struct tm *mt = gmtime(&t);
    620580+
    621 +               snprintf(dest, destsize,
    622 +                       "%04d-%02d-%02d %02d:%02d:%02d ",
     581+               len = snprintf(dest, destsize,
     582+                       "%04d-%02d-%02d %02d:%02d:%02d",
    623583+                       (int)mt->tm_year + 1900,
    624584+                       (int)mt->tm_mon + 1,
     
    627587+                       (int)mt->tm_min,
    628588+                       (int)mt->tm_sec);
    629 +       } else
    630 +               strlcpy(dest, "                    ", destsize);
     589+               if (nsecs >= 0 && len >= 0)
     590+                       snprintf(dest + len, destsize - len, ".%09d", nsecs);
     591+       } else {
     592+               int has_nsecs = nsecs >= 0 ? 1 : 0;
     593+               int len = MIN(19 + 9*has_nsecs, (int)destsize - 1);
     594+               memset(dest, ' ', len);
     595+               dest[len] = '\0';
     596+       }
    631597+}
    632598+
     
    641607+       char crtimebuf[50];
    642608        char linkbuf[4096];
     609+       int nsecs;
    643610 
    644611        if (do_lstat(fname, &buf) < 0)
     
    649616        if (am_root < 0)
    650617                stat_xattr(fname, &buf);
    651 @@ -158,19 +180,11 @@ static void list_file(const char *fname)
     618@@ -159,30 +189,17 @@ static void list_file(const char *fname)
     619        }
    652620 
    653621        permstring(permbuf, buf.st_mode);
    654  
     622-
    655623-       if (buf.st_mtime) {
     624-               int len;
    656625-               mt = gmtime(&buf.st_mtime);
    657626-
    658 -               snprintf(datebuf, sizeof datebuf,
     627-               len = snprintf(datebuf, sizeof datebuf,
    659628-                       "%04d-%02d-%02d %02d:%02d:%02d",
    660629-                       (int)mt->tm_year + 1900,
     
    664633-                       (int)mt->tm_min,
    665634-                       (int)mt->tm_sec);
    666 -       } else
    667 -               strlcpy(datebuf, "                   ", sizeof datebuf);
    668 +       storetime(mtimebuf, buf.st_mtime, sizeof mtimebuf);
     635 #ifdef ST_MTIME_NSEC
     636-               if (nsec_times) {
     637-                       snprintf(datebuf + len, sizeof datebuf - len,
     638-                               ".%09d", (int)buf.ST_MTIME_NSEC);
     639-               }
     640+       if (nsec_times)
     641+               nsecs = (int)buf.ST_MTIME_NSEC;
     642+       else
     643 #endif
     644-       } else {
     645-               int len = MIN(19 + 9*nsec_times, (int)sizeof datebuf - 1);
     646-               memset(datebuf, ' ', len);
     647-               datebuf[len] = '\0';
     648-       }
     649+               nsecs = -1;
     650+       storetime(mtimebuf, sizeof mtimebuf, buf.st_mtime, nsecs);
    669651+       if (display_crtimes)
    670 +               storetime(crtimebuf, crtime, sizeof crtimebuf);
     652+               storetime(crtimebuf, sizeof crtimebuf, crtime, -1);
    671653+       else
    672654+               crtimebuf[0] = '\0';
     
    674656        /* TODO: Perhaps escape special characters in fname? */
    675657 
    676 @@ -181,13 +195,14 @@ static void list_file(const char *fname)
     658@@ -193,13 +210,14 @@ static void list_file(const char *fname)
    677659                    (long)minor(buf.st_rdev));
    678         } else /* NB: use double for size since it might not fit in a long. */
    679                 printf("%12.0f", (double)buf.st_size);
     660        } else
     661                printf("%15s", do_big_num(buf.st_size, 1, NULL));
    680662-       printf(" %6ld.%-6ld %6ld %s %s%s\n",
    681663+       printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
     
    691673   {"link-owner",      'L', POPT_ARG_NONE,   &link_owner, 0, 0, 0 },
    692674 #ifdef SUPPORT_XATTRS
    693 @@ -203,6 +218,7 @@ static void tls_usage(int ret)
     675@@ -218,6 +236,7 @@ static void tls_usage(int ret)
    694676   fprintf(F,"usage: " PROGRAM " [OPTIONS] FILE ...\n");
    695677   fprintf(F,"Trivial file listing program for portably checking rsync\n");
     
    699681   fprintf(F," -L, --link-owner            display the owner+group on a symlink\n");
    700682 #ifdef SUPPORT_XATTRS
    701 diff -up a/proto.h b/proto.h
     683diff -Nurp a/proto.h b/proto.h
    702684--- a/proto.h
    703685+++ b/proto.h
    704 @@ -315,6 +315,8 @@ int do_stat(const char *fname, STRUCT_ST
     686@@ -327,6 +327,8 @@ int do_stat(const char *fname, STRUCT_ST
    705687 int do_lstat(const char *fname, STRUCT_STAT *st);
    706688 int do_fstat(int fd, STRUCT_STAT *st);
     
    708690+time_t get_create_time(const char *path);
    709691+int set_create_time(const char *path, time_t crtime);
    710  int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
    711  int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
    712  int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
    713 diff -up a/rsync.1 b/rsync.1
     692 int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec);
     693 int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec);
     694 int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec);
     695diff -Nurp a/rsync.1 b/rsync.1
    714696--- a/rsync.1
    715697+++ b/rsync.1
    716 @@ -443,6 +443,7 @@ to the detailed description below for a
     698@@ -449,6 +449,7 @@ to the detailed description below for a
     699      \-\-specials              preserve special files
    717700  \-D                          same as \-\-devices \-\-specials
    718701  \-t, \-\-times                 preserve modification times
     702+ \-N, \-\-crtimes               preserve create times (newness)
    719703  \-O, \-\-omit\-dir\-times        omit directories from \-\-times
    720 + \-N, \-\-crtimes               preserve create times (newness)
     704  \-J, \-\-omit\-link\-times       omit symlinks from \-\-times
    721705      \-\-super                 receiver attempts super\-user activities
    722       \-\-fake\-super            store/recover privileged attrs using xattrs
    723   \-S, \-\-sparse                handle sparse files efficiently
    724 @@ -1273,6 +1274,10 @@ it is preserving modification times (see
    725  the directories on the receiving side, it is a good idea to use \fB\-O\fP.
    726  This option is inferred if you use \fB\-\-backup\fP without \fB\-\-backup\-dir\fP.
     706@@ -1379,6 +1380,10 @@ cause the next transfer to behave as if
     707 updated (though rsync\(cq\&s delta\-transfer algorithm will make the update fairly efficient
     708 if the files haven\(cq\&t actually changed, you\(cq\&re much better off using \fB\-t\fP).
    727709 .IP
    728710+.IP "\fB\-N, \-\-crtimes\fP"
     
    730712+the destination files to the same value as the source files.
    731713+.IP
    732  .IP "\fB\-\-super\fP"
    733  This tells the receiving side to attempt super\-user
    734  activities even if the receiving rsync wasn\(cq\&t run by the super\-user.  These
    735 @@ -2067,7 +2072,7 @@ with older versions of rsync, but that a
     714 .IP "\fB\-O, \-\-omit\-dir\-times\fP"
     715 This tells rsync to omit directories when
     716 it is preserving modification times (see \fB\-\-times\fP).  If NFS is sharing
     717@@ -2390,7 +2395,7 @@ with older versions of rsync, but that a
    736718 verbose messages).
    737719 .IP
     
    742724 other letters represent attributes that may be output if they are being
    743725 modified.
    744 @@ -2142,6 +2147,9 @@ The \fBf\fP means that the fileflags inf
     726@@ -2465,6 +2470,9 @@ The \fBf\fP means that the fileflags inf
    745727 The \fBa\fP means that the ACL information changed.
    746728 .IP o
  • trunk/dports/net/rsync/files/patch-fileflags.diff

    r96189 r121462  
    99    make
    1010
    11 based-on: 40afd365cc8ca968fd16e161d24df5b8a8a520cc
     11based-on: 7cb0de6326c915a72253fd103dae93308031ec3f
    1212diff --git a/Makefile.in b/Makefile.in
    1313--- a/Makefile.in
    1414+++ b/Makefile.in
    15 @@ -42,7 +42,7 @@ popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
     15@@ -45,7 +45,7 @@ popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
    1616        popt/popthelp.o popt/poptparse.o
    17  OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
     17 OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) @BUILD_ZLIB@ @BUILD_POPT@
    1818 
    1919-TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
     
    2222 # Programs we must have to run the test cases
    2323 CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
    24 @@ -107,7 +107,7 @@ getgroups$(EXEEXT): getgroups.o
     24@@ -127,7 +127,7 @@ getgroups$(EXEEXT): getgroups.o
    2525 getfsdev$(EXEEXT): getfsdev.o
    2626        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
     
    3434--- a/compat.c
    3535+++ b/compat.c
    36 @@ -43,9 +43,11 @@ extern int checksum_seed;
     36@@ -44,9 +44,11 @@ extern int checksum_seed;
    3737 extern int basis_dir_cnt;
    3838 extern int prune_empty_dirs;
     
    4646 extern int preserve_xattrs;
    4747 extern int need_messages_from_generator;
    48 @@ -63,7 +65,7 @@ extern char *iconv_opt;
     48@@ -64,7 +66,7 @@ extern char *iconv_opt;
    4949 #endif
    5050 
     
    5555 int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
    5656 int sender_symlink_iconv = 0;  /* sender should convert symlink content */
    57 @@ -140,6 +142,8 @@ void setup_protocol(int f_out,int f_in)
     57@@ -142,6 +144,8 @@ void setup_protocol(int f_out,int f_in)
    5858                uid_ndx = ++file_extra_cnt;
    5959        if (preserve_gid)
     
    6767--- a/configure.ac
    6868+++ b/configure.ac
    69 @@ -569,6 +569,7 @@ AC_FUNC_UTIME_NULL
     69@@ -597,6 +597,7 @@ AC_FUNC_UTIME_NULL
    7070 AC_FUNC_ALLOCA
    7171 AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
     
    7575     strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
    7676     setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
     77diff --git a/delete.c b/delete.c
     78--- a/delete.c
     79+++ b/delete.c
     80@@ -25,6 +25,7 @@
     81 extern int am_root;
     82 extern int make_backups;
     83 extern int max_delete;
     84+extern int force_change;
     85 extern char *backup_dir;
     86 extern char *backup_suffix;
     87 extern int backup_suffix_len;
     88@@ -97,8 +98,12 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
     89                }
     90 
     91                strlcpy(p, fp->basename, remainder);
     92+#ifdef SUPPORT_FORCE_CHANGE
     93+               if (force_change)
     94+                       make_mutable(fname, fp->mode, F_FFLAGS(fp), force_change);
     95+#endif
     96                if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)
     97-                       do_chmod(fname, fp->mode | S_IWUSR);
     98+                       do_chmod(fname, fp->mode | S_IWUSR, NO_FFLAGS);
     99                /* Save stack by recursing to ourself directly. */
     100                if (S_ISDIR(fp->mode)) {
     101                        if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
     102@@ -139,11 +144,18 @@ enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
     103        }
     104 
     105        if (flags & DEL_NO_UID_WRITE)
     106-               do_chmod(fbuf, mode | S_IWUSR);
     107+               do_chmod(fbuf, mode | S_IWUSR, NO_FFLAGS);
     108 
     109        if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
     110                /* This only happens on the first call to delete_item() since
     111                 * delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */
     112+#ifdef SUPPORT_FORCE_CHANGE
     113+               if (force_change) {
     114+                       STRUCT_STAT st;
     115+                       if (x_lstat(fbuf, &st, NULL) == 0)
     116+                               make_mutable(fbuf, st.st_mode, st.st_flags, force_change);
     117+               }
     118+#endif
     119                ignore_perishable = 1;
     120                /* If DEL_RECURSE is not set, this just reports emptiness. */
     121                ret = delete_dir_contents(fbuf, flags);
    77122diff --git a/flist.c b/flist.c
    78123--- a/flist.c
    79124+++ b/flist.c
    80 @@ -51,6 +51,7 @@ extern int preserve_links;
     125@@ -50,6 +50,7 @@ extern int preserve_links;
    81126 extern int preserve_hard_links;
    82127 extern int preserve_devices;
     
    84129+extern int preserve_fileflags;
    85130 extern int delete_during;
     131 extern int missing_args;
    86132 extern int eol_nulls;
    87  extern int relative_paths;
    88 @@ -394,6 +395,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
     133@@ -399,6 +400,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
    89134 {
    90135        static time_t modtime;
     
    96141        static int64 dev;
    97142 #endif
    98 @@ -423,6 +427,14 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
     143@@ -442,6 +446,14 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
    99144                xflags |= XMIT_SAME_MODE;
    100145        else
     
    111156        if (preserve_devices && IS_DEVICE(mode)) {
    112157                if (protocol_version < 28) {
    113 @@ -547,6 +559,10 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
    114         }
     158@@ -583,6 +595,10 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
     159                write_varint(f, F_MOD_NSEC(file));
    115160        if (!(xflags & XMIT_SAME_MODE))
    116161                write_int(f, to_wire_mode(mode));
     
    122167                if (protocol_version < 30)
    123168                        write_int(f, uid);
    124 @@ -634,6 +650,9 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
     169@@ -672,6 +688,9 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
    125170 {
    126171        static int64 modtime;
     
    132177        static int64 dev;
    133178 #endif
    134 @@ -731,6 +750,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
    135                         file_length = F_LENGTH(first);
     179@@ -779,6 +798,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
    136180                        modtime = first->modtime;
     181                        modtime_nsec = F_MOD_NSEC(first);
    137182                        mode = first->mode;
    138183+#ifdef SUPPORT_FILEFLAGS
     
    143188                                uid = F_OWNER(first);
    144189                        if (preserve_gid)
    145 @@ -768,6 +791,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
    146  
    147         if (chmod_modes && !S_ISLNK(mode))
     190@@ -820,6 +843,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
     191 
     192        if (chmod_modes && !S_ISLNK(mode) && mode)
    148193                mode = tweak_mode(mode, chmod_modes);
    149194+#ifdef SUPPORT_FILEFLAGS
     
    154199        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
    155200                if (protocol_version < 30)
    156 @@ -909,6 +936,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
     201@@ -978,6 +1005,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x
    157202        }
    158203 #endif
    159204        file->mode = mode;
    160205+#ifdef SUPPORT_FILEFLAGS
    161 +       if (fileflags_ndx) /* check the ndx for force_change w/o preserve_fileflags */
     206+       if (preserve_fileflags)
    162207+               F_FFLAGS(file) = fileflags;
    163208+#endif
     
    165210                F_OWNER(file) = uid;
    166211        if (preserve_gid) {
    167 @@ -1283,6 +1314,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
     212@@ -1375,6 +1406,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
    168213        }
    169214 #endif
     
    176221                F_OWNER(file) = st.st_uid;
    177222        if (preserve_gid)
    178 @@ -1429,6 +1464,9 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
    179  #ifdef SUPPORT_XATTRS
    180                 if (preserve_xattrs) {
    181                         sx.st.st_mode = file->mode;
    182 +#ifdef SUPPORT_FILEFLAGS
    183 +                       sx.st.st_flags = preserve_fileflags ? F_FFLAGS(file) : 0;
    184 +#endif
    185                         sx.xattr = NULL;
    186                         if (get_xattr(fname, &sx) < 0) {
    187                                 io_error |= IOERR_GENERAL;
    188223diff --git a/generator.c b/generator.c
    189224--- a/generator.c
    190225+++ b/generator.c
    191 @@ -35,6 +35,7 @@ extern int do_progress;
    192  extern int relative_paths;
    193  extern int implied_dirs;
    194  extern int keep_dirlinks;
    195 +extern int force_change;
    196  extern int preserve_acls;
    197  extern int preserve_xattrs;
    198  extern int preserve_links;
    199 @@ -42,6 +43,7 @@ extern int preserve_devices;
     226@@ -42,8 +42,10 @@ extern int preserve_devices;
    200227 extern int preserve_specials;
    201228 extern int preserve_hard_links;
     
    204231 extern int preserve_perms;
    205232 extern int preserve_times;
     233+extern int force_change;
    206234 extern int delete_mode;
    207 @@ -164,11 +166,15 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
    208         }
    209  
    210         if (flags & DEL_NO_UID_WRITE)
    211 -               do_chmod(fbuf, mode | S_IWUSR);
    212 +               do_chmod(fbuf, mode | S_IWUSR, NO_FFLAGS);
    213  
    214         if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
    215                 /* This only happens on the first call to delete_item() since
    216                  * delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */
    217 +#ifdef SUPPORT_FORCE_CHANGE
    218 +               if (force_change)
    219 +                       make_mutable(fbuf, NULL, NO_FFLAGS, force_change);
    220 +#endif
    221                 ignore_perishable = 1;
    222                 /* If DEL_RECURSE is not set, this just reports emptiness. */
    223                 ret = delete_dir_contents(fbuf, flags);
    224 @@ -285,8 +291,14 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
    225                 }
    226  
    227                 strlcpy(p, fp->basename, remainder);
    228 +#ifdef SUPPORT_FORCE_CHANGE
    229 +               if (force_change) {
    230 +                       mode_t mode = fp->mode;
    231 +                       make_mutable(fname, &mode, F_FFLAGS(fp), force_change);
    232 +               }
    233 +#endif
    234                 if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)
    235 -                       do_chmod(fname, fp->mode | S_IWUSR);
    236 +                       do_chmod(fname, fp->mode | S_IWUSR, NO_FFLAGS);
    237                 /* Save stack by recursing to ourself directly. */
    238                 if (S_ISDIR(fp->mode)) {
    239                         if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
    240 @@ -647,6 +659,10 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
     235 extern int delete_before;
     236 extern int delete_during;
     237@@ -465,6 +467,10 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
    241238                        return 0;
    242239                if (perms_differ(file, sxp))
     
    249246                        return 0;
    250247 #ifdef SUPPORT_ACLS
    251 @@ -698,6 +714,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
     248@@ -516,6 +522,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
    252249                if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
    253250                    && sxp->st.st_gid != (gid_t)F_GROUP(file))
     
    261258                if (preserve_acls && !S_ISLNK(file->mode)) {
    262259                        if (!ACL_READY(*sxp))
    263 @@ -1491,6 +1512,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
     260@@ -1395,6 +1406,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
    264261                        file->mode = dest_mode(file->mode, sx.st.st_mode,
    265262                                               dflt_perms, statret == 0);
     
    272269                        int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
    273270                                              itemizing, code);
    274 @@ -1535,10 +1560,17 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
     271@@ -1439,10 +1454,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
    275272                 * readable and writable permissions during the time we are
    276273                 * putting files within them.  This is then restored to the
    277274                 * former permissions after the transfer is done. */
    278275+#ifdef SUPPORT_FORCE_CHANGE
    279 +               if (force_change && F_FFLAGS(file) & force_change) {
    280 +                       mode_t mode = file->mode;
    281 +                       if (make_mutable(fname, &mode, F_FFLAGS(file), force_change))
    282 +                               need_retouch_dir_perms = 1;
    283 +               }
     276+               if (force_change && F_FFLAGS(file) & force_change
     277+                && make_mutable(fname, file->mode, F_FFLAGS(file), force_change))
     278+                       need_retouch_dir_perms = 1;
    284279+#endif
    285280 #ifdef HAVE_CHMOD
     
    291286                                        "failed to modify permissions on %s",
    292287                                        full_fname(fname));
    293 @@ -1573,6 +1605,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
     288@@ -1477,6 +1497,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
    294289                file->mode = dest_mode(file->mode, sx.st.st_mode, dflt_perms,
    295290                                       exists);
     
    302297 #ifdef SUPPORT_HARD_LINKS
    303298        if (preserve_hard_links && F_HLINK_NOT_FIRST(file)
    304 @@ -2116,13 +2152,17 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
     299@@ -2045,13 +2069,17 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
    305300                        continue;
    306301                fname = f_name(file, NULL);
     
    312307                        if (link_stat(fname, &st, 0) == 0
    313308                         && cmp_time(st.st_mtime, file->modtime) != 0)
    314 -                               set_modtime(fname, file->modtime, file->mode);
    315 +                               set_modtime(fname, file->modtime, file->mode, 0);
     309-                               set_modtime(fname, file->modtime, F_MOD_NSEC(file), file->mode);
     310+                               set_modtime(fname, file->modtime, F_MOD_NSEC(file), file->mode, 0);
    316311                }
    317312+#ifdef SUPPORT_FORCE_CHANGE
     
    321316                if (counter >= loopchk_limit) {
    322317                        if (allowed_lull)
    323                                 maybe_send_keepalive();
     318                                maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH);
    324319diff --git a/log.c b/log.c
    325320--- a/log.c
    326321+++ b/log.c
    327 @@ -658,7 +658,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
     322@@ -720,7 +720,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
    328323                        c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
    329324                        c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
     
    345340+#endif
    346341 
    347  extern int verbose;
    348342 extern int dry_run;
    349 @@ -51,6 +54,7 @@ extern int protocol_version;
     343 extern int list_only;
     344@@ -51,6 +54,7 @@ extern int copy_unsafe_links;
     345 extern int keep_dirlinks;
     346 extern int preserve_hard_links;
     347 extern int protocol_version;
     348+extern int force_change;
    350349 extern int file_total;
    351350 extern int recurse;
    352351 extern int xfer_dirs;
    353 +extern int force_change;
    354  extern int protect_args;
    355  extern int relative_paths;
    356  extern int sanitize_paths;
    357 @@ -753,6 +757,22 @@ static int do_recv(int f_in, int f_out, char *local_name)
     352@@ -839,6 +843,22 @@ static int do_recv(int f_in, int f_out, char *local_name)
    358353         * points to an identical file won't be replaced by the referent. */
    359354        copy_links = copy_dirlinks = copy_unsafe_links = 0;
     
    381376--- a/options.c
    382377+++ b/options.c
    383 @@ -53,6 +53,7 @@ int preserve_hard_links = 0;
     378@@ -55,6 +55,7 @@ int preserve_hard_links = 0;
    384379 int preserve_acls = 0;
    385380 int preserve_xattrs = 0;
     
    389384 int preserve_devices = 0;
    390385 int preserve_specials = 0;
    391 @@ -84,6 +85,7 @@ int implied_dirs = 1;
    392  int numeric_ids = 0;
     386@@ -89,6 +90,7 @@ int numeric_ids = 0;
     387 int msgs2stderr = 0;
    393388 int allow_8bit_chars = 0;
    394389 int force_delete = 0;
     
    397392 int prune_empty_dirs = 0;
    398393 int use_qsort = 0;
    399 @@ -223,6 +225,7 @@ static void print_rsync_version(enum logcode f)
     394@@ -574,6 +576,7 @@ static void print_rsync_version(enum logcode f)
    400395        char const *links = "no ";
    401396        char const *iconv = "no ";
     
    405400 
    406401 #if SUBPROTOCOL_VERSION != 0
    407 @@ -256,6 +259,9 @@ static void print_rsync_version(enum logcode f)
     402@@ -610,6 +613,9 @@ static void print_rsync_version(enum logcode f)
    408403 #ifdef CAN_SET_SYMLINK_TIMES
    409404        symtimes = "";
     
    415410        rprintf(f, "%s  version %s  protocol version %d%s\n",
    416411                RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
    417 @@ -269,8 +275,8 @@ static void print_rsync_version(enum logcode f)
     412@@ -623,8 +629,8 @@ static void print_rsync_version(enum logcode f)
    418413                (int)(sizeof (int64) * 8));
    419414        rprintf(f, "    %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
    420415                got_socketpair, hardlinks, links, ipv6, have_inplace);
    421 -       rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes\n",
    422 -               have_inplace, acls, xattrs, iconv, symtimes);
    423 +       rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sfile-flags\n",
    424 +               have_inplace, acls, xattrs, iconv, symtimes, fileflags);
     416-       rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sprealloc\n",
     417-               have_inplace, acls, xattrs, iconv, symtimes, prealloc);
     418+       rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sprealloc, %sfile-flags\n",
     419+               have_inplace, acls, xattrs, iconv, symtimes, prealloc, fileflags);
    425420 
    426421 #ifdef MAINTAINER_MODE
    427422        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
    428 @@ -337,6 +343,9 @@ void usage(enum logcode F)
     423@@ -695,6 +701,9 @@ void usage(enum logcode F)
    429424   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
    430425   rprintf(F," -H, --hard-links            preserve hard links\n");
     
    436431   rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
    437432 #ifdef SUPPORT_ACLS
    438 @@ -374,7 +383,12 @@ void usage(enum logcode F)
    439    rprintf(F,"     --delete-after          receiver deletes after transfer, not during\n");
    440    rprintf(F,"     --delete-excluded       also delete excluded files from destination dirs\n");
     433@@ -740,7 +749,12 @@ void usage(enum logcode F)
     434   rprintf(F,"     --ignore-missing-args   ignore missing source args without error\n");
     435   rprintf(F,"     --delete-missing-args   delete missing source args from destination\n");
    441436   rprintf(F,"     --ignore-errors         delete even if there are I/O errors\n");
    442437-  rprintf(F,"     --force                 force deletion of directories even if not empty\n");
     
    450445   rprintf(F,"     --max-size=SIZE         don't transfer any file larger than SIZE\n");
    451446   rprintf(F,"     --min-size=SIZE         don't transfer any file smaller than SIZE\n");
    452 @@ -479,6 +493,10 @@ static struct poptOption long_options[] = {
     447@@ -857,6 +871,10 @@ static struct poptOption long_options[] = {
    453448   {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
    454449   {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
     
    461456   {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
    462457   {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
    463 @@ -557,6 +575,14 @@ static struct poptOption long_options[] = {
     458@@ -943,6 +961,14 @@ static struct poptOption long_options[] = {
    464459   {"remove-source-files",0,POPT_ARG_VAL,    &remove_source_files, 1, 0, 0 },
    465460   {"force",            0,  POPT_ARG_VAL,    &force_delete, 1, 0, 0 },
     
    476471   {"no-ignore-errors", 0,  POPT_ARG_VAL,    &ignore_errors, 0, 0, 0 },
    477472   {"max-delete",       0,  POPT_ARG_INT,    &max_delete, 0, 0, 0 },
    478 @@ -1879,6 +1905,9 @@ void server_options(char **args, int *argc_p)
     473@@ -2537,6 +2563,9 @@ void server_options(char **args, int *argc_p)
    479474        if (xfer_dirs && !recurse && delete_mode && am_sender)
    480475                args[ac++] = "--no-r";
     
    486481                if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0)
    487482                        goto oom;
    488 @@ -1966,6 +1995,16 @@ void server_options(char **args, int *argc_p)
     483@@ -2624,6 +2653,16 @@ void server_options(char **args, int *argc_p)
    489484                        args[ac++] = "--delete-excluded";
    490485                if (force_delete)
     
    506501--- a/rsync.c
    507502+++ b/rsync.c
    508 @@ -29,9 +29,11 @@
    509  
    510  extern int verbose;
    511  extern int dry_run;
    512 +extern int force_change;
     503@@ -31,6 +31,7 @@ extern int dry_run;
    513504 extern int preserve_acls;
    514505 extern int preserve_xattrs;
     
    518509 extern int preserve_times;
    519510 extern int am_root;
    520 @@ -374,6 +376,74 @@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
     511@@ -452,6 +453,39 @@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
    521512        return new_mode;
    522513 }
     
    528519+       if (do_chflags(fname, fileflags) != 0) {
    529520+               rsyserr(FERROR_XFER, errno,
    530 +                       "failed to set fileflags (%x) on %s",
    531 +                       fileflags, full_fname(fname));
     521+                       "failed to set file flags on %s",
     522+                       full_fname(fname));
    532523+               return 0;
    533524+       }
     
    536527+}
    537528+
    538 +/* Remove immutable flags from an object, so it can be altered/removed.
    539 + * Returns the fileflags if flags were removed, otherwise 0.  If the
    540 + * fileflags value is NO_FFLAGS, we will stat the fname to figure out
    541 + * what the flags are, and return the mode via *mode_ptr (if non-NULL). */
    542 +uint32 make_mutable(const char *fname, mode_t *mode_ptr, uint32 fileflags, uint32 iflags)
     529+/* Remove immutable flags from an object, so it can be altered/removed. */
     530+int make_mutable(const char *fname, mode_t mode, uint32 fileflags, uint32 iflags)
    543531+{
    544 +       if (fileflags == NO_FFLAGS) {
    545 +               STRUCT_STAT st;
    546 +               if (x_lstat(fname, &st, NULL) < 0)
    547 +                       return 0;
    548 +               fileflags = st.st_flags;
    549 +               if (mode_ptr)
    550 +                       *mode_ptr = st.st_mode;
    551 +               else
    552 +                       mode_ptr = &st.st_mode;
    553 +       }
    554 +
    555 +       if ((mode_ptr && S_ISLNK(*mode_ptr)) || !(fileflags & iflags))
     532+       if (S_ISLNK(mode) || !(fileflags & iflags))
    556533+               return 0;
    557 +
    558534+       if (!set_fileflags(fname, fileflags & ~iflags))
    559 +               return 0;
    560 +
    561 +       return fileflags;
     535+               return -1;
     536+       return 1;
    562537+}
    563538+
     
    565540+int undo_make_mutable(const char *fname, uint32 fileflags)
    566541+{
    567 +       if (!set_fileflags(fname, fileflags)) {
    568 +               rsyserr(FINFO, errno, "failed to relock %s", full_fname(fname));
     542+       if (!set_fileflags(fname, fileflags))
    569543+               return -1;
    570 +       }
    571544+       return 1;
    572 +}
    573 +
    574 +/* This returns the st_flags value if the parent directory was made mutable, otherwise 0.
    575 + * It stores the parent directory path into parent_dirbuf. */
    576 +int make_parentdir_mutable(const char *fname, uint32 iflags, char *parent_dirbuf, int parent_dirbuf_size)
    577 +{
    578 +       char *slash = strrchr(fname, '/');
    579 +
    580 +       if (slash) {
    581 +               int len = slash - fname;
    582 +               if (len >= parent_dirbuf_size)
    583 +                       return 0;
    584 +               strlcpy(parent_dirbuf, fname, len+1);
    585 +       } else
    586 +               strlcpy(parent_dirbuf, ".", parent_dirbuf_size);
    587 +
    588 +       return make_mutable(parent_dirbuf, NULL, NO_FFLAGS, iflags);
    589545+}
    590546+#endif
     
    593549                   const char *fnamecmp, int flags)
    594550 {
    595 @@ -382,6 +452,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    596         int change_uid, change_gid;
    597         mode_t new_mode = file->mode;
    598         int inherit;
    599 +#ifdef SUPPORT_FORCE_CHANGE
    600 +       int became_mutable = 0;
    601 +#endif
    602  
    603         if (!sxp) {
    604                 if (dry_run)
    605 @@ -411,6 +484,11 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    606         if (daemon_chmod_modes && !S_ISLNK(new_mode))
    607                 new_mode = tweak_mode(new_mode, daemon_chmod_modes);
    608  
    609 +#ifdef SUPPORT_FORCE_CHANGE
    610 +       if (force_change)
    611 +               became_mutable = make_mutable(fname, &sxp->st.st_mode, sxp->st.st_flags, force_change);
    612 +#endif
    613 +
    614  #ifdef SUPPORT_ACLS
    615         if (preserve_acls && !S_ISLNK(file->mode) && !ACL_READY(*sxp))
    616                 get_acl(fname, sxp);
    617 @@ -429,7 +507,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    618                 flags |= ATTRS_SKIP_MTIME;
    619         if (!(flags & ATTRS_SKIP_MTIME)
    620             && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
    621 -               int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
    622 +               int ret = set_modtime(fname, file->modtime, sxp->st.st_mode, ST_FLAGS(sxp->st));
    623                 if (ret < 0) {
    624                         rsyserr(FERROR_XFER, errno, "failed to set times on %s",
    625                                 full_fname(fname));
    626 @@ -465,7 +543,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
     551@@ -513,7 +547,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    627552                if (am_root >= 0) {
    628553                        uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid;
     
    633558                                 * or gid unless have the privilege. */
    634559                                rsyserr(FERROR_XFER, errno, "%s %s failed",
    635 @@ -503,7 +581,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
     560@@ -549,7 +583,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
     561                flags |= ATTRS_SKIP_MTIME;
     562        if (!(flags & ATTRS_SKIP_MTIME)
     563            && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
     564-               int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode);
     565+               int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode, ST_FLAGS(sxp->st));
     566                if (ret < 0) {
     567                        rsyserr(FERROR_XFER, errno, "failed to set times on %s",
     568                                full_fname(fname));
     569@@ -576,7 +610,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    636570 
    637571 #ifdef HAVE_CHMOD
     
    642576                        rsyserr(FERROR_XFER, errno,
    643577                                "failed to set permissions on %s",
    644 @@ -515,6 +593,24 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
     578@@ -588,6 +622,19 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    645579        }
    646580 #endif
    647581 
    648 +#ifdef SUPPORT_FORCE_CHANGE
    649 +       if (became_mutable)
    650 +               undo_make_mutable(fname, sxp->st.st_flags);
    651 +#endif
    652 +
    653582+#ifdef SUPPORT_FILEFLAGS
    654583+       if (preserve_fileflags && !S_ISLNK(sxp->st.st_mode)
     
    664593+#endif
    665594+
    666         if (verbose > 1 && flags & ATTRS_REPORT) {
     595        if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) {
    667596                if (updated)
    668597                        rprintf(FCLIENT, "%s\n", fname);
    669 @@ -578,7 +674,8 @@ int finish_transfer(const char *fname, const char *fnametmp,
     598@@ -662,7 +709,8 @@ int finish_transfer(const char *fname, const char *fnametmp,
    670599 
    671600        /* Change permissions before putting the file into place. */
     
    676605 
    677606        /* move tmp file over real file */
    678         if (verbose > 2)
    679 @@ -597,6 +694,10 @@ int finish_transfer(const char *fname, const char *fnametmp,
     607        if (DEBUG_GTE(RECV, 1))
     608@@ -679,6 +727,10 @@ int finish_transfer(const char *fname, const char *fnametmp,
    680609        }
    681610        if (ret == 0) {
     
    691620--- a/rsync.h
    692621+++ b/rsync.h
    693 @@ -61,6 +61,7 @@
    694  #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
     622@@ -62,6 +62,7 @@
    695623 #define XMIT_HLINK_FIRST (1<<12)       /* protocols 30 - now (HLINKED files only) */
    696624 #define XMIT_IO_ERROR_ENDLIST (1<<12)  /* protocols 31*- now (w/XMIT_EXTENDED_FLAGS) (also protocol 30 w/'f' compat flag) */
     625 #define XMIT_MOD_NSEC (1<<13)          /* protocols 31 - now */
    697626+#define XMIT_SAME_FLAGS (1<<14)                /* protocols ?? - now */
    698627 
    699628 /* These flags are used in the live flist data. */
    700629 
    701 @@ -160,6 +161,7 @@
     630@@ -165,6 +166,7 @@
    702631 
    703632 #define ATTRS_REPORT           (1<<0)
     
    707636 #define FULL_FLUSH     1
    708637 #define NORMAL_FLUSH   0
    709 @@ -186,6 +188,7 @@
     638@@ -191,6 +193,7 @@
    710639 #define ITEM_REPORT_GROUP (1<<6)
    711640 #define ITEM_REPORT_ACL (1<<7)
     
    715644 #define ITEM_XNAME_FOLLOWS (1<<12)
    716645 #define ITEM_IS_NEW (1<<13)
    717 @@ -482,6 +485,28 @@ typedef unsigned int size_t;
     646@@ -522,6 +525,28 @@ typedef unsigned int size_t;
    718647 #endif
    719648 #endif
     
    744673  * If some code depends on 32-bit truncation, it will need to
    745674  * take special action in a "#if SIZEOF_INT32 > 4" section. */
    746 @@ -652,6 +677,7 @@ extern int file_extra_cnt;
     675@@ -709,6 +734,7 @@ extern int file_extra_cnt;
    747676 extern int inc_recurse;
    748677 extern int uid_ndx;
     
    752681 extern int xattrs_ndx;
    753682 
    754 @@ -689,6 +715,11 @@ extern int xattrs_ndx;
     683@@ -750,6 +776,11 @@ extern int xattrs_ndx;
    755684 /* When the associated option is on, all entries will have these present: */
    756685 #define F_OWNER(f) REQ_EXTRA(f, uid_ndx)->unum
     
    767696--- a/rsync.yo
    768697+++ b/rsync.yo
    769 @@ -355,6 +355,7 @@ to the detailed description below for a complete description.  verb(
     698@@ -362,6 +362,7 @@ to the detailed description below for a complete description.  verb(
    770699  -K, --keep-dirlinks         treat symlinked dir on receiver as dir
    771700  -H, --hard-links            preserve hard links
     
    775704      --chmod=CHMOD           affect file and/or directory permissions
    776705  -A, --acls                  preserve ACLs (implies -p)
    777 @@ -386,7 +387,10 @@ to the detailed description below for a complete description.  verb(
    778       --delete-after          receiver deletes after transfer, not during
    779       --delete-excluded       also delete excluded files from dest dirs
     706@@ -397,7 +398,10 @@ to the detailed description below for a complete description.  verb(
     707      --ignore-missing-args   ignore missing source args without error
     708      --delete-missing-args   delete missing source args from destination
    780709      --ignore-errors         delete even if there are I/O errors
    781710-     --force                 force deletion of dirs even if not empty
     
    787716      --max-size=SIZE         don't transfer any file larger than SIZE
    788717      --min-size=SIZE         don't transfer any file smaller than SIZE
    789 @@ -566,7 +570,8 @@ specified, in which case bf(-r) is not implied.
     718@@ -644,7 +648,8 @@ specified, in which case bf(-r) is not implied.
    790719 
    791720 Note that bf(-a) bf(does not preserve hardlinks), because
     
    797726 dit(--no-OPTION) You may turn off one or more implied options by prefixing
    798727 the option name with "no-".  Not all options may be prefixed with a "no-":
    799 @@ -846,7 +851,7 @@ they would be using bf(--copy-links).
     728@@ -943,7 +948,7 @@ they would be using bf(--copy-links).
    800729 Without this option, if the sending side has replaced a directory with a
    801730 symlink to a directory, the receiving side will delete anything that is in
     
    806735 See also bf(--keep-dirlinks) for an analogous option for the receiving
    807736 side.
    808 @@ -1009,6 +1014,29 @@ Note that this option does not copy rsyncs special xattr values (e.g. those
     737@@ -1106,6 +1111,29 @@ Note that this option does not copy rsyncs special xattr values (e.g. those
    809738 used by bf(--fake-super)) unless you repeat the option (e.g. -XX).  This
    810739 "copy all xattrs" mode cannot be used with bf(--fake-super).
     
    831760+flags on files and directories that are being updated or deleted on the
    832761+receiving side.  It does not try to affect user flags.  This option overrides
    833 +bf(--force-change) and bf(--force-schange).
     762+bf(--force-change) and bf(--force-uchange).
    834763+
    835764 dit(bf(--chmod)) This option tells rsync to apply one or more
    836765 comma-separated "chmod" modes to the permission of the files in the
    837766 transfer.  The resulting value is treated as though it were the permissions
    838 @@ -1289,12 +1317,13 @@ See bf(--delete) (which is implied) for more details on file-deletion.
     767@@ -1435,12 +1463,13 @@ display as a "*missing" entry in the bf(--list-only) output.
    839768 dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files
    840769 even when there are I/O errors.
     
    853782 
    854783 dit(bf(--max-delete=NUM)) This tells rsync not to delete more than NUM
    855 @@ -1782,7 +1811,7 @@ with older versions of rsync, but that also turns on the output of other
     784@@ -2074,7 +2103,7 @@ with older versions of rsync, but that also turns on the output of other
    856785 verbose messages).
    857786 
     
    862791 other letters represent attributes that may be output if they are being
    863792 modified.
    864 @@ -1838,7 +1867,7 @@ quote(itemization(
     793@@ -2130,7 +2159,7 @@ quote(itemization(
    865794   sender's value (requires bf(--owner) and super-user privileges).
    866795   it() A bf(g) means the group is different and is being updated to the
     
    874803--- a/syscall.c
    875804+++ b/syscall.c
    876 @@ -33,6 +33,7 @@ extern int dry_run;
    877  extern int am_root;
     805@@ -38,6 +38,7 @@ extern int am_root;
     806 extern int am_sender;
    878807 extern int read_only;
    879808 extern int list_only;
     
    882811 extern int preserve_executability;
    883812 
    884 @@ -50,14 +51,56 @@ int do_unlink(const char *fname)
     813@@ -55,7 +56,23 @@ int do_unlink(const char *fname)
    885814 {
    886815        if (dry_run) return 0;
     
    889818+       if (unlink(fname) == 0)
    890819+               return 0;
    891 +
    892 +#ifdef SUPPORT_FORCE_CHANGE
    893 +       if (force_change && (errno == EPERM || errno == EACCES)) {
    894 +               char parent[MAXPATHLEN];
    895 +               int parent_flags;
    896 +               int saved_errno = errno;
    897 +               int file_flags = make_mutable(fname, NULL, NO_FFLAGS, force_change);
    898 +               if (file_flags && unlink(fname) == 0)
    899 +                       return 0;
    900 +               parent_flags = make_parentdir_mutable(fname, force_change, parent, sizeof parent);
    901 +               if (parent_flags) {
    902 +                       int ret = unlink(fname);
    903 +                       undo_make_mutable(parent, parent_flags);
    904 +                       if (ret == 0)
     820+#ifdef SUPPORT_FORCE_CHANGE
     821+       if (force_change && errno == EPERM) {
     822+               STRUCT_STAT st;
     823+
     824+               if (x_lstat(fname, &st, NULL) == 0
     825+                && make_mutable(fname, st.st_mode, st.st_flags, force_change) > 0) {
     826+                       if (unlink(fname) == 0)
    905827+                               return 0;
     828+                       undo_make_mutable(fname, st.st_flags);
    906829+               }
    907 +               if (file_flags)
    908 +                       undo_make_mutable(fname, file_flags);
    909 +               errno = saved_errno;
     830+               /* TODO: handle immutable directories */
     831+               errno = EPERM;
    910832+       }
    911833+#endif
    912 +
    913834+       return -1;
    914835 }
    915836 
    916  int do_symlink(const char *fname1, const char *fname2)
    917  {
    918         if (dry_run) return 0;
    919         RETURN_ERROR_IF_RO_OR_LO;
    920 -       return symlink(fname1, fname2);
    921 +       if (symlink(fname1, fname2) == 0)
    922 +               return 0;
    923 +
    924 +#ifdef SUPPORT_FORCE_CHANGE
    925 +       if (force_change && (errno == EPERM || errno == EACCES)) {
    926 +               char parent[MAXPATHLEN];
    927 +               int saved_errno = errno;
    928 +               int parent_flags = make_parentdir_mutable(fname2, force_change, parent, sizeof parent);
    929 +               if (parent_flags) {
    930 +                       int ret = symlink(fname1, fname2);
    931 +                       undo_make_mutable(parent, parent_flags);
    932 +                       if (ret == 0)
    933 +                               return 0;
    934 +               }
    935 +               errno = saved_errno;
    936 +       }
    937 +#endif
    938 +
    939 +       return -1;
    940  }
    941  
    942  #ifdef HAVE_LINK
    943 @@ -65,18 +108,55 @@ int do_link(const char *fname1, const char *fname2)
    944  {
    945         if (dry_run) return 0;
    946         RETURN_ERROR_IF_RO_OR_LO;
    947 -       return link(fname1, fname2);
    948 +       if (link(fname1, fname2) == 0)
    949 +               return 0;
    950 +
    951 +#ifdef SUPPORT_FORCE_CHANGE
    952 +       if (force_change && (errno == EPERM || errno == EACCES)) {
    953 +               char parent[MAXPATHLEN];
    954 +               int saved_errno = errno;
    955 +               int parent_flags = make_parentdir_mutable(fname2, force_change, parent, sizeof parent);
    956 +               if (parent_flags) {
    957 +                       int ret = link(fname1, fname2);
    958 +                       undo_make_mutable(parent, parent_flags);
    959 +                       if (ret == 0)
    960 +                               return 0;
    961 +               }
    962 +               errno = saved_errno;
    963 +       }
    964 +#endif
    965 +
    966 +       return -1;
     837 #ifdef SUPPORT_LINKS
     838@@ -116,14 +133,37 @@ int do_link(const char *fname1, const char *fname2)
    967839 }
    968840 #endif
     
    979851+       if (lchown(path, owner, group) == 0)
    980852+               return 0;
    981 +
    982 +#ifdef SUPPORT_FORCE_CHANGE
    983 +       if (force_change && (errno == EPERM || errno == EACCES)) {
    984 +               int saved_errno = errno;
    985 +               fileflags = make_mutable(path, &mode, fileflags, force_change);
    986 +               if (fileflags) {
     853+#ifdef SUPPORT_FORCE_CHANGE
     854+       if (force_change && errno == EPERM) {
     855+               if (fileflags == NO_FFLAGS) {
     856+                       STRUCT_STAT st;
     857+                       if (x_lstat(path, &st, NULL) == 0) {
     858+                               mode = st.st_mode;
     859+                               fileflags = st.st_flags;
     860+                       }
     861+               }
     862+               if (fileflags != NO_FFLAGS
     863+                && make_mutable(path, mode, fileflags, force_change) > 0) {
    987864+                       int ret = lchown(path, owner, group);
    988865+                       undo_make_mutable(path, fileflags);
     
    990867+                               return 0;
    991868+               }
    992 +               errno = saved_errno;
     869+               errno = EPERM;
    993870+       }
    994871+#else
    995872+       mode = fileflags = 0; /* avoid compiler warning */
    996873+#endif
    997 +
    998874+       return -1;
    999875 }
    1000876 
    1001877 int do_mknod(const char *pathname, mode_t mode, dev_t dev)
    1002 @@ -116,7 +196,7 @@ int do_mknod(const char *pathname, mode_t mode, dev_t dev)
     878@@ -163,7 +203,7 @@ int do_mknod(const char *pathname, mode_t mode, dev_t dev)
    1003879                        return -1;
    1004880                close(sock);
     
    1009885                return 0;
    1010886 #endif
    1011 @@ -133,21 +213,63 @@ int do_rmdir(const char *pathname)
     887@@ -180,7 +220,22 @@ int do_rmdir(const char *pathname)
    1012888 {
    1013889        if (dry_run) return 0;
     
    1016892+       if (rmdir(pathname) == 0)
    1017893+               return 0;
    1018 +
    1019 +#ifdef SUPPORT_FORCE_CHANGE
    1020 +       if (force_change && (errno == EPERM || errno == EACCES)) {
    1021 +               char parent[MAXPATHLEN];
    1022 +               int parent_flags;
    1023 +               int saved_errno = errno;
    1024 +               int file_flags = make_mutable(pathname, NULL, NO_FFLAGS, force_change);
    1025 +               if (file_flags && rmdir(pathname) == 0)
    1026 +                       return 0;
    1027 +               parent_flags = make_parentdir_mutable(pathname, force_change, parent, sizeof parent);
    1028 +               if (parent_flags) {
    1029 +                       int ret = rmdir(pathname);
    1030 +                       undo_make_mutable(parent, parent_flags);
    1031 +                       if (ret == 0)
     894+#ifdef SUPPORT_FORCE_CHANGE
     895+       if (force_change && errno == EPERM) {
     896+               STRUCT_STAT st;
     897+
     898+               if (x_lstat(pathname, &st, NULL) == 0
     899+                && make_mutable(pathname, st.st_mode, st.st_flags, force_change) > 0) {
     900+                       if (rmdir(pathname) == 0)
    1032901+                               return 0;
     902+                       undo_make_mutable(pathname, st.st_flags);
    1033903+               }
    1034 +               if (file_flags)
    1035 +                       undo_make_mutable(pathname, file_flags);
    1036 +               errno = saved_errno;
     904+               errno = EPERM;
    1037905+       }
    1038906+#endif
    1039 +
    1040907+       return -1;
    1041908 }
    1042909 
    1043910 int do_open(const char *pathname, int flags, mode_t mode)
    1044  {
    1045 +       int fd;
    1046         if (flags != O_RDONLY) {
    1047                 RETURN_ERROR_IF(dry_run, 0);
    1048                 RETURN_ERROR_IF_RO_OR_LO;
    1049         }
    1050 +       if ((fd = open(pathname, flags | O_BINARY, mode)) >= 0)
    1051 +               return fd;
    1052 +
    1053 +#ifdef SUPPORT_FORCE_CHANGE
    1054 +       if (force_change && (errno == EPERM || errno == EACCES)) {
    1055 +               char parent[MAXPATHLEN];
    1056 +               int saved_errno = errno;
    1057 +               int parent_flags = make_parentdir_mutable(pathname, force_change, parent, sizeof parent);
    1058 +               if (parent_flags) {
    1059 +                       fd = open(pathname, flags | O_BINARY, mode);
    1060 +                       undo_make_mutable(parent, parent_flags);
    1061 +                       if (fd >= 0)
    1062 +                               return fd;
    1063 +               }
    1064 +               errno = saved_errno;
    1065 +       }
    1066 +#endif
    1067  
    1068 -       return open(pathname, flags | O_BINARY, mode);
    1069 +       return -1;
     911@@ -194,7 +249,7 @@ int do_open(const char *pathname, int flags, mode_t mode)
    1070912 }
    1071913 
     
    1076918        int code;
    1077919        if (dry_run) return 0;
    1078 @@ -170,17 +292,93 @@ int do_chmod(const char *path, mode_t mode)
     920@@ -217,17 +272,74 @@ int do_chmod(const char *path, mode_t mode)
    1079921        } else
    1080922                code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
    1081923 #endif /* !HAVE_LCHMOD */
    1082924+#ifdef SUPPORT_FORCE_CHANGE
    1083 +       if (code < 0 && force_change && (errno == EPERM || errno == EACCES) && !S_ISLNK(mode)) {
    1084 +               int saved_errno = errno;
    1085 +               fileflags = make_mutable(path, &mode, fileflags, force_change);
    1086 +               if (fileflags) {
    1087 +#ifdef HAVE_LCHMOD
    1088 +                       code = lchmod(path, mode & CHMOD_BITS);
    1089 +#else
     925+       if (code < 0 && force_change && errno == EPERM && !S_ISLNK(mode)) {
     926+               if (fileflags == NO_FFLAGS) {
     927+                       STRUCT_STAT st;
     928+                       if (x_lstat(path, &st, NULL) == 0)
     929+                               fileflags = st.st_flags;
     930+               }
     931+               if (fileflags != NO_FFLAGS
     932+                && make_mutable(path, mode, fileflags, force_change) > 0) {
    1090933+                       code = chmod(path, mode & CHMOD_BITS);
    1091 +#endif
    1092934+                       undo_make_mutable(path, fileflags);
    1093935+                       if (code == 0)
    1094936+                               return 0;
    1095937+               }
    1096 +               errno = saved_errno;
     938+               errno = EPERM;
    1097939+       }
    1098940+#else
     
    1121963+       if (rename(fname1, fname2) == 0)
    1122964+               return 0;
    1123 +
    1124 +#ifdef SUPPORT_FORCE_CHANGE
    1125 +       if (force_change && (errno == EPERM || errno == EACCES)) {
    1126 +               int saved_errno = errno;
    1127 +               int ret = -1, file2_flags = 0;
    1128 +               int file1_flags = make_mutable(fname1, NULL, NO_FFLAGS, force_change);
    1129 +               if (file1_flags && rename(fname1, fname2) == 0)
    1130 +                       ret = 0;
    1131 +               else {
    1132 +                       file2_flags = make_mutable(fname2, NULL, NO_FFLAGS, force_change);
    1133 +                       if (file2_flags && rename(fname1, fname2) == 0)
    1134 +                               ret = 0;
    1135 +                       else {
    1136 +                               char parent1[MAXPATHLEN];
    1137 +                               int parent1_flags = make_parentdir_mutable(fname1, force_change,
    1138 +                                                       parent1, sizeof parent1);
    1139 +                               if (parent1_flags && rename(fname1, fname2) == 0)
    1140 +                                       ret = 0;
    1141 +                               else {
    1142 +                                       char parent2[MAXPATHLEN];
    1143 +                                       int parent2_flags = make_parentdir_mutable(fname2, force_change,
    1144 +                                                               parent2, sizeof parent2);
    1145 +                                       if (parent2_flags) {
    1146 +                                               if (rename(fname1, fname2) == 0)
    1147 +                                                       ret = 0;
    1148 +                                               undo_make_mutable(parent2, parent2_flags);
    1149 +                                       }
    1150 +                               }
    1151 +                               if (parent1_flags)
    1152 +                                       undo_make_mutable(parent1, parent1_flags);
     965+#ifdef SUPPORT_FORCE_CHANGE
     966+       if (force_change && errno == EPERM) {
     967+               STRUCT_STAT st1, st2;
     968+               int became_mutable;
     969+
     970+               if (x_lstat(fname1, &st1, NULL) != 0)
     971+                       goto failed;
     972+               became_mutable = make_mutable(fname1, st1.st_mode, st1.st_flags, force_change) > 0;
     973+               if (became_mutable && rename(fname1, fname2) == 0)
     974+                       goto success;
     975+               if (x_lstat(fname2, &st2, NULL) == 0
     976+                && make_mutable(fname2, st2.st_mode, st2.st_flags, force_change) > 0) {
     977+                       if (rename(fname1, fname2) == 0) {
     978+                         success:
     979+                               if (became_mutable) /* Yes, use fname2 and st1! */
     980+                                       undo_make_mutable(fname2, st1.st_flags);
     981+                               return 0;
    1153982+                       }
     983+                       undo_make_mutable(fname2, st2.st_flags);
    1154984+               }
    1155 +
    1156 +               if (ret == 0)
    1157 +                       file2_flags = file1_flags; /* file1 is now file2 */
    1158 +               else if (file1_flags)
    1159 +                       undo_make_mutable(fname1, file1_flags);
    1160 +               if (file2_flags)
    1161 +                       undo_make_mutable(fname2, file2_flags);
    1162 +               if (ret == 0)
    1163 +                       return 0;
    1164 +
    1165 +               errno = saved_errno;
     985+               /* TODO: handle immutable directories */
     986+               if (became_mutable)
     987+                       undo_make_mutable(fname1, st1.st_flags);
     988+         failed:
     989+               errno = EPERM;
    1166990+       }
    1167991+#endif
    1168 +
    1169992+       return -1;
    1170993 }
    1171994 
    1172995 #ifdef HAVE_FTRUNCATE
    1173 @@ -222,7 +420,25 @@ int do_mkdir(char *fname, mode_t mode)
    1174         if (dry_run) return 0;
    1175         RETURN_ERROR_IF_RO_OR_LO;
    1176         trim_trailing_slashes(fname);
    1177 -       return mkdir(fname, mode);
    1178 +       if (mkdir(fname, mode) == 0)
    1179 +               return 0;
    1180 +
    1181 +#ifdef SUPPORT_FORCE_CHANGE
    1182 +       if (force_change && (errno == EPERM || errno == EACCES)) {
    1183 +               char parent[MAXPATHLEN];
    1184 +               int saved_errno = errno;
    1185 +               int parent_flags = make_parentdir_mutable(fname, force_change, parent, sizeof parent);
    1186 +               if (parent_flags) {
    1187 +                       int ret = mkdir(fname, mode);
    1188 +                       undo_make_mutable(parent, parent_flags);
    1189 +                       if (ret == 0)
    1190 +                               return 0;
    1191 +               }
    1192 +               errno = saved_errno;
    1193 +       }
    1194 +#endif
    1195 +
    1196 +       return -1;
    1197  }
    1198  
    1199  /* like mkstemp but forces permissions */
    1200 @@ -235,7 +451,19 @@ int do_mkstemp(char *template, mode_t perms)
    1201  #if defined HAVE_SECURE_MKSTEMP && defined HAVE_FCHMOD && (!defined HAVE_OPEN64 || defined HAVE_MKSTEMP64)
    1202         {
    1203                 int fd = mkstemp(template);
    1204 -               if (fd == -1)
    1205 +#ifdef SUPPORT_FORCE_CHANGE
    1206 +               if (fd < 0 && force_change) {
    1207 +                       char parent[MAXPATHLEN];
    1208 +                       int saved_errno = errno;
    1209 +                       int parent_flags = make_parentdir_mutable(template, force_change, parent, sizeof parent);
    1210 +                       if (parent_flags) {
    1211 +                               fd = mkstemp(template);
    1212 +                               undo_make_mutable(parent, parent_flags);
    1213 +                       }
    1214 +                       errno = saved_errno;
    1215 +               }
    1216 +#endif
    1217 +               if (fd < 0)
    1218                         return -1;
    1219                 if (fchmod(fd, perms) != 0 && preserve_perms) {
    1220                         int errno_save = errno;
    1221 @@ -302,7 +530,7 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
    1222  }
    1223  
    1224  #ifdef HAVE_UTIMENSAT
    1225 -int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec)
    1226 +int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags)
    1227  {
    1228         struct timespec t[2];
    1229  
    1230 @@ -313,12 +541,26 @@ int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec)
    1231         t[0].tv_nsec = UTIME_NOW;
    1232         t[1].tv_sec = modtime;
    1233         t[1].tv_nsec = mod_nsec;
    1234 -       return utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW);
    1235 +       if (utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW) == 0)
    1236 +               return 0;
    1237 +
    1238 +#ifdef SUPPORT_FORCE_CHANGE
    1239 +       fileflags = make_mutable(fname, &mode, fileflags, force_change);
    1240 +       if (fileflags) {
    1241 +               if (utimensat(AT_FDCWD, fname, t, AT_SYMLINK_NOFOLLOW) == 0)
    1242 +                       return 0;
    1243 +               undo_make_mutable(fname, fileflags);
    1244 +       }
    1245 +#else
    1246 +       mode = fileflags; /* avoid compiler warning */
    1247 +#endif
    1248 +
    1249 +       return -1;
    1250  }
    1251  #endif
    1252  
    1253  #ifdef HAVE_LUTIMES
    1254 -int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec)
    1255 +int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags)
    1256  {
    1257         struct timeval t[2];
    1258  
    1259 @@ -329,12 +571,26 @@ int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec)
    1260         t[0].tv_usec = 0;
    1261         t[1].tv_sec = modtime;
    1262         t[1].tv_usec = mod_nsec / 1000;
    1263 -       return lutimes(fname, t);
    1264 +       if (lutimes(fname, t) == 0)
    1265 +               return 0;
    1266 +
    1267 +#ifdef SUPPORT_FORCE_CHANGE
    1268 +       fileflags = make_mutable(fname, &mode, fileflags, force_change);
    1269 +       if (fileflags) {
    1270 +               if (lutimes(fname, t) == 0)
    1271 +                       return 0;
    1272 +               undo_make_mutable(fname, fileflags);
    1273 +       }
    1274 +#else
    1275 +       mode = fileflags; /* avoid compiler warning */
    1276 +#endif
    1277 +
    1278 +       return -1;
    1279  }
    1280  #endif
    1281  
    1282  #ifdef HAVE_UTIMES
    1283 -int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec)
    1284 +int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags)
    1285  {
    1286         struct timeval t[2];
    1287  
    1288 @@ -345,14 +601,28 @@ int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec)
    1289         t[0].tv_usec = 0;
    1290         t[1].tv_sec = modtime;
    1291         t[1].tv_usec = mod_nsec / 1000;
    1292 -       return utimes(fname, t);
    1293 +       if (utimes(fname, t) == 0)
    1294 +               return 0;
    1295 +
    1296 +#ifdef SUPPORT_FORCE_CHANGE
    1297 +       fileflags = make_mutable(fname, &mode, fileflags, force_change);
    1298 +       if (fileflags) {
    1299 +               if (utimes(fname, t) == 0)
    1300 +                       return 0;
    1301 +               undo_make_mutable(fname, fileflags);
    1302 +       }
    1303 +#else
    1304 +       mode = fileflags; /* avoid compiler warning */
    1305 +#endif
    1306 +
    1307 +       return -1;
    1308  }
    1309  
    1310  #elif defined HAVE_UTIME
    1311 -int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec))
    1312 +int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec), mode_t mode, uint32 fileflags)
    1313  {
    1314  #ifdef HAVE_STRUCT_UTIMBUF
    1315 -       struct utimbuf tbuf;
    1316 +       struct utimbuf tbuf, *t = &tbuf;
    1317  #else
    1318         time_t t[2];
    1319  #endif
    1320 @@ -360,15 +630,28 @@ int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec))
    1321         if (dry_run) return 0;
    1322         RETURN_ERROR_IF_RO_OR_LO;
    1323  
    1324 -# ifdef HAVE_STRUCT_UTIMBUF
    1325 +#ifdef HAVE_STRUCT_UTIMBUF
    1326         tbuf.actime = time(NULL);
    1327         tbuf.modtime = modtime;
    1328 -       return utime(fname, &tbuf);
    1329 -# else
    1330 +#else
    1331         t[0] = time(NULL);
    1332         t[1] = modtime;
    1333 -       return utime(fname, t);
    1334 -# endif
    1335 +#endif
    1336 +       if (utime(fname, t) == 0)
    1337 +               return 0;
    1338 +
    1339 +#ifdef SUPPORT_FORCE_CHANGE
    1340 +       fileflags = make_mutable(fname, &mode, fileflags, force_change);
    1341 +       if (fileflags) {
    1342 +               if (utime(fname, t) == 0)
    1343 +                       return 0;
    1344 +               undo_make_mutable(fname, fileflags);
    1345 +       }
    1346 +#else
    1347 +       mode = fileflags; /* avoid compiler warning */
    1348 +#endif
    1349 +
    1350 +       return -1;
    1351  }
    1352  
    1353  #else
    1354996diff --git a/t_stub.c b/t_stub.c
    1355997--- a/t_stub.c
    1356998+++ b/t_stub.c
    1357 @@ -26,6 +26,7 @@ int module_id = -1;
     999@@ -28,6 +28,7 @@ int module_id = -1;
     1000 int checksum_len = 0;
    13581001 int relative_paths = 0;
    1359  int human_readable = 0;
    13601002 int module_dirlen = 0;
    13611003+int force_change = 0;
     1004 int preserve_acls = 0;
    13621005 int preserve_times = 0;
    13631006 int preserve_xattrs = 0;
    1364  mode_t orig_umask = 002;
    1365 @@ -90,3 +91,27 @@ struct filter_list_struct daemon_filter_list;
     1007@@ -97,3 +98,23 @@ filter_rule_list daemon_filter_list;
    13661008 {
    13671009        return "tester";
     
    13691011+
    13701012+#if defined SUPPORT_FILEFLAGS || defined SUPPORT_FORCE_CHANGE
    1371 + uint32 make_mutable(UNUSED(const char *fname), UNUSED(mode_t *mode), UNUSED(uint32 fileflags), UNUSED(uint32 iflags))
     1013+ int make_mutable(UNUSED(const char *fname), UNUSED(mode_t mode), UNUSED(uint32 fileflags), UNUSED(uint32 iflags))
    13721014+{
    13731015+       return 0;
    13741016+}
    13751017+
     1018+/* Undo a prior make_mutable() call that returned a 1. */
    13761019+ int undo_make_mutable(UNUSED(const char *fname), UNUSED(uint32 fileflags))
    1377 +{
    1378 +       return 0;
    1379 +}
    1380 +
    1381 + int make_parentdir_mutable(UNUSED(const char *fname), UNUSED(uint32 iflags), UNUSED(char *parent_dirbuf), UNUSED(int parent_dirbuf_size))
    13821020+{
    13831021+       return 0;
     
    13941032--- a/util.c
    13951033+++ b/util.c
    1396 @@ -125,7 +125,7 @@ NORETURN void overflow_exit(const char *str)
    1397  
     1034@@ -33,6 +33,7 @@ extern int relative_paths;
     1035 extern int preserve_times;
     1036 extern int preserve_xattrs;
     1037 extern int preallocate_files;
     1038+extern int force_change;
     1039 extern char *module_dir;
     1040 extern unsigned int module_dirlen;
     1041 extern char *partial_dir;
     1042@@ -115,9 +116,36 @@ void print_child_argv(const char *prefix, char **cmd)
     1043        rprintf(FCLIENT, " (%d args)\n", cnt);
     1044 }
     1045 
     1046+#ifdef SUPPORT_FORCE_CHANGE
     1047+static int try_a_force_change(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags)
     1048+{
     1049+       if (fileflags == NO_FFLAGS) {
     1050+               STRUCT_STAT st;
     1051+               if (x_lstat(fname, &st, NULL) == 0)
     1052+                       fileflags = st.st_flags;
     1053+       }
     1054+
     1055+       if (fileflags != NO_FFLAGS && make_mutable(fname, mode, fileflags, force_change) > 0) {
     1056+               int ret, save_force_change = force_change;
     1057+
     1058+               force_change = 0; /* Make certain we can't come back here. */
     1059+               ret = set_modtime(fname, modtime, mod_nsec, mode, fileflags);
     1060+               force_change = save_force_change;
     1061+
     1062+               undo_make_mutable(fname, fileflags);
     1063+
     1064+               return ret;
     1065+       }
     1066+
     1067+       errno = EPERM;
     1068+
     1069+       return -1;
     1070+}
     1071+#endif
     1072+
    13981073 /* This returns 0 for success, 1 for a symlink if symlink time-setting
    13991074  * is not possible, or -1 for any other error. */
    1400 -int set_modtime(const char *fname, time_t modtime, mode_t mode)
    1401 +int set_modtime(const char *fname, time_t modtime, mode_t mode, uint32 fileflags)
     1075-int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode)
     1076+int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags)
    14021077 {
    14031078        static int switch_step = 0;
    14041079 
    1405 @@ -138,7 +138,7 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
    1406         switch (switch_step) {
    1407  #ifdef HAVE_UTIMENSAT
     1080@@ -132,6 +160,11 @@ int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode)
    14081081 #include "case_N.h"
    1409 -               if (do_utimensat(fname, modtime, 0) == 0)
    1410 +               if (do_utimensat(fname, modtime, 0, mode, fileflags) == 0)
     1082                if (do_utimensat(fname, modtime, mod_nsec) == 0)
    14111083                        break;
     1084+#ifdef SUPPORT_FORCE_CHANGE
     1085+               if (force_change && errno == EPERM
     1086+                && try_a_force_change(fname, modtime, mod_nsec, mode, fileflags) == 0)
     1087+                       break;
     1088+#endif
    14121089                if (errno != ENOSYS)
    14131090                        return -1;
    1414 @@ -148,7 +148,7 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
    1415  
    1416  #ifdef HAVE_LUTIMES
     1091                switch_step++;
     1092@@ -142,6 +175,11 @@ int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode)
    14171093 #include "case_N.h"
    1418 -               if (do_lutimes(fname, modtime, 0) == 0)
    1419 +               if (do_lutimes(fname, modtime, 0, mode, fileflags) == 0)
     1094                if (do_lutimes(fname, modtime, mod_nsec) == 0)
    14201095                        break;
     1096+#ifdef SUPPORT_FORCE_CHANGE
     1097+               if (force_change && errno == EPERM
     1098+                && try_a_force_change(fname, modtime, mod_nsec, mode, fileflags) == 0)
     1099+                       break;
     1100+#endif
    14211101                if (errno != ENOSYS)
    14221102                        return -1;
    1423 @@ -167,10 +167,10 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
    1424  
    1425  #include "case_N.h"
    1426  #ifdef HAVE_UTIMES
    1427 -               if (do_utimes(fname, modtime, 0) == 0)
    1428 +               if (do_utimes(fname, modtime, 0, mode, fileflags) == 0)
     1103                switch_step++;
     1104@@ -165,6 +203,13 @@ int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode)
     1105                if (do_utime(fname, modtime, mod_nsec) == 0)
    14291106                        break;
    1430  #else
    1431 -               if (do_utime(fname, modtime, 0) == 0)
    1432 +               if (do_utime(fname, modtime, 0, mode, fileflags) == 0)
    1433                         break;
    1434  #endif
    1435  
     1107 #endif
     1108+#ifdef SUPPORT_FORCE_CHANGE
     1109+               if (force_change && errno == EPERM
     1110+                && try_a_force_change(fname, modtime, mod_nsec, mode, fileflags) == 0)
     1111+                       break;
     1112+#else
     1113+               fileflags = 0; /* avoid compiler warning */
     1114+#endif
     1115 
     1116                return -1;
     1117        }
    14361118diff --git a/xattrs.c b/xattrs.c
    14371119--- a/xattrs.c
    14381120+++ b/xattrs.c
    1439 @@ -1042,7 +1042,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
     1121@@ -1045,7 +1045,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
    14401122        mode = (fst.st_mode & _S_IFMT) | (fmode & ACCESSPERMS)
    14411123             | (S_ISDIR(fst.st_mode) ? 0700 : 0600);
     
    14461128                fst.st_rdev = 0; /* just in case */
    14471129 
    1448 diff -up a/config.h.in b/config.h.in
     1130diff -Nurp a/config.h.in b/config.h.in
    14491131--- a/config.h.in
    14501132+++ b/config.h.in
    1451 @@ -70,6 +70,9 @@
     1133@@ -76,6 +76,9 @@
    14521134 /* Define to 1 if vsprintf has a C99-compatible return value */
    14531135 #undef HAVE_C99_VSNPRINTF
     
    14591141 #undef HAVE_CHMOD
    14601142 
    1461 diff -up a/configure.sh b/configure.sh
     1143diff -Nurp a/configure.sh b/configure.sh
    14621144--- a/configure.sh
    14631145+++ b/configure.sh
    1464 @@ -7444,6 +7444,7 @@ fi
     1146@@ -7652,6 +7652,7 @@ fi
    14651147 
    14661148 for ac_func in waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
     
    14701152     strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
    14711153     setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
    1472 diff -up a/proto.h b/proto.h
     1154diff -Nurp a/proto.h b/proto.h
    14731155--- a/proto.h
    14741156+++ b/proto.h
    1475 @@ -274,6 +274,9 @@ int read_ndx_and_attrs(int f_in, int *if
     1157@@ -286,6 +286,8 @@ int read_ndx_and_attrs(int f_in, int f_o
    14761158 void free_sums(struct sum_struct *s);
    14771159 mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
    14781160                 int exists);
    1479 +uint32 make_mutable(const char *fname, mode_t *mode_ptr, uint32 fileflags, uint32 iflags);
     1161+int make_mutable(const char *fname, mode_t mode, uint32 fileflags, uint32 iflags);
    14801162+int undo_make_mutable(const char *fname, uint32 fileflags);
    1481 +int make_parentdir_mutable(const char *fname, uint32 iflags, char *parent_dirbuf, int parent_dirbuf_size);
    14821163 int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    14831164                   const char *fnamecmp, int flags);
    1484  RETSIGTYPE sig_int(UNUSED(int val));
    1485 @@ -297,11 +300,12 @@ void set_socket_options(int fd, char *op
    1486  int do_unlink(const char *fname);
    1487  int do_symlink(const char *fname1, const char *fname2);
     1165 RETSIGTYPE sig_int(int sig_num);
     1166@@ -310,11 +312,12 @@ int do_unlink(const char *fname);
     1167 int do_symlink(const char *lnk, const char *fname);
     1168 ssize_t do_readlink(const char *path, char *buf, size_t bufsiz);
    14881169 int do_link(const char *fname1, const char *fname2);
    14891170-int do_lchown(const char *path, uid_t owner, gid_t group);
     
    14981179 int do_ftruncate(int fd, OFF_T size);
    14991180 void trim_trailing_slashes(char *name);
    1500 @@ -311,10 +315,10 @@ int do_stat(const char *fname, STRUCT_ST
    1501  int do_lstat(const char *fname, STRUCT_STAT *st);
    1502  int do_fstat(int fd, STRUCT_STAT *st);
    1503  OFF_T do_lseek(int fd, OFF_T offset, int whence);
    1504 -int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec);
    1505 -int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec);
    1506 -int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec);
    1507 -int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec));
    1508 +int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
    1509 +int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
    1510 +int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
    1511 +int do_utime(const char *fname, time_t modtime, UNUSED(uint32 mod_nsec), mode_t mode, uint32 fileflags);
    1512  void set_compression(const char *fname);
    1513  void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
    1514                 int32 n, int32 toklen);
    1515 @@ -334,7 +338,7 @@ int fd_pair(int fd[2]);
     1181@@ -353,7 +356,7 @@ void set_nonblocking(int fd);
     1182 void set_blocking(int fd);
     1183 int fd_pair(int fd[2]);
    15161184 void print_child_argv(const char *prefix, char **cmd);
    1517  NORETURN void out_of_memory(const char *str);
    1518  NORETURN void overflow_exit(const char *str);
    1519 -int set_modtime(const char *fname, time_t modtime, mode_t mode);
    1520 +int set_modtime(const char *fname, time_t modtime, mode_t mode, uint32 fileflags);
    1521  int mkdir_defmode(char *fname);
    1522  int create_directory_path(char *fname);
     1185-int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode);
     1186+int set_modtime(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
     1187 int make_path(char *fname, int flags);
    15231188 int full_write(int desc, const char *ptr, size_t len);
    1524 diff -up a/rsync.1 b/rsync.1
     1189 int copy_file(const char *source, const char *dest, int ofd, mode_t mode);
     1190diff -Nurp a/rsync.1 b/rsync.1
    15251191--- a/rsync.1
    15261192+++ b/rsync.1
    1527 @@ -431,6 +431,7 @@ to the detailed description below for a
     1193@@ -438,6 +438,7 @@ to the detailed description below for a
    15281194  \-K, \-\-keep\-dirlinks         treat symlinked dir on receiver as dir
    15291195  \-H, \-\-hard\-links            preserve hard links
     
    15331199      \-\-chmod=CHMOD           affect file and/or directory permissions
    15341200  \-A, \-\-acls                  preserve ACLs (implies \-p)
    1535 @@ -462,7 +463,10 @@ to the detailed description below for a
    1536       \-\-delete\-after          receiver deletes after transfer, not during
    1537       \-\-delete\-excluded       also delete excluded files from dest dirs
     1201@@ -473,7 +474,10 @@ to the detailed description below for a
     1202      \-\-ignore\-missing\-args   ignore missing source args without error
     1203      \-\-delete\-missing\-args   delete missing source args from destination
    15381204      \-\-ignore\-errors         delete even if there are I/O errors
    15391205-     \-\-force                 force deletion of dirs even if not empty
     
    15451211      \-\-max\-size=SIZE         don'\&t transfer any file larger than SIZE
    15461212      \-\-min\-size=SIZE         don'\&t transfer any file smaller than SIZE
    1547 @@ -658,7 +662,8 @@ specified, in which case \fB\-r\fP is no
     1213@@ -743,7 +747,8 @@ specified, in which case \fB\-r\fP is no
    15481214 .IP
    15491215 Note that \fB\-a\fP \fBdoes not preserve hardlinks\fP, because
     
    15551221 .IP "\-\-no\-OPTION"
    15561222 You may turn off one or more implied options by prefixing
    1557 @@ -975,7 +980,7 @@ they would be using \fB\-\-copy\-links\f
     1223@@ -1080,7 +1085,7 @@ they would be using \fB\-\-copy\-links\f
    15581224 Without this option, if the sending side has replaced a directory with a
    15591225 symlink to a directory, the receiving side will delete anything that is in
     
    15641230 See also \fB\-\-keep\-dirlinks\fP for an analogous option for the receiving
    15651231 side.
    1566 @@ -1162,6 +1167,33 @@ Note that this option does not copy rsyn
     1232@@ -1267,6 +1272,33 @@ Note that this option does not copy rsyn
    15671233 used by \fB\-\-fake\-super\fP) unless you repeat the option (e.g. \-XX).  This
    15681234 \(dq\&copy all xattrs\(dq\& mode cannot be used with \fB\-\-fake\-super\fP.
     
    15931259+flags on files and directories that are being updated or deleted on the
    15941260+receiving side.  It does not try to affect user flags.  This option overrides
    1595 +\fB\-\-force\-change\fP and \fB\-\-force\-schange\fP.
     1261+\fB\-\-force\-change\fP and \fB\-\-force\-uchange\fP.
    15961262+.IP
    15971263 .IP "\fB\-\-chmod\fP"
    15981264 This option tells rsync to apply one or more
    15991265 comma\-separated \(dq\&chmod\(dq\& modes to the permission of the files in the
    1600 @@ -1472,13 +1504,14 @@ See \fB\-\-delete\fP (which is implied)
     1266@@ -1633,13 +1665,14 @@ display as a \(dq\&*missing\(dq\& entry
    16011267 Tells \fB\-\-delete\fP to go ahead and delete files
    16021268 even when there are I/O errors.
     
    16161282 .IP
    16171283 .IP "\fB\-\-max\-delete=NUM\fP"
    1618 @@ -2034,7 +2067,7 @@ with older versions of rsync, but that a
     1284@@ -2357,7 +2390,7 @@ with older versions of rsync, but that a
    16191285 verbose messages).
    16201286 .IP
     
    16251291 other letters represent attributes that may be output if they are being
    16261292 modified.
    1627 @@ -2104,7 +2137,7 @@ sender\(cq\&s value (requires \fB\-\-own
     1293@@ -2427,7 +2460,7 @@ sender\(cq\&s value (requires \fB\-\-own
    16281294 A \fBg\fP means the group is different and is being updated to the
    16291295 sender\(cq\&s value (requires \fB\-\-group\fP and the authority to set the group).
  • trunk/dports/net/rsync/files/patch-hfs-compression-options.diff

    r96200 r121462  
    1 This patch adds support for HFS+ compression status to be
    2 shown during options display.
    3 
    4 To use this patch, run these commands for a successful build:
    5 
    6     patch -p1 <patches/fileflags.diff
    7     patch -p1 <patches/crtimes.diff
    8     patch -p1 <patches/hfs-compression.diff
    9     patch -p1 <patches/hfs-compression-options.diff
    10     ./prepare-source
    11     ./configure
    12     make
    13 
    14 TODO:
    15  - Should rsync try to treat the compressed data as file data and use the
    16    rsync algorithm on the data transfer?
    17 
    181diff --git a/options.c b/options.c
    192--- a/options.c
    203+++ b/options.c
    21 @@ -228,6 +228,7 @@
     4@@ -579,6 +579,7 @@
    225        char const *iconv = "no ";
    236        char const *ipv6 = "no ";
     
    2710 
    2811 #if SUBPROTOCOL_VERSION != 0
    29 @@ -264,6 +265,9 @@
     12@@ -618,6 +619,9 @@
    3013 #ifdef SUPPORT_FILEFLAGS
    3114        fileflags = "";
     
    3720        rprintf(f, "%s  version %s  protocol version %d%s\n",
    3821                RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
    39 @@ -277,8 +281,10 @@
     22@@ -631,8 +635,10 @@
    4023                (int)(sizeof (int64) * 8));
    4124        rprintf(f, "    %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
    4225                got_socketpair, hardlinks, links, ipv6, have_inplace);
    43 -       rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sfile-flags\n",
    44 +       rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sfile-flags,\n",
    45                 have_inplace, acls, xattrs, iconv, symtimes, fileflags);
    46 +       rprintf(f, "    %sHFS-compression\n",
    47 +               hfscomp);
     26-       rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sprealloc, %sfile-flags\n",
     27+       rprintf(f, "    %sappend, %sACLs, %sxattrs, %siconv, %ssymtimes, %sprealloc, %sfile-flags,\n",
     28                have_inplace, acls, xattrs, iconv, symtimes, prealloc, fileflags);
     29+       rprintf(f, "    %sHFS-compression\n",
     30+               hfscomp);
    4831 
    4932 #ifdef MAINTAINER_MODE
  • trunk/dports/net/rsync/files/patch-hfs-compression.diff

    r96200 r121462  
    1919   rsync algorithm on the data transfer?
    2020
    21 based-on: patch/b3.0.x/crtimes
     21based-on: patch/master/crtimes
    2222diff --git a/flist.c b/flist.c
    2323--- a/flist.c
    2424+++ b/flist.c
    25 @@ -1496,6 +1496,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
    26  #ifdef SUPPORT_FILEFLAGS
    27                         sx.st.st_flags = preserve_fileflags ? F_FFLAGS(file) : 0;
    28  #endif
     25@@ -1583,6 +1583,9 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
     26 #ifdef SUPPORT_XATTRS
     27                if (preserve_xattrs) {
     28                        sx.st.st_mode = file->mode;
     29+                       if (preserve_fileflags)
     30+                               sx.st.st_flags = F_FFLAGS(file);
    2931+                       sx.st.st_mtime = file->modtime; /* get_xattr needs mtime for decmpfs xattrs */
    30                         sx.xattr = NULL;
    3132                        if (get_xattr(fname, &sx) < 0) {
    3233                                io_error |= IOERR_GENERAL;
     34                                return NULL;
    3335diff --git a/generator.c b/generator.c
    3436--- a/generator.c
    3537+++ b/generator.c
    36 @@ -39,6 +39,7 @@ extern int keep_dirlinks;
    37  extern int force_change;
     38@@ -37,6 +37,7 @@ extern int implied_dirs;
     39 extern int keep_dirlinks;
    3840 extern int preserve_acls;
    3941 extern int preserve_xattrs;
     
    4244 extern int preserve_devices;
    4345 extern int preserve_specials;
    44 @@ -1888,6 +1889,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
     46@@ -1762,6 +1763,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
    4547                                        fname, fnamecmpbuf);
    4648                        }
     
    5658                        statret = 0;
    5759                        fnamecmp = fnamecmpbuf;
    58                         fnamecmp_type = FNAMECMP_FUZZY;
    59 @@ -2072,6 +2081,18 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
     60                }
     61@@ -1929,6 +1938,18 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
    6062        if (read_batch)
    6163                goto cleanup;
     
    7981--- a/lib/sysxattrs.c
    8082+++ b/lib/sysxattrs.c
    81 @@ -22,6 +22,17 @@
     83@@ -22,10 +22,17 @@
    8284 #include "rsync.h"
    8385 #include "sysxattrs.h"
     
    8587+extern int preserve_hfs_compression;
    8688+
    87 +#ifdef HAVE_OSX_XATTRS
     89 #ifdef SUPPORT_XATTRS
     90 
     91 #ifdef HAVE_OSX_XATTRS
    8892+#ifndef XATTR_SHOWCOMPRESSION
    8993+#define XATTR_SHOWCOMPRESSION 0x0020
    9094+#endif
    91 +#define GETXATTR_FETCH_LIMIT (64*1024*1024)
     95 #define GETXATTR_FETCH_LIMIT (64*1024*1024)
    9296+
    9397+int xattr_options = XATTR_NOFOLLOW;
    94 +#endif
    95 +
    96  #ifdef SUPPORT_XATTRS
     98 #endif
    9799 
    98100 #if defined HAVE_LINUX_XATTRS
    99 @@ -55,7 +66,27 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
     101@@ -59,7 +66,12 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
    100102 
    101103 ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
    102104 {
    103 -       return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
     105-       ssize_t len = getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
    104106+       ssize_t len;
    105107+
     
    108110+
    109111+       len = getxattr(path, name, value, size, 0, xattr_options);
    110 +
    111 +       /* If we're retrieving data, handle resource forks > 64MB specially */
    112 +       if (value != NULL && strcmp(name, XATTR_RESOURCEFORK_NAME) == 0 && len == GETXATTR_FETCH_LIMIT) {
    113 +               /* getxattr will only return 64MB of data at a time, need to call again with a new offset */
    114 +               u_int32_t offset = GETXATTR_FETCH_LIMIT;
    115 +               ssize_t data_retrieved = len;
    116 +               while (data_retrieved < (ssize_t)size) {
     112 
     113        /* If we're retrieving data, handle resource forks > 64MB specially */
     114        if (value != NULL && len == GETXATTR_FETCH_LIMIT && (size_t)len < size) {
     115@@ -67,7 +79,7 @@ ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t si
     116                u_int32_t offset = len;
     117                size_t data_retrieved = len;
     118                while (data_retrieved < size) {
     119-                       len = getxattr(path, name, value + offset, size - data_retrieved, offset, XATTR_NOFOLLOW);
    117120+                       len = getxattr(path, name, value + offset, size - data_retrieved, offset, xattr_options);
    118 +                       data_retrieved += len;
    119 +                       offset += (u_int32_t)len;
    120 +               }
    121 +               len = data_retrieved;
    122 +       }
    123 +
    124 +       return len;
    125  }
    126  
    127  ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
    128 @@ -70,12 +101,16 @@ int sys_lsetxattr(const char *path, const char *name, const void *value, size_t
     121                        if (len <= 0)
     122                                break;
     123                        data_retrieved += len;
     124@@ -91,12 +103,16 @@ int sys_lsetxattr(const char *path, const char *name, const void *value, size_t
    129125 
    130126 int sys_lremovexattr(const char *path, const char *name)
     
    157153+#endif
    158154 
    159  extern int verbose;
    160155 extern int dry_run;
    161 @@ -50,7 +54,9 @@ extern int copy_dirlinks;
     156 extern int list_only;
     157@@ -53,6 +57,7 @@ extern int copy_dirlinks;
    162158 extern int copy_unsafe_links;
    163159 extern int keep_dirlinks;
     
    165161+extern int preserve_hfs_compression;
    166162 extern int protocol_version;
    167 +extern int force_change;
     163 extern int force_change;
    168164 extern int file_total;
    169  extern int recurse;
    170  extern int xfer_dirs;
    171 @@ -490,6 +496,43 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
     165@@ -107,6 +112,7 @@ int daemon_over_rsh = 0;
     166 mode_t orig_umask = 0;
     167 int batch_gen_fd = -1;
     168 int sender_keeps_checksum = 0;
     169+int fs_supports_hfs_compression = 0;
     170 
     171 /* There's probably never more than at most 2 outstanding child processes,
     172  * but set it higher, just in case. */
     173@@ -559,6 +565,43 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, in
    172174        return 0; /* not reached */
    173175 }
     
    213215  *
    214216  * 1. it receives any number of files into a destination directory,
    215 @@ -548,6 +591,9 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
     217@@ -617,6 +660,9 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
    216218                                exit_cleanup(RERR_FILESELECT);
    217219                        }
     
    223225                }
    224226                if (file_total > 1) {
    225 @@ -608,7 +654,9 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
     227@@ -677,7 +723,9 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
    226228                                full_fname(dest_path));
    227229                        exit_cleanup(RERR_FILESELECT);
     
    234236        }
    235237 
    236 @@ -628,6 +676,9 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
     238@@ -697,6 +745,9 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
    237239                        full_fname(dest_path));
    238240                exit_cleanup(RERR_FILESELECT);
     
    244246 
    245247        return cp + 1;
    246 @@ -981,7 +1032,6 @@ int child_main(int argc, char *argv[])
    247         return 0;
    248  }
    249  
    250 -
    251  void start_server(int f_in, int f_out, int argc, char *argv[])
    252  {
    253         set_nonblocking(f_in);
    254248diff --git a/options.c b/options.c
    255249--- a/options.c
    256250+++ b/options.c
    257 @@ -52,6 +52,7 @@ int preserve_links = 0;
     251@@ -54,6 +54,7 @@ int preserve_links = 0;
    258252 int preserve_hard_links = 0;
    259253 int preserve_acls = 0;
     
    263257 int preserve_fileflags = 0;
    264258 int preserve_executability = 0;
    265 @@ -355,6 +356,10 @@ void usage(enum logcode F)
     259@@ -713,6 +714,10 @@ void usage(enum logcode F)
    266260 #ifdef SUPPORT_XATTRS
    267261   rprintf(F," -X, --xattrs                preserve extended attributes\n");
     
    274268   rprintf(F," -g, --group                 preserve group\n");
    275269   rprintf(F,"     --devices               preserve device files (super-user only)\n");
    276 @@ -588,6 +593,12 @@ static struct poptOption long_options[] = {
     270@@ -974,6 +979,12 @@ static struct poptOption long_options[] = {
    277271   {"force-uchange",    0,  POPT_ARG_VAL,    &force_change, USR_IMMUTABLE, 0, 0 },
    278272   {"force-schange",    0,  POPT_ARG_VAL,    &force_change, SYS_IMMUTABLE, 0, 0 },
     
    287281   {"no-ignore-errors", 0,  POPT_ARG_VAL,    &ignore_errors, 0, 0, 0 },
    288282   {"max-delete",       0,  POPT_ARG_INT,    &max_delete, 0, 0, 0 },
    289 @@ -1362,6 +1373,15 @@ int parse_arguments(int *argc_p, const char ***argv_p)
     283@@ -1974,6 +1985,15 @@ int parse_arguments(int *argc_p, const char ***argv_p)
    290284        }
    291285 #endif
     
    300294+#endif
    301295+
    302         if (write_batch && read_batch) {
     296        if (block_size > MAX_BLOCK_SIZE) {
    303297                snprintf(err_buf, sizeof err_buf,
    304                         "--write-batch and --read-batch can not be used together\n");
    305 @@ -1915,6 +1935,11 @@ void server_options(char **args, int *argc_p)
     298                         "--block-size=%lu is too large (max: %u)\n", block_size, MAX_BLOCK_SIZE);
     299@@ -2573,6 +2593,11 @@ void server_options(char **args, int *argc_p)
    306300        if (preserve_fileflags)
    307301                args[ac++] = "--fileflags";
     
    318312--- a/rsync.c
    319313+++ b/rsync.c
    320 @@ -498,8 +498,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
     314@@ -573,8 +573,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    321315 #ifdef SUPPORT_XATTRS
    322316        if (am_root < 0)
     
    334328 
    335329        if (!preserve_times
    336 @@ -510,6 +516,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
     330@@ -585,6 +591,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    337331        if (sxp->st.st_ino == 2 && S_ISDIR(sxp->st.st_mode))
    338332                flags |= ATTRS_SKIP_CRTIME;
     
    342336+#endif
    343337            && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
    344                 int ret = set_modtime(fname, file->modtime, sxp->st.st_mode, ST_FLAGS(sxp->st));
     338                int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), sxp->st.st_mode, ST_FLAGS(sxp->st));
    345339                if (ret < 0) {
    346 @@ -620,6 +629,16 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
     340@@ -643,6 +652,16 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
    347341                 && !set_fileflags(fname, fileflags))
    348342                        goto cleanup;
    349343                updated = 1;
    350344+#ifdef SUPPORT_HFS_COMPRESSION
    351 +               int ret = set_modtime(fname, file->modtime, new_mode, fileflags);
     345+               int ret = set_modtime(fname, file->modtime, F_MOD_NSEC(file), new_mode, fileflags);
    352346+               if (ret < 0) {
    353347+                       rsyserr(FERROR_XFER, errno, "failed to set times on %s",
     
    364358--- a/rsync.h
    365359+++ b/rsync.h
    366 @@ -509,6 +509,17 @@ typedef unsigned int size_t;
     360@@ -549,6 +549,17 @@ typedef unsigned int size_t;
    367361 #define ST_FLAGS(st) NO_FFLAGS
    368362 #endif
     
    385379--- a/rsync.yo
    386380+++ b/rsync.yo
    387 @@ -360,6 +360,8 @@ to the detailed description below for a complete description.  verb(
     381@@ -367,6 +367,8 @@ to the detailed description below for a complete description.  verb(
    388382      --chmod=CHMOD           affect file and/or directory permissions
    389383  -A, --acls                  preserve ACLs (implies -p)
     
    394388  -g, --group                 preserve group
    395389      --devices               preserve device files (super-user only)
    396 @@ -1038,6 +1040,42 @@ flags on files and directories that are being updated or deleted on the
     390@@ -1135,6 +1137,42 @@ flags on files and directories that are being updated or deleted on the
    397391 receiving side.  It does not try to affect user flags.  This option overrides
    398  bf(--force-change) and bf(--force-schange).
     392 bf(--force-change) and bf(--force-uchange).
    399393 
    400394+dit(bf(--hfs-compression)) This option causes rsync to preserve HFS+
     
    440434--- a/t_stub.c
    441435+++ b/t_stub.c
    442 @@ -29,6 +29,7 @@ int module_dirlen = 0;
    443  int force_change = 0;
     436@@ -32,6 +32,7 @@ int force_change = 0;
     437 int preserve_acls = 0;
    444438 int preserve_times = 0;
    445439 int preserve_xattrs = 0;
    446440+int preserve_hfs_compression = 0;
    447  mode_t orig_umask = 002;
    448441 char *partial_dir;
    449442 char *module_dir;
     443 filter_rule_list daemon_filter_list;
    450444diff --git a/xattrs.c b/xattrs.c
    451445--- a/xattrs.c
    452446+++ b/xattrs.c
    453 @@ -32,6 +32,7 @@ extern int am_generator;
     447@@ -33,6 +33,7 @@ extern int am_generator;
    454448 extern int read_only;
    455449 extern int list_only;
     
    459453 extern int preserve_devices;
    460454 extern int preserve_specials;
    461 @@ -40,6 +41,10 @@ extern int checksum_seed;
     455@@ -41,6 +42,10 @@ extern int checksum_seed;
    462456 #define RSYNC_XAL_INITIAL 5
    463457 #define RSYNC_XAL_LIST_INITIAL 100
     
    470464 
    471465 #define HAS_PREFIX(str, prfx) (*(str) == *(prfx) \
    472 @@ -72,6 +77,17 @@ extern int checksum_seed;
     466@@ -73,6 +78,17 @@ extern int checksum_seed;
    473467 #define XDEF_ACL_SUFFIX "dacl"
    474468 #define XDEF_ACL_ATTR RSYNC_PREFIX "%" XDEF_ACL_SUFFIX
     
    488482        char *datum, *name;
    489483        size_t datum_len, name_len;
    490 @@ -166,8 +182,7 @@ static ssize_t get_xattr_names(const char *fname)
     484@@ -167,8 +183,7 @@ static ssize_t get_xattr_names(const char *fname)
    491485 /* On entry, the *len_ptr parameter contains the size of the extra space we
    492486  * should allocate when we create a buffer for the data.  On exit, it contains
     
    498492        size_t datum_len = sys_lgetxattr(fname, name, NULL, 0);
    499493        size_t extra_len = *len_ptr;
    500 @@ -176,7 +191,7 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
     494@@ -177,7 +192,7 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
    501495        *len_ptr = datum_len;
    502496 
     
    507501                rsyserr(FERROR_XFER, errno,
    508502                        "get_xattr_data: lgetxattr(\"%s\",\"%s\",0) failed",
    509 @@ -184,6 +199,15 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
     503@@ -185,6 +200,15 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
    510504                return NULL;
    511505        }
     
    523517                extra_len = 1; /* request non-zero amount of memory */
    524518        if (datum_len + extra_len < datum_len)
    525 @@ -212,7 +236,29 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
     519@@ -213,7 +237,29 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
    526520        return ptr;
    527521 }
     
    554548        ssize_t list_len, name_len;
    555549        size_t datum_len, name_offset;
    556 @@ -221,7 +267,8 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
    557         int user_only = am_sender ? 0 : am_root <= 0;
     550@@ -222,7 +268,8 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
     551        int user_only = am_sender ? 0 : !am_root;
    558552 #endif
    559553        rsync_xa *rxa;
     
    564558        /* This puts the name list into the "namebuf" buffer. */
    565559        if ((list_len = get_xattr_names(fname)) < 0)
    566 @@ -251,20 +298,22 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
     560@@ -252,20 +299,22 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
    567561                }
    568562 
     
    593587                        name_offset = datum_len;
    594588 
    595 @@ -309,7 +358,7 @@ int get_xattr(const char *fname, stat_x *sxp)
    596                         return 0;
    597         }
     589@@ -311,7 +360,7 @@ int get_xattr(const char *fname, stat_x *sxp)
     590        } else if (IS_MISSING_FILE(sxp->st))
     591                return 0;
    598592 
    599593-       if (rsync_xal_get(fname, sxp->xattr) < 0) {
     
    602596                return -1;
    603597        }
    604 @@ -344,6 +393,8 @@ int copy_xattrs(const char *source, const char *dest)
     598@@ -346,6 +395,8 @@ int copy_xattrs(const char *source, const char *dest)
    605599                datum_len = 0;
    606600                if (!(ptr = get_xattr_data(source, name, &datum_len, 0)))
     
    611605                        int save_errno = errno ? errno : EINVAL;
    612606                        rsyserr(FERROR_XFER, errno,
    613 @@ -360,6 +411,10 @@ int copy_xattrs(const char *source, const char *dest)
     607@@ -362,6 +413,10 @@ int copy_xattrs(const char *source, const char *dest)
    614608 
    615609 static int find_matching_xattr(item_list *xalp)
     
    622616        item_list *lst = rsync_xal_l.items;
    623617 
    624 @@ -393,6 +448,7 @@ static int find_matching_xattr(item_list *xalp)
     618@@ -395,6 +450,7 @@ static int find_matching_xattr(item_list *xalp)
    625619        }
    626620 
     
    630624 
    631625 /* Store *xalp on the end of rsync_xal_l */
    632 @@ -572,11 +628,13 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
     626@@ -574,11 +630,13 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
    633627 
    634628                        /* Re-read the long datum. */
     
    643637+                       assert(ptr != UNREAD_DATA);
    644638                        write_varint(f_out, len); /* length might have changed! */
    645                         write_buf(f_out, ptr, len);
     639                        write_bigbuf(f_out, ptr, len);
    646640                        free(ptr);
    647 @@ -792,7 +850,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
     641@@ -795,7 +853,7 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
    648642        int user_only = am_root <= 0;
    649643 #endif
     
    654648        /* This puts the current name list into the "namebuf" buffer. */
    655649        if ((list_len = get_xattr_names(fname)) < 0)
    656 @@ -804,7 +862,10 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
     650@@ -807,7 +865,10 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
    657651                if (XATTR_ABBREV(rxas[i])) {
    658652                        /* See if the fnamecmp version is identical. */
     
    666660                                if (am_generator)
    667661                                        continue;
    668 @@ -813,14 +874,14 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
     662@@ -816,14 +877,14 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
    669663                                ret = -1;
    670664                                continue;
     
    684678                                free(ptr);
    685679                                goto still_abbrev;
    686 @@ -889,6 +950,10 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
     680@@ -892,6 +953,10 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
    687681                }
    688682        }
     
    695689 }
    696690 
    697 @@ -935,7 +1000,7 @@ char *get_xattr_acl(const char *fname, int is_access_acl, size_t *len_p)
     691@@ -938,7 +1003,7 @@ char *get_xattr_acl(const char *fname, int is_access_acl, size_t *len_p)
    698692 {
    699693        const char *name = is_access_acl ? XACC_ACL_ATTR : XDEF_ACL_ATTR;
     
    704698 
    705699 int set_xattr_acl(const char *fname, int is_access_acl, const char *buf, size_t buf_len)
    706 @@ -1078,11 +1143,33 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
     700@@ -1081,11 +1146,33 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
    707701        return 0;
    708702 }
     
    738732 }
    739733 
    740 @@ -1091,6 +1178,9 @@ int x_lstat(const char *fname, STRUCT_STAT *fst, STRUCT_STAT *xst)
     734@@ -1094,6 +1181,9 @@ int x_lstat(const char *fname, STRUCT_STAT *fst, STRUCT_STAT *xst)
    741735        int ret = do_lstat(fname, fst);
    742736        if ((ret < 0 || get_stat_xattr(fname, -1, fst, xst) < 0) && xst)
     
    748742 }
    749743 
    750 @@ -1099,6 +1189,9 @@ int x_fstat(int fd, STRUCT_STAT *fst, STRUCT_STAT *xst)
     744@@ -1102,6 +1192,9 @@ int x_fstat(int fd, STRUCT_STAT *fst, STRUCT_STAT *xst)
    751745        int ret = do_fstat(fd, fst);
    752746        if ((ret < 0 || get_stat_xattr(NULL, fd, fst, xst) < 0) && xst)
     
    758752 }
    759753 
    760 diff -up a/rsync.1 b/rsync.1
     754diff -Nurp a/rsync.1 b/rsync.1
    761755--- a/rsync.1
    762756+++ b/rsync.1
    763 @@ -436,6 +436,8 @@ to the detailed description below for a
     757@@ -443,6 +443,8 @@ to the detailed description below for a
    764758      \-\-chmod=CHMOD           affect file and/or directory permissions
    765759  \-A, \-\-acls                  preserve ACLs (implies \-p)
     
    770764  \-g, \-\-group                 preserve group
    771765      \-\-devices               preserve device files (super\-user only)
    772 @@ -1195,6 +1197,44 @@ flags on files and directories that are
     766@@ -1300,6 +1302,44 @@ flags on files and directories that are
    773767 receiving side.  It does not try to affect user flags.  This option overrides
    774  \fB\-\-force\-change\fP and \fB\-\-force\-schange\fP.
     768 \fB\-\-force\-change\fP and \fB\-\-force\-uchange\fP.
    775769 .IP
    776770+.IP "\fB\-\-hfs\-compression\fP"
Note: See TracChangeset for help on using the changeset viewer.