Add "store create time" parameter (docs to follow)
authorJeremy Allison <jra@samba.org>
Wed, 12 Aug 2009 20:00:54 +0000 (13:00 -0700)
committerJeremy Allison <jra@samba.org>
Wed, 12 Aug 2009 20:00:54 +0000 (13:00 -0700)
that stores the create time in the user.DosTimestamps EA.
Jeremy.

source3/include/proto.h
source3/include/smb.h
source3/modules/vfs_default.c
source3/param/loadparm.c
source3/script/tests/selftest.sh
source3/smbd/dosmode.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/reply.c
source3/smbd/trans2.c

index 8b3e029d3f59313986a03697ff0639c2e2b0ad27..963e6df0c80f8bc3cb388a7e63c2ba3d51c4d985 100644 (file)
@@ -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  */
index fb01a921130a2cd8133297e2675ceb3820ce9bd4..28bd60a670f5e1390dbb9f4c11a3bdc063eca487 100644 (file)
@@ -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
 
index 2ee2fd124997f41199c1b277697dbe28a120a50d..a793b337a84270e720cd87e6227702d160aa5893 100644 (file)
@@ -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;
index dbbd6e327da718e1600c144da02884ce275d9db3..35984716a26f8c3840e416246415f89e08dd37a5 100644 (file)
@@ -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 */
@@ -3065,6 +3067,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .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,
@@ -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)
index e3871132d2d027b0c9df65ace9b5fa65a9cbdcab..3fcfa4d60dbcfd509591662720e8b94df83e63ea 100755 (executable)
@@ -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
index f4803cb68d503993995d4b8c504ba8335fa2fc34..e9e92ada20e5d6964c2f804be61d7f56b6c0b2d7 100644 (file)
@@ -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;
index 9f4074c8656b6bcedecfe91dd555e824c0ab22e6..03fdff3900e8c0f075be5204c9f64561887cc73b 100644 (file)
@@ -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);
index 62a0fa73b7aa1558830207775040b919a0b2de32..63982341ac6459c0b3ac41e438f37048759a3fbd 100644 (file)
@@ -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:
index de187e902bf34935318027bae6d0aebae10a214d..7b290a6b0ea909e6050d3052f393016f7999af8d 100644 (file)
@@ -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));
index 93b217558dc13cceb3e1d505b5a2e36bb3f2483a..b14d50594c2e7c6e583464258518a34cb625de38 100644 (file)
@@ -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);