json_ref field_list_to_json_name_array(const w_query_field_list& fieldList) { auto templ = json_array_of_size(fieldList.size()); for (auto& f : fieldList) { json_array_append_new(templ, w_string_to_json(f->name)); } return templ; }
static json_t *build_legacy_trigger( w_root_t *root, struct watchman_client *client, json_t *args) { json_t *trig, *expr; json_t *command; char *errmsg; uint32_t next_arg = 0; uint32_t i; size_t n; w_query *query; trig = json_pack("{s:O, s:b, s:[s, s, s, s, s]}", "name", json_array_get(args, 2), "append_files", true, "stdin", // [ "name", "exists", "new", "size", "mode" // ] ); query = w_query_parse_legacy(root, args, &errmsg, 3, &next_arg, NULL, &expr); if (!query) { send_error_response(client, "invalid rule spec: %s", errmsg); free(errmsg); json_decref(trig); return NULL; } w_query_delref(query); json_object_set(trig, "expression", json_object_get(expr, "expression")); json_decref(expr); if (next_arg >= json_array_size(args)) { send_error_response(client, "no command was specified"); json_decref(trig); return NULL; } n = json_array_size(args) - next_arg; command = json_array_of_size(n); for (i = 0; i < n; i++) { json_t *ele = json_array_get(args, i + next_arg); if (!json_is_string(ele)) { send_error_response(client, "expected argument %d to be a string", i); json_decref(trig); return NULL; } json_array_append(command, ele); } json_object_set_new(trig, "command", command); return trig; }
json_t *w_capability_get_list(void) { json_t *arr = json_array_of_size(w_ht_size(capabilities)); w_ht_iter_t iter; w_ht_first(capabilities, &iter); do { w_string_t *name = w_ht_val_ptr(iter.key); json_array_append(arr, w_string_to_json(name)); } while (w_ht_next(capabilities, &iter)); return arr; }
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; }
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; }