diff options
author | Jeremy Allison <jra@samba.org> | 2007-03-05 23:40:03 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:18:24 -0500 |
commit | 4952fe368a40b239140b3035db6075427d237bb9 (patch) | |
tree | 4522aa1bd6ec5f4b627aa7fa2868297e4dcea99f /source3/smbd | |
parent | 242927bd5cae1d2ab8739b1c424e702ab97726b5 (diff) | |
download | samba-4952fe368a40b239140b3035db6075427d237bb9.tar.gz samba-4952fe368a40b239140b3035db6075427d237bb9.tar.bz2 samba-4952fe368a40b239140b3035db6075427d237bb9.zip |
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)
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/close.c | 4 | ||||
-rw-r--r-- | source3/smbd/dosmode.c | 36 | ||||
-rw-r--r-- | source3/smbd/fileio.c | 4 | ||||
-rw-r--r-- | source3/smbd/files.c | 6 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 2 | ||||
-rw-r--r-- | source3/smbd/reply.c | 43 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 91 |
7 files changed, 99 insertions, 87 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 50111f62bb..1c9f6ea8c4 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 ad79bbacdd..71d4fa179d 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 e0945be889..65238c0e9e 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 0706548334..062bebd58e 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 968c536caf..eedc3cfba4 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 25c2aaa4dc..df560390c9 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 <frush@engr.colostate.edu> * 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 33618360f1..41fd2c5102 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 <eggert@twinsun.com>. */ - 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) { |