static void contract_and_expand(const char *data, size_t s_window, uint32_t base, size_t s_pcodes) { struct diag_vcdiff_script *script; struct diag_rollinghash32 *rh; size_t size, s; uint8_t *result; char *result0; size = strlen(data); rh = (struct diag_rollinghash32 *)diag_rollinghash32_new_rabin_karp((const uint8_t *)data, size, s_window, base); ASSERT_NOT_NULL(rh); script = diag_vcdiff_contract(rh); ASSERT_NOT_NULL(script); dump_pcodes(script); ASSERT_EQ_UINT(s_pcodes, script->s_pcodes); result = diag_vcdiff_expand(script, &s); ASSERT_EQ_UINT(size, s); result0 = diag_malloc(s + 1); (void)memcpy(result0, result, s); result0[s] = '\0'; ASSERT_EQ_STRING(data, result0); diag_free(result0); diag_free(result); diag_vcdiff_script_destroy(script); diag_rollinghash32_destroy(rh); }
int main(void) { struct diag_vcdiff_pcode *pcodes; struct diag_vcdiff_script *script; uint8_t *result; size_t size, i; pcodes = diag_calloc(2, sizeof(struct diag_vcdiff_pcode)); pcodes[0].inst = DIAG_VCD_RUN; pcodes[0].size = 1; pcodes[0].attr.byte = 'a'; pcodes[1].inst = DIAG_VCD_COPY; pcodes[1].size = 20; pcodes[1].attr.addr = 0; script = diag_malloc(sizeof(struct diag_vcdiff_script)); script->source = NULL; script->s_pcodes = 2; script->pcodes = pcodes; result = diag_vcdiff_expand(script, &size); ASSERT_NOT_NULL(result); ASSERT_EQ_UINT32(21, size); for (i = 0; i < size; i++) { ASSERT_EQ_UINT8('a', result[i]); } diag_free(result); diag_free(script); diag_free(pcodes); return EXIT_SUCCESS; }
void diag_deque_destroy(struct diag_deque *deque) { if (deque) { struct diag_deque_elem *elem = deque->first; while (elem) { struct diag_deque_elem *tmp = elem; elem = tmp->next; diag_free(tmp); } diag_free(deque); } }
int hash_table_remove(hash_table * hash_t, void *key, void **pdata) { hash_node **node, *dest; node = hash_table_lookup_node(hash_t, key); if (*node) { if (pdata != NULL) *pdata = (*node)->value; dest = *node; *node = dest->next; if (pdata == NULL) { if (hash_t->hash_free) hash_t->hash_free(dest->value); } diag_free(dest); hash_t->nnodes--; hash_table_resize(hash_t); return 1; } return 0; }
hash_table * hash_table_new(hash_func hash_f, hash_comp hash_c, hash_free hash_fr) { hash_table *hash_t; hash_t = (struct _hash_table *) diag_malloc(sizeof(hash_table)); if (hash_t == NULL) diag_fatal("Unable to allocate memory\n"); hash_t->size = HASH_TABLE_MIN_SIZE; hash_t->nnodes = 0; if (hash_f) hash_t->hash_func = default_hash_func; else hash_t->hash_func = hash_f; if (hash_c) hash_t->hash_comp = default_compare_func; else hash_t->hash_comp = hash_c; hash_t->hash_free = hash_fr; hash_t->nodes = (hash_node **) diag_malloc(sizeof(hash_node *) * hash_t->size); if (hash_t->nodes == NULL) { diag_free(hash_t); diag_fatal("Unable to allocate memory\n"); } memset(hash_t->nodes, 0, sizeof(hash_node *) * hash_t->size); return hash_t; }
char *diag_get_command_line(char **argv) { assert(argv); char *line = diag_malloc(32768); char *lp = line; int i; for (i = 0; argv[i]; i++) { const char *s = argv[i]; int slen = (int)strlen(s); if (lp + slen >= line + 32768) { diag_free(line); return NULL; } if (i > 0) { *lp++ = ' '; } if (contains_space(s)) { *lp++ = '"'; strcpy(lp, s); lp += slen; *lp++ = '"'; } else { strcpy(lp, s); lp += slen; } } *lp = '\0'; return line; }
void diag_datum_destroy(struct diag_datum *datum) { if (!datum) return; if (DIAG_DATUM_CUSTOMIZED_P(datum)) { struct diag_customized_datum *customized_datum; customized_datum = (struct diag_customized_datum *)datum; customized_datum->finalize(datum); } diag_free(datum); }
void hash_table_destroy(hash_table * hash_t) { long i; hash_node *next, *hash_n; for (i = 0; i < hash_t->size; i++) { hash_n = hash_t->nodes[i]; while (hash_n) { next = hash_n->next; if (hash_t->hash_free) hash_t->hash_free(hash_n->value); diag_free(hash_n); hash_n = next; } } diag_free(hash_t->nodes); diag_free(hash_t); }
void diag_command_destroy(struct diag_command *command) { if (!command) return; int i; for (i = 0; command->argv[i]; i++) { diag_free(command->argv[i]); } diag_free(command->argv); diag_free(command->dir); diag_free(command->in); diag_free(command->out); diag_free(command->err); diag_free(command); }
intptr_t diag_run_agent(char **argv) { SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; STARTUPINFO si; GetStartupInfo(&si); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); char *line = diag_get_command_line(argv); BOOL b = CreateProcess(NULL, line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); if (!b) { diag_fatal("could not create process: %s: 0x%x", line, (unsigned int)GetLastError()); } /* We do not want WaitForInputIdle() because there is no interaction between the parent process and this child */ diag_free(line); CloseHandle(pi.hThread); return (intptr_t)pi.hProcess; }
void hash_table_removecurrval(hash_table_iter *iterator) { if (iterator) if (iterator->hash_t && iterator->curr_item) { hash_node *dest, *removed = *(iterator->curr_item); if (removed) { hash_table *hash_t = iterator->hash_t; dest = removed; removed = dest->next; if (hash_t->hash_free) hash_t->hash_free(dest->value); diag_free(dest); hash_t->nnodes--; } } }
static void hash_table_resize(hash_table * hash_t) { hash_node **new_nodes; hash_node *node; hash_node *next; long hash_val; long new_size; long i; if ((hash_t->size >= 3 * hash_t->nnodes && hash_t->size > HASH_TABLE_MIN_SIZE) || (3 * hash_t->size <= hash_t->nnodes && hash_t->size < HASH_TABLE_MAX_SIZE)) { new_size = get_closest(hash_t->nnodes); new_nodes = (hash_node **) diag_malloc(sizeof(hash_node *) * new_size); if (new_nodes == NULL) { diag_msg("Unable to allocate memory\n"); return; } memset(new_nodes, 0, sizeof(hash_node *) * new_size); for (i = 0; i < hash_t->size; i++) for (node = hash_t->nodes[i]; node; node = next) { next = node->next; hash_val = (*hash_t->hash_func) (node->key, new_size); node->next = new_nodes[hash_val]; new_nodes[hash_val] = node; } diag_free(hash_t->nodes); hash_t->nodes = new_nodes; hash_t->size = new_size; } }
void diag_analysis_destroy(struct diag_analysis *analysis) { diag_free(analysis); }
void diag_process_destroy(struct diag_process *process) { diag_free(process); }
struct diag_process *diag_run_program(struct diag_command *command) { assert(command); char *out = NULL; if (!command->out) { out = diag_malloc(PATH_LENGTH); } char *err = NULL; if (!command->err) { err = diag_malloc(PATH_LENGTH); } pid_t pid = fork(); if (pid < 0) { perror(command->file); diag_free(out); diag_free(err); return NULL; } if (pid == 0) { pid = getpid(); if (!command->out) { build_path(command->dir, pid, "out", out); command->out = out; } if (!command->err) { build_path(command->dir, pid, "err", err); command->err = err; } if (command->in) { /* redirect stdin only when specified */ if (!freopen(command->in, "rb", stdin)) { perror(command->in); _Exit(EXIT_FAILURE); } } /* Both stdout and stderr should be always redirected */ if (!freopen(command->out, "wb", stdout)) { perror(command->out); _Exit(EXIT_FAILURE); } if (!freopen(command->err, "wb", stderr)) { perror(command->err); _Exit(EXIT_FAILURE); } if (execvp(command->file, command->argv) == -1) { perror(command->file); _Exit(EXIT_FAILURE); } } if (!command->out) { build_path(command->dir, pid, "out", out); command->out = out; } if (!command->err) { build_path(command->dir, pid, "err", err); command->err = err; } struct diag_process *p = diag_malloc(sizeof(*p)); p->pid = (intptr_t)pid; p->status = 0; return p; }
/* * References: * * How to spawn console processes with redirected standard handles * http://support.microsoft.com/kb/190351 */ struct diag_process *diag_run_program(struct diag_command *command) { assert(command); if (!command->out) { command->out = diag_malloc(PATH_LENGTH); build_path(command->dir, local_pid, "out", command->out); } if (!command->err) { command->err = diag_malloc(PATH_LENGTH); build_path(command->dir, local_pid, "err", command->err); } local_pid++; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; HANDLE ih = NULL; if (command->in) { ih = CreateFile(command->in, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING, 0, NULL); if (ih == INVALID_HANDLE_VALUE) { diag_error("failed to open file: %s: 0x%x", command->in, (unsigned int)GetLastError()); return NULL; } } HANDLE oh = CreateFile(command->out, GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_DELETE, &sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (oh == INVALID_HANDLE_VALUE) { diag_error("failed to open file: %s: 0x%x", command->out, (unsigned int)GetLastError()); return NULL; } HANDLE eh = CreateFile(command->err, GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_DELETE, &sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (eh == INVALID_HANDLE_VALUE) { diag_error("failed to open file: %s: 0x%x", command->err, (unsigned int)GetLastError()); return NULL; } STARTUPINFO si; GetStartupInfo(&si); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = ih; si.hStdOutput = oh; si.hStdError = eh; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); char *line = diag_get_command_line(command->argv); BOOL b = CreateProcess(NULL, line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); if (!b) { diag_error("could not create process: %s: 0x%x", line, (unsigned int)GetLastError()); // should follow GetLastError() diag_free(line); if (ih) CloseHandle(ih); CloseHandle(oh); CloseHandle(eh); return NULL; } /* We do not want WaitForInputIdle() because there is no interaction between the parent process and this child */ diag_free(line); if (ih) CloseHandle(ih); CloseHandle(oh); CloseHandle(eh); CloseHandle(pi.hThread); struct diag_process *p = diag_malloc(sizeof(*p)); p->pid = (intptr_t)pi.hProcess; return p; }
void hash_str_free(void *str) { if (str != NULL) diag_free(str); }
void *diag_qselect(void *base, size_t nmemb, size_t size, int (*cmp)(const void *, const void *), size_t k) { assert(base); assert(nmemb > 0); assert(size > 0); if (nmemb <= k) return NULL; if (nmemb == 1) return base; int *rv = diag_calloc(nmemb, sizeof(int)); size_t i; size_t n_lt; size_t n_gt; size_t n_eq; char *p; partition: assert(k < nmemb); if (nmemb == 1) goto done; n_lt = 0; n_gt = 0; p = (char *)base; for (i = 1; i < nmemb; i++) { int r = cmp(p, p + size * i); if (r < 0) n_lt++; if (0 < r) n_gt++; rv[i] = r; } n_eq = nmemb - n_lt - n_gt; if (k < n_lt) { size_t j = n_lt + 1; for (i = 1; i <= n_lt; i++) { if (rv[i] >= 0) { while (j < nmemb && rv[j] >= 0) { j++; } assert(j < nmemb); memcpy(p + size * i, p + size * j++, size); } } base = p + size; nmemb = n_lt; /* k is unchanged */ goto partition; } if (k >= n_lt + n_eq) { size_t j = n_gt + 1; for (i = 1; i <= n_gt; i++) { if (rv[i] <= 0) { while (j < nmemb && rv[j] <= 0) { j++; } assert(j < nmemb); memcpy(p + size * i, p + size * j++, size); } } base = p + size; nmemb = n_gt; k -= n_lt + n_eq; goto partition; } done: diag_free(rv); return base; }
int main(void) { struct diag_deque *head, *tail; struct diag_deque_elem *elem; intptr_t i; size_t len; head = diag_deque_new(); tail = diag_deque_new(); /* both are empty */ len = diag_deque_append(head, tail); ASSERT_EQ_UINT(0, len); ASSERT_EQ_UINT(0, head->length); ASSERT_EQ_UINT(0, tail->length); /* head is trivial */ i = 0; while (i < 29) { diag_deque_push(tail, i++); } len = diag_deque_append(head, tail); ASSERT_EQ_UINT(29, head->length); ASSERT_EQ_UINT(0, tail->length); i = 0; while ( (elem = diag_deque_shift(head)) ) { ASSERT_EQ_UINTPTR(i++, elem->attr); diag_free(elem); } ASSERT_EQ_UINTPTR(29, i); /* tail is trivial */ i = 0; while (i < 31) { diag_deque_push(head, i++); } len = diag_deque_append(head, tail); ASSERT_EQ_UINT(31, head->length); ASSERT_EQ_UINT(0, tail->length); i = 0; while ( (elem = diag_deque_shift(head)) ) { ASSERT_EQ_UINTPTR(i++, elem->attr); diag_free(elem); } ASSERT_EQ_UINTPTR(31, i); /* general */ i = 0; while (i < 100) { diag_deque_push(head, i++); } while (i < 300) { diag_deque_push(tail, i++); } len = diag_deque_append(head, tail); ASSERT_EQ_UINT(300, len); ASSERT_EQ_UINT(300, head->length); ASSERT_EQ_UINT(0, tail->length); i = 0; while ( (elem = diag_deque_shift(head)) ) { ASSERT_EQ_UINTPTR(i++, elem->attr); diag_free(elem); } ASSERT_EQ_UINTPTR(300, i); diag_deque_destroy(head); diag_deque_destroy(tail); return EXIT_SUCCESS; }
void diag_delta_destroy(struct diag_delta *delta) { diag_free(delta); }
void diag_code_destroy(struct diag_code *datum) { diag_free(datum); }
int main(int argc, char *argv[]) { int c; int n = 0; int r = EXIT_FAILURE; char *in = NULL; diag_init(); while ( (c = getopt(argc, argv, "+Vhi:n:")) >=0) { switch (c) { case 'V': diag_print_version(); exit(EXIT_SUCCESS); break; case 'h': usage(); exit(EXIT_SUCCESS); break; case 'i': in = optarg; break; case 'n': n = atoi(optarg); if (n < 0) { diag_fatal("non-negative integer expected, but %d", n); } else if (n == 0) { exit(EXIT_SUCCESS); } break; case ':': case '?': usage(); exit(EXIT_FAILURE); break; } } if (!argv[optind]) { usage(); exit(EXIT_FAILURE); } if (n == 0) { diag_fatal("please specify the number with the -n option"); } char *tfin = NULL; if (!in) { struct diag_temporary_file *tf = diag_temporary_file_new(); if (!tf) { return EXIT_FAILURE; } tfin = diag_strdup(tf->path); struct diag_port *ip = diag_port_new_stdin(); assert(ip); ssize_t s = diag_port_copy(ip, tf->port); diag_port_destroy(ip); diag_temporary_file_destroy(tf); if (s < 0) { assert(tfin); diag_remove(tfin); diag_free(tfin); return EXIT_FAILURE; } } int i = 0; char *file = in ? in : tfin; struct diag_command *cmd; run: cmd = diag_command_new(argv + optind, NULL, file, NULL, NULL); if (!cmd) { goto done; } struct diag_process *p = diag_run_program(cmd); if (!p) { goto done; } diag_process_wait(p); int status = p->status; diag_process_destroy(p); if (status != 0) { r = status; goto done; } assert(cmd->err); diag_remove(cmd->err); if (i) { diag_remove(file); diag_free(file); } else if (tfin) { diag_remove(tfin); diag_free(tfin); tfin = NULL; } if (++i < n) { file = diag_strdup(cmd->out); diag_command_destroy(cmd); goto run; } struct diag_port *ip = diag_port_new_path(cmd->out, "rb"); if (!ip) { goto done; } struct diag_port *op = diag_port_new_stdout(); assert(op); ssize_t s = diag_port_copy(ip, op); diag_port_destroy(op); diag_port_destroy(ip); if (s < 0) { goto done; } diag_remove(cmd->out); r = EXIT_SUCCESS; done: diag_command_destroy(cmd); if (tfin) { diag_remove(tfin); diag_free(tfin); } return r; }
void diag_cluster_destroy(struct diag_cluster *cluster) { diag_free(cluster); }