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; }
/** * 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; }
/** * 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; }
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, "."); }
/* 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'); } }
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'; }
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); }
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; }
/* 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); }
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 } }
/** * 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; }
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; }
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; }
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; }
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; } } }
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); } }
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); } } }