summaryrefslogtreecommitdiffstats
path: root/source/smbd
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-03-11 10:52:54 +0000
committerGerald Carter <jerry@samba.org>2005-03-11 10:52:54 +0000
commit061a07f6b476428c622618d83a5a1e54c5f05fe5 (patch)
tree5e926c06e720253210687391b68aa82f553c9ad3 /source/smbd
parent6c30768e14f5639328e06a73940f133f9078b90e (diff)
downloadsamba-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.c4
-rw-r--r--source/smbd/dir.c20
-rw-r--r--source/smbd/fileio.c6
-rw-r--r--source/smbd/files.c63
-rw-r--r--source/smbd/nttrans.c14
-rw-r--r--source/smbd/open.c11
-rw-r--r--source/smbd/posix_acls.c16
-rw-r--r--source/smbd/reply.c29
-rw-r--r--source/smbd/service.c16
-rw-r--r--source/smbd/trans2.c136
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);