Пример #1
0
Файл: log.c Проект: DonCN/haiku
static int
count_nonprint (const char *source)
{
  const char *p;
  int cnt;
  for (p = source, cnt = 0; *p; p++)
    if (!c_isprint (*p))
      ++cnt;
  return cnt;
}
Пример #2
0
/**
 * virStringIsPrintable:
 *
 * Returns true @str contains only printable characters.
 */
bool
virStringIsPrintable(const char *str)
{
    size_t i;

    for (i = 0; str[i]; i++)
        if (!c_isprint(str[i]))
            return false;

    return true;
}
Пример #3
0
/**
 * virBufferIsPrintable:
 *
 * Returns true if @buf of @buflen contains only printable characters
 */
bool
virStringBufferIsPrintable(const uint8_t *buf,
                           size_t buflen)
{
    size_t i;

    for (i = 0; i < buflen; i++)
        if (!c_isprint(buf[i]))
            return false;

    return true;
}
Пример #4
0
void
_gnutls_buffer_asciiprint (gnutls_buffer_st * str,
                           const char *data, size_t len)
{
    size_t j;

    for (j = 0; j < len; j++)
        if (c_isprint (data[j]))
            _gnutls_buffer_append_printf (str, "%c", (unsigned char) data[j]);
        else
            _gnutls_buffer_append_printf (str, ".");
}
Пример #5
0
/* Tests whether a string is entirely ASCII.  Returns 1 if yes.
   Returns 0 if the string is in an 8-bit encoding or an ISO-2022 encoding.  */
int
is_all_ascii (const char *s, size_t n)
{
  for (; n > 0; s++, n--)
    {
      unsigned char c = (unsigned char) *s;

      if (!(c_isprint (c) || c_isspace (c)))
        return 0;
    }
  return 1;
}
/* Assume that every ASCII character starts a new grapheme, which is often
   true, except that CR-LF is a single grapheme. */
static void
ascii_grapheme_breaks (const char *s, size_t n, char *p)
{
  size_t i;

  p[0] = 1;
  for (i = 1; i < n; i++)
    {
      bool is_ascii = c_isprint (s[i]) || c_isspace (s[i]);
      p[i] = is_ascii && (s[i] != '\n' || s[i - 1] != '\r');
    }
}
Пример #7
0
Файл: log.c Проект: DonCN/haiku
static void
copy_and_escape (const char *source, char *dest, char escape, int base)
{
  const char *from = source;
  char *to = dest;
  unsigned char c;

  /* Copy chars from SOURCE to DEST, escaping non-printable ones. */
  switch (base)
    {
    case 8:
      while ((c = *from++) != '\0')
        if (c_isprint (c))
          *to++ = c;
        else
          {
            *to++ = escape;
            *to++ = '0' + (c >> 6);
            *to++ = '0' + ((c >> 3) & 7);
            *to++ = '0' + (c & 7);
          }
      break;
    case 16:
      while ((c = *from++) != '\0')
        if (c_isprint (c))
          *to++ = c;
        else
          {
            *to++ = escape;
            *to++ = XNUM_TO_DIGIT (c >> 4);
            *to++ = XNUM_TO_DIGIT (c & 0xf);
          }
      break;
    default:
      abort ();
    }
  *to = '\0';
}
Пример #8
0
static char *
qemuAgentEscapeNonPrintable(const char *text)
{
    int i;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    for (i = 0 ; text[i] != '\0' ; i++) {
        if (text[i] == '\\')
            virBufferAddLit(&buf, "\\\\");
        else if (c_isprint(text[i]) || text[i] == '\n' ||
                 (text[i] == '\r' && text[i+1] == '\n'))
            virBufferAddChar(&buf, text[i]);
        else
            virBufferAsprintf(&buf, "\\x%02x", text[i]);
    }
    return virBufferContentAndReset(&buf);
}
Пример #9
0
static void *
format_parse (const char *format, bool translated, char **invalid_reason)
{
  struct spec spec;
  struct spec *result;

  spec.directives = 0;
  spec.arg_count = 0;

  for (; *format != '\0';)
    if (*format++ == '%')
      {
	/* A directive.  */
	spec.directives++;

	if (*format == '%')
	  format++;
	else if (*format >= '1' && *format <= '9')
	  {
	    unsigned int number = *format - '1';

	    while (spec.arg_count <= number)
	      spec.args_used[spec.arg_count++] = false;
	    spec.args_used[number] = true;

	    format++;
	  }
	else
	  {
	    *invalid_reason =
	      (*format == '\0'
	       ? INVALID_UNTERMINATED_DIRECTIVE ()
	       : (c_isprint (*format)
		  ? xasprintf (_("In the directive number %u, the character '%c' is not a digit between 1 and 9."), spec.directives, *format)
		  : xasprintf (_("The character that terminates the directive number %u is not a digit between 1 and 9."), spec.directives)));
	    goto bad_format;
	  }
      }

  result = (struct spec *) xmalloc (sizeof (struct spec));
  *result = spec;
  return result;

 bad_format:
  return NULL;
}
Пример #10
0
/* When tracing, be careful how we print BufferIn parameters which
 * usually contain large amounts of binary data (RHBZ#646822).
 */
void
guestfs___print_BufferIn (FILE *out, const char *buf, size_t buf_size)
{
  size_t i;
  size_t orig_size = buf_size;

  if (buf_size > 256)
    buf_size = 256;

  fputc ('"', out);

  for (i = 0; i < buf_size; ++i) {
    if (c_isprint (buf[i]))
      fputc (buf[i], out);
    else
      fprintf (out, "\\x%02x", (unsigned char) buf[i]);
  }

  fputc ('"', out);

  if (orig_size > buf_size)
    fprintf (out,
             _("<truncated, original size %zu bytes>"), orig_size);
}
Пример #11
0
void c_gets(){
	char c;
	unsigned char len;

	len = 0;
	while((c = c_getch()) != KEY_ENTER){
		if( c == 9) c = ' '; // TAB exchange Space
		if(((c == 8) || (c == 127)) && (len > 0)){ // Backspace manipulation
			len--;
			c_putch(8); c_putch(' '); c_putch(8);
		} else
		if(c_isprint(c) && (len < (SIZE_LINE - 1))){
			lbuf[len++] = c;
			c_putch(c);
		}
	}
	newline();
	lbuf[len] = 0; // Put NULL

	if(len > 0){
		while(c_isspace(lbuf[--len])); // Skip space
		lbuf[++len] = 0; // Put NULL
	}
}
Пример #12
0
/**
 * This function reads a single message, file chunk, launch flag or
 * cancellation flag from the daemon.  If something was read, it
 * returns C<0>, otherwise C<-1>.
 *
 * Both C<size_rtn> and C<buf_rtn> must be passed by the caller as
 * non-NULL.
 *
 * C<*size_rtn> returns the size of the returned message or it may be
 * C<GUESTFS_LAUNCH_FLAG> or C<GUESTFS_CANCEL_FLAG>.
 *
 * C<*buf_rtn> is returned containing the message (if any) or will be
 * set to C<NULL>.  C<*buf_rtn> must be freed by the caller.
 *
 * This checks for EOF (appliance died) and passes that up through the
 * child_cleanup function above.
 *
 * Log message, progress messages are handled transparently here.
 */
static int
recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
{
  char lenbuf[4];
  ssize_t n;
  XDR xdr;
  size_t message_size;

  *size_rtn = 0;
  *buf_rtn = NULL;

  /* RHBZ#914931: Along some (rare) paths, we might have closed the
   * socket connection just before this function is called, so just
   * return an error if this happens.
   */
  if (!g->conn) {
    guestfs_int_unexpected_close_error (g);
    return -1;
  }

  /* Read the 4 byte size / flag. */
  n = g->conn->ops->read_data (g, g->conn, lenbuf, 4);
  if (n == -1)
    return -1;
  if (n == 0) {
    guestfs_int_unexpected_close_error (g);
    child_cleanup (g);
    return -1;
  }

  xdrmem_create (&xdr, lenbuf, 4, XDR_DECODE);
  xdr_uint32_t (&xdr, size_rtn);
  xdr_destroy (&xdr);

  if (*size_rtn == GUESTFS_LAUNCH_FLAG) {
    if (g->state != LAUNCHING)
      error (g, _("received magic signature from guestfsd, but in state %d"),
             (int) g->state);
    else {
      g->state = READY;
      guestfs_int_call_callbacks_void (g, GUESTFS_EVENT_LAUNCH_DONE);
    }
    debug (g, "recv_from_daemon: received GUESTFS_LAUNCH_FLAG");
    return 0;
  }
  else if (*size_rtn == GUESTFS_CANCEL_FLAG) {
    debug (g, "recv_from_daemon: received GUESTFS_CANCEL_FLAG");
    return 0;
  }
  else if (*size_rtn == GUESTFS_PROGRESS_FLAG)
    /*FALLTHROUGH*/;
  else if (*size_rtn > GUESTFS_MESSAGE_MAX) {
    /* If this happens, it's pretty bad and we've probably lost
     * synchronization.
     */
    error (g, _("message length (%u) > maximum possible size (%d)"),
           (unsigned) *size_rtn, GUESTFS_MESSAGE_MAX);
    return -1;
  }

  /* Calculate the message size. */
  message_size =
    *size_rtn != GUESTFS_PROGRESS_FLAG ? *size_rtn : PROGRESS_MESSAGE_SIZE;

  /* Allocate the complete buffer, size now known. */
  *buf_rtn = safe_malloc (g, message_size);

  /* Read the message. */
  n = g->conn->ops->read_data (g, g->conn, *buf_rtn, message_size);
  if (n == -1) {
    free (*buf_rtn);
    *buf_rtn = NULL;
    return -1;
  }
  if (n == 0) {
    guestfs_int_unexpected_close_error (g);
    child_cleanup (g);
    free (*buf_rtn);
    *buf_rtn = NULL;
    return -1;
  }

  /* ... it's a normal message (not progress/launch/cancel) so display
   * it if we're debugging.
   */
#ifdef ENABLE_PACKET_DUMP
  if (g->verbose) {
    ssize_t i, j;

    for (i = 0; i < n; i += 16) {
      printf ("%04zx: ", i);
      for (j = i; j < MIN (i+16, n); ++j)
        printf ("%02x ", (*(unsigned char **)buf_rtn)[j]);
      for (; j < i+16; ++j)
        printf ("   ");
      printf ("|");
      for (j = i; j < MIN (i+16, n); ++j)
        if (c_isprint ((*(char **)buf_rtn)[j]))
          printf ("%c", (*(char **)buf_rtn)[j]);
        else
          printf (".");
      for (; j < i+16; ++j)
        printf (" ");
      printf ("|\n");
    }
  }
#endif

  return 0;
}
Пример #13
0
hive_h *
hivex_open (const char *filename, int flags)
{
  hive_h *h = NULL;

  assert (sizeof (struct ntreg_header) == 0x1000);
  assert (offsetof (struct ntreg_header, csum) == 0x1fc);

  h = calloc (1, sizeof *h);
  if (h == NULL)
    goto error;

  h->msglvl = flags & HIVEX_OPEN_MSGLVL_MASK;

  const char *debug = getenv ("HIVEX_DEBUG");
  if (debug && STREQ (debug, "1"))
    h->msglvl = 2;

  DEBUG (2, "created handle %p", h);

  h->writable = !!(flags & HIVEX_OPEN_WRITE);
  h->unsafe = !!(flags & HIVEX_OPEN_UNSAFE);
  h->filename = strdup (filename);
  if (h->filename == NULL)
    goto error;

#ifdef O_CLOEXEC
  h->fd = open (filename, O_RDONLY | O_CLOEXEC | O_BINARY);
#else
  h->fd = open (filename, O_RDONLY | O_BINARY);
#endif
  if (h->fd == -1)
    goto error;
#ifndef O_CLOEXEC
  fcntl (h->fd, F_SETFD, FD_CLOEXEC);
#endif

  struct stat statbuf;
  if (fstat (h->fd, &statbuf) == -1)
    goto error;

  h->size = statbuf.st_size;

  if (h->size < 0x2000) {
    SET_ERRNO (EINVAL,
               "%s: file is too small to be a Windows NT Registry hive file",
               filename);
    goto error;
  }

  if (!h->writable) {
    h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
    if (h->addr == MAP_FAILED)
      goto error;

    DEBUG (2, "mapped file at %p", h->addr);
  } else {
    h->addr = malloc (h->size);
    if (h->addr == NULL)
      goto error;

    if (full_read (h->fd, h->addr, h->size) < h->size)
      goto error;

    /* We don't need the file descriptor along this path, since we
     * have read all the data.
     */
    if (close (h->fd) == -1)
      goto error;
    h->fd = -1;
  }

  /* Check header. */
  if (h->hdr->magic[0] != 'r' ||
      h->hdr->magic[1] != 'e' ||
      h->hdr->magic[2] != 'g' ||
      h->hdr->magic[3] != 'f') {
    SET_ERRNO (ENOTSUP,
               "%s: not a Windows NT Registry hive file", filename);
    goto error;
  }

  /* Check major version. */
  uint32_t major_ver = le32toh (h->hdr->major_ver);
  if (major_ver != 1) {
    SET_ERRNO (ENOTSUP,
               "%s: hive file major version %" PRIu32 " (expected 1)",
               filename, major_ver);
    goto error;
  }

  h->bitmap = calloc (1 + h->size / 32, 1);
  if (h->bitmap == NULL)
    goto error;

  /* Header checksum. */
  uint32_t sum = header_checksum (h);
  if (sum != le32toh (h->hdr->csum)) {
    SET_ERRNO (EINVAL, "%s: bad checksum in hive header", filename);
    goto error;
  }

  for (int t=0; t<nr_recode_types; t++) {
    gl_lock_init (h->iconv_cache[t].mutex);
    h->iconv_cache[t].handle = NULL;
  }

  /* Last modified time. */
  h->last_modified = le64toh ((int64_t) h->hdr->last_modified);

  if (h->msglvl >= 2) {
    char *name = _hivex_recode (h, utf16le_to_utf8,
                                h->hdr->name, 64, NULL);

    fprintf (stderr,
             "hivex_open: header fields:\n"
             "  file version             %" PRIu32 ".%" PRIu32 "\n"
             "  sequence nos             %" PRIu32 " %" PRIu32 "\n"
             "    (sequences nos should match if hive was synched at shutdown)\n"
             "  last modified            %" PRIi64 "\n"
             "    (Windows filetime, x 100 ns since 1601-01-01)\n"
             "  original file name       %s\n"
             "    (only 32 chars are stored, name is probably truncated)\n"
             "  root offset              0x%x + 0x1000\n"
             "  end of last page         0x%x + 0x1000 (total file size 0x%zx)\n"
             "  checksum                 0x%x (calculated 0x%x)\n",
             major_ver, le32toh (h->hdr->minor_ver),
             le32toh (h->hdr->sequence1), le32toh (h->hdr->sequence2),
             h->last_modified,
             name ? name : "(conversion failed)",
             le32toh (h->hdr->offset),
             le32toh (h->hdr->blocks), h->size,
             le32toh (h->hdr->csum), sum);
    free (name);
  }

  h->rootoffs = le32toh (h->hdr->offset) + 0x1000;
  h->endpages = le32toh (h->hdr->blocks) + 0x1000;

  DEBUG (2, "root offset = 0x%zx", h->rootoffs);

  /* We'll set this flag when we see a block with the root offset (ie.
   * the root block).
   */
  int seen_root_block = 0, bad_root_block = 0;

  /* Collect some stats. */
  size_t pages = 0;           /* Number of hbin pages read. */
  size_t smallest_page = SIZE_MAX, largest_page = 0;
  size_t blocks = 0;          /* Total number of blocks found. */
  size_t smallest_block = SIZE_MAX, largest_block = 0, blocks_bytes = 0;
  size_t used_blocks = 0;     /* Total number of used blocks found. */
  size_t used_size = 0;       /* Total size (bytes) of used blocks. */

  /* Read the pages and blocks.  The aim here is to be robust against
   * corrupt or malicious registries.  So we make sure the loops
   * always make forward progress.  We add the address of each block
   * we read to a hash table so pointers will only reference the start
   * of valid blocks.
   */
  size_t off;
  struct ntreg_hbin_page *page;
  for (off = 0x1000; off < h->size; off += le32toh (page->page_size)) {
    if (off >= h->endpages)
      break;

    page = (struct ntreg_hbin_page *) ((char *) h->addr + off);
    if (page->magic[0] != 'h' ||
        page->magic[1] != 'b' ||
        page->magic[2] != 'i' ||
        page->magic[3] != 'n') {

      if (!h->unsafe) {
        SET_ERRNO (ENOTSUP,
                   "%s: trailing garbage at end of file "
                   "(at 0x%zx, after %zu pages)",
                   filename, off, pages);
        goto error;
      }

      DEBUG (2,
             "page not found at expected offset 0x%zx, "
             "seeking until one is found or EOF is reached",
             off);

      int found = 0;
      while (off < h->size) {
        off += 0x1000;

        if (off >= h->endpages)
          break;

        page = (struct ntreg_hbin_page *) ((char *) h->addr + off);
        if (page->magic[0] == 'h' &&
            page->magic[1] == 'b' &&
            page->magic[2] == 'i' &&
            page->magic[3] == 'n') {
          DEBUG (2, "found next page by seeking at 0x%zx", off);
          found = 1;
          break;
        }
      }

      if (!found) {
        DEBUG (2, "page not found and end of pages section reached");
        break;
      }
    }

    size_t page_size = le32toh (page->page_size);
    DEBUG (2, "page at 0x%zx, size %zu", off, page_size);
    pages++;
    if (page_size < smallest_page) smallest_page = page_size;
    if (page_size > largest_page) largest_page = page_size;

    if (page_size <= sizeof (struct ntreg_hbin_page) ||
        (page_size & 0x0fff) != 0) {
      SET_ERRNO (ENOTSUP,
                 "%s: page size %zu at 0x%zx, bad registry",
                 filename, page_size, off);
      goto error;
    }

    if (off + page_size > h->size) {
      SET_ERRNO (ENOTSUP,
                 "%s: page size %zu at 0x%zx extends beyond end of file, bad registry",
                 filename, page_size, off);
      goto error;
    }

    size_t page_offset = le32toh(page->offset_first) + 0x1000;

    if (page_offset != off) {
      SET_ERRNO (ENOTSUP,
                 "%s: declared page offset (0x%zx) does not match computed "
                 "offset (0x%zx), bad registry",
                 filename, page_offset, off);
      goto error;
    }

    /* Read the blocks in this page. */
    size_t blkoff;
    struct ntreg_hbin_block *block;
    size_t seg_len;
    for (blkoff = off + 0x20;
         blkoff < off + page_size;
         blkoff += seg_len) {
      blocks++;

      int is_root = blkoff == h->rootoffs;
      if (is_root)
        seen_root_block = 1;

      block = (struct ntreg_hbin_block *) ((char *) h->addr + blkoff);
      int used;
      seg_len = block_len (h, blkoff, &used);
/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78665 */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-overflow"
      if (seg_len <= 4 || (seg_len & 3) != 0) {
#pragma GCC diagnostic pop
        if (is_root || !h->unsafe) {
          SET_ERRNO (ENOTSUP,
                     "%s, the block at 0x%zx has invalid size %" PRIu32
                     ", bad registry",
                     filename, blkoff, le32toh (block->seg_len));
          goto error;
        } else {
          DEBUG (2,
                 "%s: block at 0x%zx has invalid size %" PRIu32 ", skipping",
                 filename, blkoff, le32toh (block->seg_len));
          break;
        }
      }

      if (h->msglvl >= 2) {
        unsigned char *id = (unsigned char *) block->id;
        int id0 = id[0], id1 = id[1];

        fprintf (stderr, "%s: %s: "
                 "%s block id %d,%d (%c%c) at 0x%zx size %zu%s\n",
                 "hivex", __func__,
                 used ? "used" : "free",
                 id0, id1,
                 c_isprint (id0) ? id0 : '.',
                 c_isprint (id1) ? id1 : '.',
                 blkoff,
                 seg_len, is_root ? " (root)" : "");
      }

      blocks_bytes += seg_len;
      if (seg_len < smallest_block) smallest_block = seg_len;
      if (seg_len > largest_block) largest_block = seg_len;

      if (is_root && !used)
        bad_root_block = 1;

      if (used) {
        used_blocks++;
        used_size += seg_len;

        /* Root block must be an nk-block. */
        if (is_root && (block->id[0] != 'n' || block->id[1] != 'k'))
          bad_root_block = 1;

        /* Note this blkoff is a valid address. */
        BITMAP_SET (h->bitmap, blkoff);
      }
    }
  }

  if (!seen_root_block) {
    SET_ERRNO (ENOTSUP, "%s: no root block found", filename);
    goto error;
  }

  if (bad_root_block) {
    SET_ERRNO (ENOTSUP, "%s: bad root block (free or not nk)", filename);
    goto error;
  }

  DEBUG (1, "successfully read Windows Registry hive file:\n"
         "  pages:          %zu [sml: %zu, lge: %zu]\n"
         "  blocks:         %zu [sml: %zu, avg: %zu, lge: %zu]\n"
         "  blocks used:    %zu\n"
         "  bytes used:     %zu",
         pages, smallest_page, largest_page,
         blocks, smallest_block, blocks_bytes / blocks, largest_block,
         used_blocks, used_size);

  return h;

 error:;
  int err = errno;
  if (h) {
    free (h->bitmap);
    if (h->addr && h->size && h->addr != MAP_FAILED) {
      if (!h->writable)
        munmap (h->addr, h->size);
      else
        free (h->addr);
    }
    if (h->fd >= 0)
      close (h->fd);
    free (h->filename);
    free (h);
  }
  errno = err;
  return NULL;
}
Пример #14
0
static void *
format_parse (const char *format, bool translated, char **invalid_reason)
{
  struct spec spec;
  struct spec *result;

  spec.directives = 0;
  spec.numbered_arg_count = 0;

  for (; *format != '\0';)
    {
      char c = *format++;

      if (c == '{')
	{
	  if (*format == '{')
	    format++;
	  else
	    {
	      /* A directive.  */
	      unsigned int number;

	      spec.directives++;

	      if (!c_isdigit (*format))
		{
		  *invalid_reason =
		    xasprintf (_("In the directive number %u, '{' is not followed by an argument number."), spec.directives);
		  return NULL;
		}
	      number = 0;
	      do
		{
		  number = 10 * number + (*format - '0');
		  format++;
		}
	      while (c_isdigit (*format));

	      if (*format == ',')
		{
		  /* Parse width.  */
		  format++;
		  if (*format == '-')
		    format++;
		  if (!c_isdigit (*format))
		    {
		      *invalid_reason =
			xasprintf (_("In the directive number %u, ',' is not followed by a number."), spec.directives);
		      return NULL;
		    }
		  do
		    format++;
		  while (c_isdigit (*format));
		}

	      if (*format == ':')
		{
		  /* Parse format specifiers.  */
		  do
		    format++;
		  while (*format != '\0' && *format != '}');
		}

	      if (*format == '\0')
		{
		  *invalid_reason =
		    xstrdup (_("The string ends in the middle of a directive: found '{' without matching '}'."));
		  return NULL;
		}

	      if (*format != '}')
		{
		  *invalid_reason =
		    (c_isprint (*format)
		     ? xasprintf (_("The directive number %u ends with an invalid character '%c' instead of '}'."), spec.directives, *format)
		     : xasprintf (_("The directive number %u ends with an invalid character instead of '}'."), spec.directives));
		  return NULL;
		}

	      format++;

	      if (spec.numbered_arg_count <= number)
		spec.numbered_arg_count = number + 1;
	    }
	}
      else if (c == '}')
	{
	  if (*format == '}')
	    format++;
	  else
	    {
	      *invalid_reason =
		(spec.directives == 0
		 ? xstrdup (_("The string starts in the middle of a directive: found '}' without matching '{'."))
		 : xasprintf (_("The string contains a lone '}' after directive number %u."), spec.directives));
	      return NULL;
	    }
	}
    }

  result = (struct spec *) xmalloc (sizeof (struct spec));
  *result = spec;
  return result;
}
Пример #15
0
int
guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
{
  char summary[MAX_MESSAGE_SUMMARY];
  fd_set rset, rset2;

  FD_ZERO (&rset);

  if (g->fd[1] >= 0)            /* Read qemu stdout for log messages & EOF. */
    FD_SET (g->fd[1], &rset);
  FD_SET (g->sock, &rset);      /* Read socket for data & EOF. */

  int max_fd = MAX (g->sock, g->fd[1]);

  *size_rtn = 0;
  *buf_rtn = NULL;

  char lenbuf[4];
  /* nr is the size of the message, but we prime it as -4 because we
   * have to read the message length word first.
   */
  ssize_t nr = -4;

  for (;;) {
    ssize_t message_size =
      *size_rtn != GUESTFS_PROGRESS_FLAG ?
      *size_rtn : PROGRESS_MESSAGE_SIZE;
    if (nr >= message_size)
      break;

    rset2 = rset;
    int r = select (max_fd+1, &rset2, NULL, NULL, NULL);
    if (r == -1) {
      if (errno == EINTR || errno == EAGAIN)
        continue;
      perrorf (g, "select");
      free (*buf_rtn);
      *buf_rtn = NULL;
      return -1;
    }

    if (g->fd[1] >= 0 && FD_ISSET (g->fd[1], &rset2)) {
      if (read_log_message_or_eof (g, g->fd[1], 0) == -1) {
        free (*buf_rtn);
        *buf_rtn = NULL;
        return -1;
      }
    }
    if (FD_ISSET (g->sock, &rset2)) {
      if (nr < 0) {    /* Have we read the message length word yet? */
        r = read (g->sock, lenbuf+nr+4, -nr);
        if (r == -1) {
          if (errno == EINTR || errno == EAGAIN)
            continue;
          int err = errno;
          perrorf (g, "read");
          /* Under some circumstances we see "Connection reset by peer"
           * here when the child dies suddenly.  Catch this and call
           * the cleanup function, same as for EOF.
           */
          if (err == ECONNRESET)
            child_cleanup (g);
          return -1;
        }
        if (r == 0) {
          unexpected_end_of_file_from_daemon_error (g);
          child_cleanup (g);
          return -1;
        }
        nr += r;

        if (nr < 0)         /* Still not got the whole length word. */
          continue;

        XDR xdr;
        xdrmem_create (&xdr, lenbuf, 4, XDR_DECODE);
        xdr_uint32_t (&xdr, size_rtn);
        xdr_destroy (&xdr);

        /* *size_rtn changed, recalculate message_size */
        message_size =
          *size_rtn != GUESTFS_PROGRESS_FLAG ?
          *size_rtn : PROGRESS_MESSAGE_SIZE;

        if (*size_rtn == GUESTFS_LAUNCH_FLAG) {
          if (g->state != LAUNCHING)
            error (g, _("received magic signature from guestfsd, but in state %d"),
                   g->state);
          else {
            g->state = READY;
            guestfs___call_callbacks_void (g, GUESTFS_EVENT_LAUNCH_DONE);
          }
          debug (g, "recv_from_daemon: received GUESTFS_LAUNCH_FLAG");
          return 0;
        }
        else if (*size_rtn == GUESTFS_CANCEL_FLAG) {
          debug (g, "recv_from_daemon: received GUESTFS_CANCEL_FLAG");
          return 0;
        }
        else if (*size_rtn == GUESTFS_PROGRESS_FLAG)
          /*FALLTHROUGH*/;
        /* If this happens, it's pretty bad and we've probably lost
         * synchronization.
         */
        else if (*size_rtn > GUESTFS_MESSAGE_MAX) {
          error (g, _("message length (%u) > maximum possible size (%d)"),
                 (unsigned) *size_rtn, GUESTFS_MESSAGE_MAX);
          return -1;
        }

        /* Allocate the complete buffer, size now known. */
        *buf_rtn = safe_malloc (g, message_size);
        /*FALLTHROUGH*/
      }

      size_t sizetoread = message_size - nr;
      if (sizetoread > BUFSIZ) sizetoread = BUFSIZ;

      r = read (g->sock, (char *) (*buf_rtn) + nr, sizetoread);
      if (r == -1) {
        if (errno == EINTR || errno == EAGAIN)
          continue;
        perrorf (g, "read");
        free (*buf_rtn);
        *buf_rtn = NULL;
        return -1;
      }
      if (r == 0) {
        unexpected_end_of_file_from_daemon_error (g);
        child_cleanup (g);
        free (*buf_rtn);
        *buf_rtn = NULL;
        return -1;
      }
      nr += r;
    }
  }

  /* Got the full message, caller can start processing it. */
#ifdef ENABLE_PACKET_DUMP
  if (g->verbose) {
    ssize_t i, j;

    for (i = 0; i < nr; i += 16) {
      printf ("%04zx: ", i);
      for (j = i; j < MIN (i+16, nr); ++j)
        printf ("%02x ", (*(unsigned char **)buf_rtn)[j]);
      for (; j < i+16; ++j)
        printf ("   ");
      printf ("|");
      for (j = i; j < MIN (i+16, nr); ++j)
        if (c_isprint ((*(char **)buf_rtn)[j]))
          printf ("%c", (*(char **)buf_rtn)[j]);
        else
          printf (".");
      for (; j < i+16; ++j)
        printf (" ");
      printf ("|\n");
    }
  }
#endif

  if (*size_rtn == GUESTFS_PROGRESS_FLAG) {
    guestfs_progress message;
    XDR xdr;

    xdrmem_create (&xdr, *buf_rtn, PROGRESS_MESSAGE_SIZE, XDR_DECODE);
    xdr_guestfs_progress (&xdr, &message);
    xdr_destroy (&xdr);

    guestfs___progress_message_callback (g, &message);

    free (*buf_rtn);
    *buf_rtn = NULL;

    /* Process next message. */
    return guestfs___recv_from_daemon (g, size_rtn, buf_rtn);
  }

  debug (g, "recv_from_daemon: %" PRIu32 " bytes: %s", *size_rtn,
         message_summary (*buf_rtn, *size_rtn, summary));

  return 0;
}
Пример #16
0
static void
test_all (void)
{
  int c;

  for (c = -0x80; c < 0x100; c++)
    {
      ASSERT (c_isascii (c) == (c >= 0 && c < 0x80));

      switch (c)
        {
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
        case 'Y': case 'Z':
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
        case 'y': case 'z':
        case '0': case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9':
          ASSERT (c_isalnum (c) == 1);
          break;
        default:
          ASSERT (c_isalnum (c) == 0);
          break;
        }

      switch (c)
        {
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
        case 'Y': case 'Z':
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
        case 'y': case 'z':
          ASSERT (c_isalpha (c) == 1);
          break;
        default:
          ASSERT (c_isalpha (c) == 0);
          break;
        }

      switch (c)
        {
        case '\t': case ' ':
          ASSERT (c_isblank (c) == 1);
          break;
        default:
          ASSERT (c_isblank (c) == 0);
          break;
        }

      ASSERT (c_iscntrl (c) == ((c >= 0 && c < 0x20) || c == 0x7f));

      switch (c)
        {
        case '0': case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9':
          ASSERT (c_isdigit (c) == 1);
          break;
        default:
          ASSERT (c_isdigit (c) == 0);
          break;
        }

      switch (c)
        {
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
        case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
        case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
        case 's': case 't': case 'u': case 'v': case 'w': case 'x':
        case 'y': case 'z':
          ASSERT (c_islower (c) == 1);
          break;
        default:
          ASSERT (c_islower (c) == 0);
          break;
        }

      ASSERT (c_isgraph (c) == ((c >= 0x20 && c < 0x7f) && c != ' '));

      ASSERT (c_isprint (c) == (c >= 0x20 && c < 0x7f));

      ASSERT (c_ispunct (c) == (c_isgraph (c) && !c_isalnum (c)));

      switch (c)
        {
        case ' ': case '\t': case '\n': case '\v': case '\f': case '\r':
          ASSERT (c_isspace (c) == 1);
          break;
        default:
          ASSERT (c_isspace (c) == 0);
          break;
        }

      switch (c)
        {
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
        case 'Y': case 'Z':
          ASSERT (c_isupper (c) == 1);
          break;
        default:
          ASSERT (c_isupper (c) == 0);
          break;
        }

      switch (c)
        {
        case '0': case '1': case '2': case '3': case '4': case '5':
        case '6': case '7': case '8': case '9':
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
          ASSERT (c_isxdigit (c) == 1);
          break;
        default:
          ASSERT (c_isxdigit (c) == 0);
          break;
        }

      switch (c)
        {
        case 'A':
          ASSERT (c_tolower (c) == 'a');
          ASSERT (c_toupper (c) == c);
          break;
        case 'B':
          ASSERT (c_tolower (c) == 'b');
          ASSERT (c_toupper (c) == c);
          break;
        case 'C':
          ASSERT (c_tolower (c) == 'c');
          ASSERT (c_toupper (c) == c);
          break;
        case 'D':
          ASSERT (c_tolower (c) == 'd');
          ASSERT (c_toupper (c) == c);
          break;
        case 'E':
          ASSERT (c_tolower (c) == 'e');
          ASSERT (c_toupper (c) == c);
          break;
        case 'F':
          ASSERT (c_tolower (c) == 'f');
          ASSERT (c_toupper (c) == c);
          break;
        case 'G':
          ASSERT (c_tolower (c) == 'g');
          ASSERT (c_toupper (c) == c);
          break;
        case 'H':
          ASSERT (c_tolower (c) == 'h');
          ASSERT (c_toupper (c) == c);
          break;
        case 'I':
          ASSERT (c_tolower (c) == 'i');
          ASSERT (c_toupper (c) == c);
          break;
        case 'J':
          ASSERT (c_tolower (c) == 'j');
          ASSERT (c_toupper (c) == c);
          break;
        case 'K':
          ASSERT (c_tolower (c) == 'k');
          ASSERT (c_toupper (c) == c);
          break;
        case 'L':
          ASSERT (c_tolower (c) == 'l');
          ASSERT (c_toupper (c) == c);
          break;
        case 'M':
          ASSERT (c_tolower (c) == 'm');
          ASSERT (c_toupper (c) == c);
          break;
        case 'N':
          ASSERT (c_tolower (c) == 'n');
          ASSERT (c_toupper (c) == c);
          break;
        case 'O':
          ASSERT (c_tolower (c) == 'o');
          ASSERT (c_toupper (c) == c);
          break;
        case 'P':
          ASSERT (c_tolower (c) == 'p');
          ASSERT (c_toupper (c) == c);
          break;
        case 'Q':
          ASSERT (c_tolower (c) == 'q');
          ASSERT (c_toupper (c) == c);
          break;
        case 'R':
          ASSERT (c_tolower (c) == 'r');
          ASSERT (c_toupper (c) == c);
          break;
        case 'S':
          ASSERT (c_tolower (c) == 's');
          ASSERT (c_toupper (c) == c);
          break;
        case 'T':
          ASSERT (c_tolower (c) == 't');
          ASSERT (c_toupper (c) == c);
          break;
        case 'U':
          ASSERT (c_tolower (c) == 'u');
          ASSERT (c_toupper (c) == c);
          break;
        case 'V':
          ASSERT (c_tolower (c) == 'v');
          ASSERT (c_toupper (c) == c);
          break;
        case 'W':
          ASSERT (c_tolower (c) == 'w');
          ASSERT (c_toupper (c) == c);
          break;
        case 'X':
          ASSERT (c_tolower (c) == 'x');
          ASSERT (c_toupper (c) == c);
          break;
        case 'Y':
          ASSERT (c_tolower (c) == 'y');
          ASSERT (c_toupper (c) == c);
          break;
        case 'Z':
          ASSERT (c_tolower (c) == 'z');
          ASSERT (c_toupper (c) == c);
          break;
        case 'a':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'A');
          break;
        case 'b':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'B');
          break;
        case 'c':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'C');
          break;
        case 'd':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'D');
          break;
        case 'e':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'E');
          break;
        case 'f':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'F');
          break;
        case 'g':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'G');
          break;
        case 'h':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'H');
          break;
        case 'i':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'I');
          break;
        case 'j':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'J');
          break;
        case 'k':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'K');
          break;
        case 'l':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'L');
          break;
        case 'm':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'M');
          break;
        case 'n':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'N');
          break;
        case 'o':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'O');
          break;
        case 'p':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'P');
          break;
        case 'q':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'Q');
          break;
        case 'r':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'R');
          break;
        case 's':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'S');
          break;
        case 't':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'T');
          break;
        case 'u':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'U');
          break;
        case 'v':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'V');
          break;
        case 'w':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'W');
          break;
        case 'x':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'X');
          break;
        case 'y':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'Y');
          break;
        case 'z':
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == 'Z');
          break;
        default:
          ASSERT (c_tolower (c) == c);
          ASSERT (c_toupper (c) == c);
          break;
        }
    }
}
Пример #17
0
void
main_loop (int _sock)
{
  XDR xdr;
  char *buf;
  char lenbuf[4];
  uint32_t len;
  struct guestfs_message_header hdr;

  sock = _sock;

  for (;;) {
    /* Read the length word. */
    if (xread (sock, lenbuf, 4) == -1)
      exit (EXIT_FAILURE);

    xdrmem_create (&xdr, lenbuf, 4, XDR_DECODE);
    xdr_u_int (&xdr, &len);
    xdr_destroy (&xdr);

    if (verbose)
      fprintf (stderr,
	       "guestfsd: main_loop: new request, len 0x%" PRIx32 "\n",
	       len);

    /* Cancellation sent from the library and received after the
     * previous request has finished processing.  Just ignore it.
     */
    if (len == GUESTFS_CANCEL_FLAG)
      continue;

    if (len > GUESTFS_MESSAGE_MAX) {
      fprintf (stderr, "guestfsd: incoming message is too long (%u bytes)\n",
               len);
      exit (EXIT_FAILURE);
    }

    buf = malloc (len);
    if (!buf) {
      reply_with_perror ("malloc");
      continue;
    }

    if (xread (sock, buf, len) == -1)
      exit (EXIT_FAILURE);

#ifdef ENABLE_PACKET_DUMP
    if (verbose) {
      size_t i, j;

      for (i = 0; i < len; i += 16) {
        printf ("%04zx: ", i);
        for (j = i; j < MIN (i+16, len); ++j)
          printf ("%02x ", (unsigned char) buf[j]);
        for (; j < i+16; ++j)
          printf ("   ");
        printf ("|");
        for (j = i; j < MIN (i+16, len); ++j)
          if (c_isprint (buf[j]))
            printf ("%c", buf[j]);
          else
            printf (".");
        for (; j < i+16; ++j)
          printf (" ");
        printf ("|\n");
      }
    }
#endif

    gettimeofday (&start_t, NULL);
    last_progress_t = start_t;
    count_progress = 0;

    /* Decode the message header. */
    xdrmem_create (&xdr, buf, len, XDR_DECODE);
    if (!xdr_guestfs_message_header (&xdr, &hdr)) {
      fprintf (stderr, "guestfsd: could not decode message header\n");
      exit (EXIT_FAILURE);
    }

    /* Check the version etc. */
    if (hdr.prog != GUESTFS_PROGRAM) {
      reply_with_error ("wrong program (%u)", hdr.prog);
      goto cont;
    }
    if (hdr.vers != GUESTFS_PROTOCOL_VERSION) {
      reply_with_error ("wrong protocol version (%u)", hdr.vers);
      goto cont;
    }
    if (hdr.direction != GUESTFS_DIRECTION_CALL) {
      reply_with_error ("unexpected message direction (%d)",
                        (int) hdr.direction);
      goto cont;
    }
    if (hdr.status != GUESTFS_STATUS_OK) {
      reply_with_error ("unexpected message status (%d)", (int) hdr.status);
      goto cont;
    }

    proc_nr = hdr.proc;
    serial = hdr.serial;
    progress_hint = hdr.progress_hint;
    optargs_bitmask = hdr.optargs_bitmask;

    /* Clear errors before we call the stub functions.  This is just
     * to ensure that we can accurately report errors in cases where
     * error handling paths don't set errno correctly.
     */
    errno = 0;
#ifdef WIN32
    SetLastError (0);
    WSASetLastError (0);
#endif

    /* Now start to process this message. */
    dispatch_incoming_message (&xdr);
    /* Note that dispatch_incoming_message will also send a reply. */

    /* In verbose mode, display the time taken to run each command. */
    if (verbose) {
      struct timeval end_t;
      gettimeofday (&end_t, NULL);

      int64_t start_us, end_us, elapsed_us;
      start_us = (int64_t) start_t.tv_sec * 1000000 + start_t.tv_usec;
      end_us = (int64_t) end_t.tv_sec * 1000000 + end_t.tv_usec;
      elapsed_us = end_us - start_us;

      fprintf (stderr,
	       "guestfsd: main_loop: proc %d (%s) took %d.%02d seconds\n",
               proc_nr,
               proc_nr >= 0 && proc_nr <= GUESTFS_MAX_PROC_NR
               ? function_names[proc_nr] : "UNKNOWN PROCEDURE",
               (int) (elapsed_us / 1000000),
               (int) ((elapsed_us / 10000) % 100));
    }

  cont:
    xdr_destroy (&xdr);
    free (buf);
  }
}
Пример #18
0
static void
output_binary (const char *s, size_t len)
{
    size_t i;

    next_field ();

    if (!csv) {
print_no_quoting:
        for (i = 0; i < len; ++i) {
            if (c_isprint (s[i])) {
                if (putchar (s[i]) == EOF) {
                    perror ("putchar");
                    exit (EXIT_FAILURE);
                }
            } else {
                if (printf ("\\x%02x", (unsigned char) s[i]) < 0) {
                    perror ("printf");
                    exit (EXIT_FAILURE);
                }
            }
        }
    }
    else {
        /* Quote CSV string without requiring an external module. */
        int needs_quoting = 0;

        for (i = 0; i < len; ++i) {
            if (!c_isprint (s[i]) || s[i] == ' ' || s[i] == '"' ||
                    s[i] == '\n' || s[i] == ',') {
                needs_quoting = 1;
                break;
            }
        }

        if (!needs_quoting)
            goto print_no_quoting;

        /* Quoting for CSV fields. */
        if (putchar ('"') == EOF) {
            perror ("putchar");
            exit (EXIT_FAILURE);
        }
        for (i = 0; i < len; ++i) {
            if (s[i] == '"') {
                if (putchar ('"') == EOF || putchar ('"') == EOF) {
                    perror ("putchar");
                    exit (EXIT_FAILURE);
                }
            } else {
                if (c_isprint (s[i])) {
                    if (putchar (s[i]) == EOF) {
                        perror ("putchar");
                        exit (EXIT_FAILURE);
                    }
                } else {
                    if (printf ("\\x%2x", s[i]) < 0) {
                        perror ("printf");
                        exit (EXIT_FAILURE);
                    }
                }
            }
        }
        if (putchar ('"') == EOF) {
            perror ("putchar");
            exit (EXIT_FAILURE);
        }
    }
}