summaryrefslogtreecommitdiff
path: root/src/fileops.c
diff options
context:
space:
mode:
authorRyo Nakamura <upa@haeena.net>2024-02-06 16:15:43 +0900
committerRyo Nakamura <upa@haeena.net>2024-02-06 16:15:43 +0900
commita7f8ad948b38c450c0f9ccd52185771ae8f9754e (patch)
treec480252f0a26dca743d1c81818dec6f6a660f29e /src/fileops.c
parentff45d9d71b85a618aed6d3d5e5056bada6ff81f9 (diff)
add -p option, preserving file timestamps
Diffstat (limited to 'src/fileops.c')
-rw-r--r--src/fileops.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/src/fileops.c b/src/fileops.c
index e4e8088..5dbbebd 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -4,10 +4,13 @@
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
+#include <sys/times.h>
+#include <utime.h>
#include <fileops.h>
#include <ssh.h>
#include <message.h>
+#include <platform.h>
sftp_session __thread tls_sftp;
@@ -167,6 +170,18 @@ static void sftp_attr_to_stat(sftp_attributes attr, struct stat *st)
st->st_gid = attr->gid;
st->st_mode = attr->permissions;
+#if defined(__APPLE__)
+#define st_atim st_atimespec
+#define st_mtim st_mtimespec
+#define st_ctim st_ctimespec
+#endif
+ st->st_atim.tv_sec = attr->atime;
+ st->st_atim.tv_nsec = attr->atime_nseconds;
+ st->st_mtim.tv_sec = attr->mtime;
+ st->st_mtim.tv_nsec = attr->mtime_nseconds;
+ st->st_ctim.tv_sec = attr->createtime;
+ st->st_ctim.tv_nsec = attr->createtime_nseconds;
+
switch (attr->type) {
case SSH_FILEXFER_TYPE_REGULAR:
st->st_mode |= S_IFREG;
@@ -186,8 +201,6 @@ static void sftp_attr_to_stat(sftp_attributes attr, struct stat *st)
default:
mpr_warn("unkown SSH_FILEXFER_TYPE %d", attr->type);
}
-
- /* ToDo: convert atime, ctime, and mtime */
}
@@ -196,6 +209,8 @@ int mscp_stat(const char *path, struct stat *st, sftp_session sftp)
sftp_attributes attr;
int ret = 0;
+ memset(st, 0, sizeof(*st));
+
if (sftp) {
attr = sftp_stat(sftp, path);
sftp_err_to_errno(sftp);
@@ -292,23 +307,34 @@ off_t mscp_lseek(mf *f, off_t off)
return ret;
}
-int mscp_setstat(const char *path, mode_t mode, size_t size, sftp_session sftp)
+int mscp_setstat(const char *path, struct stat *st, bool preserve_ts, sftp_session sftp)
{
int ret;
if (sftp) {
struct sftp_attributes_struct attr;
memset(&attr, 0, sizeof(attr));
- attr.permissions = mode;
- attr.size = size;
+ attr.permissions = st->st_mode;
+ attr.size = st->st_size;
attr.flags = (SSH_FILEXFER_ATTR_PERMISSIONS|SSH_FILEXFER_ATTR_SIZE);
+ if (preserve_ts) {
+ attr.atime = st->st_atim.tv_sec;
+ attr.atime_nseconds = st->st_atim.tv_nsec;
+ attr.mtime = st->st_mtim.tv_sec;
+ attr.mtime_nseconds = st->st_mtim.tv_nsec;
+ attr.flags |= (SSH_FILEXFER_ATTR_ACCESSTIME |
+ SSH_FILEXFER_ATTR_MODIFYTIME |
+ SSH_FILEXFER_ATTR_SUBSECOND_TIMES);
+ }
ret = sftp_setstat(sftp, path, &attr);
sftp_err_to_errno(sftp);
} else {
- if ((ret = chmod(path, mode)) < 0)
+ if ((ret = chmod(path, st->st_mode)) < 0)
return ret;
- if ((ret = truncate(path, size)) < 0)
+ if ((ret = truncate(path, st->st_size)) < 0)
return ret;
+ if (preserve_ts)
+ ret = setutimes(path, st->st_atim, st->st_mtim);
}
return ret;