summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2003-08-14 21:16:06 +0000
committerJeremy Allison <jra@samba.org>2003-08-14 21:16:06 +0000
commit4e8b36a5749f4801022617b8fec1fe5d48529fef (patch)
tree8075e7b7c5ca55b0ae5e82fe9fc9de9b551763fb /source3/smbd
parent11777e6a3085a996ab2c5fa3db34d8834401c24e (diff)
downloadsamba-4e8b36a5749f4801022617b8fec1fe5d48529fef.tar.gz
samba-4e8b36a5749f4801022617b8fec1fe5d48529fef.tar.bz2
samba-4e8b36a5749f4801022617b8fec1fe5d48529fef.zip
Fix SMBseek and get/set position information SMBs. Works against
Samba4 tester. You will need a make clean; make all after this ! Jeremy. (This used to be commit 10d90171ed58bee3e5ab6476341059b585034134)
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/fileio.c22
-rw-r--r--source3/smbd/open.c3
-rw-r--r--source3/smbd/reply.c33
-rw-r--r--source3/smbd/trans2.c25
4 files changed, 51 insertions, 32 deletions
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 6be5f6af7d..6cf7014846 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -87,8 +87,11 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n)
* Serve from write cache if we can.
*/
- if(read_from_write_cache(fsp, data, pos, n))
+ if(read_from_write_cache(fsp, data, pos, n)) {
+ fsp->pos = pos + n;
+ fsp->position_information = fsp->pos;
return n;
+ }
flush_write_cache(fsp, READ_FLUSH);
@@ -123,6 +126,9 @@ tryagain:
DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n",
fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));
+ fsp->pos += ret;
+ fsp->position_information = fsp->pos;
+
return(ret);
}
@@ -145,6 +151,16 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_
DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n",
fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));
+ if (ret != -1) {
+ fsp->pos += ret;
+
+/* Yes - this is correct - writes don't update this. JRA. */
+/* Found by Samba4 tests. */
+#if 0
+ fsp->position_information = fsp->pos;
+#endif
+ }
+
return ret;
}
@@ -244,7 +260,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
if(!wcp) {
DO_PROFILE_INC(writecache_direct_writes);
total_written = real_write_file(fsp, data, pos, n);
- if ((total_written != -1) && (pos + total_written > (SMB_OFF_T)fsp->size))
+ if ((total_written != -1) && (pos + total_written > (SMB_OFF_T)fsp->size))
fsp->size = (SMB_BIG_UINT)(pos + total_written);
return total_written;
}
@@ -252,6 +268,8 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n",
fsp->fsp_name, fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size));
+ fsp->pos = pos + n;
+
/*
* If we have active cache and it isn't contiguous then we flush.
* NOTE: There is a small problem with running out of disk ....
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 2c9d3290d8..06f1ddfcf2 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -227,7 +227,6 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
fsp->dev = psbuf->st_dev;
fsp->vuid = current_user.vuid;
fsp->size = psbuf->st_size;
- fsp->pos = -1;
fsp->can_lock = True;
fsp->can_read = ((flags & O_WRONLY)==0);
fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
@@ -1362,7 +1361,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST
fsp->dev = psbuf->st_dev;
fsp->size = psbuf->st_size;
fsp->vuid = current_user.vuid;
- fsp->pos = -1;
fsp->can_lock = True;
fsp->can_read = False;
fsp->can_write = False;
@@ -1425,7 +1423,6 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST
fsp->dev = (SMB_DEV_T)0;
fsp->size = psbuf->st_size;
fsp->vuid = current_user.vuid;
- fsp->pos = -1;
fsp->can_lock = False;
fsp->can_read = False;
fsp->can_write = False;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 8347daf26b..8df118ab16 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2308,39 +2308,25 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
switch (mode) {
case 0:
umode = SEEK_SET;
+ res = startpos;
break;
case 1:
umode = SEEK_CUR;
+ res = fsp->pos + startpos;
break;
case 2:
umode = SEEK_END;
break;
default:
umode = SEEK_SET;
+ res = startpos;
break;
}
- if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
- /*
- * Check for the special case where a seek before the start
- * of the file sets the offset to zero. Added in the CIFS spec,
- * section 4.2.7.
- */
-
- if(errno == EINVAL) {
- SMB_OFF_T current_pos = startpos;
-
- if(umode == SEEK_CUR) {
-
- if((current_pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
- END_PROFILE(SMBlseek);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- current_pos += startpos;
-
- } else if (umode == SEEK_END) {
-
+ if (umode == SEEK_END) {
+ if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
+ if(errno == EINVAL) {
+ SMB_OFF_T current_pos = startpos;
SMB_STRUCT_STAT sbuf;
if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
@@ -2349,10 +2335,9 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
}
current_pos += sbuf.st_size;
+ if(current_pos < 0)
+ res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
}
-
- if(current_pos < 0)
- res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
}
if(res == -1) {
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index f81486b1ad..8adac1930f 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1821,9 +1821,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
return(UNIXERROR(ERRDOS,ERRbadfid));
}
- if((pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1)
- return(UNIXERROR(ERRDOS,ERRnoaccess));
-
+ pos = fsp->position_information;
delete_pending = fsp->delete_on_close;
}
} else {
@@ -2702,6 +2700,27 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
break;
}
+ case SMB_FILE_POSITION_INFORMATION:
+ {
+ SMB_BIG_UINT position_information;
+
+ if (total_data < 8)
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+ position_information = (SMB_BIG_UINT)IVAL(pdata,0);
+#ifdef LARGE_SMB_OFF_T
+ position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
+#else /* LARGE_SMB_OFF_T */
+ if (IVAL(pdata,4) != 0) /* more than 32 bits? */
+ return ERROR_DOS(ERRDOS,ERRunknownlevel);
+#endif /* LARGE_SMB_OFF_T */
+ DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
+ fname, (double)position_information ));
+ if (fsp)
+ fsp->position_information = position_information;
+ break;
+ }
+
/*
* CIFS UNIX extensions.
*/