}
afs_int32
-rxfs_storeDestroy(void **r, afs_int32 error)
+rxfs_storeDestroy(void **r, afs_int32 code)
{
- afs_int32 code = error;
struct rxfs_storeVariables *v = (struct rxfs_storeVariables *)*r;
*r = NULL;
if (v->call) {
RX_AFS_GUNLOCK();
- code = rx_EndCall(v->call, error);
+ code = rx_EndCall(v->call, code);
RX_AFS_GLOCK();
- if (!code && error)
- code = error;
}
if (v->tbuffer)
osi_FreeLargeSpace(v->tbuffer);
rxfs_fetchClose(void *r, struct vcache *avc, struct dcache * adc,
struct afs_FetchOutput *o)
{
- afs_int32 code, code1 = 0;
+ afs_int32 code;
struct rxfs_fetchVariables *v = (struct rxfs_fetchVariables *)r;
if (!v->call)
#endif
code = EndRXAFS_FetchData(v->call, &o->OutStatus, &o->CallBack,
&o->tsync);
- code1 = rx_EndCall(v->call, code);
+ code = rx_EndCall(v->call, code);
RX_AFS_GLOCK();
- if (!code && code1)
- code = code1;
v->call = NULL;
}
afs_int32
-rxfs_fetchDestroy(void **r, afs_int32 error)
+rxfs_fetchDestroy(void **r, afs_int32 code)
{
- afs_int32 code = error;
struct rxfs_fetchVariables *v = (struct rxfs_fetchVariables *)*r;
*r = NULL;
if (v->call) {
RX_AFS_GUNLOCK();
- code = rx_EndCall(v->call, error);
+ code = rx_EndCall(v->call, code);
RX_AFS_GLOCK();
- if (error)
- code = error;
}
if (v->tbuffer)
osi_FreeLargeSpace(v->tbuffer);
struct osi_file *fP, struct fetchOps **ops, void **rock)
{
struct rxfs_fetchVariables *v;
- int code = 0, code1 = 0;
+ int code = 0;
#ifdef AFS_64BIT_CLIENT
afs_uint32 length_hi = 0;
#endif
- afs_uint32 length, bytes;
+ afs_uint32 length = 0, bytes;
v = (struct rxfs_fetchVariables *)
osi_AllocSmallSpace(sizeof(struct rxfs_fetchVariables));
if (bytes == sizeof(afs_int32)) {
length_hi = ntohl(length_hi);
} else {
- code = rx_Error(v->call);
RX_AFS_GUNLOCK();
- code1 = rx_EndCall(v->call, code);
+ code = rx_EndCall(v->call, RX_PROTOCOL_ERROR);
RX_AFS_GLOCK();
v->call = NULL;
}
length = ntohl(length);
else {
RX_AFS_GUNLOCK();
- code = rx_Error(v->call);
- code1 = rx_EndCall(v->call, code);
+ code = rx_EndCall(v->call, RX_PROTOCOL_ERROR);
v->call = NULL;
+ length = 0;
RX_AFS_GLOCK();
}
}
FillInt64(length64, length_hi, length);
+
+ if (!code) {
+ /* Check if the fileserver said our length is bigger than can fit
+ * in a signed 32-bit integer. If it is, we can't handle that, so
+ * error out. */
+ if (length64 > MAX_AFS_INT32) {
+ RX_AFS_GUNLOCK();
+ code = rx_EndCall(v->call, RX_PROTOCOL_ERROR);
+ v->call = NULL;
+ length = 0;
+ RX_AFS_GLOCK();
+ code = code != 0 ? code : EIO;
+ }
+ }
+
+ if (!code) {
+ /* Check if the fileserver said our length was negative. If it
+ * is, just treat it as a 0 length, since some older fileservers
+ * returned negative numbers when they meant to return 0. Note
+ * that we must do this in this 64-bit-specific block, since
+ * length64 being negative will screw up our conversion to the
+ * 32-bit 'alength' below. */
+ if (length64 < 0) {
+ length_hi = length = 0;
+ FillInt64(length64, 0, 0);
+ }
+ }
+
afs_Trace3(afs_iclSetp, CM_TRACE_FETCH64LENG,
ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, code,
ICL_TYPE_OFFSET,
ICL_HANDLE_OFFSET(length64));
- *alength = length;
+ if (!code)
+ *alength = length;
#else /* AFS_64BIT_CLIENT */
RX_AFS_GUNLOCK();
code = StartRXAFS_FetchData(v->call, (struct AFSFid *)&avc->f.fid.Fid,
RX_AFS_GLOCK();
if (bytes == sizeof(afs_int32)) {
*alength = ntohl(length);
+ if (*alength < 0) {
+ /* Older fileservers can return a negative length when they
+ * meant to return 0; just assume negative lengths were
+ * meant to be 0 lengths. */
+ *alength = 0;
+ }
} else {
- code = rx_Error(v->call);
- code1 = rx_EndCall(v->call, code);
+ code = rx_EndCall(v->call, RX_PROTOCOL_ERROR);
v->call = NULL;
}
}
* requested. It shouldn't do that, and accepting that much data
* can make us take up more cache space than we're supposed to,
* so error. */
- code = rx_Error(v->call);
RX_AFS_GUNLOCK();
- code1 = rx_EndCall(v->call, code);
+ code = rx_EndCall(v->call, RX_PROTOCOL_ERROR);
RX_AFS_GLOCK();
v->call = NULL;
code = EIO;
}
- if (!code && code1)
- code = code1;
-
if (code) {
osi_FreeSmallSpace(v);
return code;
if (!code)
code = (*ops->close)(rock, avc, adc, tsmall);
if (ops)
- (*ops->destroy)(&rock, code);
+ code = (*ops->destroy)(&rock, code);
#ifndef AFS_NOSTATS
FillStoreStats(code, AFS_STATS_FS_XFERIDX_FETCHDATA, xferStartTime,