r7168: Updating file times from libsmbclient was not working for win98. Although
authorDerrell Lipman <derrell@samba.org>
Wed, 1 Jun 2005 17:40:40 +0000 (17:40 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:57:04 +0000 (10:57 -0500)
the function that was being used to set attributes is a core protocol
function (SMBsetatr = 0x09), it does not appear to work on win98.  As a
temporary measure, when file times are to be set, this version opens the
file and uses SMBsetattrE = 0x22 instead.  (The other advantage of this
function over the original one is that it supports setting access time as
well as modification time.)

The next step, the proper solution if it can be made to work, is to write
functions that use TRANS2_SET_PATH_INFO instead.

examples/libsmbclient/smbwrapper/smbw_stat.c
source/libsmb/libsmb_compat.c
source/libsmb/libsmbclient.c

index 70b3064d22717c405560a5deb227d6a4ee4c5459..a386c092092b5041a1eea884bc018ac62d480a08 100644 (file)
 
 #include "smbw.h"
 
-static int timezone_diff = -1;
-
-#define TM_YEAR_BASE 1900
-
-/*******************************************************************
-yield the difference between *A and *B, in seconds, ignoring leap seconds
-********************************************************************/
-static int tm_diff(struct tm *a, struct tm *b)
-{
-  int ay = a->tm_year + (TM_YEAR_BASE - 1);
-  int by = b->tm_year + (TM_YEAR_BASE - 1);
-  int intervening_leap_days =
-    (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
-  int years = ay - by;
-  int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
-  int hours = 24*days + (a->tm_hour - b->tm_hour);
-  int minutes = 60*hours + (a->tm_min - b->tm_min);
-  int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
-
-  return seconds;
-}
-
-/*******************************************************************
-  return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
-  ******************************************************************/
-static int TimeZone(time_t t)
-{
-  struct tm *tm = gmtime(&t);
-  struct tm tm_utc;
-  if (!tm)
-    return 0;
-  tm_utc = *tm;
-  tm = localtime(&t);
-  if (!tm)
-    return 0;
-  return tm_diff(&tm_utc,tm);
-
-}
-
-
 static void copy_stat(struct SMBW_stat *external, struct stat *internal)
 {
-        if (timezone_diff < 0)
-        {
-            timezone_diff = TimeZone(time(NULL));
-        }
-
         external->s_dev = internal->st_dev;
         external->s_ino = internal->st_ino;
         external->s_mode = internal->st_mode;
@@ -79,9 +34,9 @@ static void copy_stat(struct SMBW_stat *external, struct stat *internal)
         external->s_size = internal->st_size;
         external->s_blksize = internal->st_blksize;
         external->s_blocks = internal->st_blocks;
-        external->s_atime = internal->st_atime + timezone_diff;
-        external->s_mtime = internal->st_mtime + timezone_diff;
-        external->s_ctime = internal->st_ctime + timezone_diff;
+        external->s_atime = internal->st_atime;
+        external->s_mtime = internal->st_mtime;
+        external->s_ctime = internal->st_ctime;
 }
 
 
index 83088a14defcbc5f0fe9fd282cdb50cf41a8ede0..3dc60f7240b3a3f37bfd77d5cbc2c9c51f6f4a4c 100644 (file)
@@ -303,14 +303,16 @@ int smbc_utimes(const char *fname, struct timeval *tbuf)
 #ifdef HAVE_UTIME_H
 int smbc_utime(const char *fname, struct utimbuf *utbuf)
 {
-        struct timeval tv;
+        struct timeval tv[2];
 
         if (utbuf == NULL)
                 return statcont->utimes(statcont, fname, NULL);
 
-        tv.tv_sec = utbuf->modtime;
-        tv.tv_usec = 0;
-        return statcont->utimes(statcont, fname, &tv);
+        tv[0].tv_sec = utbuf->actime;
+        tv[1].tv_sec = utbuf->modtime;
+        tv[0].tv_usec = tv[1].tv_usec = 0;
+
+        return statcont->utimes(statcont, fname, tv);
 }
 #endif
 
index ee7516630b6edc17b166ee0ed567ad7a078c1233..296dbc7f5bb7c5180766b6f33538b15078ff42a5 100644 (file)
@@ -1245,7 +1245,10 @@ static BOOL smbc_getatr(SMBCCTX * context, SMBCSRV *srv, char *path,
         }
 
        if (cli_getatr(&srv->cli, path, mode, size, m_time)) {
-               a_time = c_time = m_time;
+                if (m_time != NULL) {
+                        if (a_time != NULL) *a_time = *m_time;
+                        if (c_time != NULL) *c_time = *m_time;
+                }
                srv->no_pathinfo2 = True;
                return True;
        }
@@ -1303,22 +1306,6 @@ static int smbc_unlink_ctx(SMBCCTX *context, const char *fname)
 
        }
 
-       /*  if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
-
-    int job = smbc_stat_printjob(srv, path, NULL, NULL);
-    if (job == -1) {
-
-      return -1;
-
-    }
-    if ((err = cli_printjob_del(&srv->cli, job)) != 0) {
-
-    
-      return -1;
-
-    }
-    } else */
-
        if (!cli_unlink(&srv->cli, path)) {
 
                errno = smbc_errno(context, &srv->cli);
@@ -2864,11 +2851,14 @@ int smbc_chmod_ctx(SMBCCTX *context, const char *fname, mode_t newmode)
 
 int smbc_utimes_ctx(SMBCCTX *context, const char *fname, struct timeval *tbuf)
 {
+        int fd;
+        int ret;
         SMBCSRV *srv;
        fstring server, share, user, password, workgroup;
        pstring path;
-       uint16 mode;
-        time_t t = (tbuf == NULL ? time(NULL) : tbuf->tv_sec);
+        time_t c_time;
+        time_t a_time;
+        time_t m_time;
 
        if (!context || !context->internal ||
            !context->internal->_initialized) {
@@ -2885,7 +2875,22 @@ int smbc_utimes_ctx(SMBCCTX *context, const char *fname, struct timeval *tbuf)
 
        }
   
-       DEBUG(4, ("smbc_utimes(%s, [%s])\n", fname, ctime(&t)));
+        if (tbuf == NULL) {
+                a_time = m_time = time(NULL);
+        } else {
+                a_time = tbuf[0].tv_sec;
+                m_time = tbuf[1].tv_sec;
+        }
+
+        {
+                char atimebuf[32];
+                char mtimebuf[32];
+
+                DEBUG(4, ("smbc_utimes(%s, atime = %s mtime = %s)\n",
+                          fname,
+                          ctime_r(&a_time, atimebuf),
+                          ctime_r(&m_time, mtimebuf)));
+        }
 
        if (smbc_parse_path(context, fname,
                             server, sizeof(server),
@@ -2908,22 +2913,46 @@ int smbc_utimes_ctx(SMBCCTX *context, const char *fname, struct timeval *tbuf)
                return -1;  /* errno set by smbc_server */
        }
 
-       if (!smbc_getatr(context, srv, path,
-                         &mode, NULL,
-                         NULL, NULL, NULL,
-                         NULL)) {
+        /*
+         * cli_setatr() does not work on win98, and it also doesn't support
+         * setting the access time (only the modification time), so in all
+         * cases, we open the specified file and use cli_setattrE() which
+         * should work on all OS versions, and supports both times.
+         */
+        if ((fd = cli_open(&srv->cli, path, O_RDWR, DENY_NONE)) < 0) {
+
+                errno = smbc_errno(context, &srv->cli);
                 return -1;
-       }
+                
+        }
 
-       if (!cli_setatr(&srv->cli, path, mode, t)) {
-               /* some servers always refuse directory changes */
-               if (!(mode & aDIR)) {
-                       errno = smbc_errno(context, &srv->cli);
-                        return -1;
-               }
-       }
+        /* Get the creat time of the file; we'll need it in the set call */
+        ret = cli_getattrE(&srv->cli, fd, NULL, NULL, &c_time, NULL, NULL);
 
-       return 0;
+        /* Some OS versions don't support create time */
+        if (c_time == 0) {
+                c_time = time(NULL);
+        }
+
+        /*
+         * 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;
+
+        /* If we sucessfully retrieved the create time... */
+        if (ret) {
+                /* ... then set the new attributes */
+                ret = cli_setattrE(&srv->cli, fd, c_time, a_time, m_time);
+        }
+
+        cli_close(&srv->cli, fd);
+
+        return ret;
 }