diff options
-rw-r--r-- | source3/include/proto.h | 12 | ||||
-rw-r--r-- | source3/include/smb.h | 2 | ||||
-rw-r--r-- | source3/modules/vfs_default.c | 9 | ||||
-rw-r--r-- | source3/param/loadparm.c | 12 | ||||
-rwxr-xr-x | source3/script/tests/selftest.sh | 1 | ||||
-rw-r--r-- | source3/smbd/dosmode.c | 91 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 8 | ||||
-rw-r--r-- | source3/smbd/open.c | 9 | ||||
-rw-r--r-- | source3/smbd/reply.c | 2 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 9 |
10 files changed, 140 insertions, 15 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index 8b3e029d3f..963e6df0c8 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4187,6 +4187,7 @@ bool lp_administrative_share(int ); bool lp_print_ok(int ); bool lp_map_hidden(int ); bool lp_map_archive(int ); +bool lp_store_create_time(int ); bool lp_store_dos_attributes(int ); bool lp_dmapi_support(int ); bool lp_locking(const struct share_params *p ); @@ -6266,10 +6267,17 @@ bool set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime); bool update_write_time(struct files_struct *fsp); -struct timespec get_create_timespec(struct files_struct *fsp, +NTSTATUS set_create_timespec_ea(connection_struct *conn, + struct files_struct *fsp, + const struct smb_filename *smb_fname, + struct timespec create_time); + +struct timespec get_create_timespec(connection_struct *conn, + struct files_struct *fsp, const struct smb_filename *smb_fname); -struct timespec get_change_timespec(struct files_struct *fsp, +struct timespec get_change_timespec(connection_struct *conn, + struct files_struct *fsp, const struct smb_filename *smb_fname); /* The following definitions come from smbd/error.c */ diff --git a/source3/include/smb.h b/source3/include/smb.h index fb01a92113..28bd60a670 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1859,6 +1859,8 @@ struct ea_list { #define SAMBA_XATTR_DOS_ATTRIB "user.DOSATTRIB" /* Prefix for DosStreams in the vfs_streams_xattr module */ #define SAMBA_XATTR_DOSSTREAM_PREFIX "user.DosStream." +/* Prefix for DOS timestamps. */ +#define SAMBA_XATTR_DOSTIMESTAMPS "user.DosTimestamps" #define UUID_SIZE 16 diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 2ee2fd1249..a793b337a8 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -817,6 +817,15 @@ static int vfswrap_ntimes(vfs_handle_struct *handle, errno = ENOSYS; result = -1; #endif + + if (!null_timespec(ft->create_time) && + lp_store_create_time(SNUM(handle->conn))) { + set_create_timespec_ea(handle->conn, + NULL, + smb_fname, + ft->create_time); + } + out: END_PROFILE(syscall_ntimes); return result; diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index dbbd6e327d..35984716a2 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -446,6 +446,7 @@ struct service { bool bMap_system; bool bMap_hidden; bool bMap_archive; + bool bStoreCreateTime; bool bStoreDosAttributes; bool bDmapiSupport; bool bLocking; @@ -589,6 +590,7 @@ static struct service sDefault = { False, /* bMap_system */ False, /* bMap_hidden */ True, /* bMap_archive */ + False, /* bStoreCreateTime */ False, /* bStoreDosAttributes */ False, /* bDmapiSupport */ True, /* bLocking */ @@ -3066,6 +3068,15 @@ static struct parm_struct parm_table[] = { .flags = FLAG_ADVANCED, }, { + .label = "store create time", + .type = P_BOOL, + .p_class = P_LOCAL, + .ptr = &sDefault.bStoreCreateTime, + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL, + }, + { .label = "store dos attributes", .type = P_BOOL, .p_class = P_LOCAL, @@ -5564,6 +5575,7 @@ FN_LOCAL_BOOL(lp_administrative_share, bAdministrative_share) FN_LOCAL_BOOL(lp_print_ok, bPrint_ok) FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden) FN_LOCAL_BOOL(lp_map_archive, bMap_archive) +FN_LOCAL_BOOL(lp_store_create_time, bStoreCreateTime) FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes) FN_LOCAL_BOOL(lp_dmapi_support, bDmapiSupport) FN_LOCAL_PARM_BOOL(lp_locking, bLocking) diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh index e3871132d2..3fcfa4d60d 100755 --- a/source3/script/tests/selftest.sh +++ b/source3/script/tests/selftest.sh @@ -243,6 +243,7 @@ cat >$SERVERCONFFILE<<EOF map hidden = yes map system = yes create mask = 755 + store create time = yes vfs objects = $BINDIR/xattr_tdb.so $BINDIR/streams_depot.so #Include user defined custom parameters if set diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index f4803cb68d..e9e92ada20 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -853,20 +853,103 @@ bool update_write_time(struct files_struct *fsp) } /****************************************************************** - Return a create time (may look at EA in future). + Set a create time EA. ******************************************************************/ -struct timespec get_create_timespec(struct files_struct *fsp, +NTSTATUS set_create_timespec_ea(connection_struct *conn, + struct files_struct *fsp, + const struct smb_filename *smb_fname, + struct timespec create_time) +{ + int ret; + char buf[8]; + + if (!lp_store_create_time(SNUM(conn))) { + return NT_STATUS_OK; + } + + put_long_date_timespec(buf, create_time); + if (fsp && fsp->fh->fd != -1) { + ret = SMB_VFS_FSETXATTR(fsp, + SAMBA_XATTR_DOSTIMESTAMPS, + buf, + sizeof(buf), + 0); + } else { + ret = SMB_VFS_SETXATTR(conn, + smb_fname->base_name, + SAMBA_XATTR_DOSTIMESTAMPS, + buf, + sizeof(buf), + 0); + } + + if (ret == -1) { + map_nt_error_from_unix(errno); + } + return NT_STATUS_OK; +} + +/****************************************************************** + Returns an EA create timespec, or a zero timespec if fail. +******************************************************************/ + +static struct timespec get_create_timespec_ea(connection_struct *conn, + struct files_struct *fsp, + const struct smb_filename *smb_fname) +{ + ssize_t ret; + char buf[8]; + struct timespec ts; + + ZERO_STRUCT(ts); + + if (!lp_store_create_time(SNUM(conn))) { + return ts; + } + + if (fsp && fsp->fh->fd != -1) { + ret = SMB_VFS_FGETXATTR(fsp, + SAMBA_XATTR_DOSTIMESTAMPS, + buf, + sizeof(buf)); + } else { + ret = SMB_VFS_GETXATTR(conn, + smb_fname->base_name, + SAMBA_XATTR_DOSTIMESTAMPS, + buf, + sizeof(buf)); + } + if (ret == sizeof(buf)) { + return interpret_long_date(buf); + } else { + return ts; + } +} + +/****************************************************************** + Return a create time - looks at EA. +******************************************************************/ + +struct timespec get_create_timespec(connection_struct *conn, + struct files_struct *fsp, const struct smb_filename *smb_fname) { - return smb_fname->st.st_ex_btime; + struct timespec ts = get_create_timespec_ea(conn, fsp, smb_fname); + + if (!null_timespec(ts)) { + return ts; + } else { + return smb_fname->st.st_ex_btime; + } } /****************************************************************** Return a change time (may look at EA in future). ******************************************************************/ -struct timespec get_change_timespec(struct files_struct *fsp, +struct timespec get_change_timespec(connection_struct *conn, + struct files_struct *fsp, const struct smb_filename *smb_fname) { return smb_fname->st.st_ex_mtime; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9f4074c865..03fdff3900 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -596,10 +596,10 @@ void reply_ntcreate_and_X(struct smb_request *req) } /* Create time. */ - create_timespec = get_create_timespec(fsp, smb_fname); + create_timespec = get_create_timespec(conn, fsp, smb_fname); a_timespec = smb_fname->st.st_ex_atime; m_timespec = smb_fname->st.st_ex_mtime; - c_timespec = get_change_timespec(fsp, smb_fname); + c_timespec = get_change_timespec(conn, fsp, smb_fname); if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_timespec); @@ -1094,10 +1094,10 @@ static void call_nt_transact_create(connection_struct *conn, } /* Create time. */ - create_timespec = get_create_timespec(fsp, smb_fname); + create_timespec = get_create_timespec(conn, fsp, smb_fname); a_timespec = smb_fname->st.st_ex_atime; m_timespec = smb_fname->st.st_ex_mtime; - c_timespec = get_change_timespec(fsp, smb_fname); + c_timespec = get_change_timespec(conn, fsp, smb_fname); if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_timespec); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 62a0fa73b7..63982341ac 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3280,6 +3280,15 @@ static NTSTATUS create_file_unixpath(connection_struct *conn, SMB_VFS_FSTAT(fsp, &smb_fname->st); fsp->fsp_name->st = smb_fname->st; } + + /* Try and make a create timestamp, if required. */ + if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { + if (lp_store_create_time(SNUM(conn))) { + set_create_timespec_ea(conn, fsp, + smb_fname, smb_fname->st.st_ex_btime); + } + } + return NT_STATUS_OK; fail: diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index de187e902b..7b290a6b0e 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -7793,7 +7793,7 @@ void reply_getattrE(struct smb_request *req) reply_outbuf(req, 11, 0); - create_ts = get_create_timespec(fsp, fsp->fsp_name); + create_ts = get_create_timespec(conn, fsp, fsp->fsp_name); srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec); srv_put_dos_date2((char *)req->outbuf, smb_vwv2, convert_timespec_to_time_t(sbuf.st_ex_atime)); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 93b217558d..b14d50594c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -72,6 +72,7 @@ static bool samba_private_attr_name(const char *unix_ea_name) static const char * const prohibited_ea_names[] = { SAMBA_POSIX_INHERITANCE_EA_NAME, SAMBA_XATTR_DOS_ATTRIB, + SAMBA_XATTR_DOSTIMESTAMPS, NULL }; @@ -1490,8 +1491,8 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, mdate_ts = smb_fname->st.st_ex_mtime; adate_ts = smb_fname->st.st_ex_atime; - create_date_ts = get_create_timespec(NULL, smb_fname); - cdate_ts = get_change_timespec(NULL, smb_fname); + create_date_ts = get_create_timespec(conn, NULL, smb_fname); + cdate_ts = get_change_timespec(conn, NULL, smb_fname); if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_date_ts); @@ -4057,10 +4058,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, update_stat_ex_mtime(&sbuf, write_time_ts); } - create_time_ts = get_create_timespec(fsp, smb_fname); + create_time_ts = get_create_timespec(conn, fsp, smb_fname); mtime_ts = sbuf.st_ex_mtime; atime_ts = sbuf.st_ex_atime; - ctime_ts = get_change_timespec(fsp, smb_fname); + ctime_ts = get_change_timespec(conn, fsp, smb_fname); if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_time_ts); |