static void write_mailbox(volatile struct ivtv_mailbox __iomem *mbox, int cmd, int args, u32 data[]) { int i; write_sync(cmd, &mbox->cmd); write_sync(IVTV_API_STD_TIMEOUT, &mbox->timeout); for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++) write_sync(data[i], &mbox->data[i]); write_sync(IVTV_MBOX_DRIVER_DONE | IVTV_MBOX_DRIVER_BUSY, &mbox->flags); }
static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply) { uint8_t buf[4 + 4 + 8]; ssize_t ret; /* Reply [ 0 .. 3] magic (NBD_REPLY_MAGIC) [ 4 .. 7] error (0 == no error) [ 7 .. 15] handle */ cpu_to_be32w((uint32_t*)buf, NBD_REPLY_MAGIC); cpu_to_be32w((uint32_t*)(buf + 4), reply->error); cpu_to_be64w((uint64_t*)(buf + 8), reply->handle); TRACE("Sending response to client"); ret = write_sync(csock, buf, sizeof(buf)); if (ret < 0) { return ret; } if (ret != sizeof(buf)) { LOG("writing to socket failed"); return -EINVAL; } return 0; }
ssize_t nbd_send_request(int csock, struct nbd_request *request) { uint8_t buf[4 + 4 + 8 + 8 + 4]; ssize_t ret; cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC); cpu_to_be32w((uint32_t*)(buf + 4), request->type); cpu_to_be64w((uint64_t*)(buf + 8), request->handle); cpu_to_be64w((uint64_t*)(buf + 16), request->from); cpu_to_be32w((uint32_t*)(buf + 24), request->len); TRACE("Sending request to client: " "{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}", request->from, request->len, request->handle, request->type); ret = write_sync(csock, buf, sizeof(buf)); if (ret < 0) { return ret; } if (ret != sizeof(buf)) { LOG("writing to socket failed"); return -EINVAL; } return 0; }
static int write_packet(AVFormatContext *s, AVPacket *pkt) { AVIOContext *pb = s->pb; WtvContext *wctx = s->priv_data; /* emit sync chunk and 'timeline.table.0.entries.Event' record every 50 frames */ if (wctx->serial - (wctx->nb_sp_pairs ? wctx->sp_pairs[wctx->nb_sp_pairs - 1].serial : 0) >= 50) write_sync(s); /* emit 'table.0.entries.time' record every 500ms */ if (pkt->pts != AV_NOPTS_VALUE && pkt->pts - (wctx->nb_st_pairs ? wctx->st_pairs[wctx->nb_st_pairs - 1].value : 0) >= 5000000) add_serial_pair(&wctx->st_pairs, &wctx->nb_st_pairs, wctx->serial, pkt->pts); if (pkt->pts != AV_NOPTS_VALUE && pkt->pts > wctx->last_pts) { wctx->last_pts = pkt->pts; wctx->last_serial = wctx->serial; } // write timestamp chunk write_timestamp(s, pkt); write_chunk_header(s, &ff_data_guid, pkt->size, INDEX_BASE + pkt->stream_index); avio_write(pb, pkt->data, pkt->size); write_pad(pb, WTV_PAD8(pkt->size) - pkt->size); wctx->serial++; avio_flush(pb); return 0; }
static int write_header(avro_file_writer_t w) { int rval; uint8_t version = 1; /* TODO: remove this static buffer */ avro_writer_t schema_writer; char schema_buf[64 * 1024]; const avro_encoding_t *enc = &avro_binary_encoding; /* Generate random sync */ generate_sync(w); check(rval, avro_write(w->writer, "Obj", 3)); check(rval, avro_write(w->writer, &version, 1)); check(rval, enc->write_long(w->writer, 3)); check(rval, enc->write_string(w->writer, "avro.sync")); check(rval, enc->write_bytes(w->writer, w->sync, sizeof(w->sync))); check(rval, enc->write_string(w->writer, "avro.codec")); check(rval, enc->write_bytes(w->writer, "null", 4)); check(rval, enc->write_string(w->writer, "avro.schema")); schema_writer = avro_writer_memory(schema_buf, sizeof(schema_buf)); rval = avro_schema_to_json(w->writers_schema, schema_writer); if (rval) { avro_writer_free(schema_writer); return rval; } check(rval, enc->write_bytes(w->writer, schema_buf, avro_writer_tell(schema_writer))); check(rval, enc->write_long(w->writer, 0)); return write_sync(w); }
int nbd_negotiate(int csock, off_t size) { char buf[8 + 8 + 8 + 128]; /* Negotiate [ 0 .. 7] passwd ("NBDMAGIC") [ 8 .. 15] magic (0x00420281861253) [16 .. 23] size [24 .. 151] reserved (0) */ TRACE("Beginning negotiation."); memcpy(buf, "NBDMAGIC", 8); cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL); cpu_to_be64w((uint64_t*)(buf + 16), size); memset(buf + 24, 0, 128); if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { LOG("write failed"); errno = EINVAL; return -1; } TRACE("Negotation succeeded."); return 0; }
static int write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; WtvContext *wctx = s->priv_data; int i, pad, ret; AVStream *st; wctx->last_chunk_pos = -1; wctx->last_timestamp_pos = -1; ff_put_guid(pb, &ff_wtv_guid); ff_put_guid(pb, &sub_wtv_guid); avio_wl32(pb, 0x01); avio_wl32(pb, 0x02); avio_wl32(pb, 1 << WTV_SECTOR_BITS); avio_wl32(pb, 1 << WTV_BIGSECTOR_BITS); //write initial root fields avio_wl32(pb, 0); // root_size, update later write_pad(pb, 4); avio_wl32(pb, 0); // root_sector, update it later. write_pad(pb, 32); avio_wl32(pb, 0); // file ends pointer, update it later. pad = (1 << WTV_SECTOR_BITS) - avio_tell(pb); write_pad(pb, pad); wctx->timeline_start_pos = avio_tell(pb); wctx->serial = 1; wctx->last_chunk_pos = -1; wctx->first_video_flag = 1; for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; ret = write_stream_codec(s, st); if (ret < 0) { av_log(s, AV_LOG_ERROR, "write stream codec failed codec_type(0x%x)\n", st->codec->codec_type); return -1; } if (!i) write_sync(s); } for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; ret = write_stream_data(s, st); if (ret < 0) { av_log(s, AV_LOG_ERROR, "write stream data failed codec_type(0x%x)\n", st->codec->codec_type); return -1; } } if (wctx->nb_index) write_index(s); return 0; }
static void clear_all_mailboxes(struct ivtv *itv, struct ivtv_mailbox_data *mbdata) { int i; for (i = 0; i <= mbdata->max_mbox; i++) { IVTV_DEBUG_WARN("Clearing mailbox %d: cmd 0x%08x flags 0x%08x\n", i, readl(&mbdata->mbox[i].cmd), readl(&mbdata->mbox[i].flags)); write_sync(0, &mbdata->mbox[i].flags); clear_bit(i, &mbdata->busy); } }
static int try_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int mb) { u32 flags = readl(&mbdata->mbox[mb].flags); int is_free = flags == IVTV_MBOX_FREE || (flags & IVTV_MBOX_FIRMWARE_DONE); /* if the mailbox is free, then try to claim it */ if (is_free && !test_and_set_bit(mb, &mbdata->busy)) { write_sync(IVTV_MBOX_DRIVER_BUSY, &mbdata->mbox[mb].flags); return 1; } return 0; }
int nbd_send_request(int csock, struct nbd_request *request) { uint8_t buf[4 + 4 + 8 + 8 + 4]; cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC); cpu_to_be32w((uint32_t*)(buf + 4), request->type); cpu_to_be64w((uint64_t*)(buf + 8), request->handle); cpu_to_be64w((uint64_t*)(buf + 16), request->from); cpu_to_be32w((uint32_t*)(buf + 24), request->len); TRACE("Sending request to client"); if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { LOG("writing to socket failed"); errno = EINVAL; return -1; } return 0; }
static int file_write_block(avro_file_writer_t w) { const avro_encoding_t *enc = &avro_binary_encoding; int rval; if (w->block_count) { int64_t blocklen = avro_writer_tell(w->datum_writer); /* Write the block count */ check(rval, enc->write_long(w->writer, w->block_count)); /* Write the block length */ check(rval, enc->write_long(w->writer, blocklen)); /* Write the block */ check(rval, avro_write(w->writer, w->datum_buffer, blocklen)); /* Write the sync marker */ check(rval, write_sync(w)); /* Reset the datum writer */ avro_writer_reset(w->datum_writer); w->block_count = 0; } return 0; }
long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) { const struct cx18_api_info *info = find_api_info(mb->cmd); struct cx18_mailbox __iomem *ack_mb; u32 ack_irq; u8 rpu = CPU; if (info == NULL && mb->cmd) { CX18_WARN("Cannot ack unknown command %x\n", mb->cmd); return -EINVAL; } if (info) rpu = info->rpu; switch (rpu) { case HPU: ack_irq = IRQ_EPU_TO_HPU_ACK; ack_mb = &cx->scb->hpu2epu_mb; break; case APU: ack_irq = IRQ_EPU_TO_APU_ACK; ack_mb = &cx->scb->apu2epu_mb; break; case CPU: ack_irq = IRQ_EPU_TO_CPU_ACK; ack_mb = &cx->scb->cpu2epu_mb; break; default: CX18_WARN("Unknown RPU for command %x\n", mb->cmd); return -EINVAL; } setup_page(SCB_OFFSET); write_sync(mb->request, &ack_mb->ack); write_reg(ack_irq, SW2_INT_SET); return 0; }
static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) { char buf[8 + 8 + 8 + 128]; int rc; /* Negotiate [ 0 .. 7] passwd ("NBDMAGIC") [ 8 .. 15] magic (0x00420281861253) [16 .. 23] size [24 .. 27] flags [28 .. 151] reserved (0) */ socket_set_block(csock); rc = -EINVAL; TRACE("Beginning negotiation."); memcpy(buf, "NBDMAGIC", 8); cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL); cpu_to_be64w((uint64_t*)(buf + 16), size); cpu_to_be32w((uint32_t*)(buf + 24), flags | NBD_FLAG_HAS_FLAGS | NBD_FLAG_SEND_TRIM | NBD_FLAG_SEND_FLUSH | NBD_FLAG_SEND_FUA); memset(buf + 28, 0, 124); if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) { LOG("write failed"); goto fail; } TRACE("Negotiation succeeded."); rc = 0; fail: socket_set_nonblock(csock); return rc; }
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, off_t *offset, bool readonly, uint8_t *data, int data_size) { struct nbd_request request; struct nbd_reply reply; TRACE("Reading request."); if (nbd_receive_request(csock, &request) == -1) return -1; if (request.len > data_size) { LOG("len (%u) is larger than max len (%u)", request.len, data_size); errno = EINVAL; return -1; } if ((request.from + request.len) < request.from) { LOG("integer overflow detected! " "you're probably being attacked"); errno = EINVAL; return -1; } if ((request.from + request.len) > size) { LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64 ", Offset: %" PRIu64 "\n", request.from, request.len, (uint64_t)size, dev_offset); LOG("requested operation past EOF--bad client?"); errno = EINVAL; return -1; } TRACE("Decoding type"); reply.handle = request.handle; reply.error = 0; switch (request.type) { case NBD_CMD_READ: TRACE("Request type is READ"); if (bdrv_read(bs, (request.from + dev_offset) / 512, data, request.len / 512) == -1) { LOG("reading from file failed"); errno = EINVAL; return -1; } *offset += request.len; TRACE("Read %u byte(s)", request.len); if (nbd_send_reply(csock, &reply) == -1) return -1; TRACE("Sending data to client"); if (write_sync(csock, data, request.len) != request.len) { LOG("writing to socket failed"); errno = EINVAL; return -1; } break; case NBD_CMD_WRITE: TRACE("Request type is WRITE"); TRACE("Reading %u byte(s)", request.len); if (read_sync(csock, data, request.len) != request.len) { LOG("reading from socket failed"); errno = EINVAL; return -1; } if (readonly) { TRACE("Server is read-only, return error"); reply.error = 1; } else { TRACE("Writing to device"); if (bdrv_write(bs, (request.from + dev_offset) / 512, data, request.len / 512) == -1) { LOG("writing to file failed"); errno = EINVAL; return -1; } *offset += request.len; } if (nbd_send_reply(csock, &reply) == -1) return -1; break; case NBD_CMD_DISC: TRACE("Request type is DISCONNECT"); errno = 0; return 1; default: LOG("invalid request type (%u) received", request.type); errno = EINVAL; return -1; } TRACE("Request/Reply complete"); return 0; }
static int console_loop(int fd, struct xs_handle *xs, char *pty_path) { int ret, xs_fd = xs_fileno(xs), max_fd; do { fd_set fds; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); max_fd = STDIN_FILENO; FD_SET(xs_fd, &fds); if (xs_fd > max_fd) max_fd = xs_fd; if (fd != -1) FD_SET(fd, &fds); if (fd > max_fd) max_fd = fd; ret = select(max_fd + 1, &fds, NULL, NULL, NULL); if (ret == -1) { if (errno == EINTR || errno == EAGAIN) { continue; } return -1; } if (FD_ISSET(xs_fileno(xs), &fds)) { int newfd = get_pty_fd(xs, pty_path, 0); if (fd != -1) close(fd); if (newfd == -1) /* Console PTY has become invalid */ return 0; fd = newfd; continue; } if (FD_ISSET(STDIN_FILENO, &fds)) { ssize_t len; char msg[60]; len = read(STDIN_FILENO, msg, sizeof(msg)); if (len == 1 && msg[0] == ESCAPE_CHARACTER) { return 0; } if (len == 0 || len == -1) { if (len == -1 && (errno == EINTR || errno == EAGAIN)) { continue; } return -1; } if (!write_sync(fd, msg, len)) { close(fd); fd = -1; continue; } } if (fd != -1 && FD_ISSET(fd, &fds)) { ssize_t len; char msg[512]; len = read(fd, msg, sizeof(msg)); if (len == 0 || len == -1) { if (len == -1 && (errno == EINTR || errno == EAGAIN)) { continue; } close(fd); fd = -1; continue; } if (!write_sync(STDOUT_FILENO, msg, len)) { perror("write() failed"); return -1; } } } while (received_signal == 0); return 0; }
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, off_t *size, size_t *blocksize) { char buf[256]; uint64_t magic, s; uint16_t tmp; TRACE("Receiving negotation."); if (read_sync(csock, buf, 8) != 8) { LOG("read failed"); errno = EINVAL; return -1; } buf[8] = '\0'; if (strlen(buf) == 0) { LOG("server connection closed"); errno = EINVAL; return -1; } TRACE("Magic is %c%c%c%c%c%c%c%c", qemu_isprint(buf[0]) ? buf[0] : '.', qemu_isprint(buf[1]) ? buf[1] : '.', qemu_isprint(buf[2]) ? buf[2] : '.', qemu_isprint(buf[3]) ? buf[3] : '.', qemu_isprint(buf[4]) ? buf[4] : '.', qemu_isprint(buf[5]) ? buf[5] : '.', qemu_isprint(buf[6]) ? buf[6] : '.', qemu_isprint(buf[7]) ? buf[7] : '.'); if (memcmp(buf, "NBDMAGIC", 8) != 0) { LOG("Invalid magic received"); errno = EINVAL; return -1; } if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { LOG("read failed"); errno = EINVAL; return -1; } magic = be64_to_cpu(magic); TRACE("Magic is 0x%" PRIx64, magic); if (name) { uint32_t reserved = 0; uint32_t opt; uint32_t namesize; TRACE("Checking magic (opts_magic)"); if (magic != 0x49484156454F5054LL) { LOG("Bad magic received"); errno = EINVAL; return -1; } if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { LOG("flags read failed"); errno = EINVAL; return -1; } *flags = be16_to_cpu(tmp) << 16; /* reserved for future use */ if (write_sync(csock, &reserved, sizeof(reserved)) != sizeof(reserved)) { LOG("write failed (reserved)"); errno = EINVAL; return -1; } /* write the export name */ magic = cpu_to_be64(magic); if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { LOG("write failed (magic)"); errno = EINVAL; return -1; } opt = cpu_to_be32(NBD_OPT_EXPORT_NAME); if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) { LOG("write failed (opt)"); errno = EINVAL; return -1; } namesize = cpu_to_be32(strlen(name)); if (write_sync(csock, &namesize, sizeof(namesize)) != sizeof(namesize)) { LOG("write failed (namesize)"); errno = EINVAL; return -1; } if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) { LOG("write failed (name)"); errno = EINVAL; return -1; } } else { TRACE("Checking magic (cli_magic)"); if (magic != 0x00420281861253LL) { LOG("Bad magic received"); errno = EINVAL; return -1; } } if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) { LOG("read failed"); errno = EINVAL; return -1; } *size = be64_to_cpu(s); *blocksize = 1024; TRACE("Size is %" PRIu64, *size); if (!name) { if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) { LOG("read failed (flags)"); errno = EINVAL; return -1; } *flags = be32_to_cpup(flags); } else { if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { LOG("read failed (tmp)"); errno = EINVAL; return -1; } *flags |= be32_to_cpu(tmp); } if (read_sync(csock, &buf, 124) != 124) { LOG("read failed (buf)"); errno = EINVAL; return -1; } return 0; }
static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) { struct ivtv_mailbox_data *mbdata = (cmd >= 128) ? &itv->enc_mbox : &itv->dec_mbox; volatile struct ivtv_mailbox __iomem *mbox; int api_timeout = msecs_to_jiffies(1000); int flags, mb, i; unsigned long then; /* sanity checks */ if (NULL == mbdata) { IVTV_ERR("No mailbox allocated\n"); return -ENODEV; } if (args < 0 || args > CX2341X_MBOX_MAX_DATA || cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) { IVTV_ERR("Invalid MB call: cmd = 0x%02x, args = %d\n", cmd, args); return -EINVAL; } if (api_info[cmd].flags & API_HIGH_VOL) { IVTV_DEBUG_HI_MB("MB Call: %s\n", api_info[cmd].name); } else { IVTV_DEBUG_MB("MB Call: %s\n", api_info[cmd].name); } /* clear possibly uninitialized part of data array */ for (i = args; i < CX2341X_MBOX_MAX_DATA; i++) data[i] = 0; /* If this command was issued within the last 30 minutes and with identical data, then just return 0 as there is no need to issue this command again. Just an optimization to prevent unnecessary use of mailboxes. */ if (itv->api_cache[cmd].last_jiffies && time_before(jiffies, itv->api_cache[cmd].last_jiffies + msecs_to_jiffies(1800000)) && !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) { itv->api_cache[cmd].last_jiffies = jiffies; return 0; } flags = api_info[cmd].flags; if (flags & API_DMA) { for (i = 0; i < 100; i++) { mb = i % (mbdata->max_mbox + 1); if (try_mailbox(itv, mbdata, mb)) { write_mailbox(&mbdata->mbox[mb], cmd, args, data); clear_bit(mb, &mbdata->busy); return 0; } IVTV_DEBUG_WARN("%s: mailbox %d not free %08x\n", api_info[cmd].name, mb, readl(&mbdata->mbox[mb].flags)); } IVTV_WARN("Could not find free DMA mailbox for %s\n", api_info[cmd].name); clear_all_mailboxes(itv, mbdata); return -EBUSY; } if ((flags & API_FAST_RESULT) == API_FAST_RESULT) api_timeout = msecs_to_jiffies(100); mb = get_mailbox(itv, mbdata, flags); if (mb < 0) { IVTV_DEBUG_WARN("No free mailbox found (%s)\n", api_info[cmd].name); clear_all_mailboxes(itv, mbdata); return -EBUSY; } mbox = &mbdata->mbox[mb]; write_mailbox(mbox, cmd, args, data); if (flags & API_CACHE) { memcpy(itv->api_cache[cmd].data, data, sizeof(itv->api_cache[cmd].data)); itv->api_cache[cmd].last_jiffies = jiffies; } if ((flags & API_RESULT) == 0) { clear_bit(mb, &mbdata->busy); return 0; } /* Get results */ then = jiffies; if (!(flags & API_NO_POLL)) { /* First try to poll, then switch to delays */ for (i = 0; i < 100; i++) { if (readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE) break; } } while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) { if (time_after(jiffies, then + api_timeout)) { IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name); /* reset the mailbox, but it is likely too late already */ write_sync(0, &mbox->flags); clear_bit(mb, &mbdata->busy); return -EIO; } if (flags & API_NO_WAIT_RES) mdelay(1); else ivtv_msleep_timeout(1, 0); } if (time_after(jiffies, then + msecs_to_jiffies(100))) IVTV_DEBUG_WARN("%s took %u jiffies\n", api_info[cmd].name, jiffies_to_msecs(jiffies - then)); for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++) data[i] = readl(&mbox->data[i]); write_sync(0, &mbox->flags); clear_bit(mb, &mbdata->busy); return 0; }
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, off_t *size, Error **errp) { char buf[256]; uint64_t magic, s; uint16_t tmp; int rc; TRACE("Receiving negotiation."); rc = -EINVAL; if (read_sync(csock, buf, 8) != 8) { error_setg(errp, "Failed to read data"); goto fail; } buf[8] = '\0'; if (strlen(buf) == 0) { error_setg(errp, "Server connection closed unexpectedly"); goto fail; } TRACE("Magic is %c%c%c%c%c%c%c%c", qemu_isprint(buf[0]) ? buf[0] : '.', qemu_isprint(buf[1]) ? buf[1] : '.', qemu_isprint(buf[2]) ? buf[2] : '.', qemu_isprint(buf[3]) ? buf[3] : '.', qemu_isprint(buf[4]) ? buf[4] : '.', qemu_isprint(buf[5]) ? buf[5] : '.', qemu_isprint(buf[6]) ? buf[6] : '.', qemu_isprint(buf[7]) ? buf[7] : '.'); if (memcmp(buf, "NBDMAGIC", 8) != 0) { error_setg(errp, "Invalid magic received"); goto fail; } if (read_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { error_setg(errp, "Failed to read magic"); goto fail; } magic = be64_to_cpu(magic); TRACE("Magic is 0x%" PRIx64, magic); if (name) { uint32_t reserved = 0; uint32_t opt; uint32_t namesize; TRACE("Checking magic (opts_magic)"); if (magic != NBD_OPTS_MAGIC) { if (magic == NBD_CLIENT_MAGIC) { error_setg(errp, "Server does not support export names"); } else { error_setg(errp, "Bad magic received"); } goto fail; } if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { error_setg(errp, "Failed to read server flags"); goto fail; } *flags = be16_to_cpu(tmp) << 16; /* reserved for future use */ if (write_sync(csock, &reserved, sizeof(reserved)) != sizeof(reserved)) { error_setg(errp, "Failed to read reserved field"); goto fail; } /* write the export name */ magic = cpu_to_be64(magic); if (write_sync(csock, &magic, sizeof(magic)) != sizeof(magic)) { error_setg(errp, "Failed to send export name magic"); goto fail; } opt = cpu_to_be32(NBD_OPT_EXPORT_NAME); if (write_sync(csock, &opt, sizeof(opt)) != sizeof(opt)) { error_setg(errp, "Failed to send export name option number"); goto fail; } namesize = cpu_to_be32(strlen(name)); if (write_sync(csock, &namesize, sizeof(namesize)) != sizeof(namesize)) { error_setg(errp, "Failed to send export name length"); goto fail; } if (write_sync(csock, (char*)name, strlen(name)) != strlen(name)) { error_setg(errp, "Failed to send export name"); goto fail; } } else { TRACE("Checking magic (cli_magic)"); if (magic != NBD_CLIENT_MAGIC) { if (magic == NBD_OPTS_MAGIC) { error_setg(errp, "Server requires an export name"); } else { error_setg(errp, "Bad magic received"); } goto fail; } } if (read_sync(csock, &s, sizeof(s)) != sizeof(s)) { error_setg(errp, "Failed to read export length"); goto fail; } *size = be64_to_cpu(s); TRACE("Size is %" PRIu64, *size); if (!name) { if (read_sync(csock, flags, sizeof(*flags)) != sizeof(*flags)) { error_setg(errp, "Failed to read export flags"); goto fail; } *flags = be32_to_cpup(flags); } else { if (read_sync(csock, &tmp, sizeof(tmp)) != sizeof(tmp)) { error_setg(errp, "Failed to read export flags"); goto fail; } *flags |= be16_to_cpu(tmp); } if (read_sync(csock, &buf, 124) != 124) { error_setg(errp, "Failed to read reserved block"); goto fail; } rc = 0; fail: return rc; }