From 48b0016cff4bad621b94fc0bf678ec15260dd7d7 Mon Sep 17 00:00:00 2001 From: todd stecher Date: Fri, 23 Jan 2009 14:40:19 -0800 Subject: [PATCH] Extend NTIMES to allow setting create_time 1) Add in smb_file_time struct to clarify code and make room for createtime. 2) Get and set create time from SMB messages. 3) Fixup existing VFS modules + examples Some OS'es allow for the setting of the birthtime through kernel interfaces. This value is generically used for Windows createtime, but is not settable in the code today. --- examples/VFS/skel_opaque.c | 4 +- examples/VFS/skel_transparent.c | 4 +- source3/include/proto.h | 5 +- source3/include/smb.h | 7 +++ source3/include/vfs.h | 4 +- source3/modules/vfs_cap.c | 5 +- source3/modules/vfs_catia.c | 4 +- source3/modules/vfs_default.c | 15 ++--- source3/modules/vfs_full_audit.c | 6 +- source3/modules/vfs_recycle.c | 10 +-- source3/modules/vfs_shadow_copy2.c | 4 +- source3/smbd/close.c | 8 +-- source3/smbd/dosmode.c | 13 ++-- source3/smbd/reply.c | 46 ++++++++------ source3/smbd/trans2.c | 99 ++++++++++++++++++------------ source3/torture/cmd_vfs.c | 11 ++-- 16 files changed, 145 insertions(+), 100 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 3df1fcd5bfb9..48b497922a59 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -231,9 +231,9 @@ static char *skel_getwd(vfs_handle_struct *handle, char *buf) return vfswrap_getwd(NULL, buf); } -static int skel_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2]) +static int skel_ntimes(vfs_handle_struct *handle, const char *path, struct smb_file_time *ft) { - return vfswrap_ntimes(NULL, path, ts); + return vfswrap_ntimes(NULL, path, ft); } static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T offset) diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index e6dee97775b9..f5562a5f444d 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -224,9 +224,9 @@ static char *skel_getwd(vfs_handle_struct *handle, char *buf) return SMB_VFS_NEXT_GETWD(handle, buf); } -static int skel_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2]) +static int skel_ntimes(vfs_handle_struct *handle, const char *path, struct smb_file_time *ft) { - return SMB_VFS_NEXT_NTIMES(handle, path, ts); + return SMB_VFS_NEXT_NTIMES(handle, path, ft); } static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T offset) diff --git a/source3/include/proto.h b/source3/include/proto.h index 1554bfdb25e2..1414ba89ecf1 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6688,7 +6688,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st, const char *parent_dir, bool newfile); -int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2]); +int file_ntimes(connection_struct *conn, const char *fname, + struct smb_file_time *ft); bool set_sticky_write_time_path(connection_struct *conn, const char *fname, struct file_id fileid, const struct timespec mtime); bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime); @@ -7424,7 +7425,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn, files_struct *fsp, const char *fname, const SMB_STRUCT_STAT *psbuf, - struct timespec ts[2], + struct smb_file_time *ft, bool setting_write_time); void reply_findclose(struct smb_request *req); void reply_findnclose(struct smb_request *req); diff --git a/source3/include/smb.h b/source3/include/smb.h index 19d2208adaf0..aa2db693a33e 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1901,4 +1901,11 @@ struct smb_extended_info { */ #define CFF_DOS_PATH 0x00000001 +/* time info */ +struct smb_file_time { + struct timespec mtime; + struct timespec atime; + struct timespec create_time; +}; + #endif /* _SMB_H */ diff --git a/source3/include/vfs.h b/source3/include/vfs.h index d02d14b854c6..5df71da9057d 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -111,6 +111,7 @@ /* Changed to version 24 - make security descriptor const in fset_nt_acl. JRA. */ /* Changed to version 25 - Jelmer's change from SMB_BIG_UINT to uint64_t. */ /* Leave at 25 - not yet released. Add create_file call. -- tprouty. */ +/* Leave at 25 - not yet released. Add create time to ntimes. -- tstecher. */ #define SMB_VFS_INTERFACE_VERSION 25 @@ -137,6 +138,7 @@ struct security_descriptor; struct vfs_statvfs_struct; struct smb_request; struct ea_list; +struct smb_file_time; /* Available VFS operations. These values must be in sync with vfs_ops struct @@ -348,7 +350,7 @@ struct vfs_ops { int (*lchown)(struct vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid); int (*chdir)(struct vfs_handle_struct *handle, const char *path); char *(*getwd)(struct vfs_handle_struct *handle, char *buf); - int (*ntimes)(struct vfs_handle_struct *handle, const char *path, const struct timespec ts[2]); + int (*ntimes)(struct vfs_handle_struct *handle, const char *path, struct smb_file_time *ft); int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_OFF_T offset); bool (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); int (*kernel_flock)(struct vfs_handle_struct *handle, struct files_struct *fsp, uint32 share_mode); diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index 6950ab21685b..ac85d3a8043d 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -208,7 +208,8 @@ static int cap_chdir(vfs_handle_struct *handle, const char *path) return SMB_VFS_NEXT_CHDIR(handle, cappath); } -static int cap_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2]) +static int cap_ntimes(vfs_handle_struct *handle, const char *path, + struct smb_file_time *ft) { char *cappath = capencode(talloc_tos(), path); @@ -216,7 +217,7 @@ static int cap_ntimes(vfs_handle_struct *handle, const char *path, const struct errno = ENOMEM; return -1; } - return SMB_VFS_NEXT_NTIMES(handle, cappath, ts); + return SMB_VFS_NEXT_NTIMES(handle, cappath, ft); } diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 47d178a33f16..d0c341fdd389 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -252,9 +252,9 @@ static char *catia_getwd(vfs_handle_struct *handle, char *buf) } static int catia_ntimes(vfs_handle_struct *handle, - const char *path, const struct timespec ts[2]) + const char *path, struct smb_file_time *ft) { - return SMB_VFS_NEXT_NTIMES(handle, path, ts); + return SMB_VFS_NEXT_NTIMES(handle, path, ft); } static bool catia_symlink(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 61e1deb81e22..a9aabab76854 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -682,25 +682,26 @@ static char *vfswrap_getwd(vfs_handle_struct *handle, char *path) system will support. **********************************************************************/ -static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2]) +static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path, + struct smb_file_time *ft) { int result; START_PROFILE(syscall_ntimes); #if defined(HAVE_UTIMES) - if (ts != NULL) { + if (ft != NULL) { struct timeval tv[2]; - tv[0] = convert_timespec_to_timeval(ts[0]); - tv[1] = convert_timespec_to_timeval(ts[1]); + tv[0] = convert_timespec_to_timeval(ft->atime); + tv[1] = convert_timespec_to_timeval(ft->mtime); result = utimes(path, tv); } else { result = utimes(path, NULL); } #elif defined(HAVE_UTIME) - if (ts != NULL) { + if (ft != NULL) { struct utimbuf times; - times.actime = convert_timespec_to_time_t(ts[0]); - times.modtime = convert_timespec_to_time_t(ts[1]); + times.actime = convert_timespec_to_time_t(ft->atime); + times.modtime = convert_timespec_to_time_t(ft->mtime); result = utime(path, times); } else { result = utime(path, NULL); diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 1d9983a753b4..73758a2d9d8a 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -172,7 +172,7 @@ static int smb_full_audit_chdir(vfs_handle_struct *handle, static char *smb_full_audit_getwd(vfs_handle_struct *handle, char *path); static int smb_full_audit_ntimes(vfs_handle_struct *handle, - const char *path, const struct timespec ts[2]); + const char *path, struct smb_file_time *ft); static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len); static bool smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, @@ -1426,11 +1426,11 @@ static char *smb_full_audit_getwd(vfs_handle_struct *handle, } static int smb_full_audit_ntimes(vfs_handle_struct *handle, - const char *path, const struct timespec ts[2]) + const char *path, struct smb_file_time *ft) { int result; - result = SMB_VFS_NEXT_NTIMES(handle, path, ts); + result = SMB_VFS_NEXT_NTIMES(handle, path, ft); do_log(SMB_VFS_OP_NTIMES, (result >= 0), handle, "%s", path); diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index cb985e1be22f..2b0edcdb4a19 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -391,19 +391,21 @@ static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, bool touch_mtime) { SMB_STRUCT_STAT st; - struct timespec ts[2]; + struct smb_file_time ft; int ret, err; + ZERO_STRUCT(ft); + if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) { DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno))); return; } - ts[0] = timespec_current(); /* atime */ - ts[1] = touch_mtime ? ts[0] : get_mtimespec(&st); /* mtime */ + ft.atime = timespec_current(); /* atime */ + ft.mtime = touch_mtime ? ft.atime : get_mtimespec(&st); /* mtime */ become_root(); - ret = SMB_VFS_NEXT_NTIMES(handle, fname, ts); + ret = SMB_VFS_NEXT_NTIMES(handle, fname, &ft); err = errno; unbecome_root(); if (ret == -1 ) { diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index c95600b642f3..56dd6ea8d875 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -393,9 +393,9 @@ static int shadow_copy2_chdir(vfs_handle_struct *handle, } static int shadow_copy2_ntimes(vfs_handle_struct *handle, - const char *fname, const struct timespec ts[2]) + const char *fname, struct smb_file_time *ft) { - SHADOW2_NEXT(NTIMES, (handle, name, ts), int, -1); + SHADOW2_NEXT(NTIMES, (handle, name, ft), int, -1); } static int shadow_copy2_readlink(vfs_handle_struct *handle, diff --git a/source3/smbd/close.c b/source3/smbd/close.c index abcd651d9388..2fb8ec2bb551 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -465,11 +465,11 @@ void set_close_write_time(struct files_struct *fsp, struct timespec ts) static NTSTATUS update_write_time_on_close(struct files_struct *fsp) { SMB_STRUCT_STAT sbuf; - struct timespec ts[2]; + struct smb_file_time ft; NTSTATUS status; ZERO_STRUCT(sbuf); - ZERO_STRUCT(ts); + ZERO_STRUCT(ft); if (!fsp->update_write_time_on_close) { return NT_STATUS_OK; @@ -495,9 +495,9 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp) return NT_STATUS_OK; } - ts[1] = fsp->close_write_time; + ft.mtime = fsp->close_write_time; status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, - &sbuf, ts, true); + &sbuf, &ft, true); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index ade5e66e86f3..555718bd83a0 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -704,7 +704,8 @@ int file_set_dosmode(connection_struct *conn, const char *fname, than POSIX. *******************************************************************/ -int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2]) +int file_ntimes(connection_struct *conn, const char *fname, + struct smb_file_time *ft) { SMB_STRUCT_STAT sbuf; int ret = -1; @@ -713,9 +714,11 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe ZERO_STRUCT(sbuf); DEBUG(6, ("file_ntime: actime: %s", - time_to_asc(convert_timespec_to_time_t(ts[0])))); + time_to_asc(convert_timespec_to_time_t(ft->atime)))); DEBUG(6, ("file_ntime: modtime: %s", - time_to_asc(convert_timespec_to_time_t(ts[1])))); + time_to_asc(convert_timespec_to_time_t(ft->mtime)))); + DEBUG(6, ("file_ntime: createtime: %s", + time_to_asc(convert_timespec_to_time_t(ft->create_time)))); /* Don't update the time on read-only shares */ /* We need this as set_filetime (which can be called on @@ -728,7 +731,7 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe return 0; } - if(SMB_VFS_NTIMES(conn, fname, ts) == 0) { + if(SMB_VFS_NTIMES(conn, fname, ft) == 0) { return 0; } @@ -750,7 +753,7 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe if (can_write_to_file(conn, fname, &sbuf)) { /* We are allowed to become root and change the filetime. */ become_root(); - ret = SMB_VFS_NTIMES(conn, fname, ts); + ret = SMB_VFS_NTIMES(conn, fname, ft); unbecome_root(); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 28836144c20c..52dab0a01396 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1063,7 +1063,7 @@ void reply_getatr(struct smb_request *req) void reply_setatr(struct smb_request *req) { - struct timespec ts[2]; + struct smb_file_time ft; connection_struct *conn = req->conn; char *fname = NULL; int mode; @@ -1075,7 +1075,7 @@ void reply_setatr(struct smb_request *req) START_PROFILE(SMBsetatr); - ZERO_STRUCT(ts); + ZERO_STRUCT(ft); if (req->wct < 2) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -1133,9 +1133,9 @@ void reply_setatr(struct smb_request *req) mode = SVAL(req->vwv+0, 0); mtime = srv_make_unix_date3(req->vwv+1); - ts[1] = convert_time_t_to_timespec(mtime); + ft.mtime = convert_time_t_to_timespec(mtime); status = smb_set_file_time(conn, NULL, fname, - &sbuf, ts, true); + &sbuf, &ft, true); if (!NT_STATUS_IS_OK(status)) { reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsetatr); @@ -1924,7 +1924,7 @@ void reply_mknew(struct smb_request *req) connection_struct *conn = req->conn; char *fname = NULL; uint32 fattr = 0; - struct timespec ts[2]; + struct smb_file_time ft; files_struct *fsp; int oplock_request = 0; SMB_STRUCT_STAT sbuf; @@ -1936,6 +1936,7 @@ void reply_mknew(struct smb_request *req) TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBcreate); + ZERO_STRUCT(ft); if (req->wct < 3) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -1946,8 +1947,8 @@ void reply_mknew(struct smb_request *req) fattr = SVAL(req->vwv+0, 0); oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); - ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1)); - /* mtime. */ + /* mtime. */ + ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1)); srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1, STR_TERMINATE, &status); @@ -1999,8 +2000,8 @@ void reply_mknew(struct smb_request *req) return; } - ts[0] = get_atimespec(&sbuf); /* atime. */ - status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true); + ft.atime = get_atimespec(&sbuf); /* atime. */ + status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); reply_openerror(req, status); @@ -7115,12 +7116,13 @@ void reply_readbs(struct smb_request *req) void reply_setattrE(struct smb_request *req) { connection_struct *conn = req->conn; - struct timespec ts[2]; + struct smb_file_time ft; files_struct *fsp; SMB_STRUCT_STAT sbuf; NTSTATUS status; START_PROFILE(SMBsetattrE); + ZERO_STRUCT(ft); if (req->wct < 7) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -7138,14 +7140,15 @@ void reply_setattrE(struct smb_request *req) /* - * Convert the DOS times into unix times. Ignore create - * time as UNIX can't set this. + * Convert the DOS times into unix times. */ - ts[0] = convert_time_t_to_timespec( - srv_make_unix_date2(req->vwv+3)); /* atime. */ - ts[1] = convert_time_t_to_timespec( - srv_make_unix_date2(req->vwv+5)); /* mtime. */ + ft.atime = convert_time_t_to_timespec( + srv_make_unix_date2(req->vwv+3)); + ft.mtime = convert_time_t_to_timespec( + srv_make_unix_date2(req->vwv+5)); + ft.create_time = convert_time_t_to_timespec( + srv_make_unix_date2(req->vwv+1)); reply_outbuf(req, 0, 0); @@ -7172,17 +7175,20 @@ void reply_setattrE(struct smb_request *req) } status = smb_set_file_time(conn, fsp, fsp->fsp_name, - &sbuf, ts, true); + &sbuf, &ft, true); if (!NT_STATUS_IS_OK(status)) { reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsetattrE); return; } - DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n", + DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u " + " createtime=%u\n", fsp->fnum, - (unsigned int)ts[0].tv_sec, - (unsigned int)ts[1].tv_sec)); + (unsigned int)ft.atime.tv_sec, + (unsigned int)ft.mtime.tv_sec, + (unsigned int)ft.create_time.tv_sec + )); END_PROFILE(SMBsetattrE); return; diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 52340d537038..1b161d533898 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1430,7 +1430,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, mdate_ts = get_mtimespec(&sbuf); adate_ts = get_atimespec(&sbuf); - create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + create_date_ts = get_create_timespec(&sbuf, + lp_fake_dir_create_times(SNUM(conn))); if (ask_sharemode) { struct timespec write_time_ts; @@ -1453,7 +1454,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, mdate = convert_timespec_to_time_t(mdate_ts); adate = convert_timespec_to_time_t(adate_ts); - DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname)); + DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n", + pathreal,fname)); found = True; @@ -4892,7 +4894,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn, files_struct *fsp, const char *fname, const SMB_STRUCT_STAT *psbuf, - struct timespec ts[2], + struct smb_file_time *ft, bool setting_write_time) { uint32 action = @@ -4904,23 +4906,29 @@ NTSTATUS smb_set_file_time(connection_struct *conn, } /* get some defaults (no modifications) if any info is zero or -1. */ - if (null_timespec(ts[0])) { - ts[0] = get_atimespec(psbuf); + if (null_timespec(ft->atime)) { + ft->atime= get_atimespec(psbuf); action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS; } - if (null_timespec(ts[1])) { - ts[1] = get_mtimespec(psbuf); + if (null_timespec(ft->mtime)) { + ft->mtime = get_mtimespec(psbuf); action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } if (!setting_write_time) { - /* ts[1] comes from change time, not write time. */ + /* ft->mtime comes from change time, not write time. */ action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } - DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) )); - DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) )); + DEBUG(5,("smb_set_filetime: actime: %s\n ", + time_to_asc(convert_timespec_to_time_t(ft->atime)))); + DEBUG(5,("smb_set_filetime: modtime: %s\n ", + time_to_asc(convert_timespec_to_time_t(ft->mtime)))); + if (!null_timespec(ft->create_time)) { + DEBUG(5,("smb_set_file_time: createtime: %s\n ", + time_to_asc(convert_timespec_to_time_t(ft->create_time)))); + } /* * Try and set the times of this file if @@ -4930,7 +4938,8 @@ NTSTATUS smb_set_file_time(connection_struct *conn, { struct timespec mts = get_mtimespec(psbuf); struct timespec ats = get_atimespec(psbuf); - if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) { + if ((timespec_compare(&ft->atime, &ats) == 0) && + (timespec_compare(&ft->mtime, &mts) == 0)) { return NT_STATUS_OK; } } @@ -4947,18 +4956,19 @@ NTSTATUS smb_set_file_time(connection_struct *conn, */ DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", - time_to_asc(convert_timespec_to_time_t(ts[1])) )); + time_to_asc(convert_timespec_to_time_t(ft->mtime)))); if (fsp != NULL) { if (fsp->base_fsp) { - set_sticky_write_time_fsp(fsp->base_fsp, ts[1]); + set_sticky_write_time_fsp(fsp->base_fsp, + ft->mtime); } else { - set_sticky_write_time_fsp(fsp, ts[1]); + set_sticky_write_time_fsp(fsp, ft->mtime); } } else { set_sticky_write_time_path(conn, fname, vfs_file_id_from_sbuf(conn, psbuf), - ts[1]); + ft->mtime); } } @@ -4968,7 +4978,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn, fname = fsp->base_fsp->fsp_name; } - if(file_ntimes(conn, fname, ts)!=0) { + if(file_ntimes(conn, fname, ft)!=0) { return map_nt_error_from_unix(errno); } notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname); @@ -5677,16 +5687,21 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf) { - struct timespec ts[2]; + struct smb_file_time ft; + ZERO_STRUCT(ft); if (total_data < 12) { return NT_STATUS_INVALID_PARAMETER; } + /* create time */ + ft.create_time = interpret_long_date(pdata); + /* access time */ - ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess)); + ft.atime = interpret_long_date(pdata + 8); + /* write time */ - ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite)); + ft.mtime = interpret_long_date(pdata + 16); DEBUG(10,("smb_set_info_standard: file %s\n", fname ? fname : fsp->fsp_name )); @@ -5695,7 +5710,7 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, fsp, fname, psbuf, - ts, + &ft, true); } @@ -5713,47 +5728,49 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, /* Patch to do this correctly from Paul Eggert . */ struct timespec write_time; struct timespec changed_time; + struct smb_file_time ft; uint32 dosmode = 0; - struct timespec ts[2]; NTSTATUS status = NT_STATUS_OK; bool setting_write_time = true; + ZERO_STRUCT(ft); + if (total_data < 36) { return NT_STATUS_INVALID_PARAMETER; } /* Set the attributes */ dosmode = IVAL(pdata,32); - status = smb_set_file_dosmode(conn, - fname, - psbuf, - dosmode); + status = smb_set_file_dosmode(conn, fname, psbuf, dosmode); if (!NT_STATUS_IS_OK(status)) { return status; } - /* Ignore create time at offset pdata. */ /* access time */ - ts[0] = interpret_long_date(pdata+8); + ft.atime = interpret_long_date(pdata+8); write_time = interpret_long_date(pdata+16); changed_time = interpret_long_date(pdata+24); /* mtime */ - ts[1] = timespec_min(&write_time, &changed_time); + ft.mtime = timespec_min(&write_time, &changed_time); - if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) { - ts[1] = write_time; + /* create time */ + ft.create_time = interpret_long_date(pdata); + + if ((timespec_compare(&write_time, &ft.mtime) == 1) && + !null_timespec(write_time)) { + ft.mtime = write_time; } /* Prefer a defined time to an undefined one. */ - if (null_timespec(ts[1])) { + if (null_timespec(ft.mtime)) { if (null_timespec(write_time)) { - ts[1] = changed_time; + ft.mtime = changed_time; setting_write_time = false; } else { - ts[1] = write_time; + ft.mtime = write_time; } } @@ -5764,7 +5781,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, fsp, fname, psbuf, - ts, + &ft, setting_write_time); } @@ -6012,7 +6029,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { - struct timespec ts[2]; + struct smb_file_time ft; uint32 raw_unixmode; mode_t unixmode; SMB_OFF_T size = 0; @@ -6022,6 +6039,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, bool delete_on_fail = False; enum perm_type ptype; + ZERO_STRUCT(ft); + if (total_data < 100) { return NT_STATUS_INVALID_PARAMETER; } @@ -6039,8 +6058,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, #endif /* LARGE_SMB_OFF_T */ } - ts[0] = interpret_long_date(pdata+24); /* access_time */ - ts[1] = interpret_long_date(pdata+32); /* modification_time */ + ft.atime = interpret_long_date(pdata+24); /* access_time */ + ft.mtime = interpret_long_date(pdata+32); /* modification_time */ set_owner = (uid_t)IVAL(pdata,40); set_grp = (gid_t)IVAL(pdata,48); raw_unixmode = IVAL(pdata,84); @@ -6083,8 +6102,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", /* Ensure we don't try and change anything else. */ raw_unixmode = SMB_MODE_NO_CHANGE; size = get_file_size(*psbuf); - ts[0] = get_atimespec(psbuf); - ts[1] = get_mtimespec(psbuf); + ft.atime = get_atimespec(psbuf); + ft.mtime = get_mtimespec(psbuf); /* * We continue here as we might want to change the * owner uid/gid. @@ -6172,7 +6191,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", fsp, fname, psbuf, - ts, + &ft, true); } diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index d984dd661c50..31eb27b7568b 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -795,14 +795,17 @@ static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { - struct timespec ts[2]; + struct smb_file_time ft; if (argc != 4) { printf("Usage: utime \n"); return NT_STATUS_OK; } - ts[0] = convert_time_t_to_timespec(atoi(argv[2])); - ts[1] = convert_time_t_to_timespec(atoi(argv[3])); - if (SMB_VFS_NTIMES(vfs->conn, argv[1], ts) != 0) { + + ZERO_STRUCT(ft); + + ft.atime = convert_time_t_to_timespec(atoi(argv[2])); + ft.mtime = convert_time_t_to_timespec(atoi(argv[3])); + if (SMB_VFS_NTIMES(vfs->conn, argv[1], &ft) != 0) { printf("utime: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } -- 2.34.1