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 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 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; }
static std::unique_ptr<watchman_stream> prepare_stdin( struct watchman_trigger_command* cmd, w_query_res* res) { char stdin_file_name[WATCHMAN_NAME_MAX]; if (cmd->stdin_style == trigger_input_style::input_dev_null) { return w_stm_open("/dev/null", O_RDONLY|O_CLOEXEC); } // Adjust result to fit within the specified limit if (cmd->max_files_stdin > 0) { auto& fileList = res->resultsArray.array(); auto n_files = std::min(size_t(cmd->max_files_stdin), fileList.size()); fileList.resize(std::min(fileList.size(), n_files)); } /* prepare the input stream for the child process */ snprintf( stdin_file_name, sizeof(stdin_file_name), "%s/wmanXXXXXX", watchman_tmp_dir); auto 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; w_log(W_LOG_ERR, "input_json: sending json object to stm\n"); if (!buffer.jsonEncodeToStream( res->resultsArray, stdin_file.get(), 0)) { w_log(W_LOG_ERR, "input_json: failed to write json data to stream: %s\n", strerror(errno)); return NULL; } break; } case input_name_list: for (auto& name : res->resultsArray.array()) { auto& nameStr = json_to_w_string(name); if (stdin_file->write(nameStr.data(), nameStr.size()) != (int)nameStr.size() || stdin_file->write("\n", 1) != 1) { w_log( W_LOG_ERR, "write failure while producing trigger stdin: %s\n", strerror(errno)); return nullptr; } } break; case input_dev_null: // already handled above break; } stdin_file->rewind(); return stdin_file; }