From: Derrell Lipman Date: Wed, 1 Jun 2005 17:40:40 +0000 (+0000) Subject: r7168: Updating file times from libsmbclient was not working for win98. Although X-Git-Tag: samba-4.0.0alpha6~801^2~10214 X-Git-Url: http://git.samba.org/samba.git/?a=commitdiff_plain;h=e317034997bbeab447298070afdb1b78c60e0e69;p=vlendec%2Fsamba-autobuild%2F.git r7168: Updating file times from libsmbclient was not working for win98. Although 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. (This used to be commit bab0bf7f4f9d2a4b6fcee4429094349302bbeb33) --- diff --git a/examples/libsmbclient/smbwrapper/smbw_stat.c b/examples/libsmbclient/smbwrapper/smbw_stat.c index 70b3064d227..a386c092092 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 83088a14def..3dc60f7240b 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 ee7516630b6..296dbc7f5bb 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; }