/* * Send a request and place it on the recvq if successfully sent. * Must be called with the server lock held. */ static int smb_request_send_req(struct smb_request *req) { struct smb_sb_info *server = req->rq_server; int result; if (req->rq_bytes_sent == 0) { WSET(req->rq_header, smb_tid, server->opt.tid); WSET(req->rq_header, smb_pid, 1); WSET(req->rq_header, smb_uid, server->opt.server_uid); } result = smb_send_request(req); if (result < 0 && result != -EAGAIN) goto out; result = 0; if (!(req->rq_flags & SMB_REQ_TRANSMITTED)) goto out; list_del_init(&req->rq_queue); list_add_tail(&req->rq_queue, &server->recvq); result = 1; out: return result; }
static int connect (Display *dpy, Window win,GC gcc, float c, int nx, float *x, int ny, float *y, float *z, int *pcell, float *pxd, float *pyd,float *x0, float *y0) /* connect draws a line from one intersection of the cell(ix,iy) = z[*pcell] to another intersection of the cell, provided the latter intersection exists, and then clears the latter intersection and updates the cell pointer connect returns 0 if the latter intersection does not exist or if the latter intersection is a grid boundary; otherwise returns 1. */ { int cell= *pcell, ix=cell%nx, iy=cell/nx; float d; /* if exiting north */ if (SSET(z[cell+nx])) { cell += nx; iy++; d = DELTA(c,z[cell],z[cell+1]); *pxd = (1.0-d)*x[ix]+d*x[ix+1]; *pyd = y[iy]; XDrawLine(dpy,win,gcc,NINT(*x0),NINT(*y0), NINT(*pxd),NINT(*pyd)); CLRS(z[cell]); *pcell = cell; if (iy<ny-1) return(1); else return(0); /* else if exiting east */ } else if (WSET(z[cell+1])) { cell += 1; ix++; d = DELTA(c,z[cell],z[cell+nx]); *pxd = x[ix]; *pyd = (1.0-d)*y[iy]+d*y[iy+1]; XDrawLine(dpy,win,gcc,NINT(*x0),NINT(*y0), NINT(*pxd),NINT(*pyd)); CLRW(z[cell]); *pcell = cell; if (ix<nx-1) return(1); else return(0); /* else if exiting south */ } else if (SSET(z[cell])) { d = DELTA(c,z[cell],z[cell+1]); *pxd = (1.0-d)*x[ix]+d*x[ix+1]; *pyd = y[iy]; XDrawLine(dpy,win,gcc,NINT(*x0),NINT(*y0), NINT(*pxd),NINT(*pyd)); CLRS(z[cell]); *pcell = cell-nx; if (iy>0) return(1); else return(0); /* else if exiting west */ } else if (WSET(z[cell])) { d = DELTA(c,z[cell],z[cell+nx]); *pxd = x[ix]; *pyd = (1.0-d)*y[iy]+d*y[iy+1]; XDrawLine(dpy,win,gcc,NINT(*x0),NINT(*y0), NINT(*pxd),NINT(*pyd)); CLRW(z[cell]); *pcell = cell-1; if (ix>0) return(1); else return(0); /* else if no intersection exists */ } else { return(0); } }
/* function */ void xContour(Display *dpy, Window win,GC gcc, GC gcl, float *cp,int nx, float x[], int ny, float y[], float z[], char lcflag,char *lcf,char *lcc, float *w, int nplaces) /************************************************************************** xContour - draw contour of a two-dimensional array via X *************************************************************************** Input: dpy the display to make the contour win the window to draw in gcc GC for the contour lines gcl GC for the contour labels cp pointer to the contour value nx number of x-coordinates x array of x-coordinates (see notes below) ny number of y-coordinates y array of y-coordinates (see notes below) lcflag flag that defines if we actually are going to have labels Least Significat Bits: z array of nx*ny z(x,y) values (see notes below) w array of nx*ny z(x,y) values (see notes below) *************************************************************************** Notes: The two-dimensional array z is actually passed as a one-dimensional array containing nx*ny values, stored with nx fast and ny slow. The x and y arrays define a grid that is not necessarily uniformly-sampled. Linear interpolation of z values on the grid defined by the x and y arrays is used to determine z values between the gridpoints. The two least significant bits of z are used to mark intersections of the contour with the x,y grid; therefore, the z values will almost always be altered (slightly) by contour. xContour is a modified version of psContour where the use of conmove and condraw call have been changed to match X-Windows. Since XDrawLine requires a start and end point, the use of a manually update of the position variables x0 and y0 is used instead of conmove. if lcflag is zero no labels are drawn The w array is used to restrict the range of contour labeling that occurs only if w<1. As suggested in the reference, the following scheme is used to refer to a cell of the two-dimensional array z: north (0) (ix,iy+1) --------- (ix+1,iy+1) | cell | west (3) | ix,iy | east (1) | | (ix,iy) --------- (ix+1,iy) south (2) *************************************************************************** Reference: Cottafava, G. and Le Moli, G., 1969, Automatic contour map: Commuincations of the ACM, v. 12, n. 7, July, 1969. *************************************************************************** Author: Morten Wendell Pedersen Aarhus University 07/20/96 Heavily based on psContour by Dave Hale, Colorado School of Mines, 06/28/89 and with contour labeling added by: Zhenyue Liu, June 1993 (actually most of the credit should go to these two guys) ***************************************************************************/ { int ix,iy,non,cell,startcell; float d; float xmin = MIN(x[0],x[nx-1]), xmax = MAX(x[0],x[nx-1]); float ymin = MIN(y[0],y[ny-1]), ymax = MAX(y[0],y[ny-1]); float xc=0.0, yc=0.0; /* contour labeling centered at (xc,yc) */ float xw, yw; /* width and length of contour labeling */ float xd, yd; /* point on contour */ float x0, y0; /* start plot values (instead of move operation )*/ float xdmin, xdmax, ydmin, ydmax; /* range of contour */ int id; /* =0 if a point on contour has been used as (xc,yc) */ int cells=0; char str[20]; XCharStruct overall; int dummy; float c=*cp; /* stupid thing I had to do since I couldn't transfer a float without messing up everything but I could transfer a pointer....strange thing I will have to track this thing down one day*/ /* convert a number into a string */ sprintf(str,"%.*g",nplaces,c); /* determine length and width for printing the string */ XQueryTextExtents(dpy,XGContextFromGC(gcl),str,(int) strlen(str),&dummy,&dummy,&dummy,&overall); xw=overall.width; yw=overall.ascent+overall.descent; /* restrict contour labeling from edges */ for (iy=0; iy<ny-1; iy++) for (ix=0,cell=iy*nx; ix<nx-1; ix++,cell++) { if(x[ix]<xmin+2.0*xw || x[ix]>xmax-2.0*xw || y[iy]<ymin+yw || y[iy]>ymax-yw) w[cell] += 1.; } /* count intersections with cell boundaries */ non = 0; /* find all the intersections */ for (iy=0; iy<ny; iy++) { for (ix=0,cell=iy*nx; ix<nx; ix++,cell++) { /* check for intersection with west edge of cell */ if (iy<ny-1 && BTWN(c,z[cell],z[cell+nx])) { SETW(z[cell]); non++; } else { CLRW(z[cell]); } /* check for intersection with south edge of cell */ if (ix<nx-1 && BTWN(c,z[cell],z[cell+1])) { SETS(z[cell]); non++; } else { CLRS(z[cell]); } } } /* follow contours intersecting north boundary */ for (ix=0,startcell=(ny-1)*nx; non>0&&ix<nx-1; ix++,startcell++) { if (SSET(z[startcell])) { d = DELTA(c,z[startcell],z[startcell+1]); x0=(1.0-d)*x[ix]+d*x[ix+1]; y0=y[ny-1]; CLRS(z[startcell]); non--; cell = startcell-nx; id = 1; xdmin = xmax; xdmax = xmin; ydmin = ymax; ydmax = ymin; while (connect(dpy, win,gcc,c,nx,x,ny,y,z,&cell,&xd,&yd,&x0,&y0)){ x0=xd;y0=yd; non--; if(w[cell]<0.5 && id) { xc = xd; yc = yd; cells = cell; id = 0; } xdmin = MIN(xdmin,xd); xdmax = MAX(xdmax,xd); ydmin = MIN(ydmin,yd); ydmax = MAX(ydmax,yd); } if(lcflag && id==0 && xdmax+ydmax-xdmin-ydmin>xw+yw) { wcell(nx,x,ny,y,w,cells,xc,yc,xw,yw); labelc(dpy,win,gcl,xc-xw/2,yc-yw/2,xw,yw,str,lcf,lcc); } } } /* follow contours intersecting east boundary */ for (iy=0,startcell=nx-1; non>0&&iy<ny-1; iy++,startcell+=nx) { if (WSET(z[startcell])) { d = DELTA(c,z[startcell],z[startcell+nx]); x0=x[nx-1]; y0=(1.0-d)*y[iy]+d*y[iy+1]; CLRW(z[startcell]); non--; cell = startcell-1; id = 1; xdmin = xmax; xdmax = xmin; ydmin = ymax; ydmax = ymin; while (connect(dpy, win,gcc,c,nx,x,ny,y,z,&cell,&xd,&yd,&x0,&y0)){ x0=xd;y0=yd; non--; if(w[cell]<0.5 && id) { xc = xd; yc = yd; cells = cell; id = 0; } xdmin = MIN(xdmin,xd); xdmax = MAX(xdmax,xd); ydmin = MIN(ydmin,yd); ydmax = MAX(ydmax,yd); } if(lcflag && id==0 && xdmax+ydmax-xdmin-ydmin>xw+yw) { wcell(nx,x,ny,y,w,cells,xc,yc,xw,yw); labelc(dpy,win,gcl,xc-xw/2,yc-yw/2,xw,yw,str,lcf,lcc); } } } /* follow contours intersecting south boundary */ for (ix=0,startcell=0; non>0&&ix<nx-1; ix++,startcell++) { if (SSET(z[startcell])) { d = DELTA(c,z[startcell],z[startcell+1]); x0=(1.0-d)*x[ix]+d*x[ix+1]; y0=y[0]; CLRS(z[startcell]); non--; cell = startcell; id = 1; xdmin = xmax; xdmax = xmin; ydmin = ymax; ydmax = ymin; while (connect(dpy, win,gcc,c,nx,x,ny,y,z,&cell,&xd,&yd,&x0,&y0)){ x0=xd;y0=yd; non--; if(w[cell]<0.5 && id) { xc = xd; yc = yd; cells = cell; id = 0; } xdmin = MIN(xdmin,xd); xdmax = MAX(xdmax,xd); ydmin = MIN(ydmin,yd); ydmax = MAX(ydmax,yd); } if(lcflag && id==0 && xdmax+ydmax-xdmin-ydmin>xw+yw) { wcell(nx,x,ny,y,w,cells,xc,yc,xw,yw); labelc(dpy,win,gcl,xc-xw/2,yc-yw/2,xw,yw,str,lcf,lcc); } } } /* follow contours intersecting west boundary */ for (iy=0,startcell=0; non>0&&iy<ny-1; iy++,startcell+=nx) { if (WSET(z[startcell])) { d = DELTA(c,z[startcell],z[startcell+nx]); x0=x[0]; y0=(1.0-d)*y[iy]+d*y[iy+1]; CLRW(z[startcell]); non--; cell = startcell; id = 1; xdmin = xmax; xdmax = xmin; ydmin = ymax; ydmax = ymin; while (connect(dpy, win,gcc,c,nx,x,ny,y,z,&cell,&xd,&yd,&x0,&y0)){ x0=xd;y0=yd; non--; if(w[cell]<0.5 && id) { xc = xd; yc = yd; cells = cell; id = 0; } xdmin = MIN(xdmin,xd); xdmax = MAX(xdmax,xd); ydmin = MIN(ydmin,yd); ydmax = MAX(ydmax,yd); } if(lcflag && id==0 && xdmax+ydmax-xdmin-ydmin>xw+yw) { wcell(nx,x,ny,y,w,cells,xc,yc,xw,yw); labelc(dpy,win,gcl,xc-xw/2,yc-yw/2,xw,yw,str,lcf,lcc); } } } /* follow interior contours */ for (iy=1; iy<ny-1; iy++) { for (ix=0,startcell=iy*nx; non>0&&ix<nx-1; ix++,startcell++) { /* check south edge of cell */ if (SSET(z[startcell])) { d = DELTA(c,z[startcell],z[startcell+1]); x0=(1.0-d)*x[ix]+d*x[ix+1]; y0=y[iy]; /* clear south edge where we started */ CLRS(z[startcell]); non--; cell = startcell; /* if another intersection exists in this cell */ if (connect(dpy, win,gcc,c,nx,x,ny,y,z,&cell,&xd,&yd,&x0,&y0)) { x0=xd;y0=yd; /* set south edge so that we finish where we started */ SETS(z[startcell]); non++; /* follow the contour */ id = 1; xdmin = xmax; xdmax = xmin; ydmin = ymax; ydmax = ymin; while (connect(dpy, win,gcc,c,nx,x,ny,y,z,&cell,&xd,&yd,&x0,&y0)){ x0=xd;y0=yd; non--; if(w[cell]<0.5 && id) { xc = xd; yc = yd; cells = cell; id = 0; } xdmin = MIN(xdmin,xd); xdmax = MAX(xdmax,xd); ydmin = MIN(ydmin,yd); ydmax = MAX(ydmax,yd); } if(lcflag && id==0 && xdmax+ydmax-xdmin-ydmin>xw+yw) { wcell(nx,x,ny,y,w,cells,xc,yc,xw,yw); labelc(dpy,win,gcl,xc-xw/2,yc-yw/2,xw,yw,str,lcf,lcc); } } } } } /* contour drawing is done */ }
/* function */ void psContour (float c, int nx, float x[], int ny, float y[], float z[], float lcs, char *lcf, char *lcc, float *w, int nplaces) /************************************************************************** psContour - draw contour of a two-dimensional array via PostScript *************************************************************************** Input: c contour value nx number of x-coordinates x array of x-coordinates (see notes below) ny number of y-coordinates y array of y-coordinates (see notes below) lcs font size of contour label lcf font name of contour label lcc color of contour label Least Significat Bits: z array of nx*ny z(x,y) values (see notes below) w array of nx*ny z(x,y) values (see notes below) *************************************************************************** Notes: The two-dimensional array z is actually passed as a one-dimensional array containing nx*ny values, stored with nx fast and ny slow. The x and y arrays define a grid that is not necessarily uniformly-sampled. Linear interpolation of z values on the grid defined by the x and y arrays is used to determine z values between the gridpoints. The two least significant bits of z are used to mark intersections of the contour with the x,y grid; therefore, the z values will almost always be altered (slightly) by contour. pscontour isolates the use of PostScript to four internal functions: void coninit(void) - called before any contour drawing void conmove(float x, float y) - moves current position to x,y void condraw(float x, float y) - draws from current position to x,y void condone(void) - called when contour drawing is done These functions can usually be replaced with equivalent functions in other graphics environments. The w array is used to restrict the range of contour labeling that occurs only if w<1. As suggested in the reference, the following scheme is used to refer to a cell of the two-dimensional array z: north (0) (ix,iy+1) --------- (ix+1,iy+1) | cell | west (3) | ix,iy | east (1) | | (ix,iy) --------- (ix+1,iy) south (2) *************************************************************************** Reference: Cottafava, G. and Le Moli, G., 1969, Automatic contour map: Commuincations of the ACM, v. 12, n. 7, July, 1969. *************************************************************************** Author: Dave Hale, Colorado School of Mines, 06/28/89 contour labeling added by: Zhenyue Liu, June 1993 ***************************************************************************/ { int ix,iy,non,cell,startcell; float d; float xmin = MIN(x[0],x[nx-1]), xmax = MAX(x[0],x[nx-1]); float ymin = MIN(y[0],y[ny-1]), ymax = MAX(y[0],y[ny-1]); float xc=0.0, yc=0.0; /* contour labeling centered at (xc,yc) */ float xw, yw; /* width and length of contour labeling */ float xd, yd; /* point on contour */ float xdmin, xdmax, ydmin, ydmax; /* range of contour */ int id; /* =0 if a point on contour has been used as (xc,yc) */ int cells=0; char str[20]; /* convert a number into a string */ sprintf(str,"%.*g",nplaces,c); /* determine length and width for printing the string */ yw = lcs*0.55*((unsigned int) strlen(str)); xw = lcs*0.8; /* restrict contour labeling from edges */ for (iy=0; iy<ny-1; iy++) for (ix=0,cell=iy*nx; ix<nx-1; ix++,cell++) { if(x[ix]<xmin+2.0*xw || x[ix]>xmax-2.0*xw || y[iy]<ymin+yw || y[iy]>ymax-yw) w[cell] += 1.; } /* count intersections with cell boundaries */ non = 0; /* find all the intersections */ for (iy=0; iy<ny; iy++) { for (ix=0,cell=iy*nx; ix<nx; ix++,cell++) { /* check for intersection with west edge of cell */ if (iy<ny-1 && BTWN(c,z[cell],z[cell+nx])) { SETW(z[cell]); non++; } else { CLRW(z[cell]); } /* check for intersection with south edge of cell */ if (ix<nx-1 && BTWN(c,z[cell],z[cell+1])) { SETS(z[cell]); non++; } else { CLRS(z[cell]); } } } /* initialize contour drawing */ coninit(); /* follow contours intersecting north boundary */ for (ix=0,startcell=(ny-1)*nx; non>0&&ix<nx-1; ix++,startcell++) { if (SSET(z[startcell])) { d = DELTA(c,z[startcell],z[startcell+1]); conmove((1.0-d)*x[ix]+d*x[ix+1],y[ny-1]); CLRS(z[startcell]); non--; cell = startcell-nx; id = 1; xdmin = xmax; xdmax = xmin; ydmin = ymax; ydmax = ymin; while (connect(c,nx,x,ny,y,z,&cell,&xd,&yd)){ non--; if(w[cell]<0.5 && id) { xc = xd; yc = yd; cells = cell; id = 0; } xdmin = MIN(xdmin,xd); xdmax = MAX(xdmax,xd); ydmin = MIN(ydmin,yd); ydmax = MAX(ydmax,yd); } if(lcs>1 && id==0 && xdmax+ydmax-xdmin-ydmin>xw+yw) { wcell(nx,x,ny,y,w,cells,xc,yc,xw,yw); labelc(xc-xw/2,yc-yw/2,xw,yw,str,lcs,lcf,lcc); } } } /* follow contours intersecting east boundary */ for (iy=0,startcell=nx-1; non>0&&iy<ny-1; iy++,startcell+=nx) { if (WSET(z[startcell])) { d = DELTA(c,z[startcell],z[startcell+nx]); conmove(x[nx-1],(1.0-d)*y[iy]+d*y[iy+1]); CLRW(z[startcell]); non--; cell = startcell-1; id = 1; xdmin = xmax; xdmax = xmin; ydmin = ymax; ydmax = ymin; while (connect(c,nx,x,ny,y,z,&cell,&xd,&yd)){ non--; if(w[cell]<0.5 && id) { xc = xd; yc = yd; cells = cell; id = 0; } xdmin = MIN(xdmin,xd); xdmax = MAX(xdmax,xd); ydmin = MIN(ydmin,yd); ydmax = MAX(ydmax,yd); } if(lcs>1 && id==0 && xdmax+ydmax-xdmin-ydmin>xw+yw) { wcell(nx,x,ny,y,w,cells,xc,yc,xw,yw); labelc(xc-xw/2,yc-yw/2,xw,yw,str,lcs,lcf,lcc); } } } /* follow contours intersecting south boundary */ for (ix=0,startcell=0; non>0&&ix<nx-1; ix++,startcell++) { if (SSET(z[startcell])) { d = DELTA(c,z[startcell],z[startcell+1]); conmove((1.0-d)*x[ix]+d*x[ix+1],y[0]); CLRS(z[startcell]); non--; cell = startcell; id = 1; xdmin = xmax; xdmax = xmin; ydmin = ymax; ydmax = ymin; while (connect(c,nx,x,ny,y,z,&cell,&xd,&yd)){ non--; if(w[cell]<0.5 && id) { xc = xd; yc = yd; cells = cell; id = 0; } xdmin = MIN(xdmin,xd); xdmax = MAX(xdmax,xd); ydmin = MIN(ydmin,yd); ydmax = MAX(ydmax,yd); } if(lcs>1 && id==0 && xdmax+ydmax-xdmin-ydmin>xw+yw) { wcell(nx,x,ny,y,w,cells,xc,yc,xw,yw); labelc(xc-xw/2,yc-yw/2,xw,yw,str,lcs,lcf,lcc); } } } /* follow contours intersecting west boundary */ for (iy=0,startcell=0; non>0&&iy<ny-1; iy++,startcell+=nx) { if (WSET(z[startcell])) { d = DELTA(c,z[startcell],z[startcell+nx]); conmove(x[0],(1.0-d)*y[iy]+d*y[iy+1]); CLRW(z[startcell]); non--; cell = startcell; id = 1; xdmin = xmax; xdmax = xmin; ydmin = ymax; ydmax = ymin; while (connect(c,nx,x,ny,y,z,&cell,&xd,&yd)){ non--; if(w[cell]<0.5 && id) { xc = xd; yc = yd; cells = cell; id = 0; } xdmin = MIN(xdmin,xd); xdmax = MAX(xdmax,xd); ydmin = MIN(ydmin,yd); ydmax = MAX(ydmax,yd); } if(lcs>1 && id==0 && xdmax+ydmax-xdmin-ydmin>xw+yw) { wcell(nx,x,ny,y,w,cells,xc,yc,xw,yw); labelc(xc-xw/2,yc-yw/2,xw,yw,str,lcs,lcf,lcc); } } } /* follow interior contours */ for (iy=1; iy<ny-1; iy++) { for (ix=0,startcell=iy*nx; non>0&&ix<nx-1; ix++,startcell++) { /* check south edge of cell */ if (SSET(z[startcell])) { d = DELTA(c,z[startcell],z[startcell+1]); conmove((1.0-d)*x[ix]+d*x[ix+1],y[iy]); /* clear south edge where we started */ CLRS(z[startcell]); non--; cell = startcell; /* if another intersection exists in this cell */ if (connect(c,nx,x,ny,y,z,&cell,&xd,&yd)) { /* set south edge so that we finish where we started */ SETS(z[startcell]); non++; /* follow the contour */ id = 1; xdmin = xmax; xdmax = xmin; ydmin = ymax; ydmax = ymin; while (connect(c,nx,x,ny,y,z,&cell,&xd,&yd)){ non--; if(w[cell]<0.5 && id) { xc = xd; yc = yd; cells = cell; id = 0; } xdmin = MIN(xdmin,xd); xdmax = MAX(xdmax,xd); ydmin = MIN(ydmin,yd); ydmax = MAX(ydmax,yd); } if(lcs>1 && id==0 && xdmax+ydmax-xdmin-ydmin>xw+yw) { wcell(nx,x,ny,y,w,cells,xc,yc,xw,yw); labelc(xc-xw/2,yc-yw/2,xw,yw,str,lcs,lcf,lcc); } } } } } /* contour drawing is done */ condone(); }
static int smb_send_trans2(struct smb_sb_info *server, __u16 trans2_command, int ldata, unsigned char *data, int lparam, unsigned char *param) { struct socket *sock = server_sock(server); struct scm_cookie scm; int err; /* I know the following is very ugly, but I want to build the smb packet as efficiently as possible. */ const int smb_parameters = 15; const int oparam = ROUND_UP(SMB_HEADER_LEN + 2 * smb_parameters + 2 + 3); const int odata = ROUND_UP(oparam + lparam); const int bcc = odata + ldata - (SMB_HEADER_LEN + 2 * smb_parameters + 2); const int packet_length = SMB_HEADER_LEN + 2 * smb_parameters + bcc + 2; unsigned char padding[4] = {0,}; char *p; struct iovec iov[4]; struct msghdr msg; /* N.B. This test isn't valid! packet_size may be < max_xmit */ if ((bcc + oparam) > server->opt.max_xmit) { return -ENOMEM; } p = smb_setup_header(server, SMBtrans2, smb_parameters, bcc); WSET(server->packet, smb_tpscnt, lparam); WSET(server->packet, smb_tdscnt, ldata); /* N.B. these values should reflect out current packet size */ WSET(server->packet, smb_mprcnt, TRANS2_MAX_TRANSFER); WSET(server->packet, smb_mdrcnt, TRANS2_MAX_TRANSFER); WSET(server->packet, smb_msrcnt, 0); WSET(server->packet, smb_flags, 0); DSET(server->packet, smb_timeout, 0); WSET(server->packet, smb_pscnt, lparam); WSET(server->packet, smb_psoff, oparam - 4); WSET(server->packet, smb_dscnt, ldata); WSET(server->packet, smb_dsoff, odata - 4); WSET(server->packet, smb_suwcnt, 1); WSET(server->packet, smb_setup0, trans2_command); *p++ = 0; /* null smb_name for trans2 */ *p++ = 'D'; /* this was added because OS/2 does it */ *p++ = ' '; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_iov = iov; msg.msg_iovlen = 4; msg.msg_flags = 0; iov[0].iov_base = (void *) server->packet; iov[0].iov_len = oparam; iov[1].iov_base = (param == NULL) ? padding : param; iov[1].iov_len = lparam; iov[2].iov_base = padding; iov[2].iov_len = odata - oparam - lparam; iov[3].iov_base = (data == NULL) ? padding : data; iov[3].iov_len = ldata; err = scm_send(sock, &msg, &scm); if (err >= 0) { err = sock->ops->sendmsg(sock, &msg, packet_length, &scm); scm_destroy(&scm); } return err; }
/* * Add a request and tell smbiod to process it */ int smb_add_request(struct smb_request *req) { long timeleft; struct smb_sb_info *server = req->rq_server; int result = 0; smb_setup_request(req); if (req->rq_trans2_command) { if (req->rq_buffer == NULL) { PARANOIA("trans2 attempted without response buffer!\n"); return -EIO; } result = smb_setup_trans2request(req); } if (result < 0) return result; #ifdef SMB_DEBUG_PACKET_SIZE add_xmit_stats(req); #endif /* add 'req' to the queue of requests */ if (smb_lock_server_interruptible(server)) return -EINTR; /* * Try to send the request as the process. If that fails we queue the * request and let smbiod send it later. */ /* FIXME: each server has a number on the maximum number of parallel requests. 10, 50 or so. We should not allow more requests to be active. */ if (server->mid > 0xf000) server->mid = 0; req->rq_mid = server->mid++; WSET(req->rq_header, smb_mid, req->rq_mid); result = 0; if (server->state == CONN_VALID) { if (list_empty(&server->xmitq)) result = smb_request_send_req(req); if (result < 0) { /* Connection lost? */ server->conn_error = result; server->state = CONN_INVALID; } } if (result != 1) list_add_tail(&req->rq_queue, &server->xmitq); smb_rget(req); if (server->state != CONN_VALID) smbiod_retry(server); smb_unlock_server(server); smbiod_wake_up(); timeleft = wait_event_interruptible_timeout(req->rq_wait, req->rq_flags & SMB_REQ_RECEIVED, 30*HZ); if (!timeleft || signal_pending(current)) { /* * On timeout or on interrupt we want to try and remove the * request from the recvq/xmitq. * First check if the request is still part of a queue. (May * have been removed by some error condition) */ smb_lock_server(server); if (!list_empty(&req->rq_queue)) { list_del_init(&req->rq_queue); smb_rput(req); } smb_unlock_server(server); } if (!timeleft) { PARANOIA("request [%p, mid=%d] timed out!\n", req, req->rq_mid); VERBOSE("smb_com: %02x\n", *(req->rq_header + smb_com)); VERBOSE("smb_rcls: %02x\n", *(req->rq_header + smb_rcls)); VERBOSE("smb_flg: %02x\n", *(req->rq_header + smb_flg)); VERBOSE("smb_tid: %04x\n", WVAL(req->rq_header, smb_tid)); VERBOSE("smb_pid: %04x\n", WVAL(req->rq_header, smb_pid)); VERBOSE("smb_uid: %04x\n", WVAL(req->rq_header, smb_uid)); VERBOSE("smb_mid: %04x\n", WVAL(req->rq_header, smb_mid)); VERBOSE("smb_wct: %02x\n", *(req->rq_header + smb_wct)); req->rq_rcls = ERRSRV; req->rq_err = ERRtimeout; /* Just in case it was "stuck" */ smbiod_wake_up(); } VERBOSE("woke up, rcls=%d\n", req->rq_rcls); if (req->rq_rcls != 0) req->rq_errno = smb_errno(req); if (signal_pending(current)) req->rq_errno = -ERESTARTSYS; return req->rq_errno; }
/* * Prepare a transaction2 request structure */ static int smb_setup_trans2request(struct smb_request *req) { struct smb_sb_info *server = req->rq_server; int mparam, mdata; static unsigned char padding[4]; /* I know the following is very ugly, but I want to build the smb packet as efficiently as possible. */ const int smb_parameters = 15; const int header = SMB_HEADER_LEN + 2 * smb_parameters + 2; const int oparam = ROUND_UP(header + 3); const int odata = ROUND_UP(oparam + req->rq_lparm); const int bcc = (req->rq_data ? odata + req->rq_ldata : oparam + req->rq_lparm) - header; if ((bcc + oparam) > server->opt.max_xmit) return -ENOMEM; smb_setup_header(req, SMBtrans2, smb_parameters, bcc); /* * max parameters + max data + max setup == bufsize to make NT4 happy * and not abort the transfer or split into multiple responses. It also * makes smbfs happy as handling packets larger than the buffer size * is extra work. * * OS/2 is probably going to hate me for this ... */ mparam = SMB_TRANS2_MAX_PARAM; mdata = req->rq_bufsize - mparam; mdata = server->opt.max_xmit - mparam - 100; if (mdata < 1024) { mdata = 1024; mparam = 20; } #if 0 /* NT/win2k has ~4k max_xmit, so with this we request more than it wants to return as one SMB. Useful for testing the fragmented trans2 handling. */ mdata = 8192; #endif WSET(req->rq_header, smb_tpscnt, req->rq_lparm); WSET(req->rq_header, smb_tdscnt, req->rq_ldata); WSET(req->rq_header, smb_mprcnt, mparam); WSET(req->rq_header, smb_mdrcnt, mdata); WSET(req->rq_header, smb_msrcnt, 0); /* max setup always 0 ? */ WSET(req->rq_header, smb_flags, 0); DSET(req->rq_header, smb_timeout, 0); WSET(req->rq_header, smb_pscnt, req->rq_lparm); WSET(req->rq_header, smb_psoff, oparam - 4); WSET(req->rq_header, smb_dscnt, req->rq_ldata); WSET(req->rq_header, smb_dsoff, req->rq_data ? odata - 4 : 0); *(req->rq_header + smb_suwcnt) = 0x01; /* setup count */ *(req->rq_header + smb_suwcnt + 1) = 0x00; /* reserved */ WSET(req->rq_header, smb_setup0, req->rq_trans2_command); req->rq_iovlen = 2; req->rq_iov[0].iov_base = (void *) req->rq_header; req->rq_iov[0].iov_len = oparam; req->rq_iov[1].iov_base = (req->rq_parm==NULL) ? padding : req->rq_parm; req->rq_iov[1].iov_len = req->rq_lparm; req->rq_slen = oparam + req->rq_lparm; if (req->rq_data) { req->rq_iovlen += 2; req->rq_iov[2].iov_base = padding; req->rq_iov[2].iov_len = odata - oparam - req->rq_lparm; req->rq_iov[3].iov_base = req->rq_data; req->rq_iov[3].iov_len = req->rq_ldata; req->rq_slen = odata + req->rq_ldata; } /* always a data part for trans2 replies */ req->rq_setup_read = smb_setup_bcc; return 0; }