static bool try_command(json_t *cmd, int timeout) { int fd; int res; int tries; w_jbuffer_t buffer; fd = socket(PF_LOCAL, SOCK_STREAM, 0); if (fd == -1) { perror("socket"); return false; } tries = 0; do { res = connect(fd, (struct sockaddr*)&un, sizeof(un)); if (res == 0) { break; } if (timeout && tries < timeout && should_start(errno)) { // Wait for socket to come up sleep(1); continue; } } while (++tries < timeout); if (res) { close(fd); return false; } if (!cmd) { close(fd); return true; } w_json_buffer_init(&buffer); // Send command w_json_buffer_write(&buffer, fd, cmd, JSON_COMPACT); do { if (!read_response(&buffer, fd)) { w_json_buffer_free(&buffer); close(fd); return false; } } while (persistent); w_json_buffer_free(&buffer); close(fd); return true; }
static bool try_command(json_t *cmd, int timeout) { w_stm_t client = NULL; w_jbuffer_t buffer; w_jbuffer_t output_pdu_buffer; int err; client = w_stm_connect(sock_name, timeout * 1000); if (client == NULL) { return false; } if (!cmd) { w_stm_close(client); return true; } w_json_buffer_init(&buffer); // Send command if (!w_ser_write_pdu(server_pdu, &buffer, client, cmd)) { err = errno; w_log(W_LOG_ERR, "error sending PDU to server\n"); w_json_buffer_free(&buffer); w_stm_close(client); errno = err; return false; } w_json_buffer_reset(&buffer); w_json_buffer_init(&output_pdu_buffer); do { if (!w_json_buffer_passthru( &buffer, output_pdu, &output_pdu_buffer, client)) { err = errno; w_json_buffer_free(&buffer); w_json_buffer_free(&output_pdu_buffer); w_stm_close(client); errno = err; return false; } } while (persistent); w_json_buffer_free(&buffer); w_json_buffer_free(&output_pdu_buffer); w_stm_close(client); return true; }
static void client_delete(w_ht_val_t val) { struct watchman_client *client = (struct watchman_client*)val; /* cancel subscriptions */ w_ht_free(client->subscriptions); w_json_buffer_free(&client->reader); w_json_buffer_free(&client->writer); close(client->ping[0]); close(client->ping[1]); close(client->fd); free(client); }
bool w_state_save(void) { json_t *state; w_jbuffer_t buffer; int fd = -1; char tmpname[WATCHMAN_NAME_MAX]; bool result = false; if (dont_save_state) { return true; } pthread_mutex_lock(&state_lock); state = json_object(); if (!w_json_buffer_init(&buffer)) { w_log(W_LOG_ERR, "save_state: failed to init json buffer\n"); goto out; } snprintf(tmpname, sizeof(tmpname), "%sXXXXXX", watchman_state_file); fd = w_mkstemp(tmpname); if (fd == -1) { w_log(W_LOG_ERR, "save_state: unable to create temporary file: %s\n", strerror(errno)); goto out; } json_object_set_new(state, "version", json_string(PACKAGE_VERSION)); /* now ask the different subsystems to fill out the state */ if (!w_root_save_state(state)) { goto out; } /* we've prepared what we're going to save, so write it out */ w_json_buffer_write(&buffer, fd, state, JSON_INDENT(4)); /* atomically replace the old contents */ result = rename(tmpname, watchman_state_file) == 0; out: if (state) { json_decref(state); } w_json_buffer_free(&buffer); if (fd != -1) { if (!result) { // If we didn't succeed, remove our temporary file unlink(tmpname); } close(fd); } pthread_mutex_unlock(&state_lock); return result; }
static json_t *build_command(int argc, char **argv) { json_t *cmd; int i; // Read blob from stdin if (json_input_arg) { json_error_t err; w_jbuffer_t buf; memset(&err, 0, sizeof(err)); w_json_buffer_init(&buf); cmd = w_json_buffer_next(&buf, w_stm_stdin(), &err); if (buf.pdu_type == is_bser) { // If they used bser for the input, select bser for output // unless they explicitly requested something else if (!server_encoding) { server_pdu = is_bser; } if (!output_encoding) { output_pdu = is_bser; } } else if (buf.pdu_type == is_bser_v2) { // If they used bser v2 for the input, select bser v2 for output // unless they explicitly requested something else if (!server_encoding) { server_pdu = is_bser_v2; } if (!output_encoding) { output_pdu = is_bser_v2; } } w_json_buffer_free(&buf); if (cmd == NULL) { fprintf(stderr, "failed to parse command from stdin: %s\n", err.text); exit(1); } return cmd; } // Special case: no arguments means that we just want // to verify that the service is up, starting it if // needed if (argc == 0) { return NULL; } cmd = json_array(); for (i = 0; i < argc; i++) { json_array_append_new(cmd, json_string(argv[i])); } return cmd; }
static void client_delete(struct watchman_client *client) { struct watchman_client_response *resp; w_log(W_LOG_DBG, "client_delete %p\n", client); derived_client_dtor(client); while (client->head) { resp = client->head; client->head = resp->next; json_decref(resp->json); free(resp); } w_json_buffer_free(&client->reader); w_json_buffer_free(&client->writer); w_event_destroy(client->ping); w_stm_shutdown(client->stm); w_stm_close(client->stm); free(client); }
static void client_delete(w_ht_val_t val) { struct watchman_client *client = w_ht_val_ptr(val); struct watchman_client_response *resp; /* cancel subscriptions */ w_ht_free(client->subscriptions); while (client->head) { resp = client->head; client->head = resp->next; json_decref(resp->json); free(resp); } w_json_buffer_free(&client->reader); w_json_buffer_free(&client->writer); close(client->ping[0]); close(client->ping[1]); close(client->fd); free(client); }
static void client_delete(w_ht_val_t val) { struct watchman_client *client = w_ht_val_ptr(val); struct watchman_client_response *resp; w_log(W_LOG_DBG, "client_delete %p\n", client); /* cancel subscriptions */ w_ht_free(client->subscriptions); while (client->head) { resp = client->head; client->head = resp->next; json_decref(resp->json); free(resp); } w_json_buffer_free(&client->reader); w_json_buffer_free(&client->writer); w_event_destroy(client->ping); w_stm_close(client->stm); free(client); }
void preprocess_command(json_t *args, enum w_pdu_type output_pdu) { char *errmsg = NULL; struct watchman_command_handler_def *def; def = lookup(args, &errmsg, 0); if (!def && !errmsg) { // Nothing known about it, pass the command on anyway for forwards // compatibility return; } if (!errmsg && def->cli_validate) { def->cli_validate(args, &errmsg); } if (errmsg) { w_jbuffer_t jr; json_t *err = json_pack( "{s:s, s:s, s:b}", "error", errmsg, "version", PACKAGE_VERSION, "cli_validated", true ); w_json_buffer_init(&jr); w_ser_write_pdu(output_pdu, &jr, w_stm_stdout(), err); json_decref(err); w_json_buffer_free(&jr); free(errmsg); exit(1); } }
static int prepare_stdin( struct watchman_trigger_command *cmd, w_query_res *res) { uint32_t n_files; char stdin_file_name[WATCHMAN_NAME_MAX]; int stdin_fd = -1; if (cmd->stdin_style == input_dev_null) { return open("/dev/null", O_RDONLY|O_CLOEXEC); } n_files = res->num_results; if (cmd->max_files_stdin > 0) { n_files = MIN(cmd->max_files_stdin, n_files); } /* prepare the input stream for the child process */ snprintf(stdin_file_name, sizeof(stdin_file_name), "%s/wmanXXXXXX", watchman_tmp_dir); stdin_fd = w_mkstemp(stdin_file_name); if (stdin_fd == -1) { w_log(W_LOG_ERR, "unable to create a temporary file: %s\n", strerror(errno)); return -1; } /* unlink the file, we don't need it in the filesystem; * we'll pass the fd on to the child as stdin */ unlink(stdin_file_name); switch (cmd->stdin_style) { case input_json: { w_jbuffer_t buffer; json_t *file_list; if (!w_json_buffer_init(&buffer)) { w_log(W_LOG_ERR, "failed to init json buffer\n"); close(stdin_fd); return -1; } file_list = w_query_results_to_json(&cmd->field_list, n_files, res->results); w_json_buffer_write(&buffer, stdin_fd, file_list, 0); w_json_buffer_free(&buffer); json_decref(file_list); break; } case input_name_list: { struct iovec iov[2]; uint32_t i; iov[1].iov_base = "\n"; iov[1].iov_len = 1; for (i = 0; i < n_files; i++) { iov[0].iov_base = (void*)res->results[i].relname->buf; iov[0].iov_len = res->results[i].relname->len; if (writev(stdin_fd, iov, 2) != (ssize_t)iov[0].iov_len + 1) { w_log(W_LOG_ERR, "write failure while producing trigger stdin: %s\n", strerror(errno)); close(stdin_fd); return -1; } } break; } case input_dev_null: // already handled above break; } lseek(stdin_fd, 0, SEEK_SET); return stdin_fd; }
static bool try_command(json_t *cmd, int timeout) { int fd; int res; int tries; int bufsize; w_jbuffer_t buffer; fd = socket(PF_LOCAL, SOCK_STREAM, 0); if (fd == -1) { perror("socket"); return false; } tries = 0; do { res = connect(fd, (struct sockaddr*)&un, sizeof(un)); if (res == 0) { break; } if (timeout && tries < timeout && should_start(errno)) { // Wait for socket to come up sleep(1); continue; } } while (++tries < timeout); if (res) { close(fd); return false; } if (!cmd) { close(fd); return true; } bufsize = WATCHMAN_IO_BUF_SIZE; setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); w_json_buffer_init(&buffer); // Send command if (!w_ser_write_pdu(server_pdu, &buffer, fd, cmd)) { w_log(W_LOG_ERR, "error sending PDU to server\n"); w_json_buffer_free(&buffer); close(fd); return false; } w_json_buffer_reset(&buffer); do { if (!w_json_buffer_passthru(&buffer, output_pdu, fd)) { w_json_buffer_free(&buffer); close(fd); return false; } } while (persistent); w_json_buffer_free(&buffer); close(fd); return true; }
static w_stm_t prepare_stdin( struct watchman_trigger_command *cmd, w_query_res *res) { uint32_t n_files; char stdin_file_name[WATCHMAN_NAME_MAX]; w_stm_t stdin_file = NULL; if (cmd->stdin_style == input_dev_null) { return w_stm_open("/dev/null", O_RDONLY|O_CLOEXEC); } n_files = res->num_results; if (cmd->max_files_stdin > 0) { n_files = MIN(cmd->max_files_stdin, n_files); } /* prepare the input stream for the child process */ snprintf(stdin_file_name, sizeof(stdin_file_name), "%s%cwmanXXXXXX", watchman_tmp_dir, WATCHMAN_DIR_SEP); stdin_file = w_mkstemp(stdin_file_name); if (!stdin_file) { w_log(W_LOG_ERR, "unable to create a temporary file: %s %s\n", stdin_file_name, strerror(errno)); return NULL; } /* unlink the file, we don't need it in the filesystem; * we'll pass the fd on to the child as stdin */ unlink(stdin_file_name); // FIXME: windows path translation switch (cmd->stdin_style) { case input_json: { w_jbuffer_t buffer; json_t *file_list; if (!w_json_buffer_init(&buffer)) { w_log(W_LOG_ERR, "failed to init json buffer\n"); w_stm_close(stdin_file); return NULL; } file_list = w_query_results_to_json(&cmd->field_list, n_files, res->results); w_log(W_LOG_ERR, "input_json: sending json object to stm\n"); if (!w_json_buffer_write(&buffer, stdin_file, file_list, 0)) { w_log(W_LOG_ERR, "input_json: failed to write json data to stream: %s\n", strerror(errno)); w_stm_close(stdin_file); return NULL; } w_json_buffer_free(&buffer); json_decref(file_list); break; } case input_name_list: { uint32_t i; for (i = 0; i < n_files; i++) { if (w_stm_write(stdin_file, res->results[i].relname->buf, res->results[i].relname->len) != (int)res->results[i].relname->len || w_stm_write(stdin_file, "\n", 1) != 1) { w_log(W_LOG_ERR, "write failure while producing trigger stdin: %s\n", strerror(errno)); w_stm_close(stdin_file); return NULL; } } break; } case input_dev_null: // already handled above break; } w_stm_rewind(stdin_file); return stdin_file; }