ftp currently uses utime(3) to set the modification time on the retrieved
file. It set the access time on the file to the current time when doing
so. By converting this to use utimensat(), we can avoid the silly call
to time(3) to get the current time for the atime by instead passing
UTIME_NOW.
However, I _think_ ftp does this just because utime(3) has no way to set
the modification time without also setting the access time and calling
stat(2) just to get the current atime (and dealing with the possible error
cases) wasn't worth it, so instead of setting the atime to the current
time with UTIME_NOW, I propose leaving the atime unchanged with
UTIME_OMIT.
Thoughts? oks?
Philip Guenther
Index: ftp.c
===================================================================
RCS file: /data/src/openbsd/src/usr.bin/ftp/ftp.c,v
retrieving revision 1.105
diff -u -p -r1.105 ftp.c
--- ftp.c 28 Jun 2019 13:35:01 -0000 1.105
+++ ftp.c 14 Oct 2019 01:32:56 -0000
@@ -72,6 +72,7 @@
#include <ctype.h>
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
#include <netdb.h>
#include <poll.h>
#include <stdarg.h>
@@ -79,7 +80,6 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <utime.h>
#include "ftp_var.h"
@@ -1211,11 +1211,12 @@ break2:
if (preserve && (closefunc == fclose)) {
mtime = remotemodtime(remote, 0);
if (mtime != -1) {
- struct utimbuf ut;
+ struct timespec times[2];
- ut.actime = time(NULL);
- ut.modtime = mtime;
- if (utime(local, &ut) == -1)
+ times[0].tv_nsec = UTIME_OMIT;
+ times[1].tv_sec = mtime;
+ times[1].tv_nsec = 0;
+ if (utimensat(AT_FDCWD, local, times, 0) == -1)
fprintf(ttyout,
"Can't change modification time on %s to %s",
local, asctime(localtime(&mtime)));