summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/libsmbclient/smbwrapper/smbw_stat.c51
-rw-r--r--source3/libsmb/libsmb_compat.c10
-rw-r--r--source3/libsmb/libsmbclient.c95
3 files changed, 71 insertions, 85 deletions
diff --git a/examples/libsmbclient/smbwrapper/smbw_stat.c b/examples/libsmbclient/smbwrapper/smbw_stat.c
index 70b3064d22..a386c09209 100644
--- a/examples/libsmbclient/smbwrapper/smbw_stat.c
+++ b/examples/libsmbclient/smbwrapper/smbw_stat.c
@@ -22,53 +22,8 @@
#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;
}
diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c
index 83088a14de..3dc60f7240 100644
--- a/source3/libsmb/libsmb_compat.c
+++ b/source3/libsmb/libsmb_compat.c
@@ -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
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index ee7516630b..296dbc7f5b 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -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;
}