1 After applying this patch and running configure, you MUST run this
7 --- orig/flist.c 2006-01-25 17:15:12
8 +++ flist.c 2006-01-25 17:46:37
9 @@ -50,6 +50,7 @@ extern int preserve_perms;
10 extern int preserve_devices;
11 extern int preserve_uid;
12 extern int preserve_gid;
13 +extern int preserve_atimes;
14 extern int relative_paths;
15 extern int implied_dirs;
16 extern int copy_links;
17 @@ -83,7 +84,13 @@ void init_flist(void)
20 /* Figure out how big the file_struct is without trailing padding */
21 - file_struct_len = offsetof(struct file_struct, flags) + sizeof f.flags;
22 + if (preserve_atimes)
23 + file_struct_len = offsetof(struct file_struct, fl4g5);
25 + file_struct_len = offsetof(struct file_struct, atime);
26 + /* The "flags" uchar is no longer accessed directly, so I
27 + * mangled the name to fl4g5 as a reminder. */
28 + file_struct_len += sizeof f.fl4g5;
29 checksum_len = protocol_version < 21 ? 2 : MD4_SUM_LENGTH;
32 @@ -139,16 +146,18 @@ static void list_file_entry(struct file_
35 if (preserve_links && S_ISLNK(f->mode)) {
36 - rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
37 + rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
39 (double)f->length, timestring(f->modtime),
40 + preserve_atimes ? timestring(f->atime) : "",
41 f_name(f, NULL), f->u.link);
45 - rprintf(FINFO, "%s %11.0f %s %s\n",
46 + rprintf(FINFO, "%s %11.0f %s %s %s\n",
48 (double)f->length, timestring(f->modtime),
49 + preserve_atimes ? timestring(f->atime) : "",
53 @@ -310,6 +319,7 @@ static void send_file_entry(struct file_
56 static time_t modtime;
57 + static time_t atime;
61 @@ -325,7 +335,7 @@ static void send_file_entry(struct file_
65 - modtime = 0, mode = 0;
66 + modtime = 0, atime = 0, mode = 0;
67 dev = 0, rdev = makedev(0, 0);
70 @@ -337,7 +347,7 @@ static void send_file_entry(struct file_
74 - flags = file->flags & XMIT_TOP_DIR;
75 + flags = FFLAGS(file) & XMIT_TOP_DIR;
77 if (file->mode == mode)
78 flags |= XMIT_SAME_MODE;
79 @@ -374,6 +384,12 @@ static void send_file_entry(struct file_
80 flags |= XMIT_SAME_TIME;
82 modtime = file->modtime;
83 + if (preserve_atimes && !S_ISDIR(mode)) {
84 + if (file->atime == atime)
85 + flags |= XMIT_SAME_ATIME;
87 + atime = file->atime;
90 #ifdef SUPPORT_HARD_LINKS
91 if (file->link_u.idev) {
92 @@ -427,6 +443,8 @@ static void send_file_entry(struct file_
93 write_int(f, modtime);
94 if (!(flags & XMIT_SAME_MODE))
95 write_int(f, to_wire_mode(mode));
96 + if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
97 + write_int(f, atime);
98 if (preserve_uid && !(flags & XMIT_SAME_UID)) {
101 @@ -494,6 +512,7 @@ static struct file_struct *receive_file_
102 unsigned short flags, int f)
104 static time_t modtime;
105 + static time_t atime;
109 @@ -512,7 +531,7 @@ static struct file_struct *receive_file_
110 struct file_struct *file;
113 - modtime = 0, mode = 0;
114 + modtime = 0, atime = 0, mode = 0;
115 dev = 0, rdev = makedev(0, 0);
118 @@ -568,6 +587,8 @@ static struct file_struct *receive_file_
119 modtime = (time_t)read_int(f);
120 if (!(flags & XMIT_SAME_MODE))
121 mode = from_wire_mode(read_int(f));
122 + if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
123 + atime = (time_t)read_int(f);
125 if (chmod_modes && !S_ISLNK(mode))
126 mode = tweak_mode(mode, chmod_modes);
127 @@ -624,6 +645,8 @@ static struct file_struct *receive_file_
131 + if (preserve_atimes)
132 + file->atime = atime;
135 file->dirname = lastdir = bp;
136 @@ -649,12 +672,12 @@ static struct file_struct *receive_file_
137 && lastname[del_hier_name_len-1] == '.'
138 && lastname[del_hier_name_len-2] == '/')
139 del_hier_name_len -= 2;
140 - file->flags |= FLAG_TOP_DIR | FLAG_DEL_HERE;
141 + FFLAGS(file) |= FLAG_TOP_DIR | FLAG_DEL_HERE;
142 } else if (in_del_hier) {
143 if (!relative_paths || !del_hier_name_len
144 || (l1 >= del_hier_name_len
145 && lastname[del_hier_name_len] == '/'))
146 - file->flags |= FLAG_DEL_HERE;
147 + FFLAGS(file) |= FLAG_DEL_HERE;
151 @@ -875,12 +898,14 @@ struct file_struct *make_file(char *fnam
152 memset(bp, 0, file_struct_len);
153 bp += file_struct_len;
155 - file->flags = flags;
156 + FFLAGS(file) = flags;
157 file->modtime = st.st_mtime;
158 file->length = st.st_size;
159 file->mode = st.st_mode;
160 file->uid = st.st_uid;
161 file->gid = st.st_gid;
162 + if (preserve_atimes)
163 + file->atime = st.st_atime;
165 #ifdef SUPPORT_HARD_LINKS
166 if (flist && flist->hlink_pool) {
167 @@ -992,7 +1017,7 @@ static void send_if_directory(int f, str
168 char is_dot_dir = fbuf[ol-1] == '.' && (ol == 1 || fbuf[ol-2] == '/');
170 if (S_ISDIR(file->mode)
171 - && !(file->flags & FLAG_MOUNT_POINT) && f_name(file, fbuf)) {
172 + && !(FFLAGS(file) & FLAG_MOUNT_POINT) && f_name(file, fbuf)) {
174 unsigned int len = strlen(fbuf);
175 if (len > 1 && fbuf[len-1] == '/')
176 @@ -1570,8 +1595,9 @@ static void clean_flist(struct file_list
178 /* Make sure that if we unduplicate '.', that we don't
179 * lose track of a user-specified top directory. */
180 - flist->files[keep]->flags |= flist->files[drop]->flags
181 - & (FLAG_TOP_DIR|FLAG_DEL_HERE);
182 + FFLAGS(flist->files[keep])
183 + |= FFLAGS(flist->files[drop])
184 + & (FLAG_TOP_DIR|FLAG_DEL_HERE);
186 clear_file(drop, flist);
188 @@ -1633,7 +1659,7 @@ static void output_flist(struct file_lis
189 file->dirname ? file->dirname : "",
190 file->dirname ? "/" : "", NS(file->basename),
191 S_ISDIR(file->mode) ? "/" : "", (int)file->mode,
192 - (double)file->length, uidbuf, gidbuf, file->flags);
193 + (double)file->length, uidbuf, gidbuf, FFLAGS(file));
197 --- orig/generator.c 2006-01-25 17:15:12
198 +++ generator.c 2006-01-26 09:15:22
199 @@ -43,6 +43,7 @@ extern int preserve_perms;
200 extern int preserve_uid;
201 extern int preserve_gid;
202 extern int preserve_times;
203 +extern int preserve_atimes;
204 extern int omit_dir_times;
205 extern int delete_before;
206 extern int delete_during;
207 @@ -89,6 +90,7 @@ extern dev_t filesystem_dev;
208 extern char *backup_dir;
209 extern char *backup_suffix;
210 extern int backup_suffix_len;
211 +extern unsigned int file_struct_len;
212 extern struct file_list *the_file_list;
213 extern struct filter_list_struct server_filter_list;
215 @@ -183,7 +185,7 @@ static int delete_item(char *fname, int
216 for (j = dirlist->count; j--; ) {
217 struct file_struct *fp = dirlist->files[j];
219 - if (fp->flags & FLAG_MOUNT_POINT)
220 + if (FFLAGS(fp) & FLAG_MOUNT_POINT)
223 strlcpy(p, fp->basename, remainder);
224 @@ -261,7 +263,7 @@ static void delete_in_dir(struct file_li
225 filt_array[cur_depth] = push_local_filters(fbuf, dlen);
227 if (one_file_system) {
228 - if (file->flags & FLAG_TOP_DIR)
229 + if (FFLAGS(file) & FLAG_TOP_DIR)
230 filesystem_dev = stp->st_dev;
231 else if (filesystem_dev != stp->st_dev)
233 @@ -273,7 +275,7 @@ static void delete_in_dir(struct file_li
234 * from the filesystem. */
235 for (i = dirlist->count; i--; ) {
236 struct file_struct *fp = dirlist->files[i];
237 - if (!fp->basename || fp->flags & FLAG_MOUNT_POINT)
238 + if (!fp->basename || FFLAGS(fp) & FLAG_MOUNT_POINT)
240 if (flist_find(flist, fp) < 0) {
242 @@ -300,11 +302,11 @@ static void do_delete_pass(struct file_l
243 for (j = 0; j < flist->count; j++) {
244 struct file_struct *file = flist->files[j];
246 - if (!(file->flags & FLAG_DEL_HERE))
247 + if (!(FFLAGS(file) & FLAG_DEL_HERE))
251 - if (verbose > 1 && file->flags & FLAG_TOP_DIR)
252 + if (verbose > 1 && FFLAGS(file) & FLAG_TOP_DIR)
253 rprintf(FINFO, "deleting in %s\n", fbuf);
255 if (link_stat(fbuf, &st, keep_dirlinks) < 0
256 @@ -346,8 +348,11 @@ void itemize(struct file_struct *file, i
257 iflags |= ITEM_REPORT_SIZE;
258 if ((iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !keep_time
259 && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
260 - || (keep_time && cmp_modtime(file->modtime, st->st_mtime) != 0))
261 + || (keep_time && cmp_time(file->modtime, st->st_mtime) != 0))
262 iflags |= ITEM_REPORT_TIME;
263 + if (preserve_atimes && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
264 + && cmp_time(file->atime, st->st_atime) != 0)
265 + iflags |= ITEM_REPORT_ATIME;
267 && (file->mode & CHMOD_BITS) != (st->st_mode & CHMOD_BITS))
268 iflags |= ITEM_REPORT_PERMS;
269 @@ -396,7 +401,7 @@ int unchanged_file(char *fn, struct file
273 - return cmp_modtime(st->st_mtime, file->modtime) == 0;
274 + return cmp_time(st->st_mtime, file->modtime) == 0;
278 @@ -550,13 +555,13 @@ static int find_fuzzy(struct file_struct
281 if (!S_ISREG(fp->mode) || !fp->length
282 - || fp->flags & FLAG_NO_FUZZY)
283 + || FFLAGS(fp) & FLAG_NO_FUZZY)
288 if (fp->length == file->length
289 - && cmp_modtime(fp->modtime, file->modtime) == 0) {
290 + && cmp_time(fp->modtime, file->modtime) == 0) {
293 "fuzzy size/modtime match for %s\n",
294 @@ -632,7 +637,7 @@ static int try_dests_reg(struct file_str
295 if (!unchanged_attrs(file, stp))
297 if ((always_checksum || ignore_times)
298 - && cmp_modtime(stp->st_mtime, file->modtime))
299 + && cmp_time(stp->st_mtime, file->modtime))
303 @@ -659,6 +664,8 @@ static int try_dests_reg(struct file_str
304 itemizing && verbose > 1,
307 + if (preserve_atimes)
308 + set_perms(fname, file, stp, 0);
309 if (preserve_hard_links && file->link_u.links)
310 hard_link_cluster(file, ndx, itemizing, code);
311 } else if (itemizing)
312 @@ -894,7 +901,7 @@ static void recv_generator(char *fname,
313 && verbose && code && f_out != -1)
314 rprintf(code, "%s/\n", fname);
315 if (delete_during && f_out != -1 && !phase && dry_run < 2
316 - && (file->flags & FLAG_DEL_HERE))
317 + && (FFLAGS(file) & FLAG_DEL_HERE))
318 delete_in_dir(the_file_list, fname, file, &st);
321 @@ -1071,7 +1078,7 @@ static void recv_generator(char *fname,
324 if (update_only && statret == 0
325 - && cmp_modtime(st.st_mtime, file->modtime) > 0) {
326 + && cmp_time(st.st_mtime, file->modtime) > 0) {
328 rprintf(FINFO, "%s is newer\n", fname);
330 @@ -1174,7 +1181,7 @@ static void recv_generator(char *fname,
332 int j = flist_find(fuzzy_dirlist, file);
333 if (j >= 0) /* don't use changing file as future fuzzy basis */
334 - fuzzy_dirlist->files[j]->flags |= FLAG_NO_FUZZY;
335 + FFLAGS(fuzzy_dirlist->files[j]) |= FLAG_NO_FUZZY;
339 --- orig/hlink.c 2006-01-14 20:27:09
340 +++ hlink.c 2006-01-24 19:17:58
341 @@ -26,6 +26,7 @@ extern int link_dest;
342 extern int make_backups;
343 extern int log_format_has_i;
344 extern char *basis_dir[];
345 +extern unsigned int file_struct_len;
346 extern struct file_list *the_file_list;
348 #ifdef SUPPORT_HARD_LINKS
349 @@ -86,10 +87,10 @@ static void link_idev_data(void)
350 FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
351 struct hlink, 1, "hlink_list");
353 - FPTR(head)->flags |= FLAG_HLINK_TOL;
354 + FFLAGS(FPTR(head)) |= FLAG_HLINK_TOL;
355 FPTR(cur)->F_HLINDEX = to;
356 FPTR(cur)->F_NEXT = head;
357 - FPTR(cur)->flags |= FLAG_HLINK_EOL;
358 + FFLAGS(FPTR(cur)) |= FLAG_HLINK_EOL;
359 hlink_list[to++] = head;
361 FPTR(cur)->link_u.links = NULL;
362 @@ -175,7 +176,7 @@ int hard_link_check(struct file_struct *
364 #ifdef SUPPORT_HARD_LINKS
366 - if (skip && !(file->flags & FLAG_HLINK_EOL))
367 + if (skip && !(FFLAGS(file) & FLAG_HLINK_EOL))
368 head = hlink_list[file->F_HLINDEX] = file->F_NEXT;
370 head = hlink_list[file->F_HLINDEX];
371 @@ -270,8 +271,8 @@ void hard_link_cluster(struct file_struc
372 file->F_HLINDEX = FINISHED_LINK;
373 if (link_stat(f_name(file, hlink1), &st1, 0) < 0)
375 - if (!(file->flags & FLAG_HLINK_TOL)) {
376 - while (!(file->flags & FLAG_HLINK_EOL)) {
377 + if (!(FFLAGS(file) & FLAG_HLINK_TOL)) {
378 + while (!(FFLAGS(file) & FLAG_HLINK_EOL)) {
382 @@ -286,6 +287,6 @@ void hard_link_cluster(struct file_struc
383 maybe_hard_link(file, ndx, hlink2, statret, &st2,
384 hlink1, &st1, itemizing, code);
385 file->F_HLINDEX = FINISHED_LINK;
386 - } while (!(file->flags & FLAG_HLINK_EOL));
387 + } while (!(FFLAGS(file) & FLAG_HLINK_EOL));
390 --- orig/log.c 2006-01-24 22:24:32
391 +++ log.c 2006-01-24 22:50:01
392 @@ -38,6 +38,7 @@ extern int module_id;
393 extern int msg_fd_out;
394 extern int protocol_version;
395 extern int preserve_times;
396 +extern int preserve_atimes;
397 extern int log_format_has_i;
398 extern int log_format_has_o_or_i;
399 extern int daemon_log_format_has_o_or_i;
400 @@ -542,10 +543,12 @@ static void log_formatted(enum logcode c
401 n[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
402 n[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
403 : !preserve_times || S_ISLNK(file->mode) ? 'T' : 't';
404 - n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
405 - n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
406 - n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
408 + n[5] = !(iflags & ITEM_REPORT_ATIME) ? '.'
409 + : S_ISLNK(file->mode) ? 'U' : 'u';
410 + n[6] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
411 + n[7] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
412 + n[8] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
415 if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
416 char ch = iflags & ITEM_IS_NEW ? '+' : '?';
417 --- orig/options.c 2006-01-23 18:48:23
418 +++ options.c 2006-01-24 22:53:18
419 @@ -50,6 +50,7 @@ int preserve_uid = 0;
420 int preserve_gid = 0;
421 int preserve_times = 0;
422 int omit_dir_times = 0;
423 +int preserve_atimes = 0;
427 @@ -291,8 +292,9 @@ void usage(enum logcode F)
428 rprintf(F," -o, --owner preserve owner (root only)\n");
429 rprintf(F," -g, --group preserve group\n");
430 rprintf(F," -D, --devices preserve devices (root only)\n");
431 - rprintf(F," -t, --times preserve times\n");
432 - rprintf(F," -O, --omit-dir-times omit directories when preserving times\n");
433 + rprintf(F," -t, --times preserve modify times\n");
434 + rprintf(F," -O, --omit-dir-times omit directories when preserving modify times\n");
435 + rprintf(F," -U, --atimes preserve access (use) times\n");
436 rprintf(F," --chmod=CHMOD change destination permissions\n");
437 rprintf(F," -S, --sparse handle sparse files efficiently\n");
438 rprintf(F," -n, --dry-run show what would have been transferred\n");
439 @@ -400,6 +402,9 @@ static struct poptOption long_options[]
440 {"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 },
441 {"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
442 {"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
443 + {"atimes", 'U', POPT_ARG_VAL, &preserve_atimes, 1, 0, 0 },
444 + {"no-atimes", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
445 + {"no-k", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
446 {"omit-dir-times", 'O', POPT_ARG_VAL, &omit_dir_times, 2, 0, 0 },
447 {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
448 {"owner", 'o', POPT_ARG_VAL, &preserve_uid, 1, 0, 0 },
449 @@ -1468,6 +1473,8 @@ void server_options(char **args,int *arg
453 + if (preserve_atimes)
455 if (omit_dir_times == 2 && am_sender)
458 --- orig/rsync.c 2006-01-25 17:15:12
459 +++ rsync.c 2006-01-26 09:19:43
460 @@ -27,6 +27,7 @@ extern int dry_run;
461 extern int daemon_log_format_has_i;
462 extern int preserve_times;
463 extern int omit_dir_times;
464 +extern int preserve_atimes;
466 extern int am_server;
467 extern int am_sender;
468 @@ -56,6 +57,7 @@ int set_perms(char *fname,struct file_st
471 int change_uid, change_gid;
472 + time_t atime, mtime;
476 @@ -68,18 +70,33 @@ int set_perms(char *fname,struct file_st
480 + /* This code must be the first update in the function due to
481 + * how it uses the "updated" variable. */
482 if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times))
483 flags |= PERMS_SKIP_MTIME;
484 + if (!preserve_atimes || S_ISDIR(st->st_mode))
485 + flags |= PERMS_SKIP_ATIME;
486 if (!(flags & PERMS_SKIP_MTIME)
487 - && cmp_modtime(st->st_mtime, file->modtime) != 0) {
488 - int ret = set_modtime(fname, file->modtime, st->st_mode);
489 + && cmp_time(st->st_mtime, file->modtime) != 0) {
490 + mtime = file->modtime;
493 + mtime = st->st_mtime;
494 + if (!(flags & PERMS_SKIP_ATIME)
495 + && cmp_time(st->st_atime, file->atime) != 0) {
496 + atime = file->atime;
499 + atime = st->st_atime;
501 + int ret = set_times(fname, mtime, atime, st->st_mode);
503 rsyserr(FERROR, errno, "failed to set times on %s",
507 - if (ret == 0) /* ret == 1 if symlink could not be set */
509 + if (ret > 0) /* ret == 1 if symlink could not be set */
513 change_uid = am_root && preserve_uid && st->st_uid != file->uid;
514 --- orig/rsync.h 2006-01-25 17:34:58
515 +++ rsync.h 2006-01-24 22:38:08
517 #define XMIT_HAS_IDEV_DATA (1<<9)
518 #define XMIT_SAME_DEV (1<<10)
519 #define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
520 +#define XMIT_SAME_ATIME (1<<12)
522 /* These flags are used in the live flist data. */
526 #define PERMS_REPORT (1<<0)
527 #define PERMS_SKIP_MTIME (1<<1)
528 +#define PERMS_SKIP_ATIME (1<<2)
531 #define NORMAL_FLUSH 0
533 #define FNAMECMP_FUZZY 0x83
535 /* For use by the itemize_changes code */
536 +#define ITEM_REPORT_ATIME (1<<0)
537 #define ITEM_REPORT_CHECKSUM (1<<1)
538 #define ITEM_REPORT_SIZE (1<<2)
539 #define ITEM_REPORT_TIME (1<<3)
540 @@ -520,9 +523,12 @@ struct file_struct {
544 - uchar flags; /* this item MUST remain last */
545 + time_t atime; /* this MUST be second to last */
546 + uchar fl4g5; /* this item MUST remain last */
549 +#define FFLAGS(f) ((uchar*)(f))[file_struct_len-1]
552 * Start the flist array at FLIST_START entries and grow it
553 * by doubling until FLIST_LINEAR then grow by FLIST_LINEAR
554 --- orig/rsync.yo 2006-01-24 22:19:58
555 +++ rsync.yo 2006-01-24 22:54:23
556 @@ -319,8 +319,9 @@ to the detailed description below for a
557 -o, --owner preserve owner (root only)
558 -g, --group preserve group
559 -D, --devices preserve devices (root only)
560 - -t, --times preserve times
561 - -O, --omit-dir-times omit directories when preserving times
562 + -t, --times preserve modify times
563 + -O, --omit-dir-times omit directories when preserving mod-times
564 + -U, --atimes preserve access (use) times
565 --chmod=CHMOD change destination permissions
566 -S, --sparse handle sparse files efficiently
567 -n, --dry-run show what would have been transferred
568 @@ -711,6 +712,12 @@ it is preserving modification times (see
569 the directories on the receiving side, it is a good idea to use bf(-O).
570 This option is inferred if you use bf(--backup) without bf(--backup-dir).
572 +dit(bf(-U, --atimes)) This tells rsync to set the access (use) times of the
573 +destination files to the same value as the source files. Note that the
574 +reading of the source file may update the atime of the source files, so
575 +repeated rsync runs with --atimes may be needed if you want to force the
576 +access-time values to be 100% identical on the two systems.
578 dit(bf(--chmod)) This options tells rsync to apply the listed "chmod" pattern
579 to the permission of the files on the destination. In addition to the normal
580 parsing rules specified in the chmod manpage, you can specify an item that
581 @@ -1219,9 +1226,13 @@ quote(itemize(
582 by the file transfer.
583 it() A bf(t) means the modification time is different and is being updated
584 to the sender's value (requires bf(--times)). An alternate value of bf(T)
585 - means that the time will be set to the transfer time, which happens
586 + means that the modify time will be set to the transfer time, which happens
587 anytime a symlink is transferred, or when a file or device is transferred
589 + it() A bf(u) means the access (use) time is different and is being updated to
590 + the sender's value (requires bf(--atimes)). An alternate value of bf(U)
591 + means that the access time will be set to the transfer time, which happens
592 + anytime a symlink is transferred.
593 it() A bf(p) means the permissions are different and are being updated to
594 the sender's value (requires bf(--perms)).
595 it() An bf(o) means the owner is different and is being updated to the
596 --- orig/sender.c 2006-01-14 20:27:10
597 +++ sender.c 2006-01-24 18:10:23
598 @@ -38,6 +38,7 @@ extern int do_progress;
601 extern int write_batch;
602 +extern unsigned int file_struct_len;
603 extern struct stats stats;
604 extern struct file_list *the_file_list;
605 extern char *log_format;
606 @@ -126,7 +127,7 @@ void successful_send(int ndx)
608 file = the_file_list->files[ndx];
609 /* The generator might tell us about symlinks we didn't send. */
610 - if (!(file->flags & FLAG_SENT) && !S_ISLNK(file->mode))
611 + if (!(FFLAGS(file) & FLAG_SENT) && !S_ISLNK(file->mode))
613 if (file->dir.root) {
614 offset = stringjoin(fname, sizeof fname,
615 @@ -370,7 +371,7 @@ void send_files(struct file_list *flist,
616 rprintf(FINFO, "sender finished %s\n", fname);
618 /* Flag that we actually sent this entry. */
619 - file->flags |= FLAG_SENT;
620 + FFLAGS(file) |= FLAG_SENT;
622 make_backups = save_make_backups;
624 --- orig/testsuite/atimes.test 2006-01-24 22:54:53
625 +++ testsuite/atimes.test 2006-01-24 22:54:53
629 +# Test rsync copying atimes
631 +. "$suitedir/rsync.fns"
637 +touch "$fromdir/foo"
638 +touch -a -t 200102031717.42 "$fromdir/foo"
642 +checkit "$RSYNC -rtUgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
644 +# The script would have aborted on error, so getting here means we've won.
646 --- orig/testsuite/devices.test 2006-01-24 22:24:32
647 +++ testsuite/devices.test 2006-01-24 22:32:30
648 @@ -55,14 +55,14 @@ touch -r "$fromdir/block" "$fromdir/bloc
649 $RSYNC -ai "$fromdir/block" "$todir/block2" \
651 cat <<EOT >"$chkfile"
655 diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
657 $RSYNC -ai "$fromdir/block2" "$todir/block" \
659 cat <<EOT >"$chkfile"
663 diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
665 @@ -71,7 +71,7 @@ sleep 1
666 $RSYNC -Di "$fromdir/block3" "$todir/block" \
668 cat <<EOT >"$chkfile"
672 diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
674 @@ -79,15 +79,15 @@ $RSYNC -aiHvv "$fromdir/" "$todir/" \
677 cat <<EOT >"$chkfile"
682 -hD++++++ block2.5 => block3
691 +hD+++++++ block2.5 => block3
697 if test ! -b "$fromdir/block2.5"; then
698 sed -e '/block2\.5/d' \
699 --- orig/testsuite/itemize.test 2006-01-24 22:24:32
700 +++ testsuite/itemize.test 2006-01-24 22:32:03
701 @@ -44,14 +44,14 @@ ln "$fromdir/foo/config1" "$fromdir/foo/
702 $RSYNC -iplr "$fromdir/" "$todir/" \
704 cat <<EOT >"$chkfile"
707 ->f++++++ bar/baz/rsync
709 ->f++++++ foo/config1
710 ->f++++++ foo/config2
712 -cL++++++ foo/sym -> ../bar/baz/rsync
715 +>f+++++++ bar/baz/rsync
717 +>f+++++++ foo/config1
718 +>f+++++++ foo/config2
720 +cL+++++++ foo/sym -> ../bar/baz/rsync
722 diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
724 @@ -63,10 +63,10 @@ chmod 601 "$fromdir/foo/config2"
725 $RSYNC -iplrH "$fromdir/" "$todir/" \
727 cat <<EOT >"$chkfile"
728 ->f..T... bar/baz/rsync
729 ->f..T... foo/config1
730 ->f.sTp.. foo/config2
731 -hf..T... foo/extra => foo/config1
732 +>f..T.... bar/baz/rsync
733 +>f..T.... foo/config1
734 +>f.sT.p.. foo/config2
735 +hf..T.... foo/extra => foo/config1
737 diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
739 @@ -83,11 +83,11 @@ chmod 777 "$todir/bar/baz/rsync"
740 $RSYNC -iplrtc "$fromdir/" "$todir/" \
742 cat <<EOT >"$chkfile"
743 -.f..tp.. bar/baz/rsync
745 -.f..t... foo/config1
746 ->fcstp.. foo/config2
747 -cL..T... foo/sym -> ../bar/baz/rsync
748 +.f..t.p.. bar/baz/rsync
750 +.f..t.... foo/config1
751 +>fcst.p.. foo/config2
752 +cL..T.... foo/sym -> ../bar/baz/rsync
754 diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
756 @@ -112,15 +112,15 @@ $RSYNC -ivvplrtH "$fromdir/" "$todir/" \
759 cat <<EOT >"$chkfile"
763 -.f...p.. bar/baz/rsync
766 ->f..t... foo/config2
768 -.L foo/sym -> ../bar/baz/rsync
772 +.f....p.. bar/baz/rsync
775 +>f..t.... foo/config2
777 +.L foo/sym -> ../bar/baz/rsync
779 diff $diffopt "$chkfile" "$outfile" || test_fail "test 5 failed"
781 @@ -139,8 +139,8 @@ touch "$todir/foo/config2"
782 $RSYNC -iplrtH "$fromdir/" "$todir/" \
784 cat <<EOT >"$chkfile"
785 -.f...p.. foo/config1
786 ->f..t... foo/config2
787 +.f....p.. foo/config1
788 +>f..t.... foo/config2
790 diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
792 @@ -149,15 +149,15 @@ $RSYNC -ivvplrtH --copy-dest="$lddir" "$
795 cat <<EOT >"$chkfile"
803 -hf foo/extra => foo/config1
804 -cL..T... foo/sym -> ../bar/baz/rsync
812 +hf foo/extra => foo/config1
813 +cL..T.... foo/sym -> ../bar/baz/rsync
815 diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
817 @@ -165,11 +165,11 @@ rm -rf "$todir"
818 $RSYNC -iplrtH --copy-dest="$lddir" "$fromdir/" "$todir/" \
820 cat <<EOT >"$chkfile"
825 -hf foo/extra => foo/config1
830 +hf foo/extra => foo/config1
832 diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
834 @@ -196,15 +196,15 @@ $RSYNC -ivvplrtH --link-dest="$lddir" "$
837 cat <<EOT >"$chkfile"
845 -hf foo/extra => foo/config1
846 -hL foo/sym -> ../bar/baz/rsync
854 +hf foo/extra => foo/config1
855 +hL foo/sym -> ../bar/baz/rsync
857 diff $diffopt "$chkfile" "$outfile" || test_fail "test 11 failed"
859 @@ -212,10 +212,10 @@ rm -rf "$todir"
860 $RSYNC -iplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
862 cat <<EOT >"$chkfile"
872 diff $diffopt "$chkfile" "$outfile" || test_fail "test 12 failed"
874 @@ -243,14 +243,14 @@ filter_outfile
875 # TODO fix really-old problem when combining -H with --compare-dest:
876 # missing output for foo/extra hard-link (and it might not be updated)!
877 cat <<EOT >"$chkfile"
885 -.L foo/sym -> ../bar/baz/rsync
893 +.L foo/sym -> ../bar/baz/rsync
895 diff $diffopt "$chkfile" "$outfile" || test_fail "test 14 failed"
897 @@ -258,10 +258,10 @@ rm -rf "$todir"
898 $RSYNC -iplrtH --compare-dest="$lddir" "$fromdir/" "$todir/" \
900 cat <<EOT >"$chkfile"
910 diff $diffopt "$chkfile" "$outfile" || test_fail "test 15 failed"
912 --- orig/testsuite/rsync.fns 2005-06-10 21:33:28
913 +++ testsuite/rsync.fns 2005-07-28 00:41:20
914 @@ -50,7 +50,7 @@ printmsg() {
918 - find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
919 + find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
923 @@ -158,6 +158,10 @@ checkit() {
924 # We can just write everything to stdout/stderr, because the
925 # wrapper hides it unless there is a problem.
927 + if test x$TLS_ARGS = x--atime; then
928 + ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
931 echo "Running: \"$1\""
934 @@ -165,10 +169,13 @@ checkit() {
938 + if test x$TLS_ARGS != x--atime; then
939 + ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
943 echo "check how the directory listings compare with diff:"
945 - ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
946 ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
947 diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
949 --- orig/tls.c 2005-09-24 17:40:31
950 +++ tls.c 2005-03-23 17:49:48
957 #define PROGRAM "tls"
959 @@ -48,6 +49,7 @@ int read_only = 1;
961 int preserve_perms = 0;
963 +static int display_atime = 0;
965 static void failed(char const *what, char const *where)
967 @@ -56,14 +58,29 @@ static void failed(char const *what, cha
971 +static void storetime(char *dest, time_t t)
974 + struct tm *mt = gmtime(&t);
976 + sprintf(dest, "%04d-%02d-%02d %02d:%02d:%02d ",
977 + (int)mt->tm_year + 1900,
978 + (int)mt->tm_mon + 1,
988 static void list_file(const char *fname)
991 char permbuf[PERMSTRING_SIZE];
998 if (do_lstat(fname, &buf) < 0)
999 @@ -96,19 +113,8 @@ static void list_file(const char *fname)
1001 permstring(permbuf, buf.st_mode);
1003 - if (buf.st_mtime) {
1004 - mt = gmtime(&buf.st_mtime);
1006 - sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
1007 - (int)mt->tm_year + 1900,
1008 - (int)mt->tm_mon + 1,
1014 - strcpy(datebuf, " ");
1016 + storetime(mtimebuf, buf.st_mtime);
1017 + storetime(atimebuf, buf.st_atime);
1019 /* TODO: Perhaps escape special characters in fname? */
1021 @@ -119,24 +125,55 @@ static void list_file(const char *fname)
1022 (long)minor(buf.st_rdev));
1023 } else /* NB: use double for size since it might not fit in a long. */
1024 printf("%12.0f", (double)buf.st_size);
1025 - printf(" %6ld.%-6ld %6ld %s %s%s\n",
1026 + printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
1027 (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
1028 - datebuf, fname, linkbuf);
1029 + mtimebuf, display_atime && !S_ISDIR(buf.st_mode) ? atimebuf : "",
1033 +static struct poptOption long_options[] = {
1034 + /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
1035 + {"atime", 'u', POPT_ARG_NONE, &display_atime, 0, 0, 0},
1036 + {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0},
1040 +static void tls_usage(int ret)
1042 + fprintf(stderr, "usage: " PROGRAM " [--atime | -u] DIR ...\n"
1043 + "Trivial file listing program for portably checking rsync\n");
1048 main(int argc, char *argv[])
1051 - fprintf(stderr, "usage: " PROGRAM " DIR ...\n"
1052 - "Trivial file listing program for portably checking rsync\n");
1055 + const char **extra_args;
1058 + pc = poptGetContext(PROGRAM, argc, (const char **)argv,
1060 + while ((opt = poptGetNextOpt(pc)) != -1) {
1067 + poptBadOption(pc, POPT_BADOPTION_NOALIAS),
1068 + poptStrerror(opt));
1073 - for (argv++; *argv; argv++) {
1076 + extra_args = poptGetArgs(pc);
1077 + if (*extra_args == NULL)
1080 + for (; *extra_args; extra_args++)
1081 + list_file(*extra_args);
1082 + poptFreeContext(pc);
1086 --- orig/util.c 2006-01-20 00:12:48
1087 +++ util.c 2006-01-14 08:20:29
1088 @@ -130,7 +130,7 @@ void overflow_exit(char *str)
1092 -int set_modtime(char *fname, time_t modtime, mode_t mode)
1093 +int set_times(char *fname, time_t modtime, time_t atime, mode_t mode)
1095 #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
1097 @@ -138,9 +138,13 @@ int set_modtime(char *fname, time_t modt
1101 - rprintf(FINFO, "set modtime of %s to (%ld) %s",
1102 + char mtimebuf[200];
1104 + strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
1106 + "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
1107 fname, (long)modtime,
1108 - asctime(localtime(&modtime)));
1109 + mtimebuf, (long)atime, timestring(atime));
1113 @@ -149,7 +153,7 @@ int set_modtime(char *fname, time_t modt
1116 struct timeval t[2];
1117 - t[0].tv_sec = time(NULL);
1118 + t[0].tv_sec = atime;
1120 t[1].tv_sec = modtime;
1122 @@ -160,12 +164,12 @@ int set_modtime(char *fname, time_t modt
1123 return utimes(fname, t);
1124 #elif defined HAVE_UTIMBUF
1125 struct utimbuf tbuf;
1126 - tbuf.actime = time(NULL);
1127 + tbuf.actime = atime;
1128 tbuf.modtime = modtime;
1129 return utime(fname,&tbuf);
1130 #elif defined HAVE_UTIME
1132 - t[0] = time(NULL);
1135 return utime(fname,t);
1137 @@ -1175,8 +1179,8 @@ int msleep(int t)
1141 - * Determine if two file modification times are equivalent (either
1142 - * exact or in the modification timestamp window established by
1143 + * Determine if two file times are equivalent (either
1144 + * exact or in the timestamp window established by
1147 * @retval 0 if the times should be treated as the same
1148 @@ -1185,7 +1189,7 @@ int msleep(int t)
1150 * @retval -1 if the 2nd is later
1152 -int cmp_modtime(time_t file1, time_t file2)
1153 +int cmp_time(time_t file1, time_t file2)
1155 if (file2 > file1) {
1156 if (file2 - file1 <= modify_window)