static void cmd_debug_show_cursors(struct watchman_client *client, json_t *args) { w_root_t *root; json_t *resp, *cursors; w_ht_iter_t i; /* resolve the root */ if (json_array_size(args) != 2) { send_error_response(client, "wrong number of arguments for 'debug-show-cursors'"); return; } root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } resp = make_response(); w_root_lock(root); cursors = json_object_of_size(w_ht_size(root->cursors)); if (w_ht_first(root->cursors, &i)) do { w_string_t *name = w_ht_val_ptr(i.key); set_prop(cursors, name->buf, json_integer(i.value)); } while (w_ht_next(root->cursors, &i)); w_root_unlock(root); set_prop(resp, "cursors", cursors); send_and_dispose_response(client, resp); w_root_delref(root); }
static void cmd_debug_show_cursors( struct watchman_client* client, const json_ref& args) { json_ref cursors; /* resolve the root */ if (json_array_size(args) != 2) { send_error_response(client, "wrong number of arguments for 'debug-show-cursors'"); return; } auto root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } auto resp = make_response(); { auto map = root->inner.cursors.rlock(); cursors = json_object_of_size(map->size()); for (const auto& it : *map) { const auto& name = it.first; const auto& ticks = it.second; cursors.set(name.c_str(), json_integer(ticks)); } } resp.set("cursors", std::move(cursors)); send_and_dispose_response(client, std::move(resp)); }
json_ref file_result_to_json( const w_query_field_list& fieldList, const watchman_rule_match& match) { if (fieldList.size() == 1) { return fieldList.front()->make(&match); } auto value = json_object_of_size(fieldList.size()); for (auto& f : fieldList) { auto ele = f->make(&match); value.set(f->name, std::move(ele)); } return value; }
json_t *w_query_results_to_json( struct w_query_field_list *field_list, uint32_t num_results, struct watchman_rule_match *results) { json_t *file_list = json_array_of_size(num_results); uint32_t i, f; // build a template for the serializer if (num_results && field_list->num_fields > 1) { json_t *templ = json_array_of_size(field_list->num_fields); for (f = 0; f < field_list->num_fields; f++) { json_array_append_new(templ, json_string_nocheck(field_list->fields[f]->name)); } json_array_set_template_new(file_list, templ); } for (i = 0; i < num_results; i++) { json_t *value, *ele; if (field_list->num_fields == 1) { value = field_list->fields[0]->make(&results[i]); } else { value = json_object_of_size(field_list->num_fields); for (f = 0; f < field_list->num_fields; f++) { ele = field_list->fields[f]->make(&results[i]); set_prop(value, field_list->fields[f]->name, ele); } } json_array_append_new(file_list, value); } return file_list; }
/* version */ static void cmd_version(struct watchman_client* client, const json_ref& args) { auto resp = make_response(); #ifdef WATCHMAN_BUILD_INFO resp.set( "buildinfo", typed_string_to_json(WATCHMAN_BUILD_INFO, W_STRING_UNICODE)); #endif /* ["version"] * -> just returns the basic version information. * ["version", {"required": ["foo"], "optional": ["bar"]}] * -> includes capability matching information */ if (json_array_size(args) == 2) { const auto& arg_obj = args.at(1); auto req_cap = arg_obj.get_default("required"); auto opt_cap = arg_obj.get_default("optional"); auto cap_res = json_object_of_size( (opt_cap ? json_array_size(opt_cap) : 0) + (req_cap ? json_array_size(req_cap) : 0)); if (opt_cap && opt_cap.isArray()) { query_caps(resp, cap_res, opt_cap, false); } if (req_cap && req_cap.isArray()) { query_caps(resp, cap_res, req_cap, true); } resp.set("capabilities", std::move(cap_res)); } send_and_dispose_response(client, std::move(resp)); }
json_t *w_match_results_to_json( uint32_t num_matches, struct watchman_rule_match *matches) { json_t *file_list = json_array_of_size(num_matches); uint32_t i; if (num_matches) { // Build a template for the serializer json_t *templ = json_array_of_size(15); static const char *field_list[] = { "name", "exists", "size", "mode", "uid", "gid", "mtime", "ctime", "ino", "dev", "nlink", "new", "oclock", "cclock", }; for (i = 0; i < sizeof(field_list)/sizeof(field_list[0]); i++) { json_array_append_new(templ, json_string_nocheck(field_list[i])); } json_array_set_template_new(file_list, templ); } for (i = 0; i < num_matches; i++) { struct watchman_file *file = matches[i].file; w_string_t *relname = matches[i].relname; char buf[128]; json_t *record = json_object_of_size(15); set_prop(record, "name", json_string_nocheck(relname->buf)); set_prop(record, "exists", json_boolean(file->exists)); // Only report stat data if we think this file exists. If it doesn't, // we probably have stale data cached in file->st which is useless to // report on. if (file->exists) { // Note: our JSON library supports 64-bit integers, but this may // pose a compatibility issue for others. We'll see if anyone // runs into an issue and deal with it then... set_prop(record, "size", json_integer(file->st.st_size)); set_prop(record, "mode", json_integer(file->st.st_mode)); set_prop(record, "uid", json_integer(file->st.st_uid)); set_prop(record, "gid", json_integer(file->st.st_gid)); set_prop(record, "mtime", json_integer(file->st.st_mtime)); set_prop(record, "ctime", json_integer(file->st.st_ctime)); set_prop(record, "ino", json_integer(file->st.st_ino)); set_prop(record, "dev", json_integer(file->st.st_dev)); set_prop(record, "nlink", json_integer(file->st.st_nlink)); set_prop(record, "new", json_boolean(matches[i].is_new)); if (clock_id_string(matches[i].root_number, file->ctime.ticks, buf, sizeof(buf))) { set_prop(record, "cclock", json_string_nocheck(buf)); } } if (clock_id_string(matches[i].root_number, file->otime.ticks, buf, sizeof(buf))) { set_prop(record, "oclock", json_string_nocheck(buf)); } json_array_append_new(file_list, record); } return file_list; }
static json_t *bunser_template(const char *buf, const char *end, json_int_t *used, json_error_t *jerr) { json_int_t needed = 0; json_int_t total = 0; json_int_t i, nelems; json_int_t ip, np; json_t *templ = NULL, *arrval, *ret = NULL; buf++; total++; if (*buf != BSER_ARRAY) { snprintf(jerr->text, sizeof(jerr->text), "Expected array encoding, but found 0x%02x", *buf); *used = total; return NULL; } // Load in the property names template templ = bunser_array(buf, end, &needed, jerr); if (!templ) { *used = needed + total; goto bail; } total += needed; buf += needed; // And the number of objects needed = 0; if (!bunser_int(buf, end - buf, &needed, &nelems)) { *used = needed + total; snprintf(jerr->text, sizeof(jerr->text), "invalid object number encoding (needed %d but have %d)", (int)needed, (int)(end - buf)); goto bail; } total += needed; buf += needed; np = json_array_size(templ); // Now load up the array with object values arrval = json_array_of_size((size_t)nelems); for (i = 0; i < nelems; i++) { json_t *item, *val; item = json_object_of_size((size_t)np); for (ip = 0; ip < np; ip++) { if (*buf == BSER_SKIP) { buf++; total++; continue; } needed = 0; val = bunser(buf, end, &needed, jerr); if (!val) { *used = needed + total; goto bail; } buf += needed; total += needed; json_object_set_new_nocheck(item, json_string_value(json_array_get(templ, (size_t)ip)), val); } json_array_append_new(arrval, item); } *used = total; ret = arrval; bail: json_decref(templ); return ret; }
json_t *json_object(void) { return json_object_of_size(0); }