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

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

rsync: update to 3.0.8.

File size: 25.5 KB
  • compat.c

    This patch adds a --crtimes (-N) option that will preserve
    create times on OS X.
    
    To use this patch, run these commands for a successful build:
    
        patch -p1 <patches/fileflags.diff
        patch -p1 <patches/crtimes.diff
        ./prepare-source
        ./configure
        make
    
    based-on: patch/b3.0.x/fileflags
    diff --git a/compat.c b/compat.c
    a b extern int force_change; 
    4747extern int protect_args;
    4848extern int preserve_uid;
    4949extern int preserve_gid;
     50extern int preserve_crtimes;
    5051extern int preserve_fileflags;
    5152extern int preserve_acls;
    5253extern int preserve_xattrs;
    extern char *iconv_opt; 
    6566#endif
    6667
    6768/* These index values are for the file-list's extra-attribute array. */
    68 int uid_ndx, gid_ndx, fileflags_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
     69int uid_ndx, gid_ndx, crtimes_ndx, fileflags_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
    6970
    7071int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
    7172int sender_symlink_iconv = 0;   /* sender should convert symlink content */
    void setup_protocol(int f_out,int f_in) 
    142143                uid_ndx = ++file_extra_cnt;
    143144        if (preserve_gid)
    144145                gid_ndx = ++file_extra_cnt;
     146        if (preserve_crtimes)
     147                crtimes_ndx = (file_extra_cnt += TIME_EXTRA_CNT);
    145148        if (preserve_fileflags || (force_change && !am_sender))
    146149                fileflags_ndx = ++file_extra_cnt;
    147150        if (preserve_acls && !am_sender)
  • flist.c

    diff --git a/flist.c b/flist.c
    a b extern int preserve_specials; 
    5454extern int preserve_fileflags;
    5555extern int delete_during;
    5656extern int eol_nulls;
     57extern int crtimes_ndx;
    5758extern int relative_paths;
    5859extern int implied_dirs;
    5960extern int ignore_perishable;
    static void send_file_entry(int f, const char *fname, struct file_struct *file, 
    393394#endif
    394395                            int ndx, int first_ndx)
    395396{
    396         static time_t modtime;
     397        static time_t modtime, crtime;
    397398        static mode_t mode;
    398399#ifdef SUPPORT_FILEFLAGS
    399400        static uint32 fileflags;
    static void send_file_entry(int f, const char *fname, struct file_struct *file, 
    488489                xflags |= XMIT_SAME_TIME;
    489490        else
    490491                modtime = file->modtime;
     492        if (crtimes_ndx) {
     493                time_t file_crtime = f_crtime(file);
     494                if (file_crtime == modtime)
     495                        xflags |= XMIT_CRTIME_EQ_MTIME;
     496                else
     497                        crtime = file_crtime;
     498        }
    491499
    492500#ifdef SUPPORT_HARD_LINKS
    493501        if (tmp_dev != -1) {
    static void send_file_entry(int f, const char *fname, struct file_struct *file, 
    557565                else
    558566                        write_int(f, modtime);
    559567        }
     568        if (crtimes_ndx && !(xflags & XMIT_CRTIME_EQ_MTIME))
     569                write_varlong(f, crtime, 4);
    560570        if (!(xflags & XMIT_SAME_MODE))
    561571                write_int(f, to_wire_mode(mode));
    562572#ifdef SUPPORT_FILEFLAGS
    static void send_file_entry(int f, const char *fname, struct file_struct *file, 
    648658
    649659static struct file_struct *recv_file_entry(int f, struct file_list *flist, int xflags)
    650660{
    651         static int64 modtime;
     661        static int64 modtime, crtime;
    652662        static mode_t mode;
    653663#ifdef SUPPORT_FILEFLAGS
    654664        static uint32 fileflags;
    static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 
    758768                                uid = F_OWNER(first);
    759769                        if (preserve_gid)
    760770                                gid = F_GROUP(first);
     771                        if (crtimes_ndx)
     772                                crtime = f_crtime(first);
    761773                        if (preserve_devices && IS_DEVICE(mode)) {
    762774                                uint32 *devp = F_RDEV_P(first);
    763775                                rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
    static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 
    786798                } else
    787799                        modtime = read_int(f);
    788800        }
     801        if (crtimes_ndx) {
     802                if (!(xflags & XMIT_CRTIME_EQ_MTIME)) {
     803                        crtime = read_varlong(f, 4);
     804#if SIZEOF_TIME_T < SIZEOF_INT64
     805                        if (!am_generator && (int64)(time_t)crtime != crtime) {
     806                                rprintf(FERROR_XFER,
     807                                    "Create time value of %s truncated on receiver.\n",
     808                                    lastname);
     809                        }
     810#endif
     811                } else
     812                        crtime = modtime;
     813        }
    789814        if (!(xflags & XMIT_SAME_MODE))
    790815                mode = from_wire_mode(read_int(f));
    791816
    static struct file_struct *recv_file_entry(int f, struct file_list *flist, int x 
    946971                F_GROUP(file) = gid;
    947972                file->flags |= gid_flags;
    948973        }
     974        if (crtimes_ndx)
     975                f_crtime_set(file, (time_t)crtime);
    949976        if (unsort_ndx)
    950977                F_NDX(file) = flist->used + flist->ndx_start;
    951978
    struct file_struct *make_file(const char *fname, struct file_list *flist, 
    13241351                F_GROUP(file) = st.st_gid;
    13251352        if (am_generator && st.st_uid == our_uid)
    13261353                file->flags |= FLAG_OWNED_BY_US;
     1354        if (crtimes_ndx)
     1355                f_crtime_set(file, get_create_time(fname));
    13271356
    13281357        if (basename != thisname)
    13291358                file->dirname = lastdir;
  • generator.c

    diff --git a/generator.c b/generator.c
    a b  
    2121 */
    2222
    2323#include "rsync.h"
     24#include "ifuncs.h"
    2425
    2526extern int verbose;
    2627extern int dry_run;
    extern int preserve_xattrs; 
    4142extern int preserve_links;
    4243extern int preserve_devices;
    4344extern int preserve_specials;
     45extern int preserve_fileflags;
    4446extern int preserve_hard_links;
    4547extern int preserve_executability;
    4648extern int preserve_fileflags;
    static void do_delete_pass(void) 
    576578                rprintf(FINFO, "                    \r");
    577579}
    578580
    579 static inline int time_differs(struct file_struct *file, stat_x *sxp)
     581static inline int time_differs(struct file_struct *file, stat_x *sxp, const char *fname)
    580582{
     583        if (crtimes_ndx) {
     584                if (sxp->crtime == 0)
     585                        sxp->crtime = get_create_time(fname);
     586                if (cmp_time(sxp->crtime, f_crtime(file)) != 0)
     587                        return 1;
     588        }
     589
    581590        return cmp_time(sxp->st.st_mtime, file->modtime);
    582591}
    583592
    int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp) 
    635644{
    636645        if (S_ISLNK(file->mode)) {
    637646#ifdef CAN_SET_SYMLINK_TIMES
    638                 if (preserve_times & PRESERVE_LINK_TIMES && time_differs(file, sxp))
     647                if (preserve_times & PRESERVE_LINK_TIMES && time_differs(file, sxp, fname))
    639648                        return 0;
    640649#endif
    641650#ifdef CAN_CHMOD_SYMLINK
    int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp) 
    655664                        return 0;
    656665#endif
    657666        } else {
    658                 if (preserve_times && time_differs(file, sxp))
     667                if (preserve_times && time_differs(file, sxp, fname))
    659668                        return 0;
    660669                if (perms_differ(file, sxp))
    661670                        return 0;
    void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre 
    698707                 : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
    699708                  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
    700709                        iflags |= ITEM_REPORT_TIME;
     710                if (crtimes_ndx) {
     711                        if (sxp->crtime == 0)
     712                                sxp->crtime = get_create_time(fnamecmp);
     713                        if (cmp_time(sxp->crtime, f_crtime(file)) != 0)
     714                                iflags |= ITEM_REPORT_CRTIME;
     715                }
    701716#if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
    702717                if (S_ISLNK(file->mode)) {
    703718                        ;
    static int try_dests_non(struct file_struct *file, char *fname, int ndx, 
    12631278
    12641279static void list_file_entry(struct file_struct *f)
    12651280{
    1266         char permbuf[PERMSTRING_SIZE];
     1281        char permbuf[PERMSTRING_SIZE], crtime_buf[32];
    12671282        double len;
    12681283
    12691284        if (!F_IS_ACTIVE(f)) {
    static void list_file_entry(struct file_struct *f) 
    12741289        permstring(permbuf, f->mode);
    12751290        len = F_LENGTH(f);
    12761291
     1292        if (crtimes_ndx)
     1293                snprintf(crtime_buf, sizeof crtime_buf, " %s", timestring(f_crtime(f)));
     1294        else
     1295                *crtime_buf = '\0';
     1296
    12771297        /* TODO: indicate '+' if the entry has an ACL. */
    12781298
    12791299#ifdef SUPPORT_LINKS
    12801300        if (preserve_links && S_ISLNK(f->mode)) {
    1281                 rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
     1301                rprintf(FINFO, "%s %11.0f %s%s %s -> %s\n",
    12821302                        permbuf, len, timestring(f->modtime),
    1283                         f_name(f, NULL), F_SYMLINK(f));
     1303                        crtime_buf, f_name(f, NULL), F_SYMLINK(f));
    12841304        } else
    12851305#endif
    12861306        {
    1287                 rprintf(FINFO, "%s %11.0f %s %s\n",
     1307                rprintf(FINFO, "%s %11.0f %s%s %s\n",
    12881308                        permbuf, len, timestring(f->modtime),
    1289                         f_name(f, NULL));
     1309                        crtime_buf, f_name(f, NULL));
    12901310        }
    12911311}
    12921312
    static void recv_generator(char *fname, struct file_struct *file, int ndx, 
    13831403                        return;
    13841404                }
    13851405        }
     1406        sx.crtime = 0;
    13861407
    13871408        if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
    13881409          parent_is_dry_missing:
  • hlink.c

    diff --git a/hlink.c b/hlink.c
    a b int hard_link_check(struct file_struct *file, int ndx, const char *fname, 
    371371                char cmpbuf[MAXPATHLEN];
    372372                stat_x alt_sx;
    373373                int j = 0;
     374                alt_sx.crtime = 0;
    374375#ifdef SUPPORT_ACLS
    375376                alt_sx.acc_acl = alt_sx.def_acl = NULL;
    376377#endif
    void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx, 
    499500        } else
    500501                our_name = fname;
    501502
     503        prev_sx.crtime = 0;
    502504#ifdef SUPPORT_ACLS
    503505        prev_sx.acc_acl = prev_sx.def_acl = NULL;
    504506#endif
  • ifuncs.h

    diff --git a/ifuncs.h b/ifuncs.h
    a b d_name(struct dirent *di) 
    6767#endif
    6868}
    6969
     70static inline time_t
     71f_crtime(struct file_struct *fp)
     72{
     73#if SIZEOF_TIME_T > 4
     74        time_t crtime;
     75        memcpy(&crtime, &REQ_EXTRA(fp, crtimes_ndx)->unum, SIZEOF_TIME_T);
     76        return crtime;
     77#else
     78        return REQ_EXTRA(fp, crtimes_ndx)->unum;
     79#endif
     80}
     81
     82static inline void
     83f_crtime_set(struct file_struct *fp, time_t crtime)
     84{
     85#if SIZEOF_TIME_T > 4
     86        memcpy(&REQ_EXTRA(fp, crtimes_ndx)->unum, &crtime, SIZEOF_TIME_T);
     87#else
     88        REQ_EXTRA(fp, crtimes_ndx)->unum = (uint32)crtime;
     89#endif
     90}
     91
    7092static inline int
    7193isDigit(const char *ptr)
    7294{
  • log.c

    diff --git a/log.c b/log.c
    a b static void log_formatted(enum logcode code, const char *format, const char *op, 
    661661                        c[8] = !(iflags & ITEM_REPORT_FFLAGS) ? '.' : 'f';
    662662                        c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
    663663                        c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
    664                         c[11] = '\0';
     664                        c[11] = !(iflags & ITEM_REPORT_CRTIME) ? '.' : 'n';
     665                        c[12] = '\0';
    665666
    666667                        if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
    667668                                char ch = iflags & ITEM_IS_NEW ? '+' : '?';
  • options.c

    diff --git a/options.c b/options.c
    a b int preserve_specials = 0; 
    6060int preserve_uid = 0;
    6161int preserve_gid = 0;
    6262int preserve_times = 0;
     63int preserve_crtimes = 0;
    6364int update_only = 0;
    6465int cvs_exclude = 0;
    6566int dry_run = 0;
    void usage(enum logcode F) 
    361362  rprintf(F," -D                          same as --devices --specials\n");
    362363  rprintf(F," -t, --times                 preserve modification times\n");
    363364  rprintf(F," -O, --omit-dir-times        omit directories from --times\n");
     365  rprintf(F," -N, --crtimes               preserve create times (newness)\n");
    364366  rprintf(F,"     --super                 receiver attempts super-user activities\n");
    365367#ifdef SUPPORT_XATTRS
    366368  rprintf(F,"     --fake-super            store/recover privileged attrs using xattrs\n");
    static struct poptOption long_options[] = { 
    507509  {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
    508510  {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
    509511  {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
     512  {"crtimes",         'N', POPT_ARG_VAL,    &preserve_crtimes, 1, 0, 0 },
     513  {"no-crtimes",       0,  POPT_ARG_VAL,    &preserve_crtimes, 0, 0, 0 },
     514  {"no-N",             0,  POPT_ARG_VAL,    &preserve_crtimes, 0, 0, 0 },
    510515  {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 1, 0, 0 },
    511516  {"no-omit-dir-times",0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
    512517  {"no-O",             0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
    void server_options(char **args, int *argc_p) 
    18101815                argstr[x++] = 'D';
    18111816        if (preserve_times)
    18121817                argstr[x++] = 't';
     1818        if (preserve_crtimes)
     1819                argstr[x++] = 'N';
    18131820        if (preserve_perms)
    18141821                argstr[x++] = 'p';
    18151822        else if (preserve_executability && am_sender)
  • rsync.c

    diff --git a/rsync.c b/rsync.c
    a b int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 
    464464                                full_fname(fname));
    465465                        return 0;
    466466                }
     467                sx2.crtime = 0;
    467468#ifdef SUPPORT_ACLS
    468469                sx2.acc_acl = sx2.def_acl = NULL;
    469470#endif
    int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 
    505506         || (!(preserve_times & PRESERVE_DIR_TIMES) && S_ISDIR(sxp->st.st_mode))
    506507         || (!(preserve_times & PRESERVE_LINK_TIMES) && S_ISLNK(sxp->st.st_mode)))
    507508                flags |= ATTRS_SKIP_MTIME;
     509        /* Don't set the creation date on the root folder of an HFS+ volume. */
     510        if (sxp->st.st_ino == 2 && S_ISDIR(sxp->st.st_mode))
     511                flags |= ATTRS_SKIP_CRTIME;
    508512        if (!(flags & ATTRS_SKIP_MTIME)
    509513            && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
    510514                int ret = set_modtime(fname, file->modtime, sxp->st.st_mode, ST_FLAGS(sxp->st));
    int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp, 
    518522                else
    519523                        file->flags |= FLAG_TIME_FAILED;
    520524        }
     525        if (crtimes_ndx && !(flags & ATTRS_SKIP_CRTIME)) {
     526                time_t file_crtime = f_crtime(file);
     527                if (sxp->crtime == 0)
     528                        sxp->crtime = get_create_time(fname);
     529                if (cmp_time(sxp->crtime, file_crtime) != 0
     530                 && set_create_time(fname, file_crtime) == 0)
     531                        updated = 1;
     532        }
    521533
    522534        change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
    523535        change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
    int finish_transfer(const char *fname, const char *fnametmp, 
    675687        /* Change permissions before putting the file into place. */
    676688        set_file_attrs(fnametmp, file, NULL, fnamecmp,
    677689                       ATTRS_DELAY_IMMUTABLE
    678                        | (ok_to_set_time ? 0 : ATTRS_SKIP_MTIME));
     690                       | (ok_to_set_time ? 0 : ATTRS_SKIP_MTIME | ATTRS_SKIP_CRTIME));
    679691
    680692        /* move tmp file over real file */
    681693        if (verbose > 2)
    int finish_transfer(const char *fname, const char *fnametmp, 
    706718
    707719  do_set_file_attrs:
    708720        set_file_attrs(fnametmp, file, NULL, fnamecmp,
    709                        ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
     721                       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME | ATTRS_SKIP_CRTIME);
    710722
    711723        if (temp_copy_name) {
    712724                if (do_rename(fnametmp, fname) < 0) {
  • rsync.h

    diff --git a/rsync.h b/rsync.h
    a b  
    6161#define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
    6262#define XMIT_HLINK_FIRST (1<<12)        /* protocols 30 - now (HLINKED files only) */
    6363#define XMIT_IO_ERROR_ENDLIST (1<<12)   /* protocols 31*- now (w/XMIT_EXTENDED_FLAGS) (also protocol 30 w/'f' compat flag) */
     64#define XMIT_CRTIME_EQ_MTIME (1<<13)    /* protocols ?? - now */
    6465#define XMIT_SAME_FLAGS (1<<14)         /* protocols ?? - now */
    6566
    6667/* These flags are used in the live flist data. */
     
    162163#define ATTRS_REPORT            (1<<0)
    163164#define ATTRS_SKIP_MTIME        (1<<1)
    164165#define ATTRS_DELAY_IMMUTABLE   (1<<2)
     166#define ATTRS_SKIP_CRTIME       (1<<3)
    165167
    166168#define FULL_FLUSH      1
    167169#define NORMAL_FLUSH    0
     
    178180#define FNAMECMP_FUZZY          0x83
    179181
    180182/* For use by the itemize_changes code */
    181 #define ITEM_REPORT_ATIME (1<<0)
     183#define ITEM_REPORT_CRTIME (1<<0)
    182184#define ITEM_REPORT_CHANGE (1<<1)
    183185#define ITEM_REPORT_SIZE (1<<2)     /* regular files only */
    184186#define ITEM_REPORT_TIMEFAIL (1<<2) /* symlinks only */
    extern int file_extra_cnt; 
    677679extern int inc_recurse;
    678680extern int uid_ndx;
    679681extern int gid_ndx;
     682extern int crtimes_ndx;
    680683extern int fileflags_ndx;
    681684extern int acls_ndx;
    682685extern int xattrs_ndx;
    extern int xattrs_ndx; 
    684687#define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
    685688#define EXTRA_LEN (sizeof (union file_extras))
    686689#define PTR_EXTRA_CNT ((sizeof (char *) + EXTRA_LEN - 1) / EXTRA_LEN)
     690#define TIME_EXTRA_CNT ((SIZEOF_TIME_T + EXTRA_LEN - 1) / EXTRA_LEN)
    687691#define DEV_EXTRA_CNT 2
    688692#define DIRNODE_EXTRA_CNT 3
    689693#define SUM_EXTRA_CNT ((MAX_DIGEST_LEN + EXTRA_LEN - 1) / EXTRA_LEN)
    typedef struct { 
    951955
    952956typedef struct {
    953957    STRUCT_STAT st;
     958    time_t crtime;
    954959#ifdef SUPPORT_ACLS
    955960    struct rsync_acl *acc_acl; /* access ACL */
    956961    struct rsync_acl *def_acl; /* default ACL */
  • rsync.yo

    diff --git a/rsync.yo b/rsync.yo
    a b to the detailed description below for a complete description. verb( 
    354354 -D                          same as --devices --specials
    355355 -t, --times                 preserve modification times
    356356 -O, --omit-dir-times        omit directories from --times
     357 -N, --crtimes               preserve create times (newness)
    357358     --super                 receiver attempts super-user activities
    358359     --fake-super            store/recover privileged attrs using xattrs
    359360 -S, --sparse                handle sparse files efficiently
    it is preserving modification times (see bf(--times)). If NFS is sharing 
    10861087the directories on the receiving side, it is a good idea to use bf(-O).
    10871088This option is inferred if you use bf(--backup) without bf(--backup-dir).
    10881089
     1090dit(bf(-N, --crtimes)) This tells rsync to set the create times (newness) of
     1091the destination files to the same value as the source files.
     1092
    10891093dit(bf(--super)) This tells the receiving side to attempt super-user
    10901094activities even if the receiving rsync wasn't run by the super-user.  These
    10911095activities include: preserving users via the bf(--owner) option, preserving
    with older versions of rsync, but that also turns on the output of other 
    17821786verbose messages).
    17831787
    17841788The "%i" escape has a cryptic output that is 11 letters long.  The general
    1785 format is like the string bf(YXcstpogfax), where bf(Y) is replaced by the
     1789format is like the string bf(YXcstpogfaxn), where bf(Y) is replaced by the
    17861790type of update being done, bf(X) is replaced by the file-type, and the
    17871791other letters represent attributes that may be output if they are being
    17881792modified.
    quote(itemization( 
    18411845  it() The bf(f) means that the fileflags information changed.
    18421846  it() The bf(a) means that the ACL information changed.
    18431847  it() The bf(x) means that the extended attribute information changed.
     1848  it() A bf(n) means the create time (newness) is different and is being
     1849  updated to the sender's value (requires bf(--crtimes)).
    18441850))
    18451851
    18461852One other output is possible:  when deleting files, the "%i" will output
  • syscall.c

    diff --git a/syscall.c b/syscall.c
    a b extern int force_change; 
    3737extern int preserve_perms;
    3838extern int preserve_executability;
    3939
     40#pragma pack(push, 4)
     41struct create_time {
     42        uint32 length;
     43        struct timespec crtime;
     44};
     45#pragma pack(pop)
     46
    4047#define RETURN_ERROR_IF(x,e) \
    4148        do { \
    4249                if (x) { \
    OFF_T do_lseek(int fd, OFF_T offset, int whence) 
    529536#endif
    530537}
    531538
     539time_t get_create_time(const char *path)
     540{
     541        static struct create_time attrBuf;
     542        struct attrlist attrList;
     543
     544        memset(&attrList, 0, sizeof attrList);
     545        attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
     546        attrList.commonattr = ATTR_CMN_CRTIME;
     547        if (getattrlist(path, &attrList, &attrBuf, sizeof attrBuf, FSOPT_NOFOLLOW) < 0)
     548                return 0;
     549        return attrBuf.crtime.tv_sec;
     550}
     551
     552int set_create_time(const char *path, time_t crtime)
     553{
     554        struct attrlist attrList;
     555        struct timespec ts;
     556
     557        if (dry_run) return 0;
     558        RETURN_ERROR_IF_RO_OR_LO;
     559
     560        ts.tv_sec = crtime;
     561        ts.tv_nsec = 0;
     562
     563        memset(&attrList, 0, sizeof attrList);
     564        attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
     565        attrList.commonattr = ATTR_CMN_CRTIME;
     566        return setattrlist(path, &attrList, &ts, sizeof ts, FSOPT_NOFOLLOW);
     567}
     568
    532569#ifdef HAVE_UTIMENSAT
    533570int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags)
    534571{
  • new file testsuite/crtimes.test

    diff --git a/testsuite/crtimes.test b/testsuite/crtimes.test
    new file mode 100644
    - +  
     1#! /bin/sh
     2
     3# Test rsync copying create times
     4
     5. "$suitedir/rsync.fns"
     6
     7# Setting an older time via touch sets the create time to the mtime.
     8# Setting it to a newer time affects just the mtime.
     9
     10mkdir "$fromdir"
     11echo hiho "$fromdir/foo"
     12
     13touch -t 200101011111.11 "$fromdir"
     14touch -t 200202022222.22 "$fromdir"
     15
     16touch -t 200111111111.11 "$fromdir/foo"
     17touch -t 200212122222.22 "$fromdir/foo"
     18
     19TLS_ARGS=--crtimes
     20
     21checkit "$RSYNC -rtgvvv --crtimes \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
     22
     23# The script would have aborted on error, so getting here means we've won.
     24exit 0
  • testsuite/rsync.fns

    diff --git a/testsuite/rsync.fns b/testsuite/rsync.fns
    a b todir="$tmpdir/to" 
    2424chkdir="$tmpdir/chk"
    2525
    2626# For itemized output:
    27 all_plus='+++++++++'
    28 allspace='         '
    29 dots='.....' # trailing dots after changes
     27all_plus='++++++++++'
     28allspace='          '
     29dots='......' # trailing dots after changes
    3030tab_ch='        ' # a single tab character
    3131
    3232# Berkley's nice.
  • tls.c

    diff --git a/tls.c b/tls.c
    a b static int stat_xattr(const char *fname, STRUCT_STAT *fst) 
    107107
    108108#endif
    109109
     110static int display_crtimes = 0;
     111
    110112static void failed(char const *what, char const *where)
    111113{
    112114        fprintf(stderr, PROGRAM ": %s %s: %s\n",
    static void failed(char const *what, char const *where) 
    114116        exit(1);
    115117}
    116118
     119static void storetime(char *dest, time_t t, size_t destsize)
     120{
     121        if (t) {
     122                struct tm *mt = gmtime(&t);
     123
     124                snprintf(dest, destsize,
     125                        "%04d-%02d-%02d %02d:%02d:%02d ",
     126                        (int)mt->tm_year + 1900,
     127                        (int)mt->tm_mon + 1,
     128                        (int)mt->tm_mday,
     129                        (int)mt->tm_hour,
     130                        (int)mt->tm_min,
     131                        (int)mt->tm_sec);
     132        } else
     133                strlcpy(dest, "                    ", destsize);
     134}
     135
    117136static void list_file(const char *fname)
    118137{
    119138        STRUCT_STAT buf;
     139        time_t crtime = 0;
    120140        char permbuf[PERMSTRING_SIZE];
    121         struct tm *mt;
    122         char datebuf[50];
     141        char mtimebuf[50];
     142        char crtimebuf[50];
    123143        char linkbuf[4096];
    124144
    125145        if (do_lstat(fname, &buf) < 0)
    126146                failed("stat", fname);
     147        if (display_crtimes && (crtime = get_create_time(fname)) == 0)
     148                failed("get_create_time", fname);
    127149#ifdef SUPPORT_XATTRS
    128150        if (am_root < 0)
    129151                stat_xattr(fname, &buf);
    static void list_file(const char *fname) 
    158180
    159181        permstring(permbuf, buf.st_mode);
    160182
    161         if (buf.st_mtime) {
    162                 mt = gmtime(&buf.st_mtime);
    163 
    164                 snprintf(datebuf, sizeof datebuf,
    165                         "%04d-%02d-%02d %02d:%02d:%02d",
    166                         (int)mt->tm_year + 1900,
    167                         (int)mt->tm_mon + 1,
    168                         (int)mt->tm_mday,
    169                         (int)mt->tm_hour,
    170                         (int)mt->tm_min,
    171                         (int)mt->tm_sec);
    172         } else
    173                 strlcpy(datebuf, "                   ", sizeof datebuf);
     183        storetime(mtimebuf, buf.st_mtime, sizeof mtimebuf);
     184        if (display_crtimes)
     185                storetime(crtimebuf, crtime, sizeof crtimebuf);
     186        else
     187                crtimebuf[0] = '\0';
    174188
    175189        /* TODO: Perhaps escape special characters in fname? */
    176190
    static void list_file(const char *fname) 
    181195                    (long)minor(buf.st_rdev));
    182196        } else /* NB: use double for size since it might not fit in a long. */
    183197                printf("%12.0f", (double)buf.st_size);
    184         printf(" %6ld.%-6ld %6ld %s %s%s\n",
     198        printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
    185199               (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
    186                datebuf, fname, linkbuf);
     200               mtimebuf, crtimebuf, fname, linkbuf);
    187201}
    188202
    189203static struct poptOption long_options[] = {
    190204  /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
     205  {"crtimes",         'N', POPT_ARG_NONE,   &display_crtimes, 0, 0, 0},
    191206  {"link-times",      'l', POPT_ARG_NONE,   &link_times, 0, 0, 0 },
    192207  {"link-owner",      'L', POPT_ARG_NONE,   &link_owner, 0, 0, 0 },
    193208#ifdef SUPPORT_XATTRS
    static void tls_usage(int ret) 
    203218  fprintf(F,"usage: " PROGRAM " [OPTIONS] FILE ...\n");
    204219  fprintf(F,"Trivial file listing program for portably checking rsync\n");
    205220  fprintf(F,"\nOptions:\n");
     221  fprintf(F," -N, --crtimes               display create times (newness)\n");
    206222  fprintf(F," -l, --link-times            display the time on a symlink\n");
    207223  fprintf(F," -L, --link-owner            display the owner+group on a symlink\n");
    208224#ifdef SUPPORT_XATTRS
  • proto.h

    diff -up a/proto.h b/proto.h
    a b int do_stat(const char *fname, STRUCT_ST 
    315315int do_lstat(const char *fname, STRUCT_STAT *st);
    316316int do_fstat(int fd, STRUCT_STAT *st);
    317317OFF_T do_lseek(int fd, OFF_T offset, int whence);
     318time_t get_create_time(const char *path);
     319int set_create_time(const char *path, time_t crtime);
    318320int do_utimensat(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
    319321int do_lutimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
    320322int do_utimes(const char *fname, time_t modtime, uint32 mod_nsec, mode_t mode, uint32 fileflags);
  • rsync.1

    diff -up a/rsync.1 b/rsync.1
    a b to the detailed description below for a 
    429429 \-D                          same as \-\-devices \-\-specials
    430430 \-t, \-\-times                 preserve modification times
    431431 \-O, \-\-omit\-dir\-times        omit directories from \-\-times
     432 \-N, \-\-crtimes               preserve create times (newness)
    432433     \-\-super                 receiver attempts super\-user activities
    433434     \-\-fake\-super            store/recover privileged attrs using xattrs
    434435 \-S, \-\-sparse                handle sparse files efficiently
    it is preserving modification times (see 
    12531254the directories on the receiving side, it is a good idea to use \fB\-O\fP.
    12541255This option is inferred if you use \fB\-\-backup\fP without \fB\-\-backup\-dir\fP.
    12551256.IP
     1257.IP "\fB\-N, \-\-crtimes\fP"
     1258This tells rsync to set the create times (newness) of
     1259the destination files to the same value as the source files.
     1260.IP
    12561261.IP "\fB\-\-super\fP"
    12571262This tells the receiving side to attempt super\-user
    12581263activities even if the receiving rsync wasn\(cq\&t run by the super\-user.  These
    with older versions of rsync, but that a 
    20372042verbose messages).
    20382043.IP
    20392044The \(dq\&%i\(dq\& escape has a cryptic output that is 11 letters long.  The general
    2040 format is like the string \fBYXcstpogfax\fP, where \fBY\fP is replaced by the
     2045format is like the string \fBYXcstpogfaxn\fP, where \fBY\fP is replaced by the
    20412046type of update being done, \fBX\fP is replaced by the file\-type, and the
    20422047other letters represent attributes that may be output if they are being
    20432048modified.
    The \fBf\fP means that the fileflags inf 
    21122117The \fBa\fP means that the ACL information changed.
    21132118.IP o
    21142119The \fBx\fP means that the extended attribute information changed.
     2120.IP o
     2121A \fBn\fP means the create time (newness) is different and is being
     2122updated to the sender\(cq\&s value (requires \fB\-\-crtimes\fP).
    21152123.RE
    21162124
    21172125.IP
Note: See TracBrowser for help on using the repository browser.