static struct watchman_query_result * watchman_query_json(struct watchman_connection *conn, json_t *query, struct watchman_error *error) { struct watchman_query_result *result = NULL; struct watchman_query_result *res = NULL; if (watchman_send(conn, query, error)) { return NULL; } /* parse the result */ json_t *obj = watchman_read(conn, error); if (!obj) { return NULL; } JSON_ASSERT(json_is_object, obj, "Failed to send watchman query %s"); json_t *jerror = json_object_get(obj, "error"); if (jerror) { watchman_err(error, "Error result from watchman: %s", json_string_value(jerror)); goto done; } res = calloc(1, sizeof(*res)); json_t *files = json_object_get(obj, "files"); JSON_ASSERT(json_is_array, files, "Bad files %s"); int nr = json_array_size(files); res->stats = calloc(nr, sizeof(*res->stats)); int i; for (i = 0; i < nr; ++i) { struct watchman_stat *stat = res->stats + i; json_t *statobj = json_array_get(files, i); if (json_is_string(statobj)) { /* then hopefully we only requested names */ stat->name = strdup(json_string_value(statobj)); res->nr++; continue; } JSON_ASSERT(json_is_object, statobj, "must be object: %s"); json_t *name = json_object_get(statobj, "name"); JSON_ASSERT(json_is_string, name, "name must be string: %s"); stat->name = strdup(json_string_value(name)); WRITE_BOOL_STAT(stat, statobj, exists); WRITE_INT_STAT(stat, statobj, ctime); WRITE_INT_STAT(stat, statobj, ctime_ms); WRITE_INT_STAT(stat, statobj, ctime_us); WRITE_INT_STAT(stat, statobj, ctime_ns); WRITE_INT_STAT(stat, statobj, dev); WRITE_INT_STAT(stat, statobj, gid); WRITE_INT_STAT(stat, statobj, ino); WRITE_INT_STAT(stat, statobj, mode); WRITE_INT_STAT(stat, statobj, mtime); WRITE_INT_STAT(stat, statobj, mtime_ms); WRITE_INT_STAT(stat, statobj, mtime_us); WRITE_INT_STAT(stat, statobj, mtime_ns); WRITE_INT_STAT(stat, statobj, nlink); WRITE_INT_STAT(stat, statobj, size); WRITE_INT_STAT(stat, statobj, uid); WRITE_STR_STAT(stat, statobj, cclock); WRITE_STR_STAT(stat, statobj, oclock); WRITE_FLOAT_STAT(stat, statobj, ctime_f); WRITE_FLOAT_STAT(stat, statobj, mtime_f); /* the one we have to do manually because we don't * want to use the name "new" */ json_t *newer = json_object_get(statobj, "new"); if (newer) { stat->newer = json_is_true(newer); } res->nr++; } json_t *version = json_object_get(obj, "version"); JSON_ASSERT(json_is_string, version, "Bad version %s"); res->version = strdup(json_string_value(version)); json_t *clock = json_object_get(obj, "clock"); JSON_ASSERT(json_is_string, clock, "Bad clock %s"); res->clock = strdup(json_string_value(clock)); json_t *fresh = json_object_get(obj, "is_fresh_instance"); JSON_ASSERT(json_is_boolean, fresh, "Bad is_fresh_instance %s"); res->is_fresh_instance = json_is_true(fresh); result = res; res = NULL; done: if (res) { watchman_free_query_result(res); } json_decref(obj); return result; }
static struct watchman_query_result * watchman_query_json(struct watchman_connection *conn, json_t *query, struct timeval *timeout, struct watchman_error *error) { struct watchman_query_result *result = NULL; struct watchman_query_result *res = NULL; if (watchman_send(conn, query, error)) { return NULL; } /* parse the result */ proto_t obj = watchman_read_with_timeout(conn, timeout, error); if (proto_is_null(obj)) { return NULL; } PROTO_ASSERT(proto_is_object, obj, "Failed to send watchman query %s"); proto_t jerror = proto_object_get(obj, "error"); if (!proto_is_null(jerror)) { watchman_err(error, WATCHMAN_ERR_WATCHMAN_REPORTED, "Error result from watchman: %s", proto_strdup(jerror)); goto done; } res = calloc(1, sizeof(*res)); proto_t files = proto_object_get(obj, "files"); PROTO_ASSERT(proto_is_array, files, "Bad files %s"); int nr = proto_array_size(files); res->stats = calloc(nr, sizeof(*res->stats)); int i; for (i = 0; i < nr; ++i) { struct watchman_stat *stat = res->stats + i; proto_t statobj = proto_array_get(files, i); if (proto_is_string(statobj)) { /* then hopefully we only requested names */ stat->name = proto_strdup(statobj); res->nr++; continue; } PROTO_ASSERT(proto_is_object, statobj, "must be object: %s"); proto_t name = proto_object_get(statobj, "name"); PROTO_ASSERT(proto_is_string, name, "name must be string: %s"); stat->name = proto_strdup(name); WRITE_BOOL_STAT(stat, statobj, exists); WRITE_INT_STAT(stat, statobj, ctime); WRITE_INT_STAT(stat, statobj, ctime_ms); WRITE_INT_STAT(stat, statobj, ctime_us); WRITE_INT_STAT(stat, statobj, ctime_ns); WRITE_INT_STAT(stat, statobj, dev); WRITE_INT_STAT(stat, statobj, gid); WRITE_INT_STAT(stat, statobj, ino); WRITE_INT_STAT(stat, statobj, mode); WRITE_INT_STAT(stat, statobj, mtime); WRITE_INT_STAT(stat, statobj, mtime_ms); WRITE_INT_STAT(stat, statobj, mtime_us); WRITE_INT_STAT(stat, statobj, mtime_ns); WRITE_INT_STAT(stat, statobj, nlink); WRITE_INT_STAT(stat, statobj, size); WRITE_INT_STAT(stat, statobj, uid); WRITE_STR_STAT(stat, statobj, cclock); WRITE_STR_STAT(stat, statobj, oclock); WRITE_FLOAT_STAT(stat, statobj, ctime_f); WRITE_FLOAT_STAT(stat, statobj, mtime_f); /* the one we have to do manually because we don't * want to use the name "new" */ proto_t newer = proto_object_get(statobj, "new"); if (!proto_is_null(newer)) { stat->newer = proto_is_true(newer); } res->nr++; } proto_t version = proto_object_get(obj, "version"); PROTO_ASSERT(proto_is_string, version, "Bad version %s"); res->version = proto_strdup(version); proto_t clock = proto_object_get(obj, "clock"); PROTO_ASSERT(proto_is_string, clock, "Bad clock %s"); res->clock = proto_strdup(clock); proto_t fresh = proto_object_get(obj, "is_fresh_instance"); PROTO_ASSERT(proto_is_boolean, fresh, "Bad is_fresh_instance %s"); res->is_fresh_instance = proto_is_true(fresh); result = res; res = NULL; done: if (res) { watchman_free_query_result(res); } proto_free(obj); return result; }