summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2001-10-19 00:56:03 +0000
committerJeremy Allison <jra@samba.org>2001-10-19 00:56:03 +0000
commit6cc3953196e3feb340f7b9b7bb823575414c5683 (patch)
tree28bf3943f76f952a8c2bb38e47dc22cadf38fffb
parentb49b5b94818827da43dee53346ced84c789fd73d (diff)
downloadsamba-6cc3953196e3feb340f7b9b7bb823575414c5683.tar.gz
samba-6cc3953196e3feb340f7b9b7bb823575414c5683.tar.bz2
samba-6cc3953196e3feb340f7b9b7bb823575414c5683.zip
Restored old Bmpx code - actually used by OS/2.
Jeremy. (This used to be commit 7c1688fd67c1bda1477aaf870371c825280db870)
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/include/smb_macros.h12
-rw-r--r--source3/smbd/error.c16
-rw-r--r--source3/smbd/process.c8
-rw-r--r--source3/smbd/reply.c304
5 files changed, 280 insertions, 61 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index a805407b9f..fba08aed43 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -401,6 +401,7 @@ typedef struct files_struct
SMB_OFF_T size;
mode_t mode;
uint16 vuid;
+ write_bmpx_struct *wbmpx_ptr;
write_cache *wcp;
struct timeval open_time;
int share_mode;
diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h
index b4264937cf..05a358573d 100644
--- a/source3/include/smb_macros.h
+++ b/source3/include/smb_macros.h
@@ -82,6 +82,9 @@
#define CHECK_WRITE(fsp) if (!(fsp)->can_write) \
return(ERROR_DOS(ERRDOS,ERRbadaccess))
+#define CHECK_ERROR(fsp) if (HAS_CACHED_ERROR(fsp)) \
+ return(CACHED_ERROR(fsp))
+
/* translates a connection number into a service number */
#define SNUM(conn) ((conn)?(conn)->service:-1)
@@ -136,6 +139,15 @@
#define SMB_LARGE_LKLEN_OFFSET_HIGH(indx) (12 + (20 * (indx)))
#define SMB_LARGE_LKLEN_OFFSET_LOW(indx) (16 + (20 * (indx)))
+/* Macro to cache an error in a write_bmpx_struct */
+#define CACHE_ERROR(w,c,e) ((w)->wr_errclass = (c), (w)->wr_error = (e), \
+ w->wr_discard = True, -1)
+/* Macro to test if an error has been cached for this fnum */
+#define HAS_CACHED_ERROR(fsp) ((fsp)->wbmpx_ptr && \
+ (fsp)->wbmpx_ptr->wr_discard)
+/* Macro to turn the cached error into an error packet */
+#define CACHED_ERROR(fsp) cached_error_packet(outbuf,fsp,__LINE__,__FILE__)
+
/* these are the datagram types */
#define DGRAM_DIRECT_UNIQUE 0x10
diff --git a/source3/smbd/error.c b/source3/smbd/error.c
index 913f2ac266..3c829deb09 100644
--- a/source3/smbd/error.c
+++ b/source3/smbd/error.c
@@ -25,6 +25,22 @@
int unix_ERR_class=SMB_SUCCESS;
int unix_ERR_code=0;
+/****************************************************************************
+ Create an error packet from a cached error.
+****************************************************************************/
+
+int cached_error_packet(char *outbuf,files_struct *fsp,int line,const char *file)
+{
+ write_bmpx_struct *wbmpx = fsp->wbmpx_ptr;
+
+ int32 eclass = wbmpx->wr_errclass;
+ int32 err = wbmpx->wr_error;
+
+ /* We can now delete the auxiliary struct */
+ free((char *)wbmpx);
+ fsp->wbmpx_ptr = NULL;
+ return error_packet(outbuf,NT_STATUS_OK,eclass,err,line,file);
+}
struct
{
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index edcb6b345f..a0bfdbb2a2 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -361,11 +361,11 @@ struct smb_message_struct
/* 0x19 */ { NULL, NULL, 0 },
/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
-/* 0x1c */ { "SMBreadBs",NULL,AS_USER},
+/* 0x1c */ { "SMBreadBs",NULL,0 },
/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
-/* 0x1e */ { NULL,NULL,0},
-/* 0x1f */ { NULL,NULL,0},
-/* 0x20 */ { NULL,NULL,0},
+/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
+/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
+/* 0x20 */ { "SMBwritec",NULL,0},
/* 0x21 */ { NULL, NULL, 0 },
/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 8b6e754549..845fabda92 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3786,84 +3786,83 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
return chain_reply(inbuf,outbuf,length,bufsize);
}
-
/****************************************************************************
- reply to a SMBreadbmpx (read block multiplex) request
+ Reply to a SMBreadbmpx (read block multiplex) request.
****************************************************************************/
+
int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
- ssize_t nread = -1;
- ssize_t total_read;
- char *data;
- SMB_OFF_T startpos;
- int outsize;
- size_t maxcount;
- int max_per_packet;
- size_t tcount;
- int pad;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBreadBmpx);
+ ssize_t nread = -1;
+ ssize_t total_read;
+ char *data;
+ SMB_OFF_T startpos;
+ int outsize;
+ size_t maxcount;
+ int max_per_packet;
+ size_t tcount;
+ int pad;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBreadBmpx);
- /* this function doesn't seem to work - disable by default */
- if (!lp_readbmpx()) {
- END_PROFILE(SMBreadBmpx);
- return ERROR_DOS(ERRSRV,ERRuseSTD);
- }
+ /* this function doesn't seem to work - disable by default */
+ if (!lp_readbmpx()) {
+ END_PROFILE(SMBreadBmpx);
+ return ERROR_DOS(ERRSRV,ERRuseSTD);
+ }
- outsize = set_message(outbuf,8,0,True);
+ outsize = set_message(outbuf,8,0,True);
- CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ CHECK_FSP(fsp,conn);
+ CHECK_READ(fsp);
- startpos = IVAL(inbuf,smb_vwv1);
- maxcount = SVAL(inbuf,smb_vwv3);
+ startpos = IVAL(inbuf,smb_vwv1);
+ maxcount = SVAL(inbuf,smb_vwv3);
- data = smb_buf(outbuf);
- pad = ((long)data)%4;
- if (pad) pad = 4 - pad;
- data += pad;
+ data = smb_buf(outbuf);
+ pad = ((long)data)%4;
+ if (pad)
+ pad = 4 - pad;
+ data += pad;
- max_per_packet = bufsize-(outsize+pad);
- tcount = maxcount;
- total_read = 0;
+ max_per_packet = bufsize-(outsize+pad);
+ tcount = maxcount;
+ total_read = 0;
- if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
- END_PROFILE(SMBreadBmpx);
- return ERROR_DOS(ERRDOS,ERRlock);
- }
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+ END_PROFILE(SMBreadBmpx);
+ return ERROR_DOS(ERRDOS,ERRlock);
+ }
- do
- {
- size_t N = MIN(max_per_packet,tcount-total_read);
+ do {
+ size_t N = MIN(max_per_packet,tcount-total_read);
- nread = read_file(fsp,data,startpos,N);
+ nread = read_file(fsp,data,startpos,N);
- if (nread <= 0) nread = 0;
+ if (nread <= 0)
+ nread = 0;
- if (nread < (ssize_t)N)
- tcount = total_read + nread;
+ if (nread < (ssize_t)N)
+ tcount = total_read + nread;
- set_message(outbuf,8,nread,False);
- SIVAL(outbuf,smb_vwv0,startpos);
- SSVAL(outbuf,smb_vwv2,tcount);
- SSVAL(outbuf,smb_vwv6,nread);
- SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
+ set_message(outbuf,8,nread,False);
+ SIVAL(outbuf,smb_vwv0,startpos);
+ SSVAL(outbuf,smb_vwv2,tcount);
+ SSVAL(outbuf,smb_vwv6,nread);
+ SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_readbmpx: send_smb failed.\n");
+ if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server("reply_readbmpx: send_smb failed.\n");
- total_read += nread;
- startpos += nread;
- }
- while (total_read < (ssize_t)tcount);
+ total_read += nread;
+ startpos += nread;
+ } while (total_read < (ssize_t)tcount);
- END_PROFILE(SMBreadBmpx);
- return(-1);
+ END_PROFILE(SMBreadBmpx);
+ return(-1);
}
-
/****************************************************************************
- reply to a SMBsetattrE
+ Reply to a SMBsetattrE.
****************************************************************************/
int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
@@ -3919,8 +3918,199 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
}
+/* Back from the dead for OS/2..... JRA. */
+
+/****************************************************************************
+ Reply to a SMBwritebmpx (write block multiplex primary) request.
+****************************************************************************/
+
+int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
+{
+ size_t numtowrite;
+ ssize_t nwritten = -1;
+ int outsize = 0;
+ SMB_OFF_T startpos;
+ size_t tcount;
+ BOOL write_through;
+ int smb_doff;
+ char *data;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBwriteBmpx);
+
+ CHECK_FSP(fsp,conn);
+ CHECK_WRITE(fsp);
+ CHECK_ERROR(fsp);
+
+ tcount = SVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv3);
+ write_through = BITSETW(inbuf+smb_vwv7,0);
+ numtowrite = SVAL(inbuf,smb_vwv10);
+ smb_doff = SVAL(inbuf,smb_vwv11);
+
+ data = smb_base(inbuf) + smb_doff;
+
+ /* If this fails we need to send an SMBwriteC response,
+ not an SMBwritebmpx - set this up now so we don't forget */
+ CVAL(outbuf,smb_com) = SMBwritec;
+
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
+ END_PROFILE(SMBwriteBmpx);
+ return(ERROR_DOS(ERRDOS,ERRlock));
+ }
+
+ nwritten = write_file(fsp,data,startpos,numtowrite);
+
+ if(lp_syncalways(SNUM(conn)) || write_through)
+ sync_file(conn,fsp);
+
+ if(nwritten < (ssize_t)numtowrite) {
+ END_PROFILE(SMBwriteBmpx);
+ return(UNIXERROR(ERRHRD,ERRdiskfull));
+ }
+
+ /* If the maximum to be written to this file
+ is greater than what we just wrote then set
+ up a secondary struct to be attached to this
+ fd, we will use this to cache error messages etc. */
+
+ if((ssize_t)tcount > nwritten) {
+ write_bmpx_struct *wbms;
+ if(fsp->wbmpx_ptr != NULL)
+ wbms = fsp->wbmpx_ptr; /* Use an existing struct */
+ else
+ wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
+ if(!wbms) {
+ DEBUG(0,("Out of memory in reply_readmpx\n"));
+ END_PROFILE(SMBwriteBmpx);
+ return(ERROR_DOS(ERRSRV,ERRnoresource));
+ }
+ wbms->wr_mode = write_through;
+ wbms->wr_discard = False; /* No errors yet */
+ wbms->wr_total_written = nwritten;
+ wbms->wr_errclass = 0;
+ wbms->wr_error = 0;
+ fsp->wbmpx_ptr = wbms;
+ }
+
+ /* We are returning successfully, set the message type back to
+ SMBwritebmpx */
+ CVAL(outbuf,smb_com) = SMBwriteBmpx;
+
+ outsize = set_message(outbuf,1,0,True);
+
+ SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
+
+ DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
+ fsp->fnum, (int)numtowrite, (int)nwritten ) );
+
+ if (write_through && tcount==nwritten) {
+ /* We need to send both a primary and a secondary response */
+ smb_setlen(outbuf,outsize - 4);
+ if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server("reply_writebmpx: send_smb failed.\n");
+
+ /* Now the secondary */
+ outsize = set_message(outbuf,1,0,True);
+ CVAL(outbuf,smb_com) = SMBwritec;
+ SSVAL(outbuf,smb_vwv0,nwritten);
+ }
+
+ END_PROFILE(SMBwriteBmpx);
+ return(outsize);
+}
+
+/****************************************************************************
+ Reply to a SMBwritebs (write block multiplex secondary) request.
+****************************************************************************/
+
+int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+{
+ size_t numtowrite;
+ ssize_t nwritten = -1;
+ int outsize = 0;
+ SMB_OFF_T startpos;
+ size_t tcount;
+ BOOL write_through;
+ int smb_doff;
+ char *data;
+ write_bmpx_struct *wbms;
+ BOOL send_response = False;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBwriteBs);
+
+ CHECK_FSP(fsp,conn);
+ CHECK_WRITE(fsp);
+
+ tcount = SVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv2);
+ numtowrite = SVAL(inbuf,smb_vwv6);
+ smb_doff = SVAL(inbuf,smb_vwv7);
+
+ data = smb_base(inbuf) + smb_doff;
+
+ /* We need to send an SMBwriteC response, not an SMBwritebs */
+ CVAL(outbuf,smb_com) = SMBwritec;
+
+ /* This fd should have an auxiliary struct attached,
+ check that it does */
+ wbms = fsp->wbmpx_ptr;
+ if(!wbms) {
+ END_PROFILE(SMBwriteBs);
+ return(-1);
+ }
+
+ /* If write through is set we can return errors, else we must cache them */
+ write_through = wbms->wr_mode;
+
+ /* Check for an earlier error */
+ if(wbms->wr_discard) {
+ END_PROFILE(SMBwriteBs);
+ return -1; /* Just discard the packet */
+ }
+
+ nwritten = write_file(fsp,data,startpos,numtowrite);
+
+ if(lp_syncalways(SNUM(conn)) || write_through)
+ sync_file(conn,fsp);
+
+ if (nwritten < (ssize_t)numtowrite) {
+ if(write_through) {
+ /* We are returning an error - we can delete the aux struct */
+ if (wbms)
+ free((char *)wbms);
+ fsp->wbmpx_ptr = NULL;
+ END_PROFILE(SMBwriteBs);
+ return(ERROR_DOS(ERRHRD,ERRdiskfull));
+ }
+ END_PROFILE(SMBwriteBs);
+ return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
+ }
+
+ /* Increment the total written, if this matches tcount
+ we can discard the auxiliary struct (hurrah !) and return a writeC */
+ wbms->wr_total_written += nwritten;
+ if(wbms->wr_total_written >= tcount) {
+ if (write_through) {
+ outsize = set_message(outbuf,1,0,True);
+ SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
+ send_response = True;
+ }
+
+ free((char *)wbms);
+ fsp->wbmpx_ptr = NULL;
+ }
+
+ if(send_response) {
+ END_PROFILE(SMBwriteBs);
+ return(outsize);
+ }
+
+ END_PROFILE(SMBwriteBs);
+ return(-1);
+}
+
/****************************************************************************
- reply to a SMBgetattrE
+ Reply to a SMBgetattrE.
****************************************************************************/
int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)