static void _sendto (cbuf_t cbuf, int fd, struct sockaddr_in *destaddr) { int n, rv; uint8_t buf[IPMIPOWER_PACKET_BUFLEN]; if ((n = cbuf_read (cbuf, buf, IPMIPOWER_PACKET_BUFLEN)) < 0) { IPMIPOWER_ERROR (("cbuf_read: %s", fd, strerror (errno))); exit (EXIT_FAILURE); } if (n == IPMIPOWER_PACKET_BUFLEN) { IPMIPOWER_ERROR (("cbuf_read: buffer full")); exit (EXIT_FAILURE); } do { if (cmd_args.common_args.driver_type == IPMI_DEVICE_LAN) rv = ipmi_lan_sendto (fd, buf, n, 0, (struct sockaddr *)destaddr, sizeof (struct sockaddr_in)); else { if (ipmi_is_ipmi_1_5_packet (buf, n)) rv = ipmi_lan_sendto (fd, buf, n, 0, (struct sockaddr *)destaddr, sizeof (struct sockaddr_in)); else rv = ipmi_rmcpplus_sendto (fd, buf, n, 0, (struct sockaddr *)destaddr, sizeof (struct sockaddr_in)); } } while (rv < 0 && errno == EINTR); if (rv < 0) { IPMIPOWER_ERROR (("ipmi_lan/rmcpplus_sendto: %s", strerror (errno))); exit (EXIT_FAILURE); } /* cbuf should be empty now */ if (!cbuf_is_empty (cbuf)) { IPMIPOWER_ERROR (("cbuf not empty")); exit (EXIT_FAILURE); } }
static int zio_fd_read (zio_t *zio, void *dst, int len) { assert (zio != NULL); assert (zio->magic == ZIO_MAGIC); assert (zio->buf); if (zio_line_buffered (zio) && !zio_eof (zio)) return cbuf_read_line (zio->buf, dst, len, -1); else return cbuf_read (zio->buf, dst, len); }
int sys_read_console(char* buffer, int size) { if (!list_empty(&keyboardqueue) || keyboard_serving_read) block_current_task(&keyboardqueue, BLOCK_AT_END); keyboard_serving_read = 1; // 1) If we can satisfy the read(), copy the needed bytes and return // 2) If we can't and the buffer is full, copy the entire input buffer and block // 3) Otherwise, block int* remaining_bytes = &keyboard_req_bytes[task_struct_to_task_index(current())]; *remaining_bytes = size; for (;;) { // Copy bytes from the keyboard buffer to the user buffer int read_bytes = 0; if (cbuf_size(&keyboard_input) >= *remaining_bytes) read_bytes = cbuf_read(&keyboard_input, buffer, *remaining_bytes, copy_to_user); else if (cbuf_full(&keyboard_input)) read_bytes = cbuf_read(&keyboard_input, buffer, cbuf_size(&keyboard_input), copy_to_user); buffer += read_bytes; *remaining_bytes -= read_bytes; if (*remaining_bytes == 0) break; // Block process back at the beginning of the keyboard queue keyboard_serving_read = 0; block_current_task(&keyboardqueue, BLOCK_AT_BEGINNING); } keyboard_serving_read = 0; return size - *remaining_bytes; }
/** * Backend helper: read from a cbuf * * This function is compatible to the glip_read() function and can be used in * backend implementations using a cbuf for storing incoming data. * * @param[in] buf the buffer to read from * @param[in] size how much data is supposed to be read * @param[out] data the read data * @param[out] size_read how much data has been read * * @return 0 if reading was successful * @return any other value indicates failure * * @see glip_read() */ int gb_util_cbuf_read(struct cbuf *buf, size_t size, uint8_t *data, size_t *size_read) { /* Check the fill level */ size_t fill_level = cbuf_fill_level(buf); /* We read as much as possible up to size */ size_t size_read_req = min(fill_level, size); /* Read from buffer */ int rv = cbuf_read(buf, data, size_read_req); if (rv < 0) { return -1; } /* Update actual read information */ *size_read = size_read_req; return 0; }
static void _recvfrom (cbuf_t cbuf, int fd, struct sockaddr_in *srcaddr) { int n, rv, dropped = 0; uint8_t buf[IPMIPOWER_PACKET_BUFLEN]; struct sockaddr_in from; unsigned int fromlen = sizeof (struct sockaddr_in); do { /* For receive side, ipmi_lan_recvfrom and * ipmi_rmcpplus_recvfrom are identical. So we just use * ipmi_lan_recvfrom for both. * * In event of future change, should use util functions * ipmi_is_ipmi_1_5_packet or ipmi_is_ipmi_2_0_packet * appropriately. */ rv = ipmi_lan_recvfrom (fd, buf, IPMIPOWER_PACKET_BUFLEN, 0, (struct sockaddr *)&from, &fromlen); } while (rv < 0 && errno == EINTR); /* achu & hliebig: * * Premise from ipmitool (http://ipmitool.sourceforge.net/) * * On some OSes (it seems Unixes), the behavior is to not return * port denied errors up to the client for UDP responses (i.e. you * need to timeout). But on some OSes (it seems Windows), the * behavior is to return port denied errors up to the user for UDP * responses via ECONNRESET or ECONNREFUSED. * * If this were just the case, we could return or handle errors * properly and move on. However, it's not the case. * * According to Ipmitool, on some motherboards, both the OS and the * BMC are capable of responding to an IPMI request. That means you * can get an ECONNRESET or ECONNREFUSED, then later on, get your * real IPMI response. * * Our solution is copied from Ipmitool, we'll ignore some specific * errors and try to read again. * * If the ECONNREFUSED or ECONNRESET is from the OS, but we will get * an IPMI response later, the recvfrom later on gets the packet we * want. * * If the ECONNREFUSED or ECONNRESET is from the OS but there is no * BMC (or IPMI disabled, etc.), just do the recvfrom again to * eventually get a timeout, which is the behavior we'd like. */ if (rv < 0 && (errno == ECONNRESET || errno == ECONNREFUSED)) { IPMIPOWER_DEBUG (("ipmi_lan_recvfrom: connection refused: %s", strerror (errno))); return; } if (rv < 0) { IPMIPOWER_ERROR (("ipmi_lan_recvfrom: %s", strerror (errno))); exit (EXIT_FAILURE); } if (!rv) { IPMIPOWER_ERROR (("ipmi_lan_recvfrom: EOF")); exit (EXIT_FAILURE); } /* Don't store if this packet is strange for some reason */ if (from.sin_family != AF_INET || from.sin_addr.s_addr != srcaddr->sin_addr.s_addr) return; /* cbuf should be empty, but if it isn't, empty it */ if (!cbuf_is_empty (cbuf)) { IPMIPOWER_DEBUG (("cbuf not empty, draining")); do { uint8_t tempbuf[IPMIPOWER_PACKET_BUFLEN]; if (cbuf_read (cbuf, tempbuf, IPMIPOWER_PACKET_BUFLEN) < 0) { IPMIPOWER_ERROR (("cbuf_read: %s", strerror (errno))); exit (EXIT_FAILURE); } } while(!cbuf_is_empty (cbuf)); } if ((n = cbuf_write (cbuf, buf, rv, &dropped)) < 0) { IPMIPOWER_ERROR (("cbuf_write: %s", strerror (errno))); exit (EXIT_FAILURE); } if (n != rv) { IPMIPOWER_ERROR (("cbuf_write: rv=%d n=%d", rv, n)); exit (EXIT_FAILURE); } if (dropped) IPMIPOWER_DEBUG (("cbuf_write: read dropped %d bytes", dropped)); }
int platform_dgetc(char *c, bool wait) { return cbuf_read(&debug_rx_buf, c, 1, wait); }