Fixed the sending of new files with long xattrs.
[rsync/rsync-patches.git] / atimes.diff
CommitLineData
03019e41 1To use this patch, run these commands for a successful build:
8a529471 2
03019e41 3 patch -p1 <patches/atimes.diff
27e96866
WD
4 ./prepare-source
5 ./configure (optional if already run)
6 make
8a529471
WD
7
8
fdf967c7
WD
9--- old/compat.c
10+++ new/compat.c
4306c620 11@@ -62,6 +62,8 @@ void setup_protocol(int f_out,int f_in)
7e27b6c0 12 preserve_uid = ++file_extra_cnt;
fdf967c7 13 if (preserve_gid)
7e27b6c0 14 preserve_gid = ++file_extra_cnt;
fdf967c7 15+ if (preserve_atimes)
7e27b6c0 16+ preserve_atimes = ++file_extra_cnt;
4306c620
WD
17 if (preserve_acls && !am_sender)
18 preserve_acls = ++file_extra_cnt;
fdf967c7 19
9a7eef96
WD
20--- old/flist.c
21+++ new/flist.c
caf38d8d 22@@ -49,6 +49,7 @@ extern int preserve_devices;
4a65fe72 23 extern int preserve_specials;
81c32ffd
WD
24 extern int preserve_uid;
25 extern int preserve_gid;
26+extern int preserve_atimes;
27 extern int relative_paths;
a5e0f697 28 extern int implied_dirs;
7e27b6c0 29 extern int file_extra_cnt;
caf38d8d 30@@ -144,6 +145,7 @@ void show_flist_stats(void)
672ad041
WD
31 static void list_file_entry(struct file_struct *f)
32 {
33 char permbuf[PERMSTRING_SIZE];
70891d26 34+ time_t atime = preserve_atimes ? F_ATIME(f) : 0;
1aa236e1 35 double len;
1cb60481 36
1aa236e1 37 if (!F_IS_ACTIVE(f)) {
caf38d8d 38@@ -158,14 +160,16 @@ static void list_file_entry(struct file_
43581f16 39
09fb8f03 40 #ifdef SUPPORT_LINKS
43581f16
WD
41 if (preserve_links && S_ISLNK(f->mode)) {
42- rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
43+ rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
1aa236e1 44 permbuf, len, timestring(f->modtime),
672ad041 45+ preserve_atimes ? timestring(atime) : "",
70891d26 46 f_name(f, NULL), F_SYMLINK(f));
43581f16
WD
47 } else
48 #endif
896c61d0 49 {
43581f16
WD
50- rprintf(FINFO, "%s %11.0f %s %s\n",
51+ rprintf(FINFO, "%s %11.0f %s %s %s\n",
1aa236e1 52 permbuf, len, timestring(f->modtime),
672ad041 53+ preserve_atimes ? timestring(atime) : "",
bd68c3c2 54 f_name(f, NULL));
896c61d0 55 }
43581f16 56 }
caf38d8d 57@@ -349,6 +353,7 @@ int push_flist_dir(const char *dir, int
fc068916 58 static void send_file_entry(int f, struct file_struct *file, int ndx)
43581f16 59 {
43581f16
WD
60 static time_t modtime;
61+ static time_t atime;
62 static mode_t mode;
ba50e96c 63 static int64 dev;
43581f16 64 static dev_t rdev;
caf38d8d 65@@ -416,6 +421,13 @@ static void send_file_entry(int f, struc
43581f16
WD
66 flags |= XMIT_SAME_TIME;
67 else
68 modtime = file->modtime;
81c32ffd 69+ if (preserve_atimes && !S_ISDIR(mode)) {
70891d26 70+ time_t file_atime = F_ATIME(file);
672ad041 71+ if (file_atime == atime)
43581f16
WD
72+ flags |= XMIT_SAME_ATIME;
73+ else
672ad041 74+ atime = file_atime;
43581f16
WD
75+ }
76
09fb8f03 77 #ifdef SUPPORT_HARD_LINKS
fdf967c7 78 if (tmp_dev != 0) {
caf38d8d 79@@ -483,6 +495,8 @@ static void send_file_entry(int f, struc
43581f16
WD
80 write_int(f, modtime);
81 if (!(flags & XMIT_SAME_MODE))
82 write_int(f, to_wire_mode(mode));
81c32ffd 83+ if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
43581f16
WD
84+ write_int(f, atime);
85 if (preserve_uid && !(flags & XMIT_SAME_UID)) {
caf38d8d
WD
86 if (protocol_version < 30)
87 write_int(f, uid);
88@@ -569,7 +583,7 @@ static void send_file_entry(int f, struc
70891d26 89 static struct file_struct *recv_file_entry(struct file_list *flist,
7e27b6c0 90 int flags, int f)
43581f16 91 {
70891d26
WD
92- static time_t modtime;
93+ static time_t modtime, atime;
43581f16 94 static mode_t mode;
ba50e96c 95 static int64 dev;
43581f16 96 static dev_t rdev;
caf38d8d 97@@ -667,6 +681,8 @@ static struct file_struct *recv_file_ent
43581f16
WD
98 modtime = (time_t)read_int(f);
99 if (!(flags & XMIT_SAME_MODE))
100 mode = from_wire_mode(read_int(f));
81c32ffd 101+ if (preserve_atimes && !S_ISDIR(mode) && !(flags & XMIT_SAME_ATIME))
43581f16
WD
102+ atime = (time_t)read_int(f);
103
1cb60481
WD
104 if (chmod_modes && !S_ISLNK(mode))
105 mode = tweak_mode(mode, chmod_modes);
caf38d8d 106@@ -791,6 +807,8 @@ static struct file_struct *recv_file_ent
fc068916 107 F_OWNER(file) = uid;
70891d26 108 if (preserve_gid)
fc068916 109 F_GROUP(file) = gid;
1cb60481 110+ if (preserve_atimes)
70891d26 111+ F_ATIME(file) = atime;
1cb60481 112
fc068916
WD
113 if (basename != thisname) {
114 file->dirname = lastdir;
caf38d8d 115@@ -1096,6 +1114,8 @@ struct file_struct *make_file(const char
fc068916 116 F_OWNER(file) = st.st_uid;
70891d26 117 if (preserve_gid)
fc068916 118 F_GROUP(file) = st.st_gid;
1cb60481 119+ if (preserve_atimes)
70891d26 120+ F_ATIME(file) = st.st_atime;
1cb60481 121
fc068916
WD
122 if (basename != thisname)
123 file->dirname = lastdir;
9a7eef96
WD
124--- old/generator.c
125+++ new/generator.c
fc068916 126@@ -44,6 +44,7 @@ extern int preserve_perms;
55602791 127 extern int preserve_uid;
81c32ffd
WD
128 extern int preserve_gid;
129 extern int preserve_times;
81c32ffd 130+extern int preserve_atimes;
55602791 131 extern int omit_dir_times;
4a65fe72 132 extern int delete_mode;
81c32ffd 133 extern int delete_before;
4306c620 134@@ -552,6 +553,9 @@ void itemize(const char *fname, struct f
9a70b743 135 && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
4306c620 136 || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0))
f20eb450 137 iflags |= ITEM_REPORT_TIME;
55602791 138+ if (preserve_atimes && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
85a65b82 139+ && cmp_time(F_ATIME(file), sxp->st.st_atime) != 0)
55602791 140+ iflags |= ITEM_REPORT_ATIME;
4306c620 141 if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
f20eb450 142 iflags |= ITEM_REPORT_PERMS;
4306c620
WD
143 if (preserve_uid && am_root && F_UID(file) != sxp->st.st_uid)
144@@ -852,6 +856,8 @@ static int try_dests_reg(struct file_str
8aec0853
WD
145 if (link_dest) {
146 if (!hard_link_one(file, fname, cmpbuf, 1))
8a04c9a7
WD
147 goto try_a_copy;
148+ if (preserve_atimes)
85a65b82 149+ set_file_attrs(fname, file, sxp, 0);
1aa236e1 150 if (preserve_hard_links && F_IS_HLINKED(file))
4306c620 151 finish_hard_link(file, fname, &sxp->st, itemizing, code, j);
8aec0853 152 if (itemizing && (verbose > 1 || stdout_format_has_i > 1)) {
85a65b82
WD
153@@ -1700,7 +1706,7 @@ static void touch_up_dirs(struct file_li
154 if (!(file->mode & S_IWUSR))
155 do_chmod(fname, file->mode);
156 if (need_retouch_dir_times)
157- set_modtime(fname, file->modtime, file->mode);
158+ set_times(fname, file->modtime, file->modtime, file->mode);
159 if (allowed_lull && !(++j % lull_mod))
160 maybe_send_keepalive();
161 else if (!(j % 200))
9a7eef96
WD
162--- old/log.c
163+++ new/log.c
4306c620 164@@ -36,6 +36,7 @@ extern int msg_fd_out;
577db5e2 165 extern int allow_8bit_chars;
81c32ffd
WD
166 extern int protocol_version;
167 extern int preserve_times;
168+extern int preserve_atimes;
70891d26
WD
169 extern int preserve_uid;
170 extern int preserve_gid;
1aa236e1 171 extern int stdout_format_has_i;
4306c620 172@@ -624,7 +625,8 @@ static void log_formatted(enum logcode c
fb11cdd7
WD
173 c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
174 c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
175 c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
4306c620 176- c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.' : 'u';
fb11cdd7 177+ c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.'
55602791 178+ : S_ISLNK(file->mode) ? 'U' : 'u';
4306c620
WD
179 c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
180 c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
181 c[11] = '\0';
9a7eef96
WD
182--- old/options.c
183+++ new/options.c
b3593e7c 184@@ -55,6 +55,7 @@ int preserve_uid = 0;
43581f16
WD
185 int preserve_gid = 0;
186 int preserve_times = 0;
9a21ad72 187 int omit_dir_times = 0;
81c32ffd 188+int preserve_atimes = 0;
43581f16
WD
189 int update_only = 0;
190 int cvs_exclude = 0;
191 int dry_run = 0;
4306c620 192@@ -315,8 +316,9 @@ void usage(enum logcode F)
4a65fe72
WD
193 rprintf(F," --devices preserve device files (super-user only)\n");
194 rprintf(F," --specials preserve special files\n");
195 rprintf(F," -D same as --devices --specials\n");
81c32ffd
WD
196- rprintf(F," -t, --times preserve times\n");
197- rprintf(F," -O, --omit-dir-times omit directories when preserving times\n");
198+ rprintf(F," -t, --times preserve modify times\n");
199+ rprintf(F," -O, --omit-dir-times omit directories when preserving modify times\n");
55602791 200+ rprintf(F," -U, --atimes preserve access (use) times\n");
4a65fe72 201 rprintf(F," --super receiver attempts super-user activities\n");
43581f16
WD
202 rprintf(F," -S, --sparse handle sparse files efficiently\n");
203 rprintf(F," -n, --dry-run show what would have been transferred\n");
4306c620 204@@ -436,6 +438,9 @@ static struct poptOption long_options[]
489b0a72
WD
205 {"times", 't', POPT_ARG_VAL, &preserve_times, 1, 0, 0 },
206 {"no-times", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
207 {"no-t", 0, POPT_ARG_VAL, &preserve_times, 0, 0, 0 },
55602791 208+ {"atimes", 'U', POPT_ARG_VAL, &preserve_atimes, 1, 0, 0 },
489b0a72 209+ {"no-atimes", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
70891d26 210+ {"no-U", 0, POPT_ARG_VAL, &preserve_atimes, 0, 0, 0 },
52f25864 211 {"omit-dir-times", 'O', POPT_ARG_VAL, &omit_dir_times, 2, 0, 0 },
489b0a72 212 {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
4a65fe72 213 {"super", 0, POPT_ARG_VAL, &am_root, 2, 0, 0 },
4306c620 214@@ -1577,6 +1582,8 @@ void server_options(char **args,int *arg
43581f16
WD
215 argstr[x++] = 'D';
216 if (preserve_times)
217 argstr[x++] = 't';
81c32ffd 218+ if (preserve_atimes)
55602791 219+ argstr[x++] = 'U';
43581f16 220 if (preserve_perms)
4a65fe72
WD
221 argstr[x++] = 'p';
222 else if (preserve_executability && am_sender)
9a7eef96
WD
223--- old/rsync.c
224+++ new/rsync.c
4306c620
WD
225@@ -34,6 +34,7 @@ extern int dry_run;
226 extern int preserve_acls;
d9a67109 227 extern int preserve_perms;
4a65fe72 228 extern int preserve_executability;
d9a67109 229+extern int preserve_atimes;
43581f16 230 extern int preserve_times;
9a21ad72 231 extern int omit_dir_times;
43581f16 232 extern int am_root;
4306c620 233@@ -234,6 +235,7 @@ int set_file_attrs(char *fname, struct f
9a21ad72 234 int updated = 0;
4306c620 235 statx sx2;
9a21ad72
WD
236 int change_uid, change_gid;
237+ time_t atime, mtime;
1ed0b5c9 238 mode_t new_mode = file->mode;
9a21ad72 239
4306c620
WD
240 if (!sxp) {
241@@ -261,18 +263,36 @@ int set_file_attrs(char *fname, struct f
242 get_acl(fname, sxp);
243 #endif
9a21ad72 244
8a04c9a7
WD
245+ /* This code must be the first update in the function due to
246+ * how it uses the "updated" variable. */
4306c620 247 if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && omit_dir_times))
4a65fe72 248 flags |= ATTRS_SKIP_MTIME;
4306c620 249+ if (!preserve_atimes || S_ISDIR(sxp->st.st_mode))
4a65fe72
WD
250+ flags |= ATTRS_SKIP_ATIME;
251 if (!(flags & ATTRS_SKIP_MTIME)
4306c620
WD
252 && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
253- int ret = set_modtime(fname, file->modtime, sxp->st.st_mode);
9a21ad72 254+ mtime = file->modtime;
9e355bf1 255+ updated = 1;
9a21ad72 256+ } else
4306c620 257+ mtime = sxp->st.st_mtime;
672ad041 258+ if (!(flags & ATTRS_SKIP_ATIME)) {
70891d26 259+ time_t file_atime = F_ATIME(file);
4306c620 260+ if (cmp_time(sxp->st.st_atime, file_atime) != 0) {
672ad041
WD
261+ atime = file_atime;
262+ updated = 1;
263+ } else
4306c620 264+ atime = sxp->st.st_atime;
81c32ffd 265+ } else
4306c620 266+ atime = sxp->st.st_atime;
9e355bf1 267+ if (updated) {
4306c620 268+ int ret = set_times(fname, mtime, atime, sxp->st.st_mode);
9e355bf1
WD
269 if (ret < 0) {
270 rsyserr(FERROR, errno, "failed to set times on %s",
271 full_fname(fname));
4306c620 272 goto cleanup;
9e355bf1
WD
273 }
274- if (ret == 0) /* ret == 1 if symlink could not be set */
275- updated = 1;
276+ if (ret > 0) /* ret == 1 if symlink could not be set */
277+ updated = 0;
43581f16
WD
278 }
279
4306c620 280 change_uid = am_root && preserve_uid && sxp->st.st_uid != F_UID(file);
9a7eef96
WD
281--- old/rsync.h
282+++ new/rsync.h
4306c620 283@@ -56,6 +56,7 @@
caf38d8d
WD
284 #define XMIT_RDEV_MINOR_8_pre30 (1<<11) /* protocols 28 - 29 */
285 #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - NOW */
286 #define XMIT_HLINK_FIRST (1<<12) /* protocols 30 - NOW */
287+#define XMIT_SAME_ATIME (1<<13) /* protocols ?? - NOW */
43581f16
WD
288
289 /* These flags are used in the live flist data. */
290
4306c620 291@@ -136,6 +137,7 @@
8a529471 292
4a65fe72
WD
293 #define ATTRS_REPORT (1<<0)
294 #define ATTRS_SKIP_MTIME (1<<1)
295+#define ATTRS_SKIP_ATIME (1<<2)
8a529471
WD
296
297 #define FULL_FLUSH 1
298 #define NORMAL_FLUSH 0
4306c620 299@@ -571,6 +573,7 @@ extern int file_extra_cnt;
fdf967c7
WD
300 extern int preserve_uid;
301 extern int preserve_gid;
4306c620 302 extern int preserve_acls;
fdf967c7
WD
303+extern int preserve_atimes;
304
305 #define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
306 #define EXTRA_LEN (sizeof (union file_extras))
4306c620 307@@ -603,6 +606,7 @@ extern int preserve_acls;
1aa236e1 308 /* When the associated option is on, all entries will have these present: */
fc068916
WD
309 #define F_OWNER(f) REQ_EXTRA(f, preserve_uid)->unum
310 #define F_GROUP(f) REQ_EXTRA(f, preserve_gid)->unum
fdf967c7 311+#define F_ATIME(f) REQ_EXTRA(f, preserve_atimes)->unum
4306c620 312 #define F_ACL(f) REQ_EXTRA(f, preserve_acls)->unum
70891d26 313
1071853f 314 /* These items are per-entry optional and mutally exclusive: */
9a7eef96
WD
315--- old/rsync.yo
316+++ new/rsync.yo
4306c620 317@@ -329,8 +329,9 @@ to the detailed description below for a
4a65fe72
WD
318 --devices preserve device files (super-user only)
319 --specials preserve special files
320 -D same as --devices --specials
81c32ffd 321- -t, --times preserve times
610969d1 322- -O, --omit-dir-times omit directories when preserving times
81c32ffd 323+ -t, --times preserve modify times
610969d1 324+ -O, --omit-dir-times omit directories when preserving mod-times
55602791 325+ -U, --atimes preserve access (use) times
4a65fe72 326 --super receiver attempts super-user activities
43581f16
WD
327 -S, --sparse handle sparse files efficiently
328 -n, --dry-run show what would have been transferred
4306c620 329@@ -896,6 +897,12 @@ it is preserving modification times (see
a7219d20 330 the directories on the receiving side, it is a good idea to use bf(-O).
333b8af4 331 This option is inferred if you use bf(--backup) without bf(--backup-dir).
7b675ff5 332
55602791
WD
333+dit(bf(-U, --atimes)) This tells rsync to set the access (use) times of the
334+destination files to the same value as the source files. Note that the
81c32ffd
WD
335+reading of the source file may update the atime of the source files, so
336+repeated rsync runs with --atimes may be needed if you want to force the
337+access-time values to be 100% identical on the two systems.
7b675ff5 338+
4a65fe72
WD
339 dit(bf(--super)) This tells the receiving side to attempt super-user
340 activities even if the receiving rsync wasn't run by the super-user. These
341 activities include: preserving users via the bf(--owner) option, preserving
4306c620 342@@ -1482,7 +1489,7 @@ quote(itemization(
81c32ffd
WD
343 by the file transfer.
344 it() A bf(t) means the modification time is different and is being updated
345 to the sender's value (requires bf(--times)). An alternate value of bf(T)
346- means that the time will be set to the transfer time, which happens
347+ means that the modify time will be set to the transfer time, which happens
348 anytime a symlink is transferred, or when a file or device is transferred
349 without bf(--times).
ccc3a12c 350 it() A bf(p) means the permissions are different and are being updated to
4306c620 351@@ -1491,8 +1498,10 @@ quote(itemization(
ccc3a12c
WD
352 sender's value (requires bf(--owner) and super-user privileges).
353 it() A bf(g) means the group is different and is being updated to the
354 sender's value (requires bf(--group) and the authority to set the group).
4306c620
WD
355- it() The bf(u) slot is reserved for reporting update (access) time changes
356- (a feature that is not yet released).
55602791
WD
357+ it() A bf(u) means the access (use) time is different and is being updated to
358+ the sender's value (requires bf(--atimes)). An alternate value of bf(U)
359+ means that the access time will be set to the transfer time, which happens
ccc3a12c 360+ when a symlink or directory is updated.
4306c620
WD
361 it() The bf(a) means that the ACL information changed.
362 it() The bf(x) slot is reserved for reporting extended attribute changes
363 (a feature that is not yet released).
9a7eef96
WD
364--- old/sender.c
365+++ new/sender.c
4306c620 366@@ -41,6 +41,7 @@ extern int do_progress;
1cb60481
WD
367 extern int inplace;
368 extern int batch_fd;
369 extern int write_batch;
370+extern unsigned int file_struct_len;
371 extern struct stats stats;
fc068916 372 extern struct file_list *cur_flist, *first_flist;
4306c620 373
9a7eef96
WD
374--- old/testsuite/atimes.test
375+++ new/testsuite/atimes.test
13bed3dd
WD
376@@ -0,0 +1,19 @@
377+#! /bin/sh
378+
379+# Test rsync copying atimes
380+
381+. "$suitedir/rsync.fns"
382+
383+set -x
384+
385+mkdir "$fromdir"
386+
387+touch "$fromdir/foo"
388+touch -a -t 200102031717.42 "$fromdir/foo"
389+
390+TLS_ARGS=--atime
391+
55602791 392+checkit "$RSYNC -rtUgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
13bed3dd
WD
393+
394+# The script would have aborted on error, so getting here means we've won.
395+exit 0
9a7eef96
WD
396--- old/testsuite/rsync.fns
397+++ new/testsuite/rsync.fns
7a56a8f1
WD
398@@ -66,7 +66,7 @@ printmsg() {
399 }
13bed3dd
WD
400
401 rsync_ls_lR() {
b78a6aba
WD
402- find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
403+ find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls" $TLS_ARGS
13bed3dd
WD
404 }
405
7a56a8f1
WD
406 check_perms() {
407@@ -184,6 +184,10 @@ checkit() {
13bed3dd
WD
408 # We can just write everything to stdout/stderr, because the
409 # wrapper hides it unless there is a problem.
410
81c32ffd
WD
411+ if test x$TLS_ARGS = x--atime; then
412+ ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
413+ fi
13bed3dd
WD
414+
415 echo "Running: \"$1\""
416 eval "$1"
417 status=$?
7a56a8f1 418@@ -191,10 +195,13 @@ checkit() {
81c32ffd
WD
419 failed="YES";
420 fi
421
422+ if test x$TLS_ARGS != x--atime; then
423+ ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
424+ fi
425+
13bed3dd 426 echo "-------------"
b78a6aba
WD
427 echo "check how the directory listings compare with diff:"
428 echo ""
13bed3dd 429- ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
b78a6aba
WD
430 ( cd "$3" && rsync_ls_lR . ) > "$tmpdir/ls-to"
431 diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
4da25dad 432
9a7eef96
WD
433--- old/tls.c
434+++ new/tls.c
b3593e7c
WD
435@@ -34,6 +34,7 @@
436 * change. */
43581f16
WD
437
438 #include "rsync.h"
439+#include "popt.h"
440
441 #define PROGRAM "tls"
442
b3593e7c 443@@ -43,6 +44,8 @@ int read_only = 1;
43581f16
WD
444 int list_only = 0;
445 int preserve_perms = 0;
446
447+static int display_atime = 0;
b3593e7c 448+
fe6407b5
WD
449 static void failed(char const *what, char const *where)
450 {
b3593e7c
WD
451 fprintf(stderr, PROGRAM ": %s %s: %s\n",
452@@ -50,12 +53,29 @@ static void failed(char const *what, cha
fe6407b5 453 exit(1);
43581f16
WD
454 }
455
3f053c45 456+static void storetime(char *dest, time_t t, size_t destsize)
43581f16
WD
457+{
458+ if (t) {
459+ struct tm *mt = gmtime(&t);
b3593e7c 460+
3f053c45
WD
461+ snprintf(dest, destsize,
462+ "%04d-%02d-%02d %02d:%02d:%02d ",
9d95bd65
WD
463+ (int)mt->tm_year + 1900,
464+ (int)mt->tm_mon + 1,
465+ (int)mt->tm_mday,
466+ (int)mt->tm_hour,
467+ (int)mt->tm_min,
468+ (int)mt->tm_sec);
3f053c45
WD
469+ } else
470+ strlcpy(dest, " ", destsize);
b3593e7c
WD
471+}
472+
fe6407b5 473 static void list_file(const char *fname)
43581f16
WD
474 {
475 STRUCT_STAT buf;
476 char permbuf[PERMSTRING_SIZE];
477- struct tm *mt;
478- char datebuf[50];
479+ char mtimebuf[50];
480+ char atimebuf[50];
481 char linkbuf[4096];
482
ba50e96c 483 if (do_lstat(fname, &buf) < 0)
b3593e7c 484@@ -88,19 +108,8 @@ static void list_file(const char *fname)
43581f16
WD
485
486 permstring(permbuf, buf.st_mode);
487
488- if (buf.st_mtime) {
489- mt = gmtime(&buf.st_mtime);
490-
3f053c45
WD
491- snprintf(datebuf, sizeof datebuf,
492- "%04d-%02d-%02d %02d:%02d:%02d",
9d95bd65
WD
493- (int)mt->tm_year + 1900,
494- (int)mt->tm_mon + 1,
495- (int)mt->tm_mday,
496- (int)mt->tm_hour,
497- (int)mt->tm_min,
498- (int)mt->tm_sec);
3f053c45
WD
499- } else
500- strlcpy(datebuf, " ", sizeof datebuf);
501+ storetime(mtimebuf, buf.st_mtime, sizeof mtimebuf);
502+ storetime(atimebuf, buf.st_atime, sizeof atimebuf);
43581f16
WD
503
504 /* TODO: Perhaps escape special characters in fname? */
505
b3593e7c 506@@ -111,23 +120,55 @@ static void list_file(const char *fname)
43581f16
WD
507 (long)minor(buf.st_rdev));
508 } else /* NB: use double for size since it might not fit in a long. */
509 printf("%12.0f", (double)buf.st_size);
510- printf(" %6ld.%-6ld %6ld %s %s%s\n",
511+ printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
512 (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
513- datebuf, fname, linkbuf);
c0be1af2 514+ mtimebuf, display_atime && !S_ISDIR(buf.st_mode) ? atimebuf : "",
43581f16 515+ fname, linkbuf);
b3593e7c
WD
516+}
517+
43581f16
WD
518+static struct poptOption long_options[] = {
519+ /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
520+ {"atime", 'u', POPT_ARG_NONE, &display_atime, 0, 0, 0},
521+ {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0},
522+ {0,0,0,0,0,0,0}
523+};
524+
525+static void tls_usage(int ret)
526+{
041d67b8 527+ fprintf(stderr, "usage: " PROGRAM " [--atime | -u] FILE ...\n"
43581f16
WD
528+ "Trivial file listing program for portably checking rsync\n");
529+ exit(ret);
b3593e7c 530 }
43581f16
WD
531
532 int
533 main(int argc, char *argv[])
534 {
535- if (argc < 2) {
041d67b8 536- fprintf(stderr, "usage: " PROGRAM " FILE ...\n"
fe6407b5 537- "Trivial file listing program for portably checking rsync\n");
43581f16 538- return 1;
03019e41 539- }
43581f16
WD
540+ poptContext pc;
541+ const char **extra_args;
542+ int opt;
03019e41
WD
543
544- for (argv++; *argv; argv++) {
545- list_file(*argv);
43581f16
WD
546+ pc = poptGetContext(PROGRAM, argc, (const char **)argv,
547+ long_options, 0);
548+ while ((opt = poptGetNextOpt(pc)) != -1) {
549+ switch (opt) {
550+ case 'h':
551+ tls_usage(0);
552+ default:
553+ fprintf(stderr,
554+ "%s: %s\n",
555+ poptBadOption(pc, POPT_BADOPTION_NOALIAS),
556+ poptStrerror(opt));
557+ tls_usage(1);
558+ }
559 }
560
43581f16
WD
561+ extra_args = poptGetArgs(pc);
562+ if (*extra_args == NULL)
563+ tls_usage(1);
564+
565+ for (; *extra_args; extra_args++)
566+ list_file(*extra_args);
567+ poptFreeContext(pc);
03019e41 568+
43581f16
WD
569 return 0;
570 }
9a7eef96
WD
571--- old/util.c
572+++ new/util.c
4306c620 573@@ -120,7 +120,7 @@ NORETURN void overflow_exit(const char *
577db5e2
WD
574 exit_cleanup(RERR_MALLOC);
575 }
43581f16 576
fb11cdd7
WD
577-int set_modtime(const char *fname, time_t modtime, mode_t mode)
578+int set_times(const char *fname, time_t modtime, time_t atime, mode_t mode)
43581f16 579 {
9e355bf1
WD
580 #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
581 if (S_ISLNK(mode))
4306c620 582@@ -128,9 +128,13 @@ int set_modtime(const char *fname, time_
9e355bf1
WD
583 #endif
584
43581f16
WD
585 if (verbose > 2) {
586- rprintf(FINFO, "set modtime of %s to (%ld) %s",
587+ char mtimebuf[200];
43581f16 588+
125d7fca 589+ strlcpy(mtimebuf, timestring(modtime), sizeof mtimebuf);
43581f16
WD
590+ rprintf(FINFO,
591+ "set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
93ca4d27 592 fname, (long)modtime,
43581f16 593- asctime(localtime(&modtime)));
9e355bf1 594+ mtimebuf, (long)atime, timestring(atime));
43581f16
WD
595 }
596
ba50e96c 597 if (dry_run)
4306c620 598@@ -139,7 +143,7 @@ int set_modtime(const char *fname, time_
43581f16 599 {
9e355bf1
WD
600 #ifdef HAVE_UTIMES
601 struct timeval t[2];
602- t[0].tv_sec = time(NULL);
603+ t[0].tv_sec = atime;
604 t[0].tv_usec = 0;
605 t[1].tv_sec = modtime;
606 t[1].tv_usec = 0;
4306c620 607@@ -152,12 +156,12 @@ int set_modtime(const char *fname, time_
9e355bf1
WD
608 return utimes(fname, t);
609 #elif defined HAVE_UTIMBUF
43581f16
WD
610 struct utimbuf tbuf;
611- tbuf.actime = time(NULL);
612+ tbuf.actime = atime;
613 tbuf.modtime = modtime;
614 return utime(fname,&tbuf);
09fb8f03 615 #elif defined HAVE_UTIME
43581f16
WD
616 time_t t[2];
617- t[0] = time(NULL);
618+ t[0] = atime;
619 t[1] = modtime;
620 return utime(fname,t);
621 #else