diff --git a/generator.c b/generator.c index fe5fece..75bfa41 100644 --- a/generator.c +++ b/generator.c @@ -1833,12 +1833,16 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, goto notify_others; } + AMTIMES_SAVE(fd); + if (inplace && make_backups > 0 && fnamecmp_type == FNAMECMP_FNAME) { if (!(backupptr = get_backup_name(fname))) { + AMTIMES_RESTORE(fd); close(fd); goto cleanup; } if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) { + AMTIMES_RESTORE(fd); close(fd); goto pretend_missing; } @@ -1847,6 +1851,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, full_fname(backupptr)); unmake_file(back_file); back_file = NULL; + AMTIMES_RESTORE(fd); close(fd); goto cleanup; } @@ -1854,6 +1859,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, rsyserr(FERROR_XFER, errno, "open %s", full_fname(backupptr)); unmake_file(back_file); back_file = NULL; + AMTIMES_RESTORE(fd); close(fd); goto cleanup; } @@ -1905,6 +1911,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, write_sum_head(f_out, NULL); else if (sx.st.st_size <= 0) { write_sum_head(f_out, NULL); + AMTIMES_RESTORE(fd); close(fd); } else { if (generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy) < 0) { @@ -1913,6 +1920,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, fnamecmp); write_sum_head(f_out, NULL); } + AMTIMES_RESTORE(fd); close(fd); } diff --git a/options.c b/options.c index 64ec8b8..e1a46ad 100644 --- a/options.c +++ b/options.c @@ -642,6 +642,8 @@ static void print_rsync_version(enum logcode f) rprintf(f,"rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"); rprintf(f,"are welcome to redistribute it under certain conditions. See the GNU\n"); rprintf(f,"General Public Licence for details.\n"); + + rprintf(f, "Extra patches: preserveatime\n"); } diff --git a/receiver.c b/receiver.c index 3d9bc65..7af7fed 100644 --- a/receiver.c +++ b/receiver.c @@ -774,6 +774,8 @@ int recv_files(int f_in, int f_out, char *local_name) continue; } + AMTIMES_KEEP(st); + if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) { /* this special handling for directories * wouldn't be necessary if robust_rename() @@ -783,6 +785,7 @@ int recv_files(int f_in, int f_out, char *local_name) rprintf(FERROR_XFER, "recv_files: %s is a directory\n", full_fname(fnamecmp)); discard_receive_data(f_in, F_LENGTH(file)); + AMTIMES_RESTORE(fd1); close(fd1); if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); @@ -790,6 +793,7 @@ int recv_files(int f_in, int f_out, char *local_name) } if (fd1 != -1 && !S_ISREG(st.st_mode)) { + AMTIMES_RESTORE(fd1); close(fd1); fd1 = -1; } @@ -826,8 +830,10 @@ int recv_files(int f_in, int f_out, char *local_name) if (fd2 == -1) { discard_receive_data(f_in, F_LENGTH(file)); - if (fd1 != -1) + if (fd1 != -1) { + AMTIMES_RESTORE(fd1); close(fd1); + } if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); continue; @@ -845,8 +851,10 @@ int recv_files(int f_in, int f_out, char *local_name) log_item(log_code, file, iflags, NULL); - if (fd1 != -1) + if (fd1 != -1) { + AMTIMES_RESTORE(fd1); close(fd1); + } if (close(fd2) < 0) { rsyserr(FERROR, errno, "close failed on %s", full_fname(fnametmp)); diff --git a/rsync.h b/rsync.h index 1720293..84174a6 100644 --- a/rsync.h +++ b/rsync.h @@ -1296,3 +1296,26 @@ char *getpass(const char *prompt); #ifdef MAINTAINER_MODE const char *get_panic_action(void); #endif + +#define AMTIMES_SAVE(fd) \ + AMTIMES_STAT(fd); \ + AMTIMES_KEEP(fdst) + +#define AMTIMES_STAT(fd) \ + struct stat fdst; \ + if (fstat(fd, &fdst) == -1) { \ + memset(&fdst, 0, sizeof(struct stat)); \ + } + +#define AMTIMES_KEEP(fdst) \ + struct timeval fdtv[2]; \ + fdtv[0].tv_sec = fdst.st_atimespec.tv_sec; \ + fdtv[0].tv_usec = (fdst.st_atimespec.tv_nsec + 500) / 1000; \ + fdtv[1].tv_sec = fdst.st_mtimespec.tv_sec; \ + fdtv[1].tv_usec = (fdst.st_mtimespec.tv_nsec + 500) / 1000 + +#define AMTIMES_RESTORE(fd) \ + if (fdtv[0].tv_sec) { \ + futimes(fd, fdtv); \ + } + diff --git a/sender.c b/sender.c index 907cf21..afb364b 100644 --- a/sender.c +++ b/sender.c @@ -365,6 +365,8 @@ void send_files(int f_in, int f_out) exit_cleanup(RERR_FILEIO); } + AMTIMES_KEEP(st); + if (st.st_size) { int32 read_size = MAX(s->blength * 3, MAX_MAP_SIZE); mbuf = map_file(fd, st.st_size, read_size, s->blength); @@ -405,6 +407,7 @@ void send_files(int f_in, int f_out) full_fname(fname)); } } + AMTIMES_RESTORE(fd); close(fd); free_sums(s); diff --git a/util.c b/util.c index 49c5b71..07ea531 100644 --- a/util.c +++ b/util.c @@ -332,6 +332,8 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode) return -1; } + AMTIMES_SAVE(ifd); + if (ofd < 0) { if (robust_unlink(dest) && errno != ENOENT) { int save_errno = errno; @@ -348,6 +350,7 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode) if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) { int save_errno = errno; rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest)); + AMTIMES_RESTORE(ifd); close(ifd); errno = save_errno; return -1; @@ -374,6 +377,7 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode) if (full_write(ofd, buf, len) < 0) { int save_errno = errno; rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest)); + AMTIMES_RESTORE(ifd); close(ifd); close(ofd); errno = save_errno; @@ -385,12 +389,14 @@ int copy_file(const char *source, const char *dest, int ofd, mode_t mode) if (len < 0) { int save_errno = errno; rsyserr(FERROR_XFER, errno, "read %s", full_fname(source)); + AMTIMES_RESTORE(ifd); close(ifd); close(ofd); errno = save_errno; return -1; } + AMTIMES_RESTORE(ifd); if (close(ifd) < 0) { rsyserr(FWARNING, errno, "close failed on %s", full_fname(source));