/* * write specified amount of bytes from buffer to given desc/offset * return amount of read bytes or negative error code if call failed */ static int32_t ZVMWriteHandle(struct NaClApp *nap, int ch, const char *buffer, int32_t size, int64_t offset) { struct ChannelDesc *channel; int64_t tail; const 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_READ) == -1) return -EINVAL; sys_buffer = (char*)NaClUserToSys(nap, (uintptr_t) buffer); /* ignore user offset for sequential access write */ if(CH_SEQ_WRITEABLE(channel)) offset = channel->putpos; /* 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 limits */ if(channel->counters[PutsLimit] >= channel->limits[PutsLimit]) return -EDQUOT; tail = channel->limits[PutSizeLimit] - channel->counters[PutSizeLimit]; if(offset >= channel->limits[PutSizeLimit] && !((CH_RW_TYPE(channel) & 1) == 1)) return -EINVAL; if(offset >= channel->size + tail) return -EINVAL; if(size > tail) size = tail; if(size < 1) return -EDQUOT; /* write data */ return ChannelWrite(channel, sys_buffer, (size_t)size, (off_t)offset); }
bool ConnWrite(TConn * const connectionP, const void * const buffer, uint32_t const size) { bool failed; ChannelWrite(connectionP->channelP, buffer, size, &failed); traceChannelWrite(connectionP, buffer, size, failed); if (!failed) connectionP->outbytes += size; return !failed; }
AdpErrs Adp_ChannelWriteAsync(const ChannelID chan, Packet *packet) { return ChannelWrite(chan, packet, async_block_on_nothing); }
AdpErrs Adp_ChannelWrite(const ChannelID chan, Packet *packet) { return ChannelWrite(chan, packet, async_block_on_write); }