static size_t channel_write_adb_hack(struct channel* c, size_t sz) { size_t nr_removed = 0; while (nr_removed < sz) { struct iovec iov[2]; char encbuf[4096]; char* enc; char* encend; unsigned state; ringbuf_readable_iov(c->rb, iov, sz - nr_removed); enc = encbuf; encend = enc + sizeof (encbuf); state = c->leftover_escape; for (int i = 0; i < ARRAYSIZE(iov); ++i) { const char* in = iov[i].iov_base; const char* inend = in + iov[i].iov_len; adb_encode(&state, &enc, encend, &in, inend); } // If we left a byte in the ringbuffer, don't actually write // its first half now (since we wrote it before), but pretend // we did. size_t skip = (c->leftover_escape != 0); ssize_t nr_written = write_skip(c->fdh->fd, encbuf, enc - encbuf, skip); if (nr_written < 0 && nr_removed == 0) die_errno("write"); if (nr_written < 0) break; size_t nr_encoded = 0; enc = encbuf; encend = enc + nr_written; state = c->leftover_escape; for (int i = 0; i < ARRAYSIZE(iov); ++i) { const char* in = iov[i].iov_base; const char* inend = in + iov[i].iov_len; adb_encode(&state, &enc, encend, &in, inend); nr_encoded += (in - (char*) iov[i].iov_base); } // If we wrote a partial encoded byte, leave the plain byte in // the ringbuf so that we know this channel still needs to // write. if (state != 0) { assert(nr_encoded > 0); nr_encoded -= 1; } ringbuf_note_removed(c->rb, nr_encoded); nr_removed += nr_encoded; c->leftover_escape = state; } return nr_removed; }
void write_all_adb_encoded(int fd, const void* buf, size_t sz) { char encbuf[4096]; unsigned state = 0; const char* in = buf; const char* inend = in + sz; size_t nr_written = 0; while (nr_written < sz) { char* enc = encbuf; char* encend = enc + sizeof (encbuf); adb_encode(&state, &enc, encend, &in, inend); write_all(fd, encbuf, enc - encbuf); nr_written += enc - encbuf; } }