unsigned long read_stream(unsigned char *dest, unsigned long bytes, struct nt_sid *sid) { unsigned long br, rc; if(sid->is_write) return(0); br=(sid->rem.HighPart==0&&sid->rem.LowPart<bytes)?sid->rem.LowPart:bytes; if(br==0) return(0); if(!BackupRead(sid->hf, dest, br, &rc, FALSE, TRUE, &sid->lpcontext)) return(0); sid->rem=LargeIntegerSubtract(sid->rem, ConvertUlongToLargeInteger(rc)); return(rc); }
unsigned long write_stream(unsigned char *src, unsigned long bytes, struct nt_sid *sid) { unsigned long bw, rc; if(!sid->is_write) return(0); /* This is crucial to prevent overflow */ bw=(sid->rem.HighPart==0&&sid->rem.LowPart<bytes)?sid->rem.LowPart:bytes; if(bw==0) return(0); if(!BackupWrite(sid->hf, src, bw, &rc, FALSE, TRUE, &sid->lpcontext)) return(0); sid->rem=LargeIntegerSubtract(sid->rem, ConvertUlongToLargeInteger(rc)); return(rc); }
/* * called with scp->rw lock held exclusive */ afs_int32 raw_ReadData( cm_scache_t *scp, osi_hyper_t *offsetp, afs_uint32 length, char *bufferp, afs_uint32 *readp, cm_user_t *userp, cm_req_t *reqp) { long code; cm_buf_t *bufp = NULL; osi_hyper_t fileLength; osi_hyper_t thyper; osi_hyper_t lastByte; osi_hyper_t bufferOffset; long bufIndex, nbytes; int sequential = 0; /* start by looking up the file's end */ code = cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); if (code) goto done; cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); /* now we have the entry locked, look up the length */ fileLength = scp->length; /* adjust length down so that it won't go past EOF */ thyper.LowPart = length; thyper.HighPart = 0; thyper = LargeIntegerAdd(*offsetp, thyper); /* where read should end */ lastByte = thyper; if (LargeIntegerGreaterThan(thyper, fileLength)) { /* we'd read past EOF, so just stop at fileLength bytes. * Start by computing how many bytes remain in the file. */ thyper = LargeIntegerSubtract(fileLength, *offsetp); /* if we are past EOF, read 0 bytes */ if (LargeIntegerLessThanZero(thyper)) length = 0; else length = thyper.LowPart; } *readp = length; /* now, copy the data one buffer at a time, * until we've filled the request packet */ while (1) { /* if we've copied all the data requested, we're done */ if (length <= 0) break; /* otherwise, load up a buffer of data */ thyper.HighPart = offsetp->HighPart; thyper.LowPart = offsetp->LowPart & ~(cm_data.blockSize-1); if (!bufp || !LargeIntegerEqualTo(thyper, bufferOffset)) { /* wrong buffer */ if (bufp) { buf_Release(bufp); bufp = NULL; } lock_ReleaseWrite(&scp->rw); code = buf_Get(scp, &thyper, reqp, 0, &bufp); lock_ObtainWrite(&scp->rw); if (code) goto done; bufferOffset = thyper; /* now get the data in the cache */ while (1) { code = cm_SyncOp(scp, bufp, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ); if (code) goto done; cm_SyncOpDone(scp, bufp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ); if (cm_HaveBuffer(scp, bufp, 0)) break; /* otherwise, load the buffer and try again */ code = cm_GetBuffer(scp, bufp, NULL, userp, reqp); if (code) break; } if (code) { buf_Release(bufp); bufp = NULL; goto done; } } /* if (wrong buffer) ... */ /* now we have the right buffer loaded. Copy out the * data from here to the user's buffer. */ bufIndex = offsetp->LowPart & (cm_data.blockSize - 1); /* and figure out how many bytes we want from this buffer */ nbytes = cm_data.blockSize - bufIndex; /* what remains in buffer */ if (nbytes > length) nbytes = length; /* don't go past EOF */ /* now copy the data */ memcpy(bufferp, bufp->datap + bufIndex, nbytes); /* adjust lengthers, pointers, etc. */ bufferp += nbytes; length -= nbytes; thyper.LowPart = nbytes; thyper.HighPart = 0; *offsetp = LargeIntegerAdd(thyper, *offsetp); } /* while 1 */ done: if (bufp) buf_Release(bufp); if (code == 0 && sequential) cm_ConsiderPrefetch(scp, &lastByte, *readp, userp, reqp); return code; }