From d6270df748dcfd8d5a02c328518c2332da8fbed5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Aug 2009 13:00:54 -0700 Subject: Add "store create time" parameter (docs to follow) that stores the create time in the user.DosTimestamps EA. Jeremy. --- source3/smbd/dosmode.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/nttrans.c | 8 ++--- source3/smbd/open.c | 9 +++++ source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 9 ++--- 5 files changed, 106 insertions(+), 13 deletions(-) (limited to 'source3/smbd') 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); -- cgit