From: Jeremy Allison Date: Mon, 5 Mar 2007 23:40:03 +0000 (+0000) Subject: r21714: Change the VFS interface to use struct timespec X-Git-Url: http://git.samba.org/samba.git/?p=jra%2Fsamba%2F.git;a=commitdiff_plain;h=4952fe368a40b239140b3035db6075427d237bb9 r21714: Change the VFS interface to use struct timespec for utimes - change the call to ntimes. This preserves nsec timestamps we get from stat (if the system supports it) and only maps back down to usec or sec resolution on time set. Looks bigger than it is as I had to move lots of internal code from using time_t and struct utimebuf to struct timespec. Jeremy. (This used to be commit 8f3d530c5a748ea90f42ed8fbe68ae92178d4875) --- diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 096068da147..18ad5eb5172 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -211,9 +211,9 @@ static char *skel_getwd(vfs_handle_struct *handle, char *buf) return vfswrap_getwd(NULL, buf); } -static int skel_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times) +static int skel_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2]) { - return vfswrap_utime(NULL, path, times); + return vfswrap_ntimes(NULL, path, ts); } static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T offset) @@ -578,7 +578,7 @@ static vfs_op_tuple skel_op_tuples[] = { {SMB_VFS_OP(skel_fchown), SMB_VFS_OP_FCHOWN, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_chdir), SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_getwd), SMB_VFS_OP_GETWD, SMB_VFS_LAYER_OPAQUE}, - {SMB_VFS_OP(skel_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_OPAQUE}, + {SMB_VFS_OP(skel_ntimes), SMB_VFS_OP_NTIMES, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(skel_getlock), SMB_VFS_OP_GETLOCK, SMB_VFS_LAYER_OPAQUE}, diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index 2a379cd6d89..b967a337ebc 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -210,9 +210,9 @@ static char *skel_getwd(vfs_handle_struct *handle, char *buf) return SMB_VFS_NEXT_GETWD(handle, buf); } -static int skel_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times) +static int skel_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2]) { - return SMB_VFS_NEXT_UTIME(handle, path, times); + return SMB_VFS_NEXT_NTIMES(handle, path, ts[2]); } static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T offset) @@ -545,7 +545,7 @@ static vfs_op_tuple skel_op_tuples[] = { {SMB_VFS_OP(skel_fchown), SMB_VFS_OP_FCHOWN, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(skel_chdir), SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(skel_getwd), SMB_VFS_OP_GETWD, SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(skel_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(skel_ntimes), SMB_VFS_OP_NTIMES, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(skel_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(skel_lock), SMB_VFS_OP_LOCK, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(skel_getlock), SMB_VFS_OP_GETLOCK, SMB_VFS_LAYER_TRANSPARENT}, diff --git a/source3/client/client.c b/source3/client/client.c index a7bb56ba88c..605beb2e06c 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -387,7 +387,7 @@ static void display_finfo(file_info *finfo) finfo->name, attrib_string(finfo->mode), (double)finfo->size, - time_to_asc(&t)); + time_to_asc(t)); dir_total += finfo->size; } else { pstring afname; @@ -404,7 +404,7 @@ static void display_finfo(file_info *finfo) d_printf( "FILENAME:%s\n", afname); d_printf( "MODE:%s\n", attrib_string(finfo->mode)); d_printf( "SIZE:%.0f\n", (double)finfo->size); - d_printf( "MTIME:%s", time_to_asc(&t)); + d_printf( "MTIME:%s", time_to_asc(t)); fnum = cli_nt_create(cli, afname, CREATE_ACCESS_READ); if (fnum == -1) { DEBUG( 0, ("display_finfo() Failed to open %s: %s\n", @@ -2713,7 +2713,7 @@ static int cmd_newer(void) if (ok && (sys_stat(buf,&sbuf) == 0)) { newer_than = sbuf.st_mtime; DEBUG(1,("Getting files newer than %s", - time_to_asc(&newer_than))); + time_to_asc(newer_than))); } else { newer_than = 0; } diff --git a/source3/client/clitar.c b/source3/client/clitar.c index f228db11998..c0748799b20 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -1650,7 +1650,7 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind) if (sys_stat(argv[Optind], &stbuf) == 0) { newer_than = stbuf.st_mtime; DEBUG(1,("Getting files newer than %s", - time_to_asc(&newer_than))); + time_to_asc(newer_than))); newOptind++; Optind++; } else { diff --git a/source3/client/smbctool.c b/source3/client/smbctool.c index b7042f99cb2..29466108c07 100644 --- a/source3/client/smbctool.c +++ b/source3/client/smbctool.c @@ -445,7 +445,7 @@ static void display_finfo(file_info *finfo) finfo->name, attrib_string(finfo->mode), (double)finfo->size, - time_to_asc(&t)); + time_to_asc(t)); dir_total += finfo->size; } } @@ -458,7 +458,7 @@ static void display_stat(char *name, struct stat *st) { time_t t = st->st_mtime; pstring time_str; - pstrcpy(time_str, time_to_asc(&t)); + pstrcpy(time_str, time_to_asc(t)); time_str[strlen(time_str)-1] = 0; d_printf("> %-30s", name); d_printf("%10.10s %8.0f %s\n", *mode_t_string(st->st_mode), (double)st->st_size, time_str); @@ -2561,7 +2561,7 @@ static int cmd_newer(void) if (ok && (sys_stat(buf,&sbuf) == 0)) { newer_than = sbuf.st_mtime; DEBUG(1,("Getting files newer than %s", - time_to_asc(&newer_than))); + time_to_asc(newer_than))); } else { newer_than = 0; } diff --git a/source3/include/smb.h b/source3/include/smb.h index cea7638d79b..1e31d8545d4 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -495,8 +495,8 @@ typedef struct files_struct { uint32 access_mask; /* NTCreateX access bits (FILE_READ_DATA etc.) */ uint32 share_access; /* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */ BOOL pending_modtime_owner; - time_t pending_modtime; - time_t last_write_time; + struct timespec pending_modtime; + struct timespec last_write_time; int oplock_type; int sent_oplock_break; struct timed_event *oplock_timeout; diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index fa7c6e4a5ae..cc501739c16 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -152,9 +152,9 @@ enum profile_stats_values #define syscall_getwd_count __profile_stats_value(PR_VALUE_SYSCALL_GETWD, count) #define syscall_getwd_time __profile_stats_value(PR_VALUE_SYSCALL_GETWD, time) - PR_VALUE_SYSCALL_UTIME, -#define syscall_utime_count __profile_stats_value(PR_VALUE_SYSCALL_UTIME, count) -#define syscall_utime_time __profile_stats_value(PR_VALUE_SYSCALL_UTIME, time) + PR_VALUE_SYSCALL_NTIMES, +#define syscall_ntimes_count __profile_stats_value(PR_VALUE_SYSCALL_NTIMES, count) +#define syscall_ntimes_time __profile_stats_value(PR_VALUE_SYSCALL_NTIMES, time) PR_VALUE_SYSCALL_FTRUNCATE, #define syscall_ftruncate_count __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, count) diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 4c2b559bea3..7bcd6cdf2c4 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -67,7 +67,9 @@ Also include kernel_flock call - jmcd */ /* Changed to version 19, kernel change notify has been merged Also included linux setlease call - jmcd */ -#define SMB_VFS_INTERFACE_VERSION 19 +/* Changed to version 20, use ntimes call instead of utime (greater + * timestamp resolition. JRA. */ +#define SMB_VFS_INTERFACE_VERSION 20 /* to bug old modules which are trying to compile with the old functions */ @@ -144,7 +146,7 @@ typedef enum _vfs_op_type { SMB_VFS_OP_FCHOWN, SMB_VFS_OP_CHDIR, SMB_VFS_OP_GETWD, - SMB_VFS_OP_UTIME, + SMB_VFS_OP_NTIMES, SMB_VFS_OP_FTRUNCATE, SMB_VFS_OP_LOCK, SMB_VFS_OP_KERNEL_FLOCK, @@ -269,7 +271,7 @@ struct vfs_ops { int (*fchown)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uid_t uid, gid_t gid); int (*chdir)(struct vfs_handle_struct *handle, const char *path); char *(*getwd)(struct vfs_handle_struct *handle, char *buf); - int (*utime)(struct vfs_handle_struct *handle, const char *path, struct utimbuf *times); + int (*ntimes)(struct vfs_handle_struct *handle, const char *path, const struct timespec ts[2]); int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset); BOOL (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); int (*kernel_flock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uint32 share_mode); @@ -392,7 +394,7 @@ struct vfs_ops { struct vfs_handle_struct *fchown; struct vfs_handle_struct *chdir; struct vfs_handle_struct *getwd; - struct vfs_handle_struct *utime; + struct vfs_handle_struct *ntimes; struct vfs_handle_struct *ftruncate; struct vfs_handle_struct *lock; struct vfs_handle_struct *kernel_flock; diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index f50da3a02b5..f4a289716bb 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -67,7 +67,7 @@ #define SMB_VFS_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs.ops.fchown((fsp)->conn->vfs.handles.fchown, (fsp), (fd), (uid), (gid))) #define SMB_VFS_CHDIR(conn, path) ((conn)->vfs.ops.chdir((conn)->vfs.handles.chdir, (path))) #define SMB_VFS_GETWD(conn, buf) ((conn)->vfs.ops.getwd((conn)->vfs.handles.getwd, (buf))) -#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (path), (times))) +#define SMB_VFS_NTIMES(conn, path, ts) ((conn)->vfs.ops.ntimes((conn)->vfs.handles.ntimes, (path), (ts))) #define SMB_VFS_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs.ops.ftruncate((fsp)->conn->vfs.handles.ftruncate, (fsp), (fd), (offset))) #define SMB_VFS_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs.ops.lock((fsp)->conn->vfs.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) #define SMB_VFS_KERNEL_FLOCK(fsp, fd, share_mode) ((fsp)->conn->vfs.ops.kernel_flock((fsp)->conn->vfs.handles.kernel_flock, (fsp), (fd), (share_mode))) @@ -182,7 +182,7 @@ #define SMB_VFS_OPAQUE_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs_opaque.ops.fchown((fsp)->conn->vfs_opaque.handles.fchown, (fsp), (fd), (uid), (gid))) #define SMB_VFS_OPAQUE_CHDIR(conn, path) ((conn)->vfs_opaque.ops.chdir((conn)->vfs_opaque.handles.chdir, (path))) #define SMB_VFS_OPAQUE_GETWD(conn, buf) ((conn)->vfs_opaque.ops.getwd((conn)->vfs_opaque.handles.getwd, (buf))) -#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (path), (times))) +#define SMB_VFS_OPAQUE_NTIMES(conn, path, ts) ((conn)->vfs_opaque.ops.ntimes((conn)->vfs_opaque.handles.ntimes, (path), (ts))) #define SMB_VFS_OPAQUE_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs_opaque.ops.ftruncate((fsp)->conn->vfs_opaque.handles.ftruncate, (fsp), (fd), (offset))) #define SMB_VFS_OPAQUE_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) #define SMB_VFS_OPAQUE_FLOCK(fsp, fd, share_mode) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.kernel_flock, (fsp), (fd), (share_mode))) @@ -298,7 +298,7 @@ #define SMB_VFS_NEXT_FCHOWN(handle, fsp, fd, uid, gid) ((handle)->vfs_next.ops.fchown((handle)->vfs_next.handles.fchown, (fsp), (fd), (uid), (gid))) #define SMB_VFS_NEXT_CHDIR(handle, path) ((handle)->vfs_next.ops.chdir((handle)->vfs_next.handles.chdir, (path))) #define SMB_VFS_NEXT_GETWD(handle, buf) ((handle)->vfs_next.ops.getwd((handle)->vfs_next.handles.getwd, (buf))) -#define SMB_VFS_NEXT_UTIME(handle, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (path), (times))) +#define SMB_VFS_NEXT_NTIMES(handle, path, ts) ((handle)->vfs_next.ops.ntimes((handle)->vfs_next.handles.ntimes, (path), (ts))) #define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset) ((handle)->vfs_next.ops.ftruncate((handle)->vfs_next.handles.ftruncate, (fsp), (fd), (offset))) #define SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type) ((handle)->vfs_next.ops.lock((handle)->vfs_next.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) #define SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, fd, share_mode)((handle)->vfs_next.ops.kernel_flock((handle)->vfs_next.handles.kernel_flock, (fsp), (fd), (share_mode))) diff --git a/source3/lib/time.c b/source3/lib/time.c index 3abe233c4ff..e98f8232abc 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-2004 Copyright (C) Stefan (metze) Metzmacher 2002 + Copyright (C) Jeremy Allison 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,17 +39,19 @@ #define NTTIME_INFINITY (NTTIME)0x8000000000000000LL -/** +/*************************************************************************** External access to time_t_min and time_t_max. -**/ +****************************************************************************/ + time_t get_time_t_max(void) { return TIME_T_MAX; } -/** -a gettimeofday wrapper -**/ +/*************************************************************************** + A gettimeofday wrapper. +****************************************************************************/ + void GetTimeOfDay(struct timeval *tval) { #ifdef HAVE_GETTIMEOFDAY_TZ @@ -58,14 +61,6 @@ void GetTimeOfDay(struct timeval *tval) #endif } -struct timespec convert_time_t_to_timespec(time_t t) -{ - struct timespec ts; - ts.tv_sec = t; - ts.tv_nsec = 0; - return ts; -} - #if (SIZEOF_LONG == 8) #define TIME_FIXUP_CONSTANT_INT 11644473600L #elif (SIZEOF_LONG_LONG == 8) @@ -113,10 +108,10 @@ void unix_to_nt_time(NTTIME *nt, time_t t) *nt = t2; } +/**************************************************************************** + Check if it's a null unix time. +****************************************************************************/ -/** -check if it's a null unix time -**/ BOOL null_time(time_t t) { return t == 0 || @@ -124,15 +119,26 @@ BOOL null_time(time_t t) t == (time_t)-1; } +/**************************************************************************** + Check if it's a null NTTIME. +****************************************************************************/ -/** -check if it's a null NTTIME -**/ BOOL null_nttime(NTTIME t) { return t == 0 || t == (NTTIME)-1; } +/**************************************************************************** + Check if it's a null timespec. +****************************************************************************/ + +BOOL null_timespec(struct timespec ts) +{ + return ts.tv_sec == 0 || + ts.tv_sec == (time_t)0xFFFFFFFF || + ts.tv_sec == (time_t)-1; +} + /******************************************************************* create a 16 bit dos packed date ********************************************************************/ @@ -549,8 +555,9 @@ NTTIME timeval_to_nttime(const struct timeval *tv) } /******************************************************************* -yield the difference between *A and *B, in seconds, ignoring leap seconds + 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 + (1900 - 1); @@ -568,9 +575,10 @@ static int tm_diff(struct tm *a, struct tm *b) int extra_time_offset=0; -/** - return the UTC offset in seconds west of UTC, or 0 if it cannot be determined - */ +/******************************************************************* + Return the UTC offset in seconds west of UTC, or 0 if it cannot be determined. +********************************************************************/ + int get_time_zone(time_t t) { struct tm *tm = gmtime(&t); @@ -780,7 +788,7 @@ void put_long_date(char *p, time_t t) structure. ****************************************************************************/ -time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs) +time_t get_create_time(const SMB_STRUCT_STAT *st,BOOL fake_dirs) { time_t ret, ret1; @@ -802,7 +810,7 @@ time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs) return ret; } -struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs) +struct timespec get_create_timespec(const SMB_STRUCT_STAT *st,BOOL fake_dirs) { struct timespec ts; ts.tv_sec = get_create_time(st, fake_dirs); @@ -814,7 +822,7 @@ struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs) Get/Set all the possible time fields from a stat struct as a timespec. ****************************************************************************/ -struct timespec get_atimespec(SMB_STRUCT_STAT *pst) +struct timespec get_atimespec(const SMB_STRUCT_STAT *pst) { #if !defined(HAVE_STAT_HIRES_TIMESTAMPS) struct timespec ret; @@ -854,7 +862,7 @@ void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts) #endif } -struct timespec get_mtimespec(SMB_STRUCT_STAT *pst) +struct timespec get_mtimespec(const SMB_STRUCT_STAT *pst) { #if !defined(HAVE_STAT_HIRES_TIMESTAMPS) struct timespec ret; @@ -894,7 +902,7 @@ void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts) #endif } -struct timespec get_ctimespec(SMB_STRUCT_STAT *pst) +struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst) { #if !defined(HAVE_STAT_HIRES_TIMESTAMPS) struct timespec ret; @@ -1022,6 +1030,81 @@ time_t convert_timespec_to_time_t(struct timespec ts) return ts.tv_sec; } +struct timespec convert_time_t_to_timespec(time_t t) +{ + struct timespec ts; + ts.tv_sec = t; + ts.tv_nsec = 0; + return ts; +} + +/**************************************************************************** + Convert a normalized timeval to a timespec. +****************************************************************************/ + +struct timespec convert_timeval_to_timespec(const struct timeval tv) +{ + struct timespec ts; + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + return ts; +} + +/**************************************************************************** + Convert a normalized timespec to a timeval. +****************************************************************************/ + +struct timeval convert_timespec_to_timeval(const struct timespec ts) +{ + struct timeval tv; + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; +} + +/**************************************************************************** + Return a timespec for the current time +****************************************************************************/ + +struct timespec timespec_current(void) +{ + struct timeval tv; + struct timespec ts; + GetTimeOfDay(&tv); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_sec * 1000; + return ts; +} + +/**************************************************************************** + Return the lesser of two timespecs. +****************************************************************************/ + +struct timespec timespec_min(const struct timespec *ts1, + const struct timespec *ts2) +{ + if (ts1->tv_sec < ts2->tv_sec) return *ts1; + if (ts1->tv_sec > ts2->tv_sec) return *ts2; + if (ts1->tv_nsec < ts2->tv_nsec) return *ts1; + return *ts2; +} + +/**************************************************************************** + compare two timespec structures. + Return -1 if ts1 < ts2 + Return 0 if ts1 == ts2 + Return 1 if ts1 > ts2 +****************************************************************************/ + +int timespec_compare(const struct timespec *ts1, const struct timespec *ts2) +{ + if (ts1->tv_sec > ts2->tv_sec) return 1; + if (ts1->tv_sec < ts2->tv_sec) return -1; + if (ts1->tv_nsec > ts2->tv_nsec) return 1; + if (ts1->tv_nsec < ts2->tv_nsec) return -1; + return 0; +} + /**************************************************************************** Interprets an nt time into a unix struct timespec. Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff @@ -1284,10 +1367,10 @@ BOOL null_mtime(time_t mtime) and asctime fail. ****************************************************************************/ -const char *time_to_asc(const time_t *t) +const char *time_to_asc(const time_t t) { const char *asct; - struct tm *lt = localtime(t); + struct tm *lt = localtime(&t); if (!lt) { return "unknown time"; @@ -1347,4 +1430,3 @@ BOOL nt_time_is_set(const NTTIME *nt) return True; } - diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index c254ba0ed97..d495ed5d146 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -131,11 +131,11 @@ static int cap_chdir(vfs_handle_struct *handle, const char *path) return SMB_VFS_NEXT_CHDIR(handle, cappath); } -static int cap_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times) +static int cap_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2]) { pstring cappath; capencode(cappath, path); - return SMB_VFS_NEXT_UTIME(handle, cappath, times); + return SMB_VFS_NEXT_NTIMES(handle, cappath, ts); } @@ -327,7 +327,7 @@ static vfs_op_tuple cap_op_tuples[] = { {SMB_VFS_OP(cap_chmod), SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(cap_chown), SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(cap_chdir), SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(cap_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_ntimes), SMB_VFS_OP_NTIMES, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(cap_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(cap_readlink), SMB_VFS_OP_READLINK, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(cap_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_TRANSPARENT}, diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 478dab6cbed..fe1ce830f7b 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -184,10 +184,10 @@ static char *catia_getwd(vfs_handle_struct *handle, char *buf) return SMB_VFS_NEXT_GETWD(handle, buf); } -static int catia_utime(vfs_handle_struct *handle, - const char *path, struct utimbuf *times) +static int catia_ntimes(vfs_handle_struct *handle, + const char *path, const struct timespec ts[2]) { - return SMB_VFS_NEXT_UTIME(handle, path, times); + return SMB_VFS_NEXT_NTIMES(handle, path, ts); } static BOOL catia_symlink(vfs_handle_struct *handle, @@ -278,7 +278,7 @@ SMB_VFS_LAYER_TRANSPARENT}, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(catia_getwd), SMB_VFS_OP_GETWD, SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(catia_utime), SMB_VFS_OP_UTIME, + {SMB_VFS_OP(catia_ntimes), SMB_VFS_OP_NTIMES, SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(catia_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_TRANSPARENT}, diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index c0b80e17754..f482a3b1f3d 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Wrap disk only vfs functions to sidestep dodgy compilers. Copyright (C) Tim Potter 1998 + Copyright (C) Jeremy Allison 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -612,13 +613,35 @@ static char *vfswrap_getwd(vfs_handle_struct *handle, char *path) return result; } -static int vfswrap_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times) +/********************************************************************* + nsec timestamp resolution call. Convert down to whatever the underlying + system will support. +**********************************************************************/ + +static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2]) { int result; - START_PROFILE(syscall_utime); - result = utime(path, times); - END_PROFILE(syscall_utime); + START_PROFILE(syscall_ntimes); +#if defined(HAVE_UTIMES) + { + struct timeval tv[2]; + tv[0] = convert_timespec_to_timeval(ts[0]); + tv[1] = convert_timespec_to_timeval(ts[1]); + result = utimes(path, tv); + } +#elif defined(HAVE_UTIME) + { + struct utimebuf times; + times.actime = convert_timespec_to_time_t(ts[0]); + times.modtime = convert_timespec_to_time_t(ts[1]); + result = utime(path, times); + } +#else + errno = ENOSYS; + result = -1; +#endif + END_PROFILE(syscall_ntimes); return result; } @@ -1239,7 +1262,7 @@ static vfs_op_tuple vfs_default_ops[] = { SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(vfswrap_getwd), SMB_VFS_OP_GETWD, SMB_VFS_LAYER_OPAQUE}, - {SMB_VFS_OP(vfswrap_utime), SMB_VFS_OP_UTIME, + {SMB_VFS_OP(vfswrap_ntimes), SMB_VFS_OP_NTIMES, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(vfswrap_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_OPAQUE}, diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 6036e49fc15..e609ae1cd1f 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -151,8 +151,8 @@ static int smb_full_audit_chdir(vfs_handle_struct *handle, const char *path); static char *smb_full_audit_getwd(vfs_handle_struct *handle, char *path); -static int smb_full_audit_utime(vfs_handle_struct *handle, - const char *path, struct utimbuf *times); +static int smb_full_audit_ntimes(vfs_handle_struct *handle, + const char *path, const struct timespec ts[2]); static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len); static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, @@ -375,7 +375,7 @@ static vfs_op_tuple audit_op_tuples[] = { SMB_VFS_LAYER_LOGGER}, {SMB_VFS_OP(smb_full_audit_getwd), SMB_VFS_OP_GETWD, SMB_VFS_LAYER_LOGGER}, - {SMB_VFS_OP(smb_full_audit_utime), SMB_VFS_OP_UTIME, + {SMB_VFS_OP(smb_full_audit_ntimes), SMB_VFS_OP_NTIMES, SMB_VFS_LAYER_LOGGER}, {SMB_VFS_OP(smb_full_audit_ftruncate), SMB_VFS_OP_FTRUNCATE, SMB_VFS_LAYER_LOGGER}, @@ -549,7 +549,7 @@ static struct { { SMB_VFS_OP_FCHOWN, "fchown" }, { SMB_VFS_OP_CHDIR, "chdir" }, { SMB_VFS_OP_GETWD, "getwd" }, - { SMB_VFS_OP_UTIME, "utime" }, + { SMB_VFS_OP_NTIMES, "ntimes" }, { SMB_VFS_OP_FTRUNCATE, "ftruncate" }, { SMB_VFS_OP_LOCK, "lock" }, { SMB_VFS_OP_KERNEL_FLOCK, "kernel_flock" }, @@ -1267,14 +1267,14 @@ static char *smb_full_audit_getwd(vfs_handle_struct *handle, return result; } -static int smb_full_audit_utime(vfs_handle_struct *handle, - const char *path, struct utimbuf *times) +static int smb_full_audit_ntimes(vfs_handle_struct *handle, + const char *path, const struct timespec ts[2]) { int result; - result = SMB_VFS_NEXT_UTIME(handle, path, times); + result = SMB_VFS_NEXT_NTIMES(handle, path, ts); - do_log(SMB_VFS_OP_UTIME, (result >= 0), handle, "%s", path); + do_log(SMB_VFS_OP_NTIMES, (result >= 0), handle, "%s", path); return result; } diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index b417b9cbff8..240931fa781 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -364,18 +364,16 @@ static BOOL matchparam(const char **haystack_list, const char *needle) static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, BOOL touch_mtime) { SMB_STRUCT_STAT st; - struct utimbuf tb; - time_t currtime; + struct timespec ts[2]; if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) { DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno))); return; } - currtime = time(&currtime); - tb.actime = currtime; - tb.modtime = touch_mtime ? currtime : st.st_mtime; + ts[0] = timespec_current(); /* atime */ + ts[1] = touch_mtime ? ts[0] : get_mtimespec(&st); /* mtime */ - if (SMB_VFS_NEXT_UTIME(handle, fname, &tb) == -1 ) { + if (SMB_VFS_NEXT_NTIMES(handle, fname, ts) == -1 ) { DEBUG(0, ("recycle: touching %s failed, reason = %s\n", fname, strerror(errno))); } } diff --git a/source3/profile/profile.c b/source3/profile/profile.c index 30b06492545..686d130b567 100644 --- a/source3/profile/profile.c +++ b/source3/profile/profile.c @@ -285,7 +285,7 @@ BOOL profile_setup(BOOL rdonly) "syscall_fchown", /* PR_VALUE_SYSCALL_FCHOWN */ "syscall_chdir", /* PR_VALUE_SYSCALL_CHDIR */ "syscall_getwd", /* PR_VALUE_SYSCALL_GETWD */ - "syscall_utime", /* PR_VALUE_SYSCALL_UTIME */ + "syscall_ntimes", /* PR_VALUE_SYSCALL_NTIMES */ "syscall_ftruncate", /* PR_VALUE_SYSCALL_FTRUNCATE */ "syscall_fcntl_lock", /* PR_VALUE_SYSCALL_FCNTL_LOCK */ "syscall_kernel_flock", /* PR_VALUE_SYSCALL_KERNEL_FLOCK */ diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 50111f62bbf..1c9f6ea8c42 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -361,9 +361,9 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ * Ensure pending modtime is set after close. */ - if(fsp->pending_modtime && fsp->pending_modtime_owner) { + if (fsp->pending_modtime_owner && !null_timespec(fsp->pending_modtime)) { set_filetime(conn, fsp->fsp_name, fsp->pending_modtime); - } else if (fsp->last_write_time) { + } else if (!null_timespec(fsp->last_write_time)) { set_filetime(conn, fsp->fsp_name, fsp->last_write_time); } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index ad79bbacddf..71d4fa179d4 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -282,7 +282,7 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_ } /* We want DOS semantics, ie allow non owner with write permission to change the - bits on a file. Just like file_utime below. + bits on a file. Just like file_ntimes below. */ /* Check if we have write access. */ @@ -504,7 +504,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, return -1; /* We want DOS semantics, ie allow non owner with write permission to change the - bits on a file. Just like file_utime below. + bits on a file. Just like file_ntimes below. */ /* Check if we have write access. */ @@ -532,11 +532,11 @@ int file_set_dosmode(connection_struct *conn, const char *fname, } /******************************************************************* - Wrapper around dos_utime that possibly allows DOS semantics rather + Wrapper around the VFS ntimes that possibly allows DOS semantics rather than POSIX. *******************************************************************/ -int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times) +int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2]) { SMB_STRUCT_STAT sbuf; int ret = -1; @@ -555,14 +555,17 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times return 0; } - if(SMB_VFS_UTIME(conn,fname, times) == 0) + if(SMB_VFS_NTIMES(conn, fname, ts) == 0) { return 0; + } - if((errno != EPERM) && (errno != EACCES)) + if((errno != EPERM) && (errno != EACCES)) { return -1; + } - if(!lp_dos_filetimes(SNUM(conn))) + if(!lp_dos_filetimes(SNUM(conn))) { return -1; + } /* We have permission (given by the Samba admin) to break POSIX semantics and allow a user to change @@ -574,7 +577,7 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times if (can_write_to_file(conn, fname, &sbuf)) { /* We are allowed to become root and change the filetime. */ become_root(); - ret = SMB_VFS_UTIME(conn,fname, times); + ret = SMB_VFS_NTIMES(conn, fname, ts); unbecome_root(); } @@ -585,16 +588,19 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times Change a filetime - possibly allowing DOS semantics. *******************************************************************/ -BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime) +BOOL set_filetime(connection_struct *conn, const char *fname, + const struct timespec mtime) { - struct utimbuf times; + struct timespec ts[2]; - if (null_mtime(mtime)) + if (null_timespec(mtime)) { return(True); + } - times.modtime = times.actime = mtime; + ts[1] = mtime; /* mtime. */ + ts[0] = ts[1]; /* atime. */ - if (file_utime(conn, fname, ×)) { + if (file_ntimes(conn, fname, ts)) { DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); return False; } @@ -602,5 +608,5 @@ BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime) notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_LAST_WRITE, fname); - return(True); -} + return True; +} diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index e0945be8893..65238c0e9ee 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -149,13 +149,13 @@ static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos * The 99% solution will hopefully be good enough in this case. JRA. */ - if (fsp->pending_modtime) { + if (!null_timespec(fsp->pending_modtime)) { set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime); /* If we didn't get the "set modtime" call ourselves, we must store the last write time to restore on close. JRA. */ if (!fsp->pending_modtime_owner) { - fsp->last_write_time = time(NULL); + fsp->last_write_time = timespec_current(); } } diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 07065483344..062bebd58e6 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -383,11 +383,11 @@ files_struct *file_find_print(void) Record the owner of that modtime. ****************************************************************************/ -void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod) +void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod) { files_struct *fsp; - if (null_mtime(pmod)) { + if (null_timespec(mod)) { return; } @@ -395,7 +395,7 @@ void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod) if ( fsp->fh->fd != -1 && fsp->dev == tfsp->dev && fsp->inode == tfsp->inode ) { - fsp->pending_modtime = pmod; + fsp->pending_modtime = mod; fsp->pending_modtime_owner = False; } } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 968c536cafd..eedc3cfba44 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1675,7 +1675,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new close_file(fsp1,NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - fsp_set_pending_modtime(fsp2, sbuf1.st_mtime); + fsp_set_pending_modtime(fsp2, get_mtimespec(&sbuf1)); status = close_file(fsp2,NORMAL_CLOSE); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 25c2aaa4dcb..df560390c94 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -828,7 +828,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } } - if (!set_filetime(conn,fname,mtime)) { + if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) { END_PROFILE(SMBsetatr); return UNIXERROR(ERRDOS, ERRnoaccess); } @@ -1483,7 +1483,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int com; int outsize = 0; uint32 fattr = SVAL(inbuf,smb_vwv0); - struct utimbuf times; + struct timespec ts[2]; files_struct *fsp; int oplock_request = CORE_OPLOCK_REQUEST(inbuf); SMB_STRUCT_STAT sbuf; @@ -1497,7 +1497,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, com = SVAL(inbuf,smb_com); - times.modtime = srv_make_unix_date3(inbuf + smb_vwv1); + ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */ srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { @@ -1550,8 +1550,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - times.actime = sbuf.st_atime; - file_utime(conn, fname, ×); + ts[0] = get_atimespec(&sbuf); /* atime. */ + file_ntimes(conn, fname, ts); outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fsp->fnum); @@ -3146,7 +3146,6 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, { NTSTATUS status = NT_STATUS_OK; int outsize = 0; - time_t mtime; files_struct *fsp = NULL; START_PROFILE(SMBclose); @@ -3188,8 +3187,8 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * Take care of any time sent in the close. */ - mtime = srv_make_unix_date3(inbuf+smb_vwv1); - fsp_set_pending_modtime(fsp, mtime); + fsp_set_pending_modtime(fsp, + convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1))); /* * close_file() returns the unix errno if an error @@ -3222,7 +3221,7 @@ int reply_writeclose(connection_struct *conn, NTSTATUS close_status = NT_STATUS_OK; SMB_OFF_T startpos; char *data; - time_t mtime; + struct timespec mtime; files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBwriteclose); @@ -3233,7 +3232,7 @@ int reply_writeclose(connection_struct *conn, numtowrite = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2); - mtime = srv_make_unix_date3(inbuf+smb_vwv4); + mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4)); data = smb_buf(inbuf) + 1; if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) { @@ -3243,7 +3242,7 @@ int reply_writeclose(connection_struct *conn, nwritten = write_file(fsp,data,startpos,numtowrite); - set_filetime(conn, fsp->fsp_name,mtime); + set_filetime(conn, fsp->fsp_name, mtime); /* * More insanity. W2K only closes the file if writelen > 0. @@ -4724,7 +4723,7 @@ NTSTATUS copy_file(connection_struct *conn, close_file(fsp1,NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime); + fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf)); /* * As we are opening fsp1 read-only we only expect @@ -5536,7 +5535,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length, int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { - struct utimbuf unix_times; + struct timespec ts[2]; int outsize = 0; files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBsetattrE); @@ -5553,15 +5552,15 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, * time as UNIX can't set this. */ - unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3); - unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5); + ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */ + ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */ /* * Patch from Ray Frush * Sometimes times are sent as zero - ignore them. */ - if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) { + if (null_timespec(ts[0]) && null_timespec(ts[1])) { /* Ignore request */ if( DEBUGLVL( 3 ) ) { dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); @@ -5569,20 +5568,22 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, } END_PROFILE(SMBsetattrE); return(outsize); - } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) { + } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) { /* set modify time = to access time if modify time was unset */ - unix_times.modtime = unix_times.actime; + ts[1] = ts[0]; } /* Set the date on this file */ /* Should we set pending modtime here ? JRA */ - if(file_utime(conn, fsp->fsp_name, &unix_times)) { + if(file_ntimes(conn, fsp->fsp_name, ts)) { END_PROFILE(SMBsetattrE); return ERROR_DOS(ERRDOS,ERRnoaccess); } - DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n", - fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) ); + DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n", + fsp->fnum, + (unsigned int)ts[0].tv_sec, + (unsigned int)ts[1].tv_sec)); END_PROFILE(SMBsetattrE); return(outsize); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 33618360f19..41fd2c5102e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3175,18 +3175,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd allocation_size = get_allocation_size(conn,fsp,&sbuf); if (fsp) { - if (fsp->pending_modtime) { + if (!null_timespec(fsp->pending_modtime)) { /* the pending modtime overrides the current modtime */ - mtime_ts.tv_sec = fsp->pending_modtime; - mtime_ts.tv_nsec = 0; + mtime_ts = fsp->pending_modtime; } } else { /* Do we have this path open ? */ files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino); - if (fsp1 && fsp1->pending_modtime) { + if (fsp1 && !null_timespec(fsp1->pending_modtime)) { /* the pending modtime overrides the current modtime */ - mtime_ts.tv_sec = fsp1->pending_modtime; - mtime_ts.tv_nsec = 0; + mtime_ts = fsp->pending_modtime; } if (fsp1 && fsp1->initial_allocation_size) { allocation_size = get_allocation_size(conn, fsp1, &sbuf); @@ -3798,7 +3796,7 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, files_struct *fsp, const char *fname, const SMB_STRUCT_STAT *psbuf, - struct utimbuf tvs) + struct timespec ts[2]) { uint32 action = FILE_NOTIFY_CHANGE_LAST_ACCESS @@ -3810,26 +3808,30 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, } /* get some defaults (no modifications) if any info is zero or -1. */ - if (null_mtime(tvs.actime)) { - tvs.actime = psbuf->st_atime; + if (null_timespec(ts[0])) { + ts[0] = get_atimespec(psbuf); action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS; } - if (null_mtime(tvs.modtime)) { - tvs.modtime = psbuf->st_mtime; + if (null_timespec(ts[1])) { + ts[1] = get_mtimespec(psbuf); action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE; } - DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime))); - DEBUG(6,("smb_set_file_time: modtime: %s ", ctime(&tvs.modtime))); + DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) )); + DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) )); /* * Try and set the times of this file if * they are different from the current values. */ - if (psbuf->st_mtime == tvs.modtime && psbuf->st_atime == tvs.actime) { - return NT_STATUS_OK; + { + struct timespec mts = get_mtimespec(psbuf); + struct timespec ats = get_atimespec(psbuf); + if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) { + return NT_STATUS_OK; + } } if(fsp != NULL) { @@ -3843,15 +3845,16 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, * away and will set it on file close and after a write. JRA. */ - if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { - DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", ctime(&tvs.modtime) )); - fsp_set_pending_modtime(fsp, tvs.modtime); + if (!null_timespec(ts[1])) { + DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", + time_to_asc(convert_timespec_to_time_t(ts[1])) )); + fsp_set_pending_modtime(fsp, ts[1]); } } DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n")); - if(file_utime(conn, fname, &tvs)!=0) { + if(file_ntimes(conn, fname, ts)!=0) { return map_nt_error_from_unix(errno); } if (action != 0) { @@ -4459,16 +4462,16 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf) { - struct utimbuf tvs; + struct timespec ts[2]; if (total_data < 12) { return NT_STATUS_INVALID_PARAMETER; } /* access time */ - tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess); + ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess)); /* write time */ - tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite); + ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite)); DEBUG(10,("smb_set_info_standard: file %s\n", fname ? fname : fsp->fsp_name )); @@ -4477,7 +4480,7 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, fsp, fname, psbuf, - tvs); + ts); } /**************************************************************************** @@ -4492,10 +4495,10 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, SMB_STRUCT_STAT *psbuf) { /* Patch to do this correctly from Paul Eggert . */ - time_t write_time; - time_t changed_time; + struct timespec write_time; + struct timespec changed_time; uint32 dosmode = 0; - struct utimbuf tvs; + struct timespec ts[2]; NTSTATUS status = NT_STATUS_OK; if (total_data < 36) { @@ -4515,19 +4518,21 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, /* Ignore create time at offset pdata. */ /* access time */ - tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); + ts[0] = interpret_long_date(pdata+8); - write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16)); - changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24)); + write_time = interpret_long_date(pdata+16); + changed_time = interpret_long_date(pdata+24); - tvs.modtime = MIN(write_time, changed_time); + /* mtime */ + ts[1] = timespec_min(&write_time, &changed_time); - if (write_time > tvs.modtime && write_time != (time_t)-1) { - tvs.modtime = write_time; + if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) { + ts[1] = write_time; } + /* Prefer a defined time to an undefined one. */ - if (null_mtime(tvs.modtime)) { - tvs.modtime = null_mtime(write_time) ? changed_time : write_time; + if (null_timespec(ts[1])) { + ts[1] = null_timespec(write_time) ? changed_time : write_time; } DEBUG(10,("smb_set_file_basic_info: file %s\n", @@ -4537,7 +4542,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, fsp, fname, psbuf, - tvs); + ts); } /**************************************************************************** @@ -4751,7 +4756,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { - struct utimbuf tvs; + struct timespec ts[2]; uint32 raw_unixmode; mode_t unixmode; SMB_OFF_T size = 0; @@ -4778,8 +4783,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn, #endif /* LARGE_SMB_OFF_T */ } - tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+24)); /* access_time */ - tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+32)); /* modification_time */ + ts[0] = interpret_long_date(pdata+24); /* access_time */ + ts[1] = interpret_long_date(pdata+32); /* modification_time */ set_owner = (uid_t)IVAL(pdata,40); set_grp = (gid_t)IVAL(pdata,48); raw_unixmode = IVAL(pdata,84); @@ -4822,8 +4827,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", /* Ensure we don't try and change anything else. */ raw_unixmode = SMB_MODE_NO_CHANGE; size = get_file_size(*psbuf); - tvs.modtime = psbuf->st_mtime; - tvs.actime = psbuf->st_atime; + ts[0] = get_atimespec(psbuf); + ts[1] = get_mtimespec(psbuf); /* * We continue here as we might want to change the * owner uid/gid. @@ -4902,7 +4907,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", fsp, fname, psbuf, - tvs); + ts); } /**************************************************************************** @@ -5360,9 +5365,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char SSVAL(params,0,0); - if (fsp && fsp->pending_modtime) { + if (fsp && !null_timespec(fsp->pending_modtime)) { /* the pending modtime overrides the current modtime */ - sbuf.st_mtime = fsp->pending_modtime; + set_mtimespec(&sbuf, fsp->pending_modtime); } switch (info_level) { diff --git a/source3/utils/net_status.c b/source3/utils/net_status.c index c68c9f6e2fb..bfc30eac78a 100644 --- a/source3/utils/net_status.c +++ b/source3/utils/net_status.c @@ -104,7 +104,7 @@ static int show_share(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, d_printf("%-10.10s %s %-12s %s", crec.name,procid_str_static(&crec.pid), crec.machine, - time_to_asc(&crec.start)); + time_to_asc(crec.start)); return 0; } @@ -173,7 +173,7 @@ static int show_share_parseable(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, guest ? "" : gidtoname(ids->entries[i].gid), crec.machine, guest ? "" : ids->entries[i].hostname, - time_to_asc(&crec.start)); + time_to_asc(crec.start)); return 0; } diff --git a/source3/utils/status.c b/source3/utils/status.c index 4f66501511b..deba6a9523b 100644 --- a/source3/utils/status.c +++ b/source3/utils/status.c @@ -162,7 +162,7 @@ static void print_share_mode(const struct share_mode_entry *e, d_printf("NONE "); } - d_printf(" %s %s %s",sharepath, fname, time_to_asc((time_t *)&e->time.tv_sec)); + d_printf(" %s %s %s",sharepath, fname, time_to_asc((time_t)e->time.tv_sec)); } } @@ -207,7 +207,7 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st d_printf("%-10s %s %-12s %s", crec.name,procid_str_static(&crec.pid), crec.machine, - time_to_asc(&crec.start)); + time_to_asc(crec.start)); return 0; } diff --git a/source3/utils/status_profile.c b/source3/utils/status_profile.c index 9224fc176cb..b4c4940f3fd 100644 --- a/source3/utils/status_profile.c +++ b/source3/utils/status_profile.c @@ -113,8 +113,8 @@ BOOL status_profile_dump(BOOL verbose) d_printf("chdir_time: %u\n", profile_p->syscall_chdir_time); d_printf("getwd_count: %u\n", profile_p->syscall_getwd_count); d_printf("getwd_time: %u\n", profile_p->syscall_getwd_time); - d_printf("utime_count: %u\n", profile_p->syscall_utime_count); - d_printf("utime_time: %u\n", profile_p->syscall_utime_time); + d_printf("ntimes_count: %u\n", profile_p->syscall_ntimes_count); + d_printf("ntimes_time: %u\n", profile_p->syscall_ntimes_time); d_printf("ftruncate_count: %u\n", profile_p->syscall_ftruncate_count); d_printf("ftruncate_time: %u\n", profile_p->syscall_ftruncate_time); d_printf("fcntl_lock_count: %u\n", profile_p->syscall_fcntl_lock_count); diff --git a/source3/web/statuspage.c b/source3/web/statuspage.c index 459b679d817..a88e5debd0e 100644 --- a/source3/web/statuspage.c +++ b/source3/web/statuspage.c @@ -101,7 +101,7 @@ static char *mapPid2Machine (struct process_id pid) static char *tstring(time_t t) { static pstring buf; - pstrcpy(buf, time_to_asc(&t)); + pstrcpy(buf, time_to_asc(t)); all_string_sub(buf," "," ",sizeof(buf)); return buf; }