r18009: Fixes bug 4026.
authorDerrell Lipman <derrell@samba.org>
Sat, 2 Sep 2006 21:47:56 +0000 (21:47 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:39:47 +0000 (11:39 -0500)
This completes the work Jeremy began last week, disambiguating the meaning of
c_time.  (In POSIX terminology, c_time means "status Change time", not "create
time".)  All uses of c_time, a_time and m_time have now been replaced with
change_time, access_time, and write_time, and when creation time is intended,
create_time is used.

Additionally, the capability of setting and retrieving the create time have
been added to the smbc_setxattr() and smbc_getxattr() functions.  An example
of setting all four times can be seen with the program

  examples/libsmbclient/testacl

with the following command line similar to:

  testacl -f -S "system.*:CREATE_TIME:1000000000,ACCESS_TIME:1000000060,WRITE_TIME:1000000120,CHANGE_TIME:1000000180" 'smb://server/share/testfile.txt'

The -f option turns on the new mode which uses full time names in the
attribute specification (e.g. ACCESS_TIME vs A_TIME).

examples/libsmbclient/testacl.c
source/include/libsmb_internal.h
source/lib/time.c
source/libsmb/clifile.c
source/libsmb/clirap.c
source/libsmb/libsmbclient.c

index ce5694b331a00f6991f0af9361bcb9ba13c75f87..4d327b39a7a11e0c7a0eea3768fd94ed66a50ced 100644 (file)
@@ -23,6 +23,7 @@ int main(int argc, const char *argv[])
     int flags;
     int debug = 0;
     int numeric = 0;
+    int full_time_names = 0;
     enum acl_mode mode = SMB_ACL_GET;
     static char *the_acl = NULL;
     int ret;
@@ -42,6 +43,11 @@ int main(int argc, const char *argv[])
                 "debug", 'd', POPT_ARG_INT, &debug,
                 0, "Set debug level (0-100)"
             },
+            {
+                "full_time_names", 'f', POPT_ARG_NONE, &full_time_names,
+                1,
+                "Use new style xattr names, which include CREATE_TIME"
+            },
             {
                 "delete", 'D', POPT_ARG_STRING, NULL,
                 'D', "Delete an acl", "ACL"
@@ -133,6 +139,11 @@ int main(int argc, const char *argv[])
         printf("Could not initialize smbc_ library\n");
         return 1;
     }
+
+    if (full_time_names) {
+        SMBCCTX *context = smbc_set_context(NULL);
+        smbc_option_set(context, "full_time_names", 1);
+    }
     
     /* Perform requested action */
     
@@ -143,11 +154,11 @@ int main(int argc, const char *argv[])
         {
             if (numeric)
             {
-                the_acl = "system.nt_sec_desc.*";
+                the_acl = "system.*";
             }
             else
             {
-                the_acl = "system.nt_sec_desc.*+";
+                the_acl = "system.*+";
             }
         }
         ret = smbc_getxattr(path, the_acl, value, sizeof(value));
index 42bf2373c1b2551be4a3d8684cd1f02798b76336..ce7a90747fc312b97c74d8cb573586df414266e0 100644 (file)
@@ -80,6 +80,15 @@ struct smbc_internal_data {
          */
         BOOL _debug_stderr;
 
+        /*
+         * Support "Create Time" in get/set with the *xattr() functions, if
+         * true.  This replaces the dos attribute strings C_TIME, A_TIME and
+         * M_TIME with CHANGE_TIME, ACCESS_TIME and WRITE_TIME, and adds
+         * CREATE_TIME.  Default is FALSE, i.e.  to use the old-style shorter
+         * names and to not support CREATE time, for backward compatibility.
+         */
+        BOOL _full_time_names;
+
         /*
          * Authentication function which includes the context.  This will be
          * used if set; otherwise context->callbacks.auth_fn() will be used.
index 2db10f98d9d934bd57aec5149750d4f75a168a06..0fb35bd97742629e34bf691611d6ca5802bd3eba 100644 (file)
@@ -1252,7 +1252,7 @@ void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
        pst->st_ctime = ts.tv_sec;
 #else
 #if defined(HAVE_STAT_ST_CTIM)
-       pst->st_atim = ts;
+       pst->st_ctim = ts;
 #elif defined(HAVE_STAT_ST_CTIMENSEC)
        pst->st_ctime = ts.tv_sec;
        pst->st_ctimensec = ts.tv_nsec
index 3cf8cae320afc99af6094ac05f54e3d964a98bc9..ad84ec03244fcaa75f538e6188bff3766714923a 100644 (file)
@@ -1179,7 +1179,9 @@ BOOL cli_posix_getlock(struct cli_state *cli, int fnum, SMB_BIG_UINT *poffset, S
 
 BOOL cli_getattrE(struct cli_state *cli, int fd, 
                  uint16 *attr, SMB_OFF_T *size, 
-                 time_t *c_time, time_t *a_time, time_t *m_time)
+                 time_t *change_time,
+                  time_t *access_time,
+                  time_t *write_time)
 {
        memset(cli->outbuf,'\0',smb_size);
        memset(cli->inbuf,'\0',smb_size);
@@ -1209,16 +1211,16 @@ BOOL cli_getattrE(struct cli_state *cli, int fd,
                *attr = SVAL(cli->inbuf,smb_vwv10);
        }
 
-       if (c_time) {
-               *c_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv0);
+       if (change_time) {
+               *change_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv0);
        }
 
-       if (a_time) {
-               *a_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv2);
+       if (access_time) {
+               *access_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv2);
        }
 
-       if (m_time) {
-               *m_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv4);
+       if (write_time) {
+               *write_time = cli_make_unix_date2(cli, cli->inbuf+smb_vwv4);
        }
 
        return True;
@@ -1229,7 +1231,7 @@ BOOL cli_getattrE(struct cli_state *cli, int fd,
 ****************************************************************************/
 
 BOOL cli_getatr(struct cli_state *cli, const char *fname, 
-               uint16 *attr, SMB_OFF_T *size, time_t *t)
+               uint16 *attr, SMB_OFF_T *size, time_t *write_time)
 {
        char *p;
 
@@ -1261,8 +1263,8 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
                *size = IVAL(cli->inbuf, smb_vwv3);
        }
 
-       if (t) {
-               *t = cli_make_unix_date3(cli, cli->inbuf+smb_vwv1);
+       if (write_time) {
+               *write_time = cli_make_unix_date3(cli, cli->inbuf+smb_vwv1);
        }
 
        if (attr) {
@@ -1278,7 +1280,9 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
 ****************************************************************************/
 
 BOOL cli_setattrE(struct cli_state *cli, int fd,
-                 time_t c_time, time_t a_time, time_t m_time)
+                 time_t change_time,
+                  time_t access_time,
+                  time_t write_time)
 
 {
        char *p;
@@ -1293,9 +1297,9 @@ BOOL cli_setattrE(struct cli_state *cli, int fd,
        cli_setup_packet(cli);
 
        SSVAL(cli->outbuf,smb_vwv0, fd);
-       cli_put_dos_date2(cli, cli->outbuf,smb_vwv1, c_time);
-       cli_put_dos_date2(cli, cli->outbuf,smb_vwv3, a_time);
-       cli_put_dos_date2(cli, cli->outbuf,smb_vwv5, m_time);
+       cli_put_dos_date2(cli, cli->outbuf,smb_vwv1, change_time);
+       cli_put_dos_date2(cli, cli->outbuf,smb_vwv3, access_time);
+       cli_put_dos_date2(cli, cli->outbuf,smb_vwv5, write_time);
 
        p = smb_buf(cli->outbuf);
        *p++ = 4;
index 677c8f1fc3d7a9cb222f99b562672c6e2a25925a..caa23b59d9a2633035ea26c1bb9daf958c94f48d 100644 (file)
@@ -379,7 +379,9 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char
 send a qpathinfo call
 ****************************************************************************/
 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, 
-                  time_t *c_time, time_t *a_time, time_t *m_time, 
+                  time_t *change_time,
+                   time_t *access_time,
+                   time_t *write_time, 
                   SMB_OFF_T *size, uint16 *mode)
 {
        unsigned int data_len = 0;
@@ -434,14 +436,14 @@ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
                date_fn = cli_make_unix_date2;
        }
 
-       if (c_time) {
-               *c_time = date_fn(cli, rdata+0);
+       if (change_time) {
+               *change_time = date_fn(cli, rdata+0);
        }
-       if (a_time) {
-               *a_time = date_fn(cli, rdata+4);
+       if (access_time) {
+               *access_time = date_fn(cli, rdata+4);
        }
-       if (m_time) {
-               *m_time = date_fn(cli, rdata+8);
+       if (write_time) {
+               *write_time = date_fn(cli, rdata+8);
        }
        if (size) {
                *size = IVAL(rdata, 12);
@@ -460,7 +462,11 @@ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
 send a setpathinfo call
 ****************************************************************************/
 BOOL cli_setpathinfo(struct cli_state *cli, const char *fname, 
-                     time_t c_time, time_t a_time, time_t m_time, uint16 mode)
+                     time_t create_time,
+                     time_t access_time,
+                     time_t write_time,
+                     time_t change_time,
+                     uint16 mode)
 {
        unsigned int data_len = 0;
        unsigned int param_len = 0;
@@ -495,16 +501,16 @@ BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
          * Add the create, last access, modification, and status change times
          */
         
-        /* Don't set create time, at offset 0 */
+        put_long_date(p, create_time);
         p += 8;
 
-        put_long_date(p, a_time);
+        put_long_date(p, access_time);
         p += 8;
         
-        put_long_date(p, m_time);
+        put_long_date(p, write_time);
         p += 8;
         
-        put_long_date(p, c_time);
+        put_long_date(p, change_time);
         p += 8;
 
         /* Add attributes */
@@ -555,8 +561,11 @@ send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
 ****************************************************************************/
 
 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, 
-                   struct timespec *create_time, struct timespec *access_time, struct timespec *write_time, 
-                   struct timespec *change_time, SMB_OFF_T *size, uint16 *mode,
+                   struct timespec *create_time,
+                    struct timespec *access_time,
+                    struct timespec *write_time, 
+                   struct timespec *change_time,
+                    SMB_OFF_T *size, uint16 *mode,
                    SMB_INO_T *ino)
 {
        unsigned int data_len = 0;
@@ -670,8 +679,11 @@ send a qfileinfo call
 ****************************************************************************/
 BOOL cli_qfileinfo(struct cli_state *cli, int fnum, 
                   uint16 *mode, SMB_OFF_T *size,
-                  struct timespec *create_time, struct timespec *access_time, struct timespec *write_time, 
-                  struct timespec *change_time, SMB_INO_T *ino)
+                  struct timespec *create_time,
+                   struct timespec *access_time,
+                   struct timespec *write_time, 
+                  struct timespec *change_time,
+                   SMB_INO_T *ino)
 {
        unsigned int data_len = 0;
        unsigned int param_len = 0;
index 2656bd0f04600d9b0627eb9d4f6feabae7781176..c74e18b13c152c91d70b7a29538e558748771006 100644 (file)
 typedef struct DOS_ATTR_DESC {
        int mode;
        SMB_OFF_T size;
-       time_t a_time;
-       time_t c_time;
-       time_t m_time;
+       time_t create_time;
+       time_t access_time;
+       time_t write_time;
+       time_t change_time;
        SMB_INO_T inode;
 } DOS_ATTR_DESC;
 
@@ -1470,15 +1471,16 @@ smbc_getatr(SMBCCTX * context,
             char *path, 
             uint16 *mode,
             SMB_OFF_T *size, 
-            struct timespec *c_time_ts,
-            struct timespec *a_time_ts,
-            struct timespec *m_time_ts,
+            struct timespec *create_time_ts,
+            struct timespec *access_time_ts,
+            struct timespec *write_time_ts,
+            struct timespec *change_time_ts,
             SMB_INO_T *ino)
 {
        pstring fixedpath;
        pstring targetpath;
        struct cli_state *targetcli;
-       time_t m_time;
+       time_t write_time;
 
        if (!context || !context->internal ||
            !context->internal->_initialized) {
@@ -1515,7 +1517,11 @@ smbc_getatr(SMBCCTX * context,
   
        if (!srv->no_pathinfo2 &&
             cli_qpathinfo2(targetcli, targetpath,
-                           NULL, a_time_ts, m_time_ts, c_time_ts, size, mode, ino)) {
+                           create_time_ts,
+                           access_time_ts,
+                           write_time_ts,
+                           change_time_ts,
+                           size, mode, ino)) {
             return True;
         }
 
@@ -1525,12 +1531,28 @@ smbc_getatr(SMBCCTX * context,
                 return False;
         }
 
-       if (cli_getatr(targetcli, targetpath, mode, size, &m_time)) {
-                if (m_time_ts != NULL) {
-                       *m_time_ts = convert_time_t_to_timespec(m_time);
-                        if (a_time_ts != NULL) *a_time_ts = *m_time_ts;
-                        if (c_time_ts != NULL) *c_time_ts = *m_time_ts;
+       if (cli_getatr(targetcli, targetpath, mode, size, &write_time)) {
+
+                struct timespec w_time_ts;
+
+                w_time_ts = convert_time_t_to_timespec(write_time);
+
+                if (write_time_ts != NULL) {
+                       *write_time_ts = w_time_ts;
+                }
+
+                if (create_time_ts != NULL) {
+                        *create_time_ts = w_time_ts;
+                }
+                
+                if (access_time_ts != NULL) {
+                        *access_time_ts = w_time_ts;
                 }
+                
+                if (change_time_ts != NULL) {
+                        *change_time_ts = w_time_ts;
+                }
+
                srv->no_pathinfo2 = True;
                return True;
        }
@@ -1552,7 +1574,10 @@ smbc_getatr(SMBCCTX * context,
  */
 static BOOL
 smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path, 
-            time_t c_time, time_t a_time, time_t m_time,
+            time_t create_time,
+            time_t access_time,
+            time_t write_time,
+            time_t change_time,
             uint16 mode)
 {
         int fd;
@@ -1565,7 +1590,12 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
          * attributes manipulated.
          */
         if (srv->no_pathinfo ||
-            ! cli_setpathinfo(srv->cli, path, c_time, a_time, m_time, mode)) {
+            ! cli_setpathinfo(srv->cli, path,
+                              create_time,
+                              access_time,
+                              write_time,
+                              change_time,
+                              mode)) {
 
                 /*
                  * setpathinfo is not supported; go to plan B. 
@@ -1587,42 +1617,14 @@ smbc_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
                         return -1;
                 }
 
-                /*
-                 * Get the creat time of the file (if it wasn't provided).
-                 * We'll need it in the set call
-                 */
-                if (c_time == 0) {
-                        ret = cli_getattrE(srv->cli, fd,
-                                           NULL, NULL,
-                                           &c_time, NULL, NULL);
-                } else {
-                        ret = True;
-                }
-                    
-                /* If we got create time, set times */
-                if (ret) {
-                        /* Some OS versions don't support create time */
-                        if (c_time == 0 || c_time == -1) {
-                                c_time = time(NULL);
-                        }
+                /* Set the new attributes */
+                ret = cli_setattrE(srv->cli, fd,
+                                   change_time,
+                                   access_time,
+                                   write_time);
 
-                        /*
-                         * For sanity sake, since there is no POSIX function
-                         * to set the create time of a file, if the existing
-                         * create time is greater than either of access time
-                         * or modification time, set create time to the
-                         * smallest of those.  This ensure that the create
-                         * time of a file is never greater than its last
-                         * access or modification time.
-                         */
-                        if (c_time > a_time) c_time = a_time;
-                        if (c_time > m_time) c_time = m_time;
-                        
-                        /* Set the new attributes */
-                        ret = cli_setattrE(srv->cli, fd,
-                                           c_time, a_time, m_time);
-                        cli_close(srv->cli, fd);
-                }
+                /* Close the file */
+                cli_close(srv->cli, fd);
 
                 /*
                  * Unfortunately, setattrE() doesn't have a provision for
@@ -1711,11 +1713,17 @@ smbc_unlink_ctx(SMBCCTX *context,
                        int saverr = errno;
                        SMB_OFF_T size = 0;
                        uint16 mode = 0;
-                       struct timespec m_time_ts, a_time_ts, c_time_ts;
+                       struct timespec write_time_ts;
+                        struct timespec access_time_ts;
+                        struct timespec change_time_ts;
                        SMB_INO_T ino = 0;
 
                        if (!smbc_getatr(context, srv, path, &mode, &size,
-                                        &c_time_ts, &a_time_ts, &m_time_ts, &ino)) {
+                                        NULL,
+                                         &access_time_ts,
+                                         &write_time_ts,
+                                         &change_time_ts,
+                                         &ino)) {
 
                                /* Hmmm, bad error ... What? */
 
@@ -2051,9 +2059,9 @@ smbc_stat_ctx(SMBCCTX *context,
         fstring password;
         fstring workgroup;
        pstring path;
-       struct timespec m_time_ts;
-        struct timespec a_time_ts;
-        struct timespec c_time_ts;
+       struct timespec write_time_ts;
+        struct timespec access_time_ts;
+        struct timespec change_time_ts;
        SMB_OFF_T size = 0;
        uint16 mode = 0;
        SMB_INO_T ino = 0;
@@ -2097,7 +2105,11 @@ smbc_stat_ctx(SMBCCTX *context,
        }
 
        if (!smbc_getatr(context, srv, path, &mode, &size, 
-                        &c_time_ts, &a_time_ts, &m_time_ts, &ino)) {
+                        NULL,
+                         &access_time_ts,
+                         &write_time_ts,
+                         &change_time_ts,
+                         &ino)) {
 
                errno = smbc_errno(context, srv->cli);
                return -1;
@@ -2108,9 +2120,9 @@ smbc_stat_ctx(SMBCCTX *context,
 
        smbc_setup_stat(context, st, path, size, mode);
 
-       set_atimespec(st, a_time_ts);
-       set_ctimespec(st, c_time_ts);
-       set_mtimespec(st, m_time_ts);
+       set_atimespec(st, access_time_ts);
+       set_ctimespec(st, change_time_ts);
+       set_mtimespec(st, write_time_ts);
        st->st_dev   = srv->dev;
 
        return 0;
@@ -2126,9 +2138,9 @@ smbc_fstat_ctx(SMBCCTX *context,
                SMBCFILE *file,
                struct stat *st)
 {
-       struct timespec c_time_ts;
-        struct timespec a_time_ts;
-        struct timespec m_time_ts;
+       struct timespec change_time_ts;
+        struct timespec access_time_ts;
+        struct timespec write_time_ts;
        SMB_OFF_T size;
        uint16 mode;
        fstring server;
@@ -2184,26 +2196,33 @@ smbc_fstat_ctx(SMBCCTX *context,
        /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
 
        if (!cli_qfileinfo(targetcli, file->cli_fd, &mode, &size,
-                           NULL, &a_time_ts, &m_time_ts, &c_time_ts, &ino)) {
-               time_t c_time, a_time, m_time;
+                           NULL,
+                           &access_time_ts,
+                           &write_time_ts,
+                           &change_time_ts,
+                           &ino)) {
+
+               time_t change_time, access_time, write_time;
+
                if (!cli_getattrE(targetcli, file->cli_fd, &mode, &size,
-                               &c_time, &a_time, &m_time)) {
+                               &change_time, &access_time, &write_time)) {
 
                        errno = EINVAL;
                        return -1;
                }
-               c_time_ts = convert_time_t_to_timespec(c_time);
-               a_time_ts = convert_time_t_to_timespec(a_time);
-               m_time_ts = convert_time_t_to_timespec(m_time);
+
+               change_time_ts = convert_time_t_to_timespec(change_time);
+               access_time_ts = convert_time_t_to_timespec(access_time);
+               write_time_ts = convert_time_t_to_timespec(write_time);
        }
 
        st->st_ino = ino;
 
        smbc_setup_stat(context, st, file->fname, size, mode);
 
-       set_atimespec(st, a_time_ts);
-       set_ctimespec(st, c_time_ts);
-       set_mtimespec(st, m_time_ts);
+       set_atimespec(st, access_time_ts);
+       set_ctimespec(st, change_time_ts);
+       set_mtimespec(st, write_time_ts);
        st->st_dev = file->srv->dev;
 
        return 0;
@@ -2902,7 +2921,7 @@ smbc_opendir_ctx(SMBCCTX *context,
 
                                     if (smbc_getatr(context, srv, path,
                                                     &mode, NULL,
-                                                    NULL, NULL, NULL,
+                                                    NULL, NULL, NULL, NULL,
                                                     NULL) &&
                                         ! IS_DOS_DIR(mode)) {
 
@@ -3592,8 +3611,8 @@ smbc_utimes_ctx(SMBCCTX *context,
         fstring password;
         fstring workgroup;
        pstring path;
-        time_t a_time;
-        time_t m_time;
+        time_t access_time;
+        time_t write_time;
 
        if (!context || !context->internal ||
            !context->internal->_initialized) {
@@ -3611,10 +3630,10 @@ smbc_utimes_ctx(SMBCCTX *context,
        }
   
         if (tbuf == NULL) {
-                a_time = m_time = time(NULL);
+                access_time = write_time = time(NULL);
         } else {
-                a_time = tbuf[0].tv_sec;
-                m_time = tbuf[1].tv_sec;
+                access_time = tbuf[0].tv_sec;
+                write_time = tbuf[1].tv_sec;
         }
 
         if (DEBUGLVL(4)) 
@@ -3623,13 +3642,13 @@ smbc_utimes_ctx(SMBCCTX *context,
                 char atimebuf[32];
                 char mtimebuf[32];
 
-                strncpy(atimebuf, ctime(&a_time), sizeof(atimebuf) - 1);
+                strncpy(atimebuf, ctime(&access_time), sizeof(atimebuf) - 1);
                 atimebuf[sizeof(atimebuf) - 1] = '\0';
                 if ((p = strchr(atimebuf, '\n')) != NULL) {
                         *p = '\0';
                 }
 
-                strncpy(mtimebuf, ctime(&m_time), sizeof(mtimebuf) - 1);
+                strncpy(mtimebuf, ctime(&write_time), sizeof(mtimebuf) - 1);
                 mtimebuf[sizeof(mtimebuf) - 1] = '\0';
                 if ((p = strchr(mtimebuf, '\n')) != NULL) {
                         *p = '\0';
@@ -3660,7 +3679,8 @@ smbc_utimes_ctx(SMBCCTX *context,
                return -1;      /* errno set by smbc_server */
        }
 
-        if (!smbc_setatr(context, srv, path, 0, a_time, m_time, 0)) {
+        if (!smbc_setatr(context, srv, path,
+                         0, access_time, write_time, 0, 0)) {
                 return -1;      /* errno set by smbc_setatr */
         }
 
@@ -4085,7 +4105,10 @@ dos_attr_query(SMBCCTX *context,
                const char *filename,
                SMBCSRV *srv)
 {
-       struct timespec m_time_ts, a_time_ts, c_time_ts;
+        struct timespec create_time_ts;
+        struct timespec write_time_ts;
+        struct timespec access_time_ts;
+        struct timespec change_time_ts;
         SMB_OFF_T size = 0;
         uint16 mode = 0;
        SMB_INO_T inode = 0;
@@ -4100,7 +4123,11 @@ dos_attr_query(SMBCCTX *context,
         /* Obtain the DOS attributes */
         if (!smbc_getatr(context, srv, CONST_DISCARD(char *, filename),
                          &mode, &size, 
-                         &c_time_ts, &a_time_ts, &m_time_ts, &inode)) {
+                         &create_time_ts,
+                         &access_time_ts,
+                         &write_time_ts,
+                         &change_time_ts, 
+                         &inode)) {
         
                 errno = smbc_errno(context, srv->cli);
                 DEBUG(5, ("dos_attr_query Failed to query old attributes\n"));
@@ -4110,9 +4137,10 @@ dos_attr_query(SMBCCTX *context,
                 
         ret->mode = mode;
         ret->size = size;
-        ret->a_time = convert_timespec_to_time_t(a_time_ts);
-        ret->c_time = convert_timespec_to_time_t(c_time_ts);
-        ret->m_time = convert_timespec_to_time_t(m_time_ts);
+        ret->create_time = convert_timespec_to_time_t(create_time_ts);
+        ret->access_time = convert_timespec_to_time_t(access_time_ts);
+        ret->write_time = convert_timespec_to_time_t(write_time_ts);
+        ret->change_time = convert_timespec_to_time_t(change_time_ts);
         ret->inode = inode;
 
         return ret;
@@ -4126,8 +4154,40 @@ dos_attr_parse(SMBCCTX *context,
                SMBCSRV *srv,
                char *str)
 {
-       const char *p = str;
+        int n;
+        const char *p = str;
        fstring tok;
+        struct {
+                const char * create_time_attr;
+                const char * access_time_attr;
+                const char * write_time_attr;
+                const char * change_time_attr;
+        } attr_strings;
+
+        /* Determine whether to use old-style or new-style attribute names */
+        if (context->internal->_full_time_names) {
+                /* new-style names */
+                attr_strings.create_time_attr = "CREATE_TIME";
+                attr_strings.access_time_attr = "ACCESS_TIME";
+                attr_strings.write_time_attr = "WRITE_TIME";
+                attr_strings.change_time_attr = "CHANGE_TIME";
+        } else {
+                /* old-style names */
+                attr_strings.create_time_attr = NULL;
+                attr_strings.access_time_attr = "A_TIME";
+                attr_strings.write_time_attr = "M_TIME";
+                attr_strings.change_time_attr = "C_TIME";
+        }
+
+        /* if this is to set the entire ACL... */
+        if (*str == '*') {
+                /* ... then increment past the first colon if there is one */
+                if ((p = strchr(str, ':')) != NULL) {
+                        ++p;
+                } else {
+                        p = str;
+                }
+        }
 
        while (next_token(&p, tok, "\t,\r\n", sizeof(tok))) {
 
@@ -4141,18 +4201,28 @@ dos_attr_parse(SMBCCTX *context,
                        continue;
                }
 
-               if (StrnCaseCmp(tok, "A_TIME:", 7) == 0) {
-                        dad->a_time = (time_t)strtol(tok+7, NULL, 10);
+                n = strlen(attr_strings.access_time_attr);
+                if (StrnCaseCmp(tok, attr_strings.access_time_attr, n) == 0) {
+                        dad->access_time = (time_t)strtol(tok+n+1, NULL, 10);
                        continue;
                }
 
-               if (StrnCaseCmp(tok, "C_TIME:", 7) == 0) {
-                        dad->c_time = (time_t)strtol(tok+7, NULL, 10);
+                n = strlen(attr_strings.change_time_attr);
+                if (StrnCaseCmp(tok, attr_strings.change_time_attr, n) == 0) {
+                        dad->change_time = (time_t)strtol(tok+n+1, NULL, 10);
                        continue;
                }
 
-               if (StrnCaseCmp(tok, "M_TIME:", 7) == 0) {
-                        dad->m_time = (time_t)strtol(tok+7, NULL, 10);
+                n = strlen(attr_strings.write_time_attr);
+                if (StrnCaseCmp(tok, attr_strings.write_time_attr, n) == 0) {
+                        dad->write_time = (time_t)strtol(tok+n+1, NULL, 10);
+                       continue;
+               }
+
+                n = strlen(attr_strings.create_time_attr);
+                if (attr_strings.create_time_attr != NULL &&
+                    StrnCaseCmp(tok, attr_strings.create_time_attr, n) == 0) {
+                        dad->create_time = (time_t)strtol(tok+n+1, NULL, 10);
                        continue;
                }
 
@@ -4193,9 +4263,10 @@ cacl_get(SMBCCTX *context,
         BOOL exclude_nt_acl = False;
         BOOL exclude_dos_mode = False;
         BOOL exclude_dos_size = False;
-        BOOL exclude_dos_ctime = False;
-        BOOL exclude_dos_atime = False;
-        BOOL exclude_dos_mtime = False;
+        BOOL exclude_dos_create_time = False;
+        BOOL exclude_dos_access_time = False;
+        BOOL exclude_dos_write_time = False;
+        BOOL exclude_dos_change_time = False;
         BOOL exclude_dos_inode = False;
         BOOL numeric = True;
         BOOL determine_size = (bufsize == 0);
@@ -4206,12 +4277,55 @@ cacl_get(SMBCCTX *context,
         char *name;
         char *pExclude;
         char *p;
-       struct timespec m_time_ts, a_time_ts, c_time_ts;
-       time_t m_time = (time_t)0, a_time = (time_t)0, c_time = (time_t)0;
+        struct timespec create_time_ts;
+       struct timespec write_time_ts;
+        struct timespec access_time_ts;
+        struct timespec change_time_ts;
+       time_t create_time = (time_t)0;
+       time_t write_time = (time_t)0;
+        time_t access_time = (time_t)0;
+        time_t change_time = (time_t)0;
        SMB_OFF_T size = 0;
        uint16 mode = 0;
        SMB_INO_T ino = 0;
         struct cli_state *cli = srv->cli;
+        struct {
+                const char * create_time_attr;
+                const char * access_time_attr;
+                const char * write_time_attr;
+                const char * change_time_attr;
+        } attr_strings;
+        struct {
+                const char * create_time_attr;
+                const char * access_time_attr;
+                const char * write_time_attr;
+                const char * change_time_attr;
+        } excl_attr_strings;
+
+        /* Determine whether to use old-style or new-style attribute names */
+        if (context->internal->_full_time_names) {
+                /* new-style names */
+                attr_strings.create_time_attr = "CREATE_TIME";
+                attr_strings.access_time_attr = "ACCESS_TIME";
+                attr_strings.write_time_attr = "WRITE_TIME";
+                attr_strings.change_time_attr = "CHANGE_TIME";
+
+                excl_attr_strings.create_time_attr = "CREATE_TIME";
+                excl_attr_strings.access_time_attr = "ACCESS_TIME";
+                excl_attr_strings.write_time_attr = "WRITE_TIME";
+                excl_attr_strings.change_time_attr = "CHANGE_TIME";
+        } else {
+                /* old-style names */
+                attr_strings.create_time_attr = NULL;
+                attr_strings.access_time_attr = "A_TIME";
+                attr_strings.write_time_attr = "M_TIME";
+                attr_strings.change_time_attr = "C_TIME";
+
+                excl_attr_strings.create_time_attr = NULL;
+                excl_attr_strings.access_time_attr = "dos_attr.A_TIME";
+                excl_attr_strings.write_time_attr = "dos_attr.M_TIME";
+                excl_attr_strings.change_time_attr = "dos_attr.C_TIME";
+        }
 
         /* Copy name so we can strip off exclusions (if any are specified) */
         strncpy(name_sandbox, attr_name, sizeof(name_sandbox) - 1);
@@ -4269,14 +4383,22 @@ cacl_get(SMBCCTX *context,
                 else if (StrCaseCmp(pExclude, "dos_attr.size") == 0) {
                     exclude_dos_size = True;
                 }
-                else if (StrCaseCmp(pExclude, "dos_attr.c_time") == 0) {
-                    exclude_dos_ctime = True;
+                else if (excl_attr_strings.create_time_attr != NULL &&
+                         StrCaseCmp(pExclude,
+                                    excl_attr_strings.change_time_attr) == 0) {
+                    exclude_dos_create_time = True;
+                }
+                else if (StrCaseCmp(pExclude,
+                                    excl_attr_strings.access_time_attr) == 0) {
+                    exclude_dos_access_time = True;
                 }
-                else if (StrCaseCmp(pExclude, "dos_attr.a_time") == 0) {
-                    exclude_dos_atime = True;
+                else if (StrCaseCmp(pExclude,
+                                    excl_attr_strings.write_time_attr) == 0) {
+                    exclude_dos_write_time = True;
                 }
-                else if (StrCaseCmp(pExclude, "dos_attr.m_time") == 0) {
-                    exclude_dos_mtime = True;
+                else if (StrCaseCmp(pExclude,
+                                    excl_attr_strings.change_time_attr) == 0) {
+                    exclude_dos_change_time = True;
                 }
                 else if (StrCaseCmp(pExclude, "dos_attr.inode") == 0) {
                     exclude_dos_inode = True;
@@ -4554,15 +4676,21 @@ cacl_get(SMBCCTX *context,
 
                 /* Obtain the DOS attributes */
                 if (!smbc_getatr(context, srv, filename, &mode, &size, 
-                                 &c_time_ts, &a_time_ts, &m_time_ts, &ino)) {
+                                 &create_time_ts,
+                                 &access_time_ts,
+                                 &write_time_ts,
+                                 &change_time_ts,
+                                 &ino)) {
                         
                         errno = smbc_errno(context, srv->cli);
                         return -1;
                         
                 }
-                c_time = convert_timespec_to_time_t(c_time_ts);
-                a_time = convert_timespec_to_time_t(a_time_ts);
-                m_time = convert_timespec_to_time_t(m_time_ts);
+
+                create_time = convert_timespec_to_time_t(create_time_ts);
+                access_time = convert_timespec_to_time_t(access_time_ts);
+                write_time = convert_timespec_to_time_t(write_time_ts);
+                change_time = convert_timespec_to_time_t(change_time_ts);
 
                 if (! exclude_dos_mode) {
                         if (all || all_dos) {
@@ -4655,12 +4783,55 @@ cacl_get(SMBCCTX *context,
                         bufsize -= n;
                 }
 
-                if (! exclude_dos_ctime) {
+                if (! exclude_dos_create_time &&
+                    attr_strings.create_time_attr != NULL) {
+                        if (all || all_dos) {
+                                if (determine_size) {
+                                        p = talloc_asprintf(ctx,
+                                                            ",%s:%lu",
+                                                            attr_strings.create_time_attr,
+                                                            create_time);
+                                        if (!p) {
+                                                errno = ENOMEM;
+                                                return -1;
+                                        }
+                                        n = strlen(p);
+                                } else {
+                                        n = snprintf(buf, bufsize,
+                                                     ",%s:%lu",
+                                                     attr_strings.create_time_attr,
+                                                     create_time);
+                                }
+                        } else if (StrCaseCmp(name, attr_strings.create_time_attr) == 0) {
+                                if (determine_size) {
+                                        p = talloc_asprintf(ctx, "%lu", create_time);
+                                        if (!p) {
+                                                errno = ENOMEM;
+                                                return -1;
+                                        }
+                                        n = strlen(p);
+                                } else {
+                                        n = snprintf(buf, bufsize,
+                                                     "%lu", create_time);
+                                }
+                        }
+        
+                        if (!determine_size && n > bufsize) {
+                                errno = ERANGE;
+                                return -1;
+                        }
+                        buf += n;
+                        n_used += n;
+                        bufsize -= n;
+                }
+
+                if (! exclude_dos_access_time) {
                         if (all || all_dos) {
                                 if (determine_size) {
                                         p = talloc_asprintf(ctx,
-                                                            ",C_TIME:%lu",
-                                                            c_time);
+                                                            ",%s:%lu",
+                                                            attr_strings.access_time_attr,
+                                                            access_time);
                                         if (!p) {
                                                 errno = ENOMEM;
                                                 return -1;
@@ -4668,11 +4839,13 @@ cacl_get(SMBCCTX *context,
                                         n = strlen(p);
                                 } else {
                                         n = snprintf(buf, bufsize,
-                                                     ",C_TIME:%lu", c_time);
+                                                     ",%s:%lu",
+                                                     attr_strings.access_time_attr,
+                                                     access_time);
                                 }
-                        } else if (StrCaseCmp(name, "c_time") == 0) {
+                        } else if (StrCaseCmp(name, attr_strings.access_time_attr) == 0) {
                                 if (determine_size) {
-                                        p = talloc_asprintf(ctx, "%lu", c_time);
+                                        p = talloc_asprintf(ctx, "%lu", access_time);
                                         if (!p) {
                                                 errno = ENOMEM;
                                                 return -1;
@@ -4680,7 +4853,7 @@ cacl_get(SMBCCTX *context,
                                         n = strlen(p);
                                 } else {
                                         n = snprintf(buf, bufsize,
-                                                     "%lu", c_time);
+                                                     "%lu", access_time);
                                 }
                         }
         
@@ -4693,12 +4866,13 @@ cacl_get(SMBCCTX *context,
                         bufsize -= n;
                 }
 
-                if (! exclude_dos_atime) {
+                if (! exclude_dos_write_time) {
                         if (all || all_dos) {
                                 if (determine_size) {
                                         p = talloc_asprintf(ctx,
-                                                            ",A_TIME:%lu",
-                                                            a_time);
+                                                            ",%s:%lu",
+                                                            attr_strings.write_time_attr,
+                                                            write_time);
                                         if (!p) {
                                                 errno = ENOMEM;
                                                 return -1;
@@ -4706,11 +4880,13 @@ cacl_get(SMBCCTX *context,
                                         n = strlen(p);
                                 } else {
                                         n = snprintf(buf, bufsize,
-                                                     ",A_TIME:%lu", a_time);
+                                                     ",%s:%lu",
+                                                     attr_strings.write_time_attr,
+                                                     write_time);
                                 }
-                        } else if (StrCaseCmp(name, "a_time") == 0) {
+                        } else if (StrCaseCmp(name, attr_strings.write_time_attr) == 0) {
                                 if (determine_size) {
-                                        p = talloc_asprintf(ctx, "%lu", a_time);
+                                        p = talloc_asprintf(ctx, "%lu", write_time);
                                         if (!p) {
                                                 errno = ENOMEM;
                                                 return -1;
@@ -4718,7 +4894,7 @@ cacl_get(SMBCCTX *context,
                                         n = strlen(p);
                                 } else {
                                         n = snprintf(buf, bufsize,
-                                                     "%lu", a_time);
+                                                     "%lu", write_time);
                                 }
                         }
         
@@ -4731,12 +4907,13 @@ cacl_get(SMBCCTX *context,
                         bufsize -= n;
                 }
 
-                if (! exclude_dos_mtime) {
+                if (! exclude_dos_change_time) {
                         if (all || all_dos) {
                                 if (determine_size) {
                                         p = talloc_asprintf(ctx,
-                                                            ",M_TIME:%lu",
-                                                            m_time);
+                                                            ",%s:%lu",
+                                                            attr_strings.change_time_attr,
+                                                            change_time);
                                         if (!p) {
                                                 errno = ENOMEM;
                                                 return -1;
@@ -4744,11 +4921,13 @@ cacl_get(SMBCCTX *context,
                                         n = strlen(p);
                                 } else {
                                         n = snprintf(buf, bufsize,
-                                                     ",M_TIME:%lu", m_time);
+                                                     ",%s:%lu",
+                                                     attr_strings.change_time_attr,
+                                                     change_time);
                                 }
-                        } else if (StrCaseCmp(name, "m_time") == 0) {
+                        } else if (StrCaseCmp(name, attr_strings.change_time_attr) == 0) {
                                 if (determine_size) {
-                                        p = talloc_asprintf(ctx, "%lu", m_time);
+                                        p = talloc_asprintf(ctx, "%lu", change_time);
                                         if (!p) {
                                                 errno = ENOMEM;
                                                 return -1;
@@ -4756,7 +4935,7 @@ cacl_get(SMBCCTX *context,
                                         n = strlen(p);
                                 } else {
                                         n = snprintf(buf, bufsize,
-                                                     "%lu", m_time);
+                                                     "%lu", change_time);
                                 }
                         }
         
@@ -5046,6 +5225,12 @@ smbc_setxattr_ctx(SMBCCTX *context,
         TALLOC_CTX *ctx;
         POLICY_HND pol;
         DOS_ATTR_DESC *dad;
+        struct {
+                const char * create_time_attr;
+                const char * access_time_attr;
+                const char * write_time_attr;
+                const char * change_time_attr;
+        } attr_strings;
 
        if (!context || !context->internal ||
            !context->internal->_initialized) {
@@ -5135,9 +5320,10 @@ smbc_setxattr_ctx(SMBCCTX *context,
 
                         /* Set the new DOS attributes */
                         if (! smbc_setatr(context, srv, path,
-                                          dad->c_time,
-                                          dad->a_time,
-                                          dad->m_time,
+                                          dad->create_time,
+                                          dad->access_time,
+                                          dad->write_time,
+                                          dad->change_time,
                                           dad->mode)) {
 
                                 /* cause failure if NT failed too */
@@ -5245,14 +5431,31 @@ smbc_setxattr_ctx(SMBCCTX *context,
                 return ret;
         }
 
+        /* Determine whether to use old-style or new-style attribute names */
+        if (context->internal->_full_time_names) {
+                /* new-style names */
+                attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME";
+                attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME";
+                attr_strings.write_time_attr = "system.dos_attr.WRITE_TIME";
+                attr_strings.change_time_attr = "system.dos_attr.CHANGE_TIME";
+        } else {
+                /* old-style names */
+                attr_strings.create_time_attr = NULL;
+                attr_strings.access_time_attr = "system.dos_attr.A_TIME";
+                attr_strings.write_time_attr = "system.dos_attr.M_TIME";
+                attr_strings.change_time_attr = "system.dos_attr.C_TIME";
+        }
+
         /*
          * Are they asking to set a DOS attribute?
          */
         if (StrCaseCmp(name, "system.dos_attr.*") == 0 ||
             StrCaseCmp(name, "system.dos_attr.mode") == 0 ||
-            StrCaseCmp(name, "system.dos_attr.c_time") == 0 ||
-            StrCaseCmp(name, "system.dos_attr.a_time") == 0 ||
-            StrCaseCmp(name, "system.dos_attr.m_time") == 0) {
+            (attr_strings.create_time_attr != NULL &&
+             StrCaseCmp(name, attr_strings.create_time_attr) == 0) ||
+            StrCaseCmp(name, attr_strings.access_time_attr) == 0 ||
+            StrCaseCmp(name, attr_strings.write_time_attr) == 0 ||
+            StrCaseCmp(name, attr_strings.change_time_attr) == 0) {
 
                 /* get a DOS Attribute Descriptor with current attributes */
                 dad = dos_attr_query(context, ctx, path, srv);
@@ -5269,9 +5472,10 @@ smbc_setxattr_ctx(SMBCCTX *context,
 
                                 /* Set the new DOS attributes */
                                 ret2 = smbc_setatr(context, srv, path,
-                                                   dad->c_time,
-                                                   dad->a_time,
-                                                   dad->m_time,
+                                                   dad->create_time,
+                                                   dad->access_time,
+                                                   dad->write_time,
+                                                   dad->change_time,
                                                    dad->mode);
 
                                 /* ret2 has True (success) / False (failure) */
@@ -5313,6 +5517,12 @@ smbc_getxattr_ctx(SMBCCTX *context,
         pstring path;
         TALLOC_CTX *ctx;
         POLICY_HND pol;
+        struct {
+                const char * create_time_attr;
+                const char * access_time_attr;
+                const char * write_time_attr;
+                const char * change_time_attr;
+        } attr_strings;
 
 
         if (!context || !context->internal ||
@@ -5369,6 +5579,21 @@ smbc_getxattr_ctx(SMBCCTX *context,
                 return -1;
         }
 
+        /* Determine whether to use old-style or new-style attribute names */
+        if (context->internal->_full_time_names) {
+                /* new-style names */
+                attr_strings.create_time_attr = "system.dos_attr.CREATE_TIME";
+                attr_strings.access_time_attr = "system.dos_attr.ACCESS_TIME";
+                attr_strings.write_time_attr = "system.dos_attr.WRITE_TIME";
+                attr_strings.change_time_attr = "system.dos_attr.CHANGE_TIME";
+        } else {
+                /* old-style names */
+                attr_strings.create_time_attr = NULL;
+                attr_strings.access_time_attr = "system.dos_attr.A_TIME";
+                attr_strings.write_time_attr = "system.dos_attr.M_TIME";
+                attr_strings.change_time_attr = "system.dos_attr.C_TIME";
+        }
+
         /* Are they requesting a supported attribute? */
         if (StrCaseCmp(name, "system.*") == 0 ||
             StrnCaseCmp(name, "system.*!", 9) == 0 ||
@@ -5389,9 +5614,11 @@ smbc_getxattr_ctx(SMBCCTX *context,
             StrnCaseCmp(name, "system.dos_attr.*!", 18) == 0 ||
             StrCaseCmp(name, "system.dos_attr.mode") == 0 ||
             StrCaseCmp(name, "system.dos_attr.size") == 0 ||
-            StrCaseCmp(name, "system.dos_attr.c_time") == 0 ||
-            StrCaseCmp(name, "system.dos_attr.a_time") == 0 ||
-            StrCaseCmp(name, "system.dos_attr.m_time") == 0 ||
+            (attr_strings.create_time_attr != NULL &&
+             StrCaseCmp(name, attr_strings.create_time_attr) == 0) ||
+            StrCaseCmp(name, attr_strings.access_time_attr) == 0 ||
+            StrCaseCmp(name, attr_strings.write_time_attr) == 0 ||
+            StrCaseCmp(name, attr_strings.change_time_attr) == 0 ||
             StrCaseCmp(name, "system.dos_attr.inode") == 0) {
 
                 /* Yup. */
@@ -5536,7 +5763,7 @@ smbc_listxattr_ctx(SMBCCTX *context,
          * the complete set of attribute names, always, rather than only those
          * attribute names which actually exist for a file.  Hmmm...
          */
-        const char supported[] =
+        const char supported_old[] =
                 "system.*\0"
                 "system.*+\0"
                 "system.nt_sec_desc.revision\0"
@@ -5555,6 +5782,33 @@ smbc_listxattr_ctx(SMBCCTX *context,
                 "system.dos_attr.a_time\0"
                 "system.dos_attr.m_time\0"
                 ;
+        const char supported_new[] =
+                "system.*\0"
+                "system.*+\0"
+                "system.nt_sec_desc.revision\0"
+                "system.nt_sec_desc.owner\0"
+                "system.nt_sec_desc.owner+\0"
+                "system.nt_sec_desc.group\0"
+                "system.nt_sec_desc.group+\0"
+                "system.nt_sec_desc.acl.*\0"
+                "system.nt_sec_desc.acl\0"
+                "system.nt_sec_desc.acl+\0"
+                "system.nt_sec_desc.*\0"
+                "system.nt_sec_desc.*+\0"
+                "system.dos_attr.*\0"
+                "system.dos_attr.mode\0"
+                "system.dos_attr.create_time\0"
+                "system.dos_attr.access_time\0"
+                "system.dos_attr.write_time\0"
+                "system.dos_attr.change_time\0"
+                ;
+        const char * supported;
+
+        if (context->internal->_full_time_names) {
+                supported = supported_new;
+        } else {
+                supported = supported_old;
+        }
 
         if (size == 0) {
                 return sizeof(supported);
@@ -6029,24 +6283,17 @@ smbc_option_set(SMBCCTX *context,
                 option_value.b = (BOOL) va_arg(ap, int);
                 context->internal->_debug_stderr = option_value.b;
 
-        } else if (strcmp(option_name, "debug_to_stderr") == 0) {
+        } else if (strcmp(option_name, "full_time_names") == 0) {
                 /*
-                 * Log to standard error instead of standard output.
-                 *
-                 * This function used to take a third parameter,
-                 * void *option_value.  Since it was a void* and we needed to
-                 * pass a boolean, a boolean value was cast to void* to be
-                 * passed in.  Now that we're using a va_list to retrieve the
-                 * parameters, the casting kludge is unnecessary.
-                 *
-                 * WARNING: DO NOT USE THIS OPTION.
-                 * This option is retained for backward compatibility.  New
-                 * applications should use "debug_to_stderr" and properly pass
-                 * in a boolean (int) value.
+                 * Use new-style time attribute names, e.g. WRITE_TIME rather
+                 * than the old-style names such as M_TIME.  This allows also
+                 * setting/getting CREATE_TIME which was previously
+                 * unimplemented.  (Note that the old C_TIME was supposed to
+                 * be CHANGE_TIME but was confused and sometimes referred to
+                 * CREATE_TIME.)
                  */
-                option_value.v = va_arg(ap, void *);
-                context->internal->_debug_stderr =
-                        (option_value.v == NULL ? False : True);
+                option_value.b = (BOOL) va_arg(ap, int);
+                context->internal->_full_time_names = option_value.b;
 
         } else if (strcmp(option_name, "auth_function") == 0) {
                 /*
@@ -6086,6 +6333,21 @@ smbc_option_get(SMBCCTX *context,
 #else
                return (void *) context->internal->_debug_stderr;
 #endif
+        } else if (strcmp(option_name, "full_time_names") == 0) {
+                /*
+                 * Use new-style time attribute names, e.g. WRITE_TIME rather
+                 * than the old-style names such as M_TIME.  This allows also
+                 * setting/getting CREATE_TIME which was previously
+                 * unimplemented.  (Note that the old C_TIME was supposed to
+                 * be CHANGE_TIME but was confused and sometimes referred to
+                 * CREATE_TIME.)
+                 */
+#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T)
+               return (void *) (intptr_t) context->internal->_full_time_names;
+#else
+               return (void *) context->internal->_full_time_names;
+#endif
+
         } else if (strcmp(option_name, "auth_function") == 0) {
                 /*
                  * Use the new-style authentication function which includes