Changeset 80017
- Timestamp:
- 07/01/11 21:52:41 (4 years ago)
- Location:
- trunk/dports/net/rsync
- Files:
-
- 3 edited
-
Portfile (modified) (2 diffs)
-
files/patch-crtimes.diff (modified) (43 diffs)
-
files/patch-fileflags.diff (modified) (76 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/dports/net/rsync/Portfile
r75561 r80017 4 4 5 5 name rsync 6 version 3.0.7 7 revision 1 6 version 3.0.8 8 7 categories net 9 8 platforms darwin freebsd sunos … … 23 22 http://rsync.samba.org/ftp/rsync/src/ 24 23 25 checksums md5 b53525900817cf1ba7ad3a516ab5bfe9\26 sha1 63426a1bc71991d93159cd522521fbacdafb7a61\27 rmd160 aa3bdec0d7692ac1de52f2efc925e9a34bbd917b24 checksums md5 0ee8346ce16bdfe4c88a236e94c752b4 \ 25 sha1 10e80173c7e9ed8b8a4dc9e8fdab08402da5f08d \ 26 rmd160 f00c5ba42e33a1745976c9af5e770c220a6fa4a6 28 27 29 28 depends_lib port:popt port:libiconv 30 29 31 # these come from http://rsync.samba.org/ftp/rsync/rsync-patches-3.0. 7.tar.gz30 # these come from http://rsync.samba.org/ftp/rsync/rsync-patches-3.0.8.tar.gz 32 31 # and need to be updated with each release 33 32 patchfiles patch-fileflags.diff \ -
trunk/dports/net/rsync/files/patch-crtimes.diff
r75561 r80017 6 6 patch -p1 <patches/fileflags.diff 7 7 patch -p1 <patches/crtimes.diff 8 ./configure (optional if already run) 8 ./prepare-source 9 ./configure 9 10 make 10 11 … … 13 14 --- a/compat.c 14 15 +++ b/compat.c 15 @@ -4 6,6 +46,7 @@ extern int force_change;16 @@ -47,6 +47,7 @@ extern int force_change; 16 17 extern int protect_args; 17 18 extern int preserve_uid; … … 21 22 extern int preserve_acls; 22 23 extern int preserve_xattrs; 23 @@ -6 4,7 +65,7 @@ extern char *iconv_opt;24 @@ -65,7 +66,7 @@ extern char *iconv_opt; 24 25 #endif 25 26 … … 30 31 int receiver_symlink_times = 0; /* receiver can set the time on a symlink */ 31 32 int sender_symlink_iconv = 0; /* sender should convert symlink content */ 32 @@ -14 1,6 +142,8 @@ void setup_protocol(int f_out,int f_in)33 @@ -142,6 +143,8 @@ void setup_protocol(int f_out,int f_in) 33 34 uid_ndx = ++file_extra_cnt; 34 35 if (preserve_gid) … … 42 43 --- a/flist.c 43 44 +++ b/flist.c 44 @@ -5 6,6 +56,7 @@ extern int delete_during;45 extern int uid_ndx;46 extern int gid_ndx;45 @@ -54,6 +54,7 @@ extern int preserve_specials; 46 extern int preserve_fileflags; 47 extern int delete_during; 47 48 extern int eol_nulls; 48 49 +extern int crtimes_ndx; 49 50 extern int relative_paths; 50 51 extern int implied_dirs; 51 extern int file_extra_cnt;52 @@ -39 5,7 +396,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,52 extern int ignore_perishable; 53 @@ -393,7 +394,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file, 53 54 #endif 54 55 int ndx, int first_ndx) … … 59 60 #ifdef SUPPORT_FILEFLAGS 60 61 static uint32 fileflags; 61 @@ -4 90,6 +491,13 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,62 @@ -488,6 +489,13 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file, 62 63 xflags |= XMIT_SAME_TIME; 63 64 else … … 72 73 73 74 #ifdef SUPPORT_HARD_LINKS 74 if (tmp_dev != 0) {75 @@ -55 9,6 +567,8 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,75 if (tmp_dev != -1) { 76 @@ -557,6 +565,8 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file, 76 77 else 77 78 write_int(f, modtime); … … 82 83 write_int(f, to_wire_mode(mode)); 83 84 #ifdef SUPPORT_FILEFLAGS 84 @@ -64 9,7 +659,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,85 static struct file_struct *recv_file_entry(struct file_list *flist,86 int xflags, int f)85 @@ -648,7 +658,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file, 86 87 static struct file_struct *recv_file_entry(int f, struct file_list *flist, int xflags) 87 88 { 88 89 - static int64 modtime; … … 91 92 #ifdef SUPPORT_FILEFLAGS 92 93 static uint32 fileflags; 93 @@ -75 5,6 +765,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,94 @@ -758,6 +768,8 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 94 95 uid = F_OWNER(first); 95 96 if (preserve_gid) … … 100 101 uint32 *devp = F_RDEV_P(first); 101 102 rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); 102 @@ -78 3,6 +795,19 @@ static struct file_struct *recv_file_entry(struct file_list *flist,103 @@ -786,6 +798,19 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 103 104 } else 104 105 modtime = read_int(f); … … 120 121 mode = from_wire_mode(read_int(f)); 121 122 122 @@ -94 3,6 +968,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,123 @@ -946,6 +971,8 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 123 124 F_GROUP(file) = gid; 124 125 file->flags |= gid_flags; … … 129 130 F_NDX(file) = flist->used + flist->ndx_start; 130 131 131 @@ -1319,6 +1346,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, 132 F_OWNER(file) = st.st_uid; 133 if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */ 132 @@ -1324,6 +1351,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, 134 133 F_GROUP(file) = st.st_gid; 134 if (am_generator && st.st_uid == our_uid) 135 file->flags |= FLAG_OWNED_BY_US; 135 136 + if (crtimes_ndx) 136 137 + f_crtime_set(file, get_create_time(fname)); … … 149 150 extern int verbose; 150 151 extern int dry_run; 151 @@ -4 0,6 +41,7 @@ extern int preserve_xattrs;152 @@ -41,6 +42,7 @@ extern int preserve_xattrs; 152 153 extern int preserve_links; 153 154 extern int preserve_devices; … … 157 158 extern int preserve_executability; 158 159 extern int preserve_fileflags; 159 @@ -623,6 +625,13 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp) 160 if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP) && sxp->st.st_gid != (gid_t)F_GROUP(file)) 161 return 0; 162 160 @@ -576,8 +578,15 @@ static void do_delete_pass(void) 161 rprintf(FINFO, " \r"); 162 } 163 164 -static inline int time_differs(struct file_struct *file, stat_x *sxp) 165 +static inline int time_differs(struct file_struct *file, stat_x *sxp, const char *fname) 166 { 163 167 + if (crtimes_ndx) { 164 168 + if (sxp->crtime == 0) 165 169 + sxp->crtime = get_create_time(fname); 166 170 + if (cmp_time(sxp->crtime, f_crtime(file)) != 0) 167 + return 0;171 + return 1; 168 172 + } 169 173 + 170 #ifdef SUPPORT_ACLS 171 if (preserve_acls && !S_ISLNK(file->mode)) { 172 if (!ACL_READY(*sxp)) 173 @@ -666,6 +675,12 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre 174 return cmp_time(sxp->st.st_mtime, file->modtime); 175 } 176 177 @@ -635,7 +644,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp) 178 { 179 if (S_ISLNK(file->mode)) { 180 #ifdef CAN_SET_SYMLINK_TIMES 181 - if (preserve_times & PRESERVE_LINK_TIMES && time_differs(file, sxp)) 182 + if (preserve_times & PRESERVE_LINK_TIMES && time_differs(file, sxp, fname)) 183 return 0; 184 #endif 185 #ifdef CAN_CHMOD_SYMLINK 186 @@ -655,7 +664,7 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp) 187 return 0; 188 #endif 189 } else { 190 - if (preserve_times && time_differs(file, sxp)) 191 + if (preserve_times && time_differs(file, sxp, fname)) 192 return 0; 193 if (perms_differ(file, sxp)) 194 return 0; 195 @@ -698,6 +707,12 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre 174 196 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED) 175 197 && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname)) … … 184 206 if (S_ISLNK(file->mode)) { 185 207 ; 186 @@ -12 25,7 +1240,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,208 @@ -1263,7 +1278,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx, 187 209 188 210 static void list_file_entry(struct file_struct *f) … … 193 215 194 216 if (!F_IS_ACTIVE(f)) { 195 @@ -12 36,19 +1251,24 @@ static void list_file_entry(struct file_struct *f)217 @@ -1274,19 +1289,24 @@ static void list_file_entry(struct file_struct *f) 196 218 permstring(permbuf, f->mode); 197 219 len = F_LENGTH(f); … … 222 244 } 223 245 224 @@ -13 39,6 +1359,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,246 @@ -1383,6 +1403,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, 225 247 return; 226 248 } … … 228 250 + sx.crtime = 0; 229 251 230 #ifdef SUPPORT_ACLS231 sx.acc_acl = sx.def_acl = NULL;252 if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) { 253 parent_is_dry_missing: 232 254 diff --git a/hlink.c b/hlink.c 233 255 --- a/hlink.c 234 256 +++ b/hlink.c 235 @@ -37 0,6 +370,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,257 @@ -371,6 +371,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname, 236 258 char cmpbuf[MAXPATHLEN]; 237 259 stat_x alt_sx; … … 241 263 alt_sx.acc_acl = alt_sx.def_acl = NULL; 242 264 #endif 243 @@ -49 8,6 +499,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,265 @@ -499,6 +500,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx, 244 266 } else 245 267 our_name = fname; … … 284 306 --- a/log.c 285 307 +++ b/log.c 286 @@ -66 3,7 +663,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,308 @@ -661,7 +661,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op, 287 309 c[8] = !(iflags & ITEM_REPORT_FFLAGS) ? '.' : 'f'; 288 310 c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a'; … … 305 327 int cvs_exclude = 0; 306 328 int dry_run = 0; 307 @@ -36 2,6 +363,7 @@ void usage(enum logcode F)329 @@ -361,6 +362,7 @@ void usage(enum logcode F) 308 330 rprintf(F," -D same as --devices --specials\n"); 309 331 rprintf(F," -t, --times preserve modification times\n"); … … 313 335 #ifdef SUPPORT_XATTRS 314 336 rprintf(F," --fake-super store/recover privileged attrs using xattrs\n"); 315 @@ -50 8,6 +510,9 @@ static struct poptOption long_options[] = {316 {"times", 't', POPT_ARG_VAL, &preserve_times, 2, 0, 0 },337 @@ -507,6 +509,9 @@ static struct poptOption long_options[] = { 338 {"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 }, 317 339 {"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 }, 318 340 {"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 }, … … 323 345 {"no-omit-dir-times",0, POPT_ARG_VAL, &omit_dir_times, 0, 0, 0 }, 324 346 {"no-O", 0, POPT_ARG_VAL, &omit_dir_times, 0, 0, 0 }, 325 @@ -18 05,6 +1810,8 @@ void server_options(char **args, int *argc_p)347 @@ -1810,6 +1815,8 @@ void server_options(char **args, int *argc_p) 326 348 argstr[x++] = 'D'; 327 349 if (preserve_times) … … 335 357 --- a/rsync.c 336 358 +++ b/rsync.c 337 @@ -4 27,6 +427,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,359 @@ -464,6 +464,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 338 360 full_fname(fname)); 339 361 return 0; … … 343 365 sx2.acc_acl = sx2.def_acl = NULL; 344 366 #endif 345 @@ -474,6 +475,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 367 @@ -505,6 +506,9 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 368 || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode)) 369 || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode))) 370 flags |= ATTRS_SKIP_MTIME; 371 + /* Don't set the creation date on the root folder of an HFS+ volume. */ 372 + if (sxp->st.st_ino == 2 && S_ISDIR(sxp->st.st_mode)) 373 + flags |= ATTRS_SKIP_CRTIME; 374 if (!(flags & ATTRS_SKIP_MTIME) 375 && 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, 346 378 else 347 379 file->flags |= FLAG_TIME_FAILED; … … 358 390 change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file); 359 391 change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP) 360 @@ -6 21,7 +630,7 @@ int finish_transfer(const char *fname, const char *fnametmp,392 @@ -675,7 +687,7 @@ int finish_transfer(const char *fname, const char *fnametmp, 361 393 /* Change permissions before putting the file into place. */ 362 394 set_file_attrs(fnametmp, file, NULL, fnamecmp, … … 367 399 /* move tmp file over real file */ 368 400 if (verbose > 2) 369 @@ - 652,7 +661,7 @@ int finish_transfer(const char *fname, const char *fnametmp,401 @@ -706,7 +718,7 @@ int finish_transfer(const char *fname, const char *fnametmp, 370 402 371 403 do_set_file_attrs: … … 387 419 388 420 /* These flags are used in the live flist data. */ 389 @@ -1 57,6 +158,7 @@421 @@ -162,6 +163,7 @@ 390 422 #define ATTRS_REPORT (1<<0) 391 423 #define ATTRS_SKIP_MTIME (1<<1) … … 395 427 #define FULL_FLUSH 1 396 428 #define NORMAL_FLUSH 0 397 @@ -17 3,7 +175,7 @@429 @@ -178,7 +180,7 @@ 398 430 #define FNAMECMP_FUZZY 0x83 399 431 … … 404 436 #define ITEM_REPORT_SIZE (1<<2) /* regular files only */ 405 437 #define ITEM_REPORT_TIMEFAIL (1<<2) /* symlinks only */ 406 @@ -6 58,6 +660,7 @@ extern int file_extra_cnt;438 @@ -677,6 +679,7 @@ extern int file_extra_cnt; 407 439 extern int inc_recurse; 408 440 extern int uid_ndx; … … 412 444 extern int acls_ndx; 413 445 extern int xattrs_ndx; 414 @@ -6 65,6 +668,7 @@ extern int xattrs_ndx;446 @@ -684,6 +687,7 @@ extern int xattrs_ndx; 415 447 #define FILE_STRUCT_LEN (offsetof(struct file_struct, basename)) 416 448 #define EXTRA_LEN (sizeof (union file_extras)) … … 420 452 #define DIRNODE_EXTRA_CNT 3 421 453 #define SUM_EXTRA_CNT ((MAX_DIGEST_LEN + EXTRA_LEN - 1) / EXTRA_LEN) 422 @@ -9 32,6 +936,7 @@ typedef struct {454 @@ -951,6 +955,7 @@ typedef struct { 423 455 424 456 typedef struct { … … 439 471 --fake-super store/recover privileged attrs using xattrs 440 472 -S, --sparse handle sparse files efficiently 441 @@ -10 39,6 +1040,9 @@ it is preserving modification times (see bf(--times)). If NFS is sharing473 @@ -1086,6 +1087,9 @@ it is preserving modification times (see bf(--times)). If NFS is sharing 442 474 the directories on the receiving side, it is a good idea to use bf(-O). 443 475 This option is inferred if you use bf(--backup) without bf(--backup-dir). … … 449 481 activities even if the receiving rsync wasn't run by the super-user. These 450 482 activities include: preserving users via the bf(--owner) option, preserving 451 @@ -17 17,7 +1721,7 @@ with older versions of rsync, but that also turns on the output of other483 @@ -1782,7 +1786,7 @@ with older versions of rsync, but that also turns on the output of other 452 484 verbose messages). 453 485 … … 458 490 other letters represent attributes that may be output if they are being 459 491 modified. 460 @@ -1 776,6 +1780,8 @@ quote(itemization(492 @@ -1841,6 +1845,8 @@ quote(itemization( 461 493 it() The bf(f) means that the fileflags information changed. 462 494 it() The bf(a) means that the ACL information changed. … … 470 502 --- a/syscall.c 471 503 +++ b/syscall.c 472 @@ -37,6 +37,1 4@@ extern int force_change;504 @@ -37,6 +37,13 @@ extern int force_change; 473 505 extern int preserve_perms; 474 506 extern int preserve_executability; 475 507 476 +#pragma pack(push) 477 +#pragma pack(4) 508 +#pragma pack(push, 4) 478 509 +struct create_time { 479 510 + uint32 length; … … 485 516 do { \ 486 517 if (x) { \ 487 @@ -394,3 +399,33 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence) 488 return lseek(fd, offset, whence); 518 @@ -529,6 +536,36 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence) 489 519 #endif 490 520 } 491 + 521 492 522 +time_t get_create_time(const char *path) 493 523 +{ … … 519 549 + return setattrlist(path, &attrList, &ts, sizeof ts, FSOPT_NOFOLLOW); 520 550 +} 551 + 552 #ifdef HAVE_UTIMENSAT 553 int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags) 554 { 521 555 diff --git a/testsuite/crtimes.test b/testsuite/crtimes.test 522 556 new file mode 100644 … … 561 595 +allspace=' ' 562 596 +dots='......' # trailing dots after changes 597 tab_ch=' ' # a single tab character 563 598 564 599 # Berkley's nice. 565 PATH="$PATH:/usr/ucb"566 600 diff --git a/tls.c b/tls.c 567 601 --- a/tls.c … … 668 702 --- a/proto.h 669 703 +++ b/proto.h 670 @@ -31 4,6 +314,8 @@ int do_stat(const char *fname, STRUCT_ST704 @@ -315,6 +315,8 @@ int do_stat(const char *fname, STRUCT_ST 671 705 int do_lstat(const char *fname, STRUCT_STAT *st); 672 706 int do_fstat(int fd, STRUCT_STAT *st); … … 674 708 +time_t get_create_time(const char *path); 675 709 +int set_create_time(const char *path, time_t crtime); 676 void set_compression(const char *fname);677 void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,678 int32 n, int32 toklen);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); 679 713 diff -up a/rsync.1 b/rsync.1 680 714 --- a/rsync.1 681 715 +++ b/rsync.1 682 @@ -429,6 +429,7 @@ to the detailed description below for a 716 @@ -429,6 +429,7 @@ to the detailed description below for a 683 717 \-D same as \-\-devices \-\-specials 684 718 \-t, \-\-times preserve modification times 685 719 \-O, \-\-omit\-dir\-times omit directories from \-\-times 686 720 + \-N, \-\-crtimes preserve create times (newness) 687 \-\-super receiver attempts super -user activities721 \-\-super receiver attempts super\-user activities 688 722 \-\-fake\-super store/recover privileged attrs using xattrs 689 723 \-S, \-\-sparse handle sparse files efficiently 690 @@ -1 194,6 +1195,10 @@ it is preserving modification times (see724 @@ -1253,6 +1254,10 @@ it is preserving modification times (see 691 725 the directories on the receiving side, it is a good idea to use \fB\-O\fP. 692 726 This option is inferred if you use \fB\-\-backup\fP without \fB\-\-backup\-dir\fP. … … 697 731 +.IP 698 732 .IP "\fB\-\-super\fP" 699 This tells the receiving side to attempt super -user700 activities even if the receiving rsync wasn\(cq\&t run by the super -user. These701 @@ - 1963,7 +1968,7 @@ with older versions of rsync, but that a733 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 @@ -2037,7 +2042,7 @@ with older versions of rsync, but that a 702 736 verbose messages). 703 737 .IP … … 705 739 -format is like the string \fBYXcstpogfax\fP, where \fBY\fP is replaced by the 706 740 +format is like the string \fBYXcstpogfaxn\fP, where \fBY\fP is replaced by the 707 type of update being done, \fBX\fP is replaced by the file -type, and the741 type of update being done, \fBX\fP is replaced by the file\-type, and the 708 742 other letters represent attributes that may be output if they are being 709 743 modified. 710 @@ -2 038,6 +2043,9 @@ The \fBf\fP means that the fileflags inf744 @@ -2112,6 +2117,9 @@ The \fBf\fP means that the fileflags inf 711 745 The \fBa\fP means that the ACL information changed. 712 746 .IP o -
trunk/dports/net/rsync/files/patch-fileflags.diff
r62301 r80017 9 9 make 10 10 11 based-on: 54f00c3f89fc147f2f9cba89d26a5bb1d20e783b11 based-on: 1ddcdaf3f6808ba53aef9e19f630a18808de22ac 12 12 diff --git a/Makefile.in b/Makefile.in 13 13 --- a/Makefile.in … … 34 34 --- a/compat.c 35 35 +++ b/compat.c 36 @@ -4 2,9 +42,11 @@ extern int checksum_seed;36 @@ -43,9 +43,11 @@ extern int checksum_seed; 37 37 extern int basis_dir_cnt; 38 38 extern int prune_empty_dirs; … … 46 46 extern int preserve_xattrs; 47 47 extern int need_messages_from_generator; 48 @@ -6 2,7 +64,7 @@ extern char *iconv_opt;48 @@ -63,7 +65,7 @@ extern char *iconv_opt; 49 49 #endif 50 50 … … 55 55 int receiver_symlink_times = 0; /* receiver can set the time on a symlink */ 56 56 int sender_symlink_iconv = 0; /* sender should convert symlink content */ 57 @@ -1 39,6 +141,8 @@ void setup_protocol(int f_out,int f_in)57 @@ -140,6 +142,8 @@ void setup_protocol(int f_out,int f_in) 58 58 uid_ndx = ++file_extra_cnt; 59 59 if (preserve_gid) … … 64 64 acls_ndx = ++file_extra_cnt; 65 65 if (preserve_xattrs) 66 diff --git a/configure. in b/configure.in67 --- a/configure. in68 +++ b/configure. in69 @@ -56 7,6 +567,7 @@ AC_FUNC_UTIME_NULL66 diff --git a/configure.ac b/configure.ac 67 --- a/configure.ac 68 +++ b/configure.ac 69 @@ -569,6 +569,7 @@ AC_FUNC_UTIME_NULL 70 70 AC_FUNC_ALLOCA 71 71 AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \ … … 84 84 +extern int preserve_fileflags; 85 85 extern int delete_during; 86 extern int uid_ndx;87 extern int gid_ndx;88 @@ -39 6,6 +397,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,86 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, 89 89 { 90 90 static time_t modtime; … … 96 96 static int64 dev; 97 97 #endif 98 @@ -42 5,6 +429,14 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,98 @@ -423,6 +427,14 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file, 99 99 xflags |= XMIT_SAME_MODE; 100 100 else … … 111 111 if (preserve_devices && IS_DEVICE(mode)) { 112 112 if (protocol_version < 28) { 113 @@ -54 9,6 +561,10 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,113 @@ -547,6 +559,10 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file, 114 114 } 115 115 if (!(xflags & XMIT_SAME_MODE)) … … 122 122 if (protocol_version < 30) 123 123 write_int(f, uid); 124 @@ -63 5,6 +651,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,124 @@ -634,6 +650,9 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 125 125 { 126 126 static int64 modtime; … … 132 132 static int64 dev; 133 133 #endif 134 @@ -769,6 +788,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist, 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); 136 modtime = first->modtime; 137 mode = first->mode; 138 +#ifdef SUPPORT_FILEFLAGS 139 + if (preserve_fileflags) 140 + fileflags = F_FFLAGS(first); 141 +#endif 142 if (preserve_uid) 143 uid = F_OWNER(first); 144 if (preserve_gid) 145 @@ -768,6 +791,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 135 146 136 147 if (chmod_modes && !S_ISLNK(mode)) … … 143 154 if (preserve_uid && !(xflags & XMIT_SAME_UID)) { 144 155 if (protocol_version < 30) 145 @@ -9 10,6 +933,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,156 @@ -909,6 +936,10 @@ static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 146 157 } 147 158 #endif 148 159 file->mode = mode; 149 160 +#ifdef SUPPORT_FILEFLAGS 150 + if ( preserve_fileflags)161 + if (fileflags_ndx) /* check the ndx for force_change w/o preserve_fileflags */ 151 162 + F_FFLAGS(file) = fileflags; 152 163 +#endif … … 154 165 F_OWNER(file) = uid; 155 166 if (preserve_gid) { 156 @@ -128 4,6 +1311,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,167 @@ -1283,6 +1314,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, 157 168 } 158 169 #endif … … 162 173 + F_FFLAGS(file) = st.st_flags; 163 174 +#endif 164 if ( uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */175 if (preserve_uid) 165 176 F_OWNER(file) = st.st_uid; 166 if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */ 167 @@ -1427,6 +1458,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist, 168 #endif 177 if (preserve_gid) 178 @@ -1429,6 +1464,9 @@ static struct file_struct *send_file_name(int f, struct file_list *flist, 169 179 #ifdef SUPPORT_XATTRS 170 180 if (preserve_xattrs) { 171 + sx.st.st_mode = file->mode; 181 sx.st.st_mode = file->mode; 182 +#ifdef SUPPORT_FILEFLAGS 183 + sx.st.st_flags = preserve_fileflags ? F_FFLAGS(file) : 0; 184 +#endif 172 185 sx.xattr = NULL; 173 186 if (get_xattr(fname, &sx) < 0) { … … 176 189 --- a/generator.c 177 190 +++ b/generator.c 178 @@ -42,8 +42,10 @@ extern int preserve_devices; 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; 179 200 extern int preserve_specials; 180 201 extern int preserve_hard_links; … … 183 204 extern int preserve_perms; 184 205 extern int preserve_times; 185 +extern int force_change;186 extern int uid_ndx;187 extern int gid_ndx;188 206 extern int delete_mode; 189 @@ -16 6,7 +168,7@@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)207 @@ -164,11 +166,15 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags) 190 208 } 191 209 … … 195 213 196 214 if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) { 197 int save_uid_ndx = uid_ndx; 198 @@ -174,6 +176,13 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags) 215 /* This only happens on the first call to delete_item() since 199 216 * delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */ 200 if (!uid_ndx) 201 uid_ndx = ++file_extra_cnt; 202 +#ifdef SUPPORT_FORCE_CHANGE 203 + if (force_change) { 204 + STRUCT_STAT st; 205 + if (x_lstat(fbuf, &st, NULL) == 0) 206 + make_mutable(fbuf, st.st_mode, st.st_flags, force_change); 207 + } 217 +#ifdef SUPPORT_FORCE_CHANGE 218 + if (force_change) 219 + make_mutable(fbuf, NULL, NO_FFLAGS, force_change); 208 220 +#endif 209 221 ignore_perishable = 1; 210 222 /* If DEL_RECURSE is not set, this just reports emptiness. */ 211 223 ret = delete_dir_contents(fbuf, flags); 212 @@ -2 94,8 +303,12@@ static enum delret delete_dir_contents(char *fname, uint16 flags)224 @@ -285,8 +291,14 @@ static enum delret delete_dir_contents(char *fname, uint16 flags) 213 225 } 214 226 215 227 strlcpy(p, fp->basename, remainder); 216 228 +#ifdef SUPPORT_FORCE_CHANGE 217 + if (force_change) 218 + make_mutable(fname, fp->mode, F_FFLAGS(fp), force_change); 219 +#endif 220 if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid) 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) 221 235 - do_chmod(fname, fp->mode | S_IWUSR); 222 236 + do_chmod(fname, fp->mode | S_IWUSR, NO_FFLAGS); … … 224 238 if (S_ISDIR(fp->mode)) { 225 239 if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS) 226 @@ - 599,6 +612,11@@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)227 && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))228 return 0;229 240 @@ -647,6 +659,10 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp) 241 return 0; 242 if (perms_differ(file, sxp)) 243 return 0; 230 244 +#ifdef SUPPORT_FILEFLAGS 231 + if (preserve_fileflags && !S_ISLNK(file->mode) && sxp->st.st_flags != F_FFLAGS(file)) 232 + return 0; 233 +#endif 234 + 235 if (am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file)) 236 return 0; 237 238 @@ -664,6 +682,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre 245 + if (preserve_fileflags && sxp->st.st_flags != F_FFLAGS(file)) 246 + return 0; 247 +#endif 248 if (ownership_differs(file, sxp)) 249 return 0; 250 #ifdef SUPPORT_ACLS 251 @@ -698,6 +714,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre 239 252 if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP) 240 253 && sxp->st.st_gid != (gid_t)F_GROUP(file)) … … 248 261 if (preserve_acls && !S_ISLNK(file->mode)) { 249 262 if (!ACL_READY(*sxp)) 250 @@ -14 42,6 +1465,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,263 @@ -1491,6 +1512,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, 251 264 file->mode = dest_mode(file->mode, sx.st.st_mode, 252 265 dflt_perms, statret == 0); … … 259 272 int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx, 260 273 itemizing, code); 261 @@ -1 482,10 +1509,15@@ static void recv_generator(char *fname, struct file_struct *file, int ndx,274 @@ -1526,10 +1551,17 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, 262 275 /* We need to ensure that the dirs in the transfer have writable 263 276 * permissions during the time we are putting files within them. 264 277 * This is then fixed after the transfer is done. */ 265 278 +#ifdef SUPPORT_FORCE_CHANGE 266 + if (force_change && F_FFLAGS(file) & force_change 267 + && make_mutable(fname, file->mode, F_FFLAGS(file), force_change)) 268 + need_retouch_dir_perms = 1; 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 + } 269 284 +#endif 270 285 #ifdef HAVE_CHMOD … … 276 291 "failed to modify permissions on %s", 277 292 full_fname(fname)); 278 @@ -15 20,6 +1552,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,293 @@ -1572,6 +1604,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, 279 294 file->mode = dest_mode(file->mode, sx.st.st_mode, dflt_perms, 280 295 exists); … … 287 302 #ifdef SUPPORT_HARD_LINKS 288 303 if (preserve_hard_links && F_HLINK_NOT_FIRST(file) 289 @@ -2 061,13 +2097,17 @@ static void touch_up_dirs(struct file_list *flist, int ndx)304 @@ -2115,13 +2151,17 @@ static void touch_up_dirs(struct file_list *flist, int ndx) 290 305 continue; 291 306 fname = f_name(file, NULL); … … 310 325 --- a/log.c 311 326 +++ b/log.c 312 @@ -6 60,7 +660,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,327 @@ -658,7 +658,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op, 313 328 c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p'; 314 329 c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o'; … … 319 334 c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x'; 320 335 c[11] = '\0'; 336 diff --git a/main.c b/main.c 337 --- a/main.c 338 +++ b/main.c 339 @@ -26,6 +26,9 @@ 340 #if defined CONFIG_LOCALE && defined HAVE_LOCALE_H 341 #include <locale.h> 342 #endif 343 +#ifdef SUPPORT_FORCE_CHANGE 344 +#include <sys/sysctl.h> 345 +#endif 346 347 extern int verbose; 348 extern int dry_run; 349 @@ -51,6 +54,7 @@ extern int protocol_version; 350 extern int file_total; 351 extern int recurse; 352 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) 358 * points to an identical file won't be replaced by the referent. */ 359 copy_links = copy_dirlinks = copy_unsafe_links = 0; 360 361 +#ifdef SUPPORT_FORCE_CHANGE 362 + if (force_change & SYS_IMMUTABLE) { 363 + /* Determine whether we'll be able to unlock a system immutable item. */ 364 + int mib[2]; 365 + int securityLevel = 0; 366 + size_t len = sizeof securityLevel; 367 + 368 + mib[0] = CTL_KERN; 369 + mib[1] = KERN_SECURELVL; 370 + if (sysctl(mib, 2, &securityLevel, &len, NULL, 0) == 0 && securityLevel > 0) { 371 + rprintf(FERROR, "System security level is too high to force mutability on system immutable files and directories.\n"); 372 + exit_cleanup(RERR_UNSUPPORTED); 373 + } 374 + } 375 +#endif 376 + 377 #ifdef SUPPORT_HARD_LINKS 378 if (preserve_hard_links && !inc_recurse) 379 match_hard_links(first_flist); 321 380 diff --git a/options.c b/options.c 322 381 --- a/options.c … … 336 395 +int force_change = 0; 337 396 int io_timeout = 0; 338 int allowed_lull = 0;339 397 int prune_empty_dirs = 0; 340 @@ -224,6 +226,7 @@ static void print_rsync_version(enum logcode f) 398 int use_qsort = 0; 399 @@ -223,6 +225,7 @@ static void print_rsync_version(enum logcode f) 341 400 char const *links = "no "; 342 401 char const *iconv = "no "; … … 346 405 347 406 #if SUBPROTOCOL_VERSION != 0 348 @@ -25 7,6 +260,9 @@ static void print_rsync_version(enum logcode f)349 #if defined HAVE_LUTIMES && defined HAVE_UTIMES407 @@ -256,6 +259,9 @@ static void print_rsync_version(enum logcode f) 408 #ifdef CAN_SET_SYMLINK_TIMES 350 409 symtimes = ""; 351 410 #endif … … 356 415 rprintf(f, "%s version %s protocol version %d%s\n", 357 416 RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol); 358 @@ -2 70,8 +276,8 @@ static void print_rsync_version(enum logcode f)417 @@ -269,8 +275,8 @@ static void print_rsync_version(enum logcode f) 359 418 (int)(sizeof (int64) * 8)); 360 419 rprintf(f, " %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n", … … 367 426 #ifdef MAINTAINER_MODE 368 427 rprintf(f, "Panic Action: \"%s\"\n", get_panic_action()); 369 @@ -33 8,6 +344,9 @@ void usage(enum logcode F)428 @@ -337,6 +343,9 @@ void usage(enum logcode F) 370 429 rprintf(F," -K, --keep-dirlinks treat symlinked dir on receiver as dir\n"); 371 430 rprintf(F," -H, --hard-links preserve hard links\n"); … … 377 436 rprintf(F," --chmod=CHMOD affect file and/or directory permissions\n"); 378 437 #ifdef SUPPORT_ACLS 379 @@ -37 5,7 +384,12 @@ void usage(enum logcode F)438 @@ -374,7 +383,12 @@ void usage(enum logcode F) 380 439 rprintf(F," --delete-after receiver deletes after transfer, not during\n"); 381 440 rprintf(F," --delete-excluded also delete excluded files from destination dirs\n"); … … 391 450 rprintf(F," --max-size=SIZE don't transfer any file larger than SIZE\n"); 392 451 rprintf(F," --min-size=SIZE don't transfer any file smaller than SIZE\n"); 393 @@ -4 80,6 +494,10 @@ static struct poptOption long_options[] = {452 @@ -479,6 +493,10 @@ static struct poptOption long_options[] = { 394 453 {"perms", 'p', POPT_ARG_VAL, &preserve_perms, 1, 0, 0 }, 395 454 {"no-perms", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 }, … … 402 461 {"acls", 'A', POPT_ARG_NONE, 0, 'A', 0, 0 }, 403 462 {"no-acls", 0, POPT_ARG_VAL, &preserve_acls, 0, 0, 0 }, 404 @@ -55 8,6 +576,14 @@ static struct poptOption long_options[] = {463 @@ -557,6 +575,14 @@ static struct poptOption long_options[] = { 405 464 {"remove-source-files",0,POPT_ARG_VAL, &remove_source_files, 1, 0, 0 }, 406 465 {"force", 0, POPT_ARG_VAL, &force_delete, 1, 0, 0 }, … … 417 476 {"no-ignore-errors", 0, POPT_ARG_VAL, &ignore_errors, 0, 0, 0 }, 418 477 {"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 }, 419 @@ -187 4,6 +1900,9 @@ void server_options(char **args, int *argc_p)478 @@ -1879,6 +1905,9 @@ void server_options(char **args, int *argc_p) 420 479 if (xfer_dirs && !recurse && delete_mode && am_sender) 421 480 args[ac++] = "--no-r"; … … 427 486 if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0) 428 487 goto oom; 429 @@ -196 1,6 +1990,16 @@ void server_options(char **args, int *argc_p)488 @@ -1966,6 +1995,16 @@ void server_options(char **args, int *argc_p) 430 489 args[ac++] = "--delete-excluded"; 431 490 if (force_delete) … … 447 506 --- a/rsync.c 448 507 +++ b/rsync.c 449 @@ -32,6 +32,7 @@ extern int dry_run; 508 @@ -29,9 +29,11 @@ 509 510 extern int verbose; 511 extern int dry_run; 512 +extern int force_change; 450 513 extern int preserve_acls; 451 514 extern int preserve_xattrs; … … 455 518 extern int preserve_times; 456 519 extern int am_root; 457 @@ -37 6,6 +377,39@@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,520 @@ -374,6 +376,74 @@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms, 458 521 return new_mode; 459 522 } … … 465 528 + if (do_chflags(fname, fileflags) != 0) { 466 529 + rsyserr(FERROR_XFER, errno, 467 + "failed to set file flagson %s",468 + f ull_fname(fname));530 + "failed to set fileflags (%x) on %s", 531 + fileflags, full_fname(fname)); 469 532 + return 0; 470 533 + } … … 473 536 +} 474 537 + 475 +/* Remove immutable flags from an object, so it can be altered/removed. */ 476 +int make_mutable(const char *fname, mode_t mode, uint32 fileflags, uint32 iflags) 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) 477 543 +{ 478 + if (S_ISLNK(mode) || !(fileflags & iflags)) 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)) 479 556 + return 0; 557 + 480 558 + if (!set_fileflags(fname, fileflags & ~iflags)) 481 + return -1; 482 + return 1; 559 + return 0; 560 + 561 + return fileflags; 483 562 +} 484 563 + … … 486 565 +int undo_make_mutable(const char *fname, uint32 fileflags) 487 566 +{ 488 + if (!set_fileflags(fname, fileflags)) 567 + if (!set_fileflags(fname, fileflags)) { 568 + rsyserr(FINFO, errno, "failed to relock %s", full_fname(fname)); 489 569 + return -1; 570 + } 490 571 + 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); 491 589 +} 492 590 +#endif … … 495 593 const char *fnamecmp, int flags) 496 594 { 497 @@ -429,7 +463,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 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, 498 618 flags |= ATTRS_SKIP_MTIME; 499 619 if (!(flags & ATTRS_SKIP_MTIME) … … 504 624 rsyserr(FERROR_XFER, errno, "failed to set times on %s", 505 625 full_fname(fname)); 506 @@ -465,7 + 499,8@@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,626 @@ -465,7 +543,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 507 627 if (am_root >= 0) { 508 if (do_lchown(fname, 509 change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid, 510 - change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid) != 0) { 511 + change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid, 512 + sxp->st.st_mode, ST_FLAGS(sxp->st)) != 0) { 628 uid_t uid = change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid; 629 gid_t gid = change_gid ? (gid_t)F_GROUP(file) : sxp->st.st_gid; 630 - if (do_lchown(fname, uid, gid) != 0) { 631 + if (do_lchown(fname, uid, gid, sxp->st.st_mode, ST_FLAGS(sxp->st)) != 0) { 513 632 /* We shouldn't have attempted to change uid 514 633 * or gid unless have the privilege. */ 515 634 rsyserr(FERROR_XFER, errno, "%s %s failed", 516 @@ - 497,7 +532,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,635 @@ -503,7 +581,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 517 636 518 637 #ifdef HAVE_CHMOD … … 523 642 rsyserr(FERROR_XFER, errno, 524 643 "failed to set permissions on %s", 525 @@ -5 09,6 +544,19@@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,644 @@ -515,6 +593,24 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 526 645 } 527 646 #endif 528 647 648 +#ifdef SUPPORT_FORCE_CHANGE 649 + if (became_mutable) 650 + undo_make_mutable(fname, sxp->st.st_flags); 651 +#endif 652 + 529 653 +#ifdef SUPPORT_FILEFLAGS 530 654 + if (preserve_fileflags && !S_ISLNK(sxp->st.st_mode) … … 543 667 if (updated) 544 668 rprintf(FCLIENT, "%s\n", fname); 545 @@ -57 2,7 +620,8 @@ int finish_transfer(const char *fname, const char *fnametmp,669 @@ -578,7 +674,8 @@ int finish_transfer(const char *fname, const char *fnametmp, 546 670 547 671 /* Change permissions before putting the file into place. */ … … 553 677 /* move tmp file over real file */ 554 678 if (verbose > 2) 555 @@ -59 1,6 +640,10 @@ int finish_transfer(const char *fname, const char *fnametmp,679 @@ -597,6 +694,10 @@ int finish_transfer(const char *fname, const char *fnametmp, 556 680 } 557 681 if (ret == 0) { … … 575 699 /* These flags are used in the live flist data. */ 576 700 577 @@ -1 55,6 +156,7 @@701 @@ -160,6 +161,7 @@ 578 702 579 703 #define ATTRS_REPORT (1<<0) … … 583 707 #define FULL_FLUSH 1 584 708 #define NORMAL_FLUSH 0 585 @@ -18 1,6 +183,7 @@709 @@ -186,6 +188,7 @@ 586 710 #define ITEM_REPORT_GROUP (1<<6) 587 711 #define ITEM_REPORT_ACL (1<<7) … … 591 715 #define ITEM_XNAME_FOLLOWS (1<<12) 592 716 #define ITEM_IS_NEW (1<<13) 593 @@ -4 63,6 +466,28 @@ typedef unsigned int size_t;717 @@ -482,6 +485,28 @@ typedef unsigned int size_t; 594 718 #endif 595 719 #endif … … 620 744 * If some code depends on 32-bit truncation, it will need to 621 745 * take special action in a "#if SIZEOF_INT32 > 4" section. */ 622 @@ -6 33,6 +658,7 @@ extern int file_extra_cnt;746 @@ -652,6 +677,7 @@ extern int file_extra_cnt; 623 747 extern int inc_recurse; 624 748 extern int uid_ndx; … … 628 752 extern int xattrs_ndx; 629 753 630 @@ -6 70,6 +696,11 @@ extern int xattrs_ndx;754 @@ -689,6 +715,11 @@ extern int xattrs_ndx; 631 755 /* When the associated option is on, all entries will have these present: */ 632 756 #define F_OWNER(f) REQ_EXTRA(f, uid_ndx)->unum … … 673 797 dit(--no-OPTION) You may turn off one or more implied options by prefixing 674 798 the option name with "no-". Not all options may be prefixed with a "no-": 675 @@ -8 09,7 +814,7 @@ they would be using bf(--copy-links).799 @@ -827,7 +832,7 @@ they would be using bf(--copy-links). 676 800 Without this option, if the sending side has replaced a directory with a 677 801 symlink to a directory, the receiving side will delete anything that is in … … 682 806 See also bf(--keep-dirlinks) for an analogous option for the receiving 683 807 side. 684 @@ -9 46,6 +951,29 @@ super-user copies all namespaces except system.*. A normal user only copies685 the user.* namespace. To be able to backup and restore non-user namespaces as686 a normal user, see the bf(--fake-super) option.808 @@ -990,6 +995,29 @@ Note that this option does not copy rsyncs special xattr values (e.g. those 809 used by bf(--fake-super)) unless you repeat the option (e.g. -XX). This 810 "copy all xattrs" mode cannot be used with bf(--fake-super). 687 811 688 812 +dit(bf(--fileflags)) This option causes rsync to update the file-flags to be … … 712 836 comma-separated "chmod" strings to the permission of the files in the 713 837 transfer. The resulting value is treated as though it were the permissions 714 @@ -12 17,12 +1245,13 @@ See bf(--delete) (which is implied) for more details on file-deletion.838 @@ -1260,12 +1288,13 @@ See bf(--delete) (which is implied) for more details on file-deletion. 715 839 dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files 716 840 even when there are I/O errors. … … 729 853 730 854 dit(bf(--max-delete=NUM)) This tells rsync not to delete more than NUM 731 @@ -1 688,7 +1717,7 @@ with older versions of rsync, but that also turns on the output of other855 @@ -1753,7 +1782,7 @@ with older versions of rsync, but that also turns on the output of other 732 856 verbose messages). 733 857 … … 738 862 other letters represent attributes that may be output if they are being 739 863 modified. 740 @@ -1 744,7 +1773,7 @@ quote(itemization(864 @@ -1809,7 +1838,7 @@ quote(itemization( 741 865 sender's value (requires bf(--owner) and super-user privileges). 742 866 it() A bf(g) means the group is different and is being updated to the … … 758 882 extern int preserve_executability; 759 883 760 @@ -50, 7 +51,23@@ int do_unlink(const char *fname)884 @@ -50,14 +51,56 @@ int do_unlink(const char *fname) 761 885 { 762 886 if (dry_run) return 0; … … 765 889 + if (unlink(fname) == 0) 766 890 + return 0; 767 +#ifdef SUPPORT_FORCE_CHANGE 768 + if (force_change && errno == EPERM) { 769 + STRUCT_STAT st; 770 + 771 + if (x_lstat(fname, &st, NULL) == 0 772 + && make_mutable(fname, st.st_mode, st.st_flags, force_change) > 0) { 773 + if (unlink(fname) == 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) 774 905 + return 0; 775 + undo_make_mutable(fname, st.st_flags);776 906 + } 777 + /* TODO: handle immutable directories */ 778 + errno = EPERM; 779 + } 780 +#endif 907 + if (file_flags) 908 + undo_make_mutable(fname, file_flags); 909 + errno = saved_errno; 910 + } 911 +#endif 912 + 781 913 + return -1; 782 914 } 783 915 784 916 int do_symlink(const char *fname1, const char *fname2) 785 @@ -69,14 +86,37 @@ int do_link(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; 786 967 } 787 968 #endif … … 798 979 + if (lchown(path, owner, group) == 0) 799 980 + return 0; 800 +#ifdef SUPPORT_FORCE_CHANGE 801 + if (force_change && errno == EPERM) { 802 + if (fileflags == NO_FFLAGS) { 803 + STRUCT_STAT st; 804 + if (x_lstat(path, &st, NULL) == 0) { 805 + mode = st.st_mode; 806 + fileflags = st.st_flags; 807 + } 808 + } 809 + if (fileflags != NO_FFLAGS 810 + && make_mutable(path, mode, fileflags, force_change) > 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) { 811 987 + int ret = lchown(path, owner, group); 812 988 + undo_make_mutable(path, fileflags); … … 814 990 + return 0; 815 991 + } 816 + errno = EPERM;992 + errno = saved_errno; 817 993 + } 818 994 +#else 819 995 + mode = fileflags = 0; /* avoid compiler warning */ 820 996 +#endif 997 + 821 998 + return -1; 822 999 } 823 1000 824 1001 int do_mknod(const char *pathname, mode_t mode, dev_t dev) 825 @@ -116,7 +1 56,7 @@ 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) 826 1003 return -1; 827 1004 close(sock); … … 832 1009 return 0; 833 1010 #endif 834 @@ -133, 7 +173,22@@ int do_rmdir(const char *pathname)1011 @@ -133,21 +213,63 @@ int do_rmdir(const char *pathname) 835 1012 { 836 1013 if (dry_run) return 0; … … 839 1016 + if (rmdir(pathname) == 0) 840 1017 + return 0; 841 +#ifdef SUPPORT_FORCE_CHANGE 842 + if (force_change && errno == EPERM) { 843 + STRUCT_STAT st; 844 + 845 + if (x_lstat(pathname, &st, NULL) == 0 846 + && make_mutable(pathname, st.st_mode, st.st_flags, force_change) > 0) { 847 + if (rmdir(pathname) == 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) 848 1032 + return 0; 849 + undo_make_mutable(pathname, st.st_flags);850 1033 + } 851 + errno = EPERM; 852 + } 853 +#endif 1034 + if (file_flags) 1035 + undo_make_mutable(pathname, file_flags); 1036 + errno = saved_errno; 1037 + } 1038 +#endif 1039 + 854 1040 + return -1; 855 1041 } 856 1042 857 1043 int do_open(const char *pathname, int flags, mode_t mode) 858 @@ -147,7 +202,7 @@ 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; 859 1070 } 860 1071 … … 865 1076 int code; 866 1077 if (dry_run) return 0; 867 @@ -168,17 +223,74 @@ int do_chmod(const char *path, mode_t mode) 868 #endif 1078 @@ -170,17 +292,93 @@ int do_chmod(const char *path, mode_t mode) 869 1079 } else 870 1080 code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */ 871 +#ifdef SUPPORT_FORCE_CHANGE 872 + if (code < 0 && force_change && errno == EPERM && !S_ISLNK(mode)) {873 + if (fileflags == NO_FFLAGS) {874 + STRUCT_STAT st;875 + if (x_lstat(path, &st, NULL) == 0)876 + fileflags = st.st_flags;877 + }878 + if (fileflags != NO_FFLAGS879 + && make_mutable(path, mode, fileflags, force_change) > 0) {1081 #endif /* !HAVE_LCHMOD */ 1082 +#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 880 1090 + code = chmod(path, mode & CHMOD_BITS); 1091 +#endif 881 1092 + undo_make_mutable(path, fileflags); 882 1093 + if (code == 0) 883 1094 + return 0; 884 1095 + } 885 + errno = EPERM;1096 + errno = saved_errno; 886 1097 + } 887 1098 +#else … … 910 1121 + if (rename(fname1, fname2) == 0) 911 1122 + return 0; 912 +#ifdef SUPPORT_FORCE_CHANGE 913 + if (force_change && errno == EPERM) { 914 + STRUCT_STAT st1, st2; 915 + int became_mutable; 916 + 917 + if (x_lstat(fname1, &st1, NULL) != 0) 918 + goto failed; 919 + became_mutable = make_mutable(fname1, st1.st_mode, st1.st_flags, force_change) > 0; 920 + if (became_mutable && rename(fname1, fname2) == 0) 921 + goto success; 922 + if (x_lstat(fname2, &st2, NULL) == 0 923 + && make_mutable(fname2, st2.st_mode, st2.st_flags, force_change) > 0) { 924 + if (rename(fname1, fname2) == 0) { 925 + success: 926 + if (became_mutable) /* Yes, use fname2 and st1! */ 927 + undo_make_mutable(fname2, st1.st_flags); 928 + 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); 929 1153 + } 930 + undo_make_mutable(fname2, st2.st_flags);931 1154 + } 932 + /* TODO: handle immutable directories */ 933 + if (became_mutable) 934 + undo_make_mutable(fname1, st1.st_flags); 935 + failed: 936 + errno = EPERM; 937 + } 938 +#endif 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; 1166 + } 1167 +#endif 1168 + 939 1169 + return -1; 940 1170 } 941 1171 942 void trim_trailing_slashes(char *name) 1172 #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 943 1354 diff --git a/t_stub.c b/t_stub.c 944 1355 --- a/t_stub.c … … 949 1360 int module_dirlen = 0; 950 1361 +int force_change = 0; 1362 int preserve_times = 0; 951 1363 int preserve_xattrs = 0; 952 1364 mode_t orig_umask = 002; 953 char *partial_dir; 954 @@ -89,3 +90,23 @@ struct filter_list_struct daemon_filter_list; 1365 @@ -90,3 +91,27 @@ struct filter_list_struct daemon_filter_list; 955 1366 { 956 1367 return "tester"; … … 958 1369 + 959 1370 +#if defined SUPPORT_FILEFLAGS || defined SUPPORT_FORCE_CHANGE 960 + int make_mutable(UNUSED(const char *fname), UNUSED(mode_tmode), UNUSED(uint32 fileflags), UNUSED(uint32 iflags))1371 + uint32 make_mutable(UNUSED(const char *fname), UNUSED(mode_t *mode), UNUSED(uint32 fileflags), UNUSED(uint32 iflags)) 961 1372 +{ 962 1373 + return 0; 963 1374 +} 964 1375 + 965 +/* Undo a prior make_mutable() call that returned a 1. */966 1376 + 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)) 967 1382 +{ 968 1383 + return 0; … … 979 1394 --- a/util.c 980 1395 +++ b/util.c 981 @@ -29,6 +29,7 @@ extern int module_id; 982 extern int modify_window; 983 extern int relative_paths; 984 extern int human_readable; 985 +extern int force_change; 986 extern int preserve_xattrs; 987 extern char *module_dir; 988 extern unsigned int module_dirlen; 989 @@ -123,7 +124,7 @@ NORETURN void overflow_exit(const char *str) 990 exit_cleanup(RERR_MALLOC); 991 } 992 1396 @@ -125,7 +125,7 @@ NORETURN void overflow_exit(const char *str) 1397 1398 /* This returns 0 for success, 1 for a symlink if symlink time-setting 1399 * is not possible, or -1 for any other error. */ 993 1400 -int set_modtime(const char *fname, time_t modtime, mode_t mode) 994 1401 +int set_modtime(const char *fname, time_t modtime, mode_t mode, uint32 fileflags) 995 1402 { 996 #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES 997 if (S_ISLNK(mode)) 998 @@ -140,6 +141,7 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode) 999 return 0; 1000 1001 { 1002 + int ret; 1403 static int switch_step = 0; 1404 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 1408 #include "case_N.h" 1409 - if (do_utimensat(fname, modtime, 0) == 0) 1410 + if (do_utimensat(fname, modtime, 0, mode, fileflags) == 0) 1411 break; 1412 if (errno != ENOSYS) 1413 return -1; 1414 @@ -148,7 +148,7 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode) 1415 1416 #ifdef HAVE_LUTIMES 1417 #include "case_N.h" 1418 - if (do_lutimes(fname, modtime, 0) == 0) 1419 + if (do_lutimes(fname, modtime, 0, mode, fileflags) == 0) 1420 break; 1421 if (errno != ENOSYS) 1422 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" 1003 1426 #ifdef HAVE_UTIMES 1004 struct timeval t[2]; 1005 t[0].tv_sec = time(NULL); 1006 @@ -153,20 +155,39 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode) 1007 return 0; 1008 } 1009 # endif 1010 - return utimes(fname, t); 1011 +#define SET_THE_TIME(fn) utimes(fn, t) 1012 #elif defined HAVE_STRUCT_UTIMBUF 1013 struct utimbuf tbuf; 1014 tbuf.actime = time(NULL); 1015 tbuf.modtime = modtime; 1016 - return utime(fname,&tbuf); 1017 +#define SET_THE_TIME(fn) utime(fn, &tbuf) 1018 #elif defined HAVE_UTIME 1019 time_t t[2]; 1020 t[0] = time(NULL); 1021 t[1] = modtime; 1022 - return utime(fname,t); 1023 +#define SET_THE_TIME(fn) utime(fn, t) 1427 - if (do_utimes(fname, modtime, 0) == 0) 1428 + if (do_utimes(fname, modtime, 0, mode, fileflags) == 0) 1429 break; 1024 1430 #else 1025 #error No file-time-modification routine found! 1026 #endif 1027 + ret = SET_THE_TIME(fname); 1028 +#ifdef SUPPORT_FORCE_CHANGE 1029 + if (ret != 0 && force_change && errno == EPERM) { 1030 + if (fileflags == NO_FFLAGS) { 1031 + STRUCT_STAT st; 1032 + if (x_lstat(fname, &st, NULL) == 0) 1033 + fileflags = st.st_flags; 1034 + } 1035 + if (fileflags != NO_FFLAGS 1036 + && make_mutable(fname, mode, fileflags, force_change) > 0) { 1037 + ret = SET_THE_TIME(fname); 1038 + undo_make_mutable(fname, fileflags); 1039 + } 1040 + errno = EPERM; 1041 + } 1042 +#else 1043 + fileflags = 0; /* avoid compiler warning */ 1044 +#endif 1045 + return ret; 1046 } 1047 } 1431 - if (do_utime(fname, modtime, 0) == 0) 1432 + if (do_utime(fname, modtime, 0, mode, fileflags) == 0) 1433 break; 1434 #endif 1048 1435 1049 1436 diff --git a/xattrs.c b/xattrs.c 1050 1437 --- a/xattrs.c 1051 1438 +++ b/xattrs.c 1052 @@ -283,6 +283,10 @@ int get_xattr(const char *fname, stat_x *sxp) 1053 { 1054 sxp->xattr = new(item_list); 1055 *sxp->xattr = empty_xattr; 1056 + 1057 + if (IS_SPECIAL(sxp->st.st_mode) || IS_DEVICE(sxp->st.st_mode)) 1058 + return 0; 1059 + 1060 if (rsync_xal_get(fname, sxp->xattr) < 0) { 1061 free_xattr(sxp); 1062 return -1; 1063 @@ -883,6 +887,11 @@ int set_xattr(const char *fname, const struct file_struct *file, 1064 return -1; 1065 } 1066 1067 + if (IS_SPECIAL(sxp->st.st_mode) || IS_DEVICE(sxp->st.st_mode)) { 1068 + errno = ENOTSUP; 1069 + return -1; 1070 + } 1071 + 1072 ndx = F_XATTR(file); 1073 return rsync_xal_set(fname, lst + ndx, fnamecmp, sxp); 1074 } 1075 @@ -999,7 +1008,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode) 1439 @@ -1041,7 +1041,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode) 1076 1440 mode = (fst.st_mode & _S_IFMT) | (fmode & ACCESSPERMS) 1077 1441 | (S_ISDIR(fst.st_mode) ? 0700 : 0600); … … 1098 1462 --- a/configure.sh 1099 1463 +++ b/configure.sh 1100 @@ -7 351,6 +7351,7 @@ fi1464 @@ -7425,6 +7425,7 @@ fi 1101 1465 1102 1466 for ac_func in waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \ … … 1109 1473 --- a/proto.h 1110 1474 +++ b/proto.h 1111 @@ -274,6 +274, 8@@ int read_ndx_and_attrs(int f_in, int *if1475 @@ -274,6 +274,9 @@ int read_ndx_and_attrs(int f_in, int *if 1112 1476 void free_sums(struct sum_struct *s); 1113 1477 mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms, 1114 1478 int exists); 1115 + int make_mutable(const char *fname, mode_t mode, uint32 fileflags, uint32 iflags);1479 +uint32 make_mutable(const char *fname, mode_t *mode_ptr, uint32 fileflags, uint32 iflags); 1116 1480 +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); 1117 1482 int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 1118 1483 const char *fnamecmp, int flags); 1119 1484 RETSIGTYPE sig_int(UNUSED(int val)); 1120 @@ -29 8,11 +300,12 @@ int sock_exec(const char *prog);1485 @@ -297,11 +300,12 @@ void set_socket_options(int fd, char *op 1121 1486 int do_unlink(const char *fname); 1122 1487 int do_symlink(const char *fname1, const char *fname2); … … 1131 1496 +int do_chflags(const char *path, uint32 fileflags); 1132 1497 int do_rename(const char *fname1, const char *fname2); 1498 int do_ftruncate(int fd, OFF_T size); 1133 1499 void trim_trailing_slashes(char *name); 1134 int do_mkdir(char *fname, mode_t mode); 1135 @@ -330,7 +333,7 @@ int fd_pair(int fd[2]); 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]); 1136 1516 void print_child_argv(const char *prefix, char **cmd); 1137 1517 NORETURN void out_of_memory(const char *str); … … 1145 1525 --- a/rsync.1 1146 1526 +++ b/rsync.1 1147 @@ -417,6 +417,7 @@ to the detailed description below for a 1527 @@ -417,6 +417,7 @@ to the detailed description below for a 1148 1528 \-K, \-\-keep\-dirlinks treat symlinked dir on receiver as dir 1149 1529 \-H, \-\-hard\-links preserve hard links 1150 1530 \-p, \-\-perms preserve permissions 1151 + \-\-fileflags preserve file -flags (aka chflags)1531 + \-\-fileflags preserve file\-flags (aka chflags) 1152 1532 \-E, \-\-executability preserve executability 1153 1533 \-\-chmod=CHMOD affect file and/or directory permissions 1154 1534 \-A, \-\-acls preserve ACLs (implies \-p) 1155 @@ -448,7 +449,10 @@ to the detailed description below for a 1535 @@ -448,7 +449,10 @@ to the detailed description below for a 1156 1536 \-\-delete\-after receiver deletes after transfer, not before 1157 1537 \-\-delete\-excluded also delete excluded files from dest dirs … … 1160 1540 + \-\-force\-delete force deletion of dirs even if not empty 1161 1541 + \-\-force\-change affect user/system immutable files/dirs 1162 + \-\-force\-uchange affect user -immutable files/dirs1163 + \-\-force\-schange affect system -immutable files/dirs1542 + \-\-force\-uchange affect user\-immutable files/dirs 1543 + \-\-force\-schange affect system\-immutable files/dirs 1164 1544 \-\-max\-delete=NUM don'\&t delete more than NUM files 1165 1545 \-\-max\-size=SIZE don'\&t transfer any file larger than SIZE … … 1168 1548 .IP 1169 1549 Note that \fB\-a\fP \fBdoes not preserve hardlinks\fP, because 1170 finding multiply -linked files is expensive. You must separately1550 finding multiply\-linked files is expensive. You must separately 1171 1551 -specify \fB\-H\fP. 1172 1552 +specify \fB\-H\fP. Note also that for backward compatibility, \fB\-a\fP … … 1175 1555 .IP "\-\-no\-OPTION" 1176 1556 You may turn off one or more implied options by prefixing 1177 @@ -9 31,7 +936,7 @@ they would be using \fB\-\-copy\-links\f1557 @@ -955,7 +960,7 @@ they would be using \fB\-\-copy\-links\f 1178 1558 Without this option, if the sending side has replaced a directory with a 1179 1559 symlink to a directory, the receiving side will delete anything that is in … … 1184 1564 See also \fB\-\-keep\-dirlinks\fP for an analogous option for the receiving 1185 1565 side. 1186 @@ -1 086,6 +1091,33 @@ super-user copies all namespaces except1187 the user.* namespace. To be able to backup and restore non-user namespaces as1188 a normal user, see the \fB\-\-fake\-super\fP option.1566 @@ -1142,6 +1147,33 @@ Note that this option does not copy rsyn 1567 used by \fB\-\-fake\-super\fP) unless you repeat the option (e.g. \-XX). This 1568 \(dq\© all xattrs\(dq\& mode cannot be used with \fB\-\-fake\-super\fP. 1189 1569 .IP 1190 1570 +.IP "\fB\-\-fileflags\fP" 1191 +This option causes rsync to update the file -flags to be1571 +This option causes rsync to update the file\-flags to be 1192 1572 +the same as the source files and directories (if your OS supports the 1193 +\fBchflags\fP(2) system call). Some flags can only be altered by the super -user1194 +and some might only be unset below a certain secure -level (usually single-user1573 +\fBchflags\fP(2) system call). Some flags can only be altered by the super\-user 1574 +and some might only be unset below a certain secure\-level (usually single\-user 1195 1575 +mode). It will not make files alterable that are set to immutable on the 1196 1576 +receiver. To do that, see \fB\-\-force\-change\fP, \fB\-\-force\-uchange\fP, and … … 1198 1578 +.IP 1199 1579 +.IP "\fB\-\-force\-change\fP" 1200 +This option causes rsync to disable both user -immutable1201 +and system -immutable flags on files and directories that are being updated or1580 +This option causes rsync to disable both user\-immutable 1581 +and system\-immutable flags on files and directories that are being updated or 1202 1582 +deleted on the receiving side. This option overrides \fB\-\-force\-uchange\fP and 1203 1583 +\fB\-\-force\-schange\fP. 1204 1584 +.IP 1205 1585 +.IP "\fB\-\-force\-uchange\fP" 1206 +This option causes rsync to disable user -immutable1586 +This option causes rsync to disable user\-immutable 1207 1587 +flags on files and directories that are being updated or deleted on the 1208 1588 +receiving side. It does not try to affect system flags. This option overrides … … 1210 1590 +.IP 1211 1591 +.IP "\fB\-\-force\-schange\fP" 1212 +This option causes rsync to disable system -immutable1592 +This option causes rsync to disable system\-immutable 1213 1593 +flags on files and directories that are being updated or deleted on the 1214 1594 +receiving side. It does not try to affect user flags. This option overrides … … 1217 1597 .IP "\fB\-\-chmod\fP" 1218 1598 This option tells rsync to apply one or more 1219 comma -separated \(dq\&chmod\(dq\& strings to the permission of the files in the1220 @@ -1 387,13 +1419,14 @@ See \fB\-\-delete\fP (which is implied)1599 comma\-separated \(dq\&chmod\(dq\& strings to the permission of the files in the 1600 @@ -1442,13 +1474,14 @@ See \fB\-\-delete\fP (which is implied) 1221 1601 Tells \fB\-\-delete\fP to go ahead and delete files 1222 1602 even when there are I/O errors. … … 1224 1604 -.IP "\fB\-\-force\fP" 1225 1605 +.IP "\fB\-\-force\-delete\fP" 1226 This option tells rsync to delete a non -empty directory1227 when it is to be replaced by a non -directory. This is only relevant if1606 This option tells rsync to delete a non\-empty directory 1607 when it is to be replaced by a non\-directory. This is only relevant if 1228 1608 deletions are not active (see \fB\-\-delete\fP for details). 1229 1609 .IP 1230 1610 -Note for older rsync versions: \fB\-\-force\fP used to still be required when 1231 -using \fB\-\-delete\-after\fP, and it used to be non -functional unless the1611 -using \fB\-\-delete\-after\fP, and it used to be non\-functional unless the 1232 1612 +This option can be abbreviated \fB\-\-force\fP for backward compatibility. 1233 1613 +Note that some older rsync versions used to still require \fB\-\-force\fP 1234 +when using \fB\-\-delete\-after\fP, and it used to be non -functional unless the1614 +when using \fB\-\-delete\-after\fP, and it used to be non\-functional unless the 1235 1615 \fB\-\-recursive\fP option was also enabled. 1236 1616 .IP 1237 1617 .IP "\fB\-\-max\-delete=NUM\fP" 1238 @@ - 1930,7 +1963,7 @@ with older versions of rsync, but that a1618 @@ -2004,7 +2037,7 @@ with older versions of rsync, but that a 1239 1619 verbose messages). 1240 1620 .IP … … 1242 1622 -format is like the string \fBYXcstpoguax\fP, where \fBY\fP is replaced by the 1243 1623 +format is like the string \fBYXcstpogfax\fP, where \fBY\fP is replaced by the 1244 type of update being done, \fBX\fP is replaced by the file -type, and the1624 type of update being done, \fBX\fP is replaced by the file\-type, and the 1245 1625 other letters represent attributes that may be output if they are being 1246 1626 modified. 1247 @@ -20 00,7 +2033,7 @@ sender\(cq\&s value (requires \fB\-\-own1627 @@ -2074,7 +2107,7 @@ sender\(cq\&s value (requires \fB\-\-own 1248 1628 A \fBg\fP means the group is different and is being updated to the 1249 1629 sender\(cq\&s value (requires \fB\-\-group\fP and the authority to set the group).
Note: See TracChangeset
for help on using the changeset viewer.

