static void readFromChannel(TConn * const connectionP, bool * const eofP, const char ** const errorP) { /*---------------------------------------------------------------------------- Read some data from the channel of Connection *connectionP. Iff there is none available to read, return *eofP == true. -----------------------------------------------------------------------------*/ uint32_t bytesRead; bool readError; ChannelRead(connectionP->channelP, connectionP->buffer.b + connectionP->buffersize, bufferSpace(connectionP) - 1, &bytesRead, &readError); if (readError) xmlrpc_asprintf(errorP, "Error reading from channel"); else { *errorP = NULL; if (bytesRead > 0) { *eofP = FALSE; traceChannelRead(connectionP, bytesRead); connectionP->inbytes += bytesRead; connectionP->buffersize += bytesRead; connectionP->buffer.t[connectionP->buffersize] = '\0'; } else *eofP = TRUE; } }
/* * read specified amount of bytes from given desc/offset to buffer * return amount of read bytes or negative error code if call failed */ static int32_t ZVMReadHandle(struct NaClApp *nap, int ch, char *buffer, int32_t size, int64_t offset) { struct ChannelDesc *channel; int64_t tail; char *sys_buffer; assert(nap != NULL); assert(nap->manifest != NULL); assert(nap->manifest->channels != NULL); /* check the channel number */ if(ch < 0 || ch >= nap->manifest->channels->len) { ZLOGS(LOG_DEBUG, "channel_id=%d, buffer=%p, size=%d, offset=%ld", ch, buffer, size, offset); return -EINVAL; } channel = CH_CH(nap->manifest, ch); ZLOGS(LOG_INSANE, "channel %s, buffer=%p, size=%d, offset=%ld", channel->alias, buffer, size, offset); /* check buffer and convert address */ if(CheckRAMAccess(nap, (uintptr_t)buffer, size, PROT_WRITE) == -1) return -EINVAL; sys_buffer = (char*)NaClUserToSys(nap, (uintptr_t)buffer); /* ignore user offset for sequential access read */ if(CH_SEQ_READABLE(channel)) offset = channel->getpos; else /* prevent reading beyond the end of the random access channels */ size = MIN(channel->size - offset, size); /* check arguments sanity */ if(size == 0) return 0; /* success. user has read 0 bytes */ if(size < 0) return -EFAULT; if(offset < 0) return -EINVAL; /* check for eof */ if(channel->eof) return 0; /* check limits */ if(channel->counters[GetsLimit] >= channel->limits[GetsLimit]) return -EDQUOT; if(CH_RND_READABLE(channel)) if(offset >= channel->limits[PutSizeLimit] - channel->counters[PutSizeLimit] + channel->size) return -EINVAL; /* calculate i/o leftovers */ tail = channel->limits[GetSizeLimit] - channel->counters[GetSizeLimit]; if(size > tail) size = tail; if(size < 1) return -EDQUOT; /* read data */ return ChannelRead(channel, sys_buffer, (size_t)size, (off_t)offset); }