diff options
author | Gerald Carter <jerry@samba.org> | 2005-03-11 10:52:54 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2005-03-11 10:52:54 +0000 |
commit | 061a07f6b476428c622618d83a5a1e54c5f05fe5 (patch) | |
tree | 5e926c06e720253210687391b68aa82f553c9ad3 /source/smbd | |
parent | 6c30768e14f5639328e06a73940f133f9078b90e (diff) | |
download | samba-061a07f6b476428c622618d83a5a1e54c5f05fe5.tar.gz samba-061a07f6b476428c622618d83a5a1e54c5f05fe5.tar.xz samba-061a07f6b476428c622618d83a5a1e54c5f05fe5.zip |
r5739: sync for 3.0.12rc1 (current with SAMBA_3_0 r5738)
Diffstat (limited to 'source/smbd')
-rw-r--r-- | source/smbd/close.c | 4 | ||||
-rw-r--r-- | source/smbd/dir.c | 20 | ||||
-rw-r--r-- | source/smbd/fileio.c | 6 | ||||
-rw-r--r-- | source/smbd/files.c | 63 | ||||
-rw-r--r-- | source/smbd/nttrans.c | 14 | ||||
-rw-r--r-- | source/smbd/open.c | 11 | ||||
-rw-r--r-- | source/smbd/posix_acls.c | 16 | ||||
-rw-r--r-- | source/smbd/reply.c | 29 | ||||
-rw-r--r-- | source/smbd/service.c | 16 | ||||
-rw-r--r-- | source/smbd/trans2.c | 136 |
10 files changed, 226 insertions, 89 deletions
diff --git a/source/smbd/close.c b/source/smbd/close.c index 4445f2516bc..b3244432ff5 100644 --- a/source/smbd/close.c +++ b/source/smbd/close.c @@ -260,8 +260,10 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); * Ensure pending modtime is set after close. */ - if(fsp->pending_modtime) { + if(fsp->pending_modtime && fsp->pending_modtime_owner) { set_filetime(conn, fsp->fsp_name, fsp->pending_modtime); + } else if (fsp->last_write_time) { + set_filetime(conn, fsp->fsp_name, fsp->last_write_time); } DEBUG(2,("%s closed file %s (numopen=%d) %s\n", diff --git a/source/smbd/dir.c b/source/smbd/dir.c index 7dde18f4306..d9fd382d520 100644 --- a/source/smbd/dir.c +++ b/source/smbd/dir.c @@ -525,10 +525,17 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT pstring pathreal; ZERO_STRUCTP(pst); + if (dptr->has_wild) { return dptr_normal_ReadDirName(dptr, poffset, pst); } + /* If poffset is -1 then we know we returned this name before and we have + no wildcards. We're at the end of the directory. */ + if (*poffset == -1) { + return NULL; + } + /* We know the stored wcard contains no wildcard characters. See if we can match with a stat call. If we can't, then set has_wild to true to prevent us from doing this on every call. */ @@ -540,6 +547,9 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT } if (VALID_STAT(*pst)) { + /* We need to set the underlying dir_hdn offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = -1; return dptr->wcard; } @@ -548,11 +558,17 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT pstrcat(pathreal,dptr->wcard); if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) { + /* We need to set the underlying dir_hdn offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = -1; return dptr->wcard; } else { /* If we get any other error than ENOENT or ENOTDIR then the file exists we just can't stat it. */ if (errno != ENOENT && errno != ENOTDIR) { + /* We need to set the underlying dir_hdn offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = -1; return dptr->wcard; } } @@ -563,6 +579,9 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT with a stat we will fail. */ if (dptr->conn->case_sensitive) { + /* We need to set the underlying dir_hdn offset to -1 also as + this function is usually called with the output from TellDir. */ + dptr->dir_hnd->offset = *poffset = -1; return NULL; } else { return dptr_normal_ReadDirName(dptr, poffset, pst); @@ -1033,6 +1052,7 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) *poffset = e->offset= dirp->offset; return e->name; } + dirp->offset = -1; return NULL; } diff --git a/source/smbd/fileio.c b/source/smbd/fileio.c index a21bd69a36c..3048c27fa25 100644 --- a/source/smbd/fileio.c +++ b/source/smbd/fileio.c @@ -142,6 +142,12 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ if (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); + } } /* Yes - this is correct - writes don't update this. JRA. */ diff --git a/source/smbd/files.c b/source/smbd/files.c index ecf39c2b54f..143c1196937 100644 --- a/source/smbd/files.c +++ b/source/smbd/files.c @@ -37,6 +37,13 @@ static files_struct *oplock_save_chain_fsp = NULL; static int files_used; +/* A singleton cache to speed up searching by dev/inode. */ +static struct fsp_singleton_cache { + files_struct *fsp; + SMB_DEV_T dev; + SMB_INO_T inode; +} fsp_fi_cache; + /**************************************************************************** Return a unique number identifying this fsp over the life of this pid. ****************************************************************************/ @@ -122,6 +129,11 @@ files_struct *file_new(connection_struct *conn) i, fsp->fnum, files_used)); chain_fsp = fsp; + + /* A new fsp invalidates a negative fsp_fi_cache. */ + if (fsp_fi_cache.fsp == NULL) { + ZERO_STRUCT(fsp_fi_cache); + } return fsp; } @@ -299,19 +311,34 @@ files_struct *file_find_fsp(files_struct *orig_fsp) /**************************************************************************** Find the first fsp given a device and inode. + We use a singleton cache here to speed up searching from getfilepathinfo + calls. ****************************************************************************/ files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode) { files_struct *fsp; + if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) { + /* Positive or negative cache hit. */ + return fsp_fi_cache.fsp; + } + + fsp_fi_cache.dev = dev; + fsp_fi_cache.inode = inode; + for (fsp=Files;fsp;fsp=fsp->next) { if ( fsp->fd != -1 && fsp->dev == dev && - fsp->inode == inode ) + fsp->inode == inode ) { + /* Setup positive cache. */ + fsp_fi_cache.fsp = fsp; return fsp; + } } + /* Setup negative cache. */ + fsp_fi_cache.fsp = NULL; return NULL; } @@ -342,13 +369,40 @@ files_struct *file_find_print(void) files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next) { - if (fsp->print_file) return fsp; + if (fsp->print_file) { + return fsp; + } } return NULL; } /**************************************************************************** + Set a pending modtime across all files with a given dev/ino pair. + Record the owner of that modtime. +****************************************************************************/ + +void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod) +{ + files_struct *fsp; + + if (null_mtime(pmod)) { + return; + } + + for (fsp = Files;fsp;fsp=fsp->next) { + if ( fsp->fd != -1 && + fsp->dev == tfsp->dev && + fsp->inode == tfsp->inode ) { + fsp->pending_modtime = pmod; + fsp->pending_modtime_owner = False; + } + } + + tfsp->pending_modtime_owner = True; +} + +/**************************************************************************** Sync open files on a connection. ****************************************************************************/ @@ -392,6 +446,11 @@ void file_free(files_struct *fsp) chain_fsp = NULL; } + /* Closing a file can invalidate the positive cache. */ + if (fsp == fsp_fi_cache.fsp) { + ZERO_STRUCT(fsp_fi_cache); + } + SAFE_FREE(fsp); } diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c index 675da4c7478..fbb73640901 100644 --- a/source/smbd/nttrans.c +++ b/source/smbd/nttrans.c @@ -929,7 +929,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); #endif if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { - fsp->initial_allocation_size = allocation_size; + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -942,7 +942,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib return ERROR_NT(NT_STATUS_DISK_FULL); } } else { - fsp->initial_allocation_size = (SMB_BIG_UINT)file_len; + fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len); } /* @@ -1012,7 +1012,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, get_allocation_size(fsp,&sbuf)); + SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; @@ -1472,7 +1472,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); #endif if (allocation_size && (allocation_size > file_len)) { - fsp->initial_allocation_size = allocation_size; + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -1484,7 +1484,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o return ERROR_NT(NT_STATUS_DISK_FULL); } } else { - fsp->initial_allocation_size = (SMB_BIG_UINT)file_len; + fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len); } /* Realloc the size of parameters and data we will return */ @@ -1529,7 +1529,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o p += 8; SIVAL(p,0,fmode); /* File Attributes. */ p += 4; - SOFF_T(p, 0, get_allocation_size(fsp,&sbuf)); + SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; @@ -1698,7 +1698,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new close_file(fsp1,False); /* Ensure the modtime is set correctly on the destination file. */ - fsp2->pending_modtime = sbuf1.st_mtime; + fsp_set_pending_modtime(fsp2, sbuf1.st_mtime); close_ret = close_file(fsp2,False); diff --git a/source/smbd/open.c b/source/smbd/open.c index 70632a20eb7..a552dc5b610 100644 --- a/source/smbd/open.c +++ b/source/smbd/open.c @@ -491,9 +491,18 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadshare; unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + return False; + } +#if 0 + /* Bluarc test may need this ... needs further investigation. */ + if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; return False; } +#endif /* * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE @@ -502,7 +511,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) || !(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) { - DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with\ + DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with \ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access )); return True; } diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c index d02edc5ea06..c5f96db85c1 100644 --- a/source/smbd/posix_acls.c +++ b/source/smbd/posix_acls.c @@ -3903,10 +3903,26 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) if (current_user.uid == sbuf.st_uid) { return (sbuf.st_mode & S_IWUSR) ? True : False; } + +#ifdef S_ISVTX + /* sticky bit means delete only by owner or root. */ + if (sbuf.st_mode & S_ISVTX) { + SMB_STRUCT_STAT sbuf_file; + if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) { + return False; + } + if (current_user.uid == sbuf_file.st_uid) { + return True; + } + return False; + } +#endif + /* Check group ownership. */ ret = check_posix_acl_group_write(conn, dname, &sbuf); if (ret == 0 || ret == 1) { return ret ? True : False; } + return (sbuf.st_mode & S_IWOTH) ? True : False; } diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 89183aed347..f149b79f793 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -2876,6 +2876,13 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, conn->num_files_open)); /* + * Take care of any time sent in the close. + */ + + mtime = make_unix_date3(inbuf+smb_vwv1); + fsp_set_pending_modtime(fsp, mtime); + + /* * close_file() returns the unix errno if an error * was detected on close - normally this is due to * a disk full error. If not then it was probably an I/O error. @@ -2886,16 +2893,6 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, END_PROFILE(SMBclose); return (UNIXERROR(ERRHRD,ERRgeneral)); } - - /* - * Now take care of any time sent in the close. - */ - - mtime = make_unix_date3(inbuf+smb_vwv1); - - /* try and set the date */ - set_filetime(conn, file_name, mtime); - } /* We have a cached error */ @@ -4233,7 +4230,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, close_file(fsp1,False); /* Ensure the modtime is set correctly on the destination file. */ - fsp2->pending_modtime = src_sbuf.st_mtime; + fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime); /* * As we are opening fsp1 read-only we only expect @@ -4917,7 +4914,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, * Sometimes times are sent as zero - ignore them. */ - if ((unix_times.actime == 0) && (unix_times.modtime == 0)) { + if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) { /* Ignore request */ if( DEBUGLVL( 3 ) ) { dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); @@ -4925,12 +4922,13 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, } END_PROFILE(SMBsetattrE); return(outsize); - } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) { - /* set modify time = to access time if modify time was 0 */ + } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) { + /* set modify time = to access time if modify time was unset */ unix_times.modtime = unix_times.actime; } /* Set the date on this file */ + /* Should we set pending modtime here ? JRA */ if(file_utime(conn, fsp->fsp_name, &unix_times)) { END_PROFILE(SMBsetattrE); return ERROR_DOS(ERRDOS,ERRnoaccess); @@ -5170,13 +5168,14 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)))); put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); + /* Should we check pending modtime here ? JRA */ put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); if (mode & aDIR) { SIVAL(outbuf,smb_vwv6,0); SIVAL(outbuf,smb_vwv8,0); } else { - uint32 allocation_size = get_allocation_size(fsp, &sbuf); + uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf); SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); SIVAL(outbuf,smb_vwv8,allocation_size); } diff --git a/source/smbd/service.c b/source/smbd/service.c index f199fe3ade6..684d49c56ae 100644 --- a/source/smbd/service.c +++ b/source/smbd/service.c @@ -278,6 +278,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *user = 0; fstrcpy(dev, pdev); + ZERO_STRUCT(st); if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) { return NULL; @@ -605,24 +606,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } #endif -#if CHECK_PATH_ON_TCONX /* win2000 does not check the permissions on the directory during the tree connect, instead relying on permission check during individual operations. To match this behaviour I have disabled this chdir check (tridge) */ - if (vfs_ChDir(conn,conn->connectpath) != 0) { - DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n", - get_remote_machine_name(), conn->client_address, - conn->connectpath,strerror(errno))); - change_to_root_user(); - yield_connection(conn, lp_servicename(SNUM(conn))); - conn_free(conn); - *status = NT_STATUS_BAD_NETWORK_NAME; - return NULL; - } -#else /* the alternative is just to check the directory exists */ - if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { + if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); @@ -630,7 +619,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, *status = NT_STATUS_BAD_NETWORK_NAME; return NULL; } -#endif string_set(&conn->origpath,conn->connectpath); diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index d22705214e4..3f3d9c2f461 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -33,11 +33,28 @@ extern struct current_user current_user; #define DIR_ENTRY_SAFETY_MARGIN 4096 /******************************************************************** + Roundup a value to the nearest allocation roundup size boundary. + Only do this for Windows clients. +********************************************************************/ + +SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val) +{ + SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn)); + + /* Only roundup for Windows clients. */ + enum remote_arch_types ra_type = get_remote_arch(); + if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) { + val = SMB_ROUNDUP(val,rval); + } + return val; +} + +/******************************************************************** Given a stat buffer return the allocated size on disk, taking into account sparse files. ********************************************************************/ -SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) +SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf) { SMB_BIG_UINT ret; @@ -50,7 +67,7 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf) if (!ret && fsp && fsp->initial_allocation_size) ret = fsp->initial_allocation_size; - return ret; + return smb_roundup(conn, ret); } /**************************************************************************** @@ -794,7 +811,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, BOOL dont_descend,char **ppdata, char *base_data, int space_remaining, BOOL *out_of_space, BOOL *got_exact_match, - int *last_name_off) + int *last_entry_off) { const char *dname; BOOL found = False; @@ -811,6 +828,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint32 len; time_t mdate=0, adate=0, cdate=0; char *nameptr; + char *last_entry_ptr; BOOL was_8_3; int nt_extmode; /* Used for NT connections instead of mode */ BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); @@ -919,7 +937,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, } file_size = get_file_size(sbuf); - allocation_size = get_allocation_size(NULL,&sbuf); + allocation_size = get_allocation_size(conn,NULL,&sbuf); mdate = sbuf.st_mtime; adate = sbuf.st_atime; cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); @@ -947,7 +965,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, mangle_map(fname,False,True,SNUM(conn)); p = pdata; - nameptr = p; + last_entry_ptr = p; nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; @@ -1215,7 +1233,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */ p+= 8; - SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */ + SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */ p+= 8; put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */ @@ -1277,8 +1295,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, return False; /* Not finished - just out of space */ } - /* Setup the last_filename pointer, as an offset from base_data */ - *last_name_off = PTR_DIFF(nameptr,base_data); + /* Setup the last entry pointer, as an offset from base_data */ + *last_entry_off = PTR_DIFF(last_entry_ptr,base_data); /* Advance the data pointer to the next slot */ *ppdata = p; @@ -1310,7 +1328,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb pstring directory; pstring mask; char *p; - int last_name_off=0; + int last_entry_off=0; int dptr_num = -1; int numentries = 0; int i; @@ -1360,7 +1378,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(ntstatus); } - RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); + RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); unix_convert(directory,conn,0,&bad_path,&sbuf); if (bad_path) { @@ -1437,7 +1455,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_name_off); + &last_entry_off); } if (finished && out_of_space) @@ -1482,7 +1500,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", SSVAL(params,2,numentries); SSVAL(params,4,finished); SSVAL(params,6,0); /* Never an EA error */ - SSVAL(params,8,last_name_off); + SSVAL(params,8,last_entry_off); send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata)); @@ -1537,7 +1555,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu char *p; uint16 dirtype; int numentries = 0; - int i, last_name_off=0; + int i, last_entry_off=0; BOOL finished = False; BOOL dont_descend = False; BOOL out_of_space = False; @@ -1674,7 +1692,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_name_off); + &last_entry_off); } if (finished && out_of_space) @@ -1706,7 +1724,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", SSVAL(params,0,numentries); SSVAL(params,2,finished); SSVAL(params,4,0); /* Never an EA error */ - SSVAL(params,6,last_name_off); + SSVAL(params,6,last_entry_off); send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata)); @@ -2422,7 +2440,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * fullpathname = fname; file_size = get_file_size(sbuf); - allocation_size = get_allocation_size(fsp,&sbuf); + allocation_size = get_allocation_size(conn,fsp,&sbuf); if (mode & aDIR) { /* This is necessary, as otherwise the desktop.ini file in * this folder is ignored */ @@ -2451,9 +2469,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); - if (fsp && fsp->pending_modtime) { - /* the pending modtime overrides the current modtime */ - sbuf.st_mtime = fsp->pending_modtime; + if (fsp) { + if (fsp->pending_modtime) { + /* the pending modtime overrides the current modtime */ + sbuf.st_mtime = 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) { + /* the pending modtime overrides the current modtime */ + sbuf.st_mtime = fsp1->pending_modtime; + } } if (lp_dos_filetime_resolution(SNUM(conn))) { @@ -2768,7 +2795,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */ pdata += 8; - SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */ + SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */ pdata += 8; put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */ @@ -3305,9 +3332,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char tvs.modtime = write_time; } /* Prefer a defined time to an undefined one. */ - if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) - tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1 - ? changed_time : write_time); + if (null_mtime(tvs.modtime)) { + tvs.modtime = null_mtime(write_time) ? changed_time : write_time; + } /* attributes */ dosmode = IVAL(pdata,32); @@ -3333,6 +3360,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n", fname, (double)allocation_size )); + if (allocation_size) { + allocation_size = smb_roundup(conn, allocation_size); + } + if(allocation_size != get_file_size(sbuf)) { SMB_STRUCT_STAT new_sbuf; @@ -3783,11 +3814,13 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } /* get some defaults (no modifications) if any info is zero or -1. */ - if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1) + if (null_mtime(tvs.actime)) { tvs.actime = sbuf.st_atime; + } - if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1) + if (null_mtime(tvs.modtime)) { tvs.modtime = sbuf.st_mtime; + } DEBUG(6,("actime: %s " , ctime(&tvs.actime))); DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); @@ -3819,30 +3852,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", * Try and set the times, size and mode of this file - * if they are different from the current values */ - if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) { - if(fsp != NULL) { - /* - * This was a setfileinfo on an open file. - * NT does this a lot. We also need to - * set the time here, as it can be read by - * FindFirst/FindNext and with the patch for bug #2045 - * in smbd/fileio.c it ensures that this timestamp is - * kept sticky even after a write. We save the request - * 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,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) )); - fsp->pending_modtime = tvs.modtime; - } - - DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n")); - - if(file_utime(conn, fname, &tvs)!=0) { - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - } - } /* check the mode isn't different, before changing it */ if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) { @@ -3855,6 +3864,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } } + /* Now the size. */ if (size != get_file_size(sbuf)) { int ret; @@ -3895,6 +3905,34 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return (UNIXERROR(ERRHRD,ERRdiskfull)); } + /* + * Finally the times. + */ + if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) { + if(fsp != NULL) { + /* + * This was a setfileinfo on an open file. + * NT does this a lot. We also need to + * set the time here, as it can be read by + * FindFirst/FindNext and with the patch for bug #2045 + * in smbd/fileio.c it ensures that this timestamp is + * kept sticky even after a write. We save the request + * 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,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) )); + fsp_set_pending_modtime(fsp, tvs.modtime); + } + + } + DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n")); + + if(file_utime(conn, fname, &tvs)!=0) { + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + } + SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); |