diff options
-rw-r--r-- | examples/libsmbclient/smbwrapper/smbw_stat.c | 51 | ||||
-rw-r--r-- | source3/libsmb/libsmb_compat.c | 10 | ||||
-rw-r--r-- | source3/libsmb/libsmbclient.c | 95 |
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; } |