int smb_write(struct smb_share *ssp, u_int16_t fid, struct uio *uio, struct smb_cred *scred) { int error = 0; size_t len, tsize, resid; int wx = (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_WRITEX); resid = 0; /* XXX gcc */ tsize = uio->uio_resid; while (tsize > 0) { len = tsize; if (wx) error = smb_smb_writex(ssp, fid, &len, &resid, uio, scred); else error = smb_smb_write(ssp, fid, &len, &resid, uio, scred); if (error) break; if (resid < len) { error = EIO; break; } tsize -= resid; } return error; }
static __inline int smb_smb_write(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid, struct uio *uio, struct smb_cred *scred) { struct smb_rq *rqp; struct mbchain *mbp; struct mdchain *mdp; u_int16_t resid; u_int8_t wc; int error, blksz; if (*len && SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX) return (smb_smb_writex(ssp, fid, len, rresid, uio, scred)); blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 16; if (blksz > 0xffff) blksz = 0xffff; resid = *len = min(blksz, *len); error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); if (error) return error; smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM); mb_put_uint16le(mbp, resid); mb_put_uint32le(mbp, uio->uio_offset); mb_put_uint16le(mbp, min(uio->uio_resid, 0xffff)); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_DATA); mb_put_uint16le(mbp, resid); do { error = mb_put_uio(mbp, uio, resid); if (error) break; smb_rq_bend(rqp); error = smb_rq_simple(rqp); if (error) break; smb_rq_getreply(rqp, &mdp); md_get_uint8(mdp, &wc); if (wc != 1) { error = EBADRPC; break; } md_get_uint16le(mdp, &resid); *rresid = resid; } while(0); smb_rq_done(rqp); return error; }