Пример #1
0
static int
watchman_read_and_handle_errors(struct watchman_connection *conn,
                                struct watchman_error *error)
{
    proto_t obj = watchman_read(conn, error);
    if (proto_is_null(obj)) {
        return 1;
    }
    if (!proto_is_object(obj)) {
        char *bogus_text = proto_dumps(obj, 0);
        watchman_err(error, WATCHMAN_ERR_WATCHMAN_BROKEN,
                     "Got non-object result from watchman : %s",
                     bogus_text);
        free(bogus_text);
        proto_free(obj);
        return 1;
    }
    proto_t error_node = proto_object_get(obj, "error");
    if (!proto_is_null(error_node)) {
        watchman_err(error, WATCHMAN_ERR_OTHER,
                     "Got error result from watchman : %s",
                     proto_strdup(error_node));
        proto_free(obj);
        return 1;
    }

    proto_free(obj);
    return 0;
}
Пример #2
0
int
watchman_version(struct watchman_connection *conn,
                 struct watchman_error *error,
                 struct watchman_version* version)
{
    const char *result = NULL;
    json_t *cmd = json_array();
    json_array_append_new(cmd, json_string("version"));

    int ret = watchman_send(conn, cmd, error);
    json_decref(cmd);
    if (ret) {
        return -1;
    }

    proto_t obj = watchman_read(conn, error);
    if (proto_is_null(obj)) {
        return -1;
    }
    PROTO_ASSERT(proto_is_object, obj, "Got bogus value from version %s");
    proto_t version_field = proto_object_get(obj, "version");
    PROTO_ASSERT(proto_is_string, version_field, "Bad version %s");
    result = proto_strdup(version_field);

    int count = sscanf(result, "%d.%d.%d", &version->major,
                       &version->minor, &version->micro);
    proto_free(obj);
    return count == 3 ? 0 : -1;

done:
    proto_free(obj);
    return -1;
}
Пример #3
0
char *
watchman_clock(struct watchman_connection *conn,
               const char *path,
               unsigned int sync_timeout,
               struct watchman_error *error)
{
    char *result = NULL;
    json_t *query = json_array();
    json_array_append_new(query, json_string("clock"));
    json_array_append_new(query, json_string(path));
    if (sync_timeout) {
        json_t *options = json_object();
        json_object_set_new(options, "sync_timeout", json_integer(sync_timeout));
        json_array_append_new(query, options);
    }

    int ret = watchman_send(conn, query, error);
    json_decref(query);
    if (ret) {
        return NULL;
    }

    proto_t obj = watchman_read(conn, error);
    if (proto_is_null(obj)) {
        return NULL;
    }
    PROTO_ASSERT(proto_is_object, obj, "Got bogus value from clock %s");
    proto_t clock = proto_object_get(obj, "clock");
    PROTO_ASSERT(proto_is_string, clock, "Bad clock %s");
    result = proto_strdup(clock);

done:
    proto_free(obj);
    return result;
}
Пример #4
0
/*
 * Connect to watchman's socket.  Sets a socket send and receive
 * timeout of `timeout`.  Pass a {0} for no-timeout.  On error,
 * returns NULL and, if `error` is non-NULL, fills it in.
 */
struct watchman_connection *
watchman_connect(struct timeval timeout, struct watchman_error *error)
{
    struct watchman_connection *conn = NULL;
    /* If an environment variable WATCHMAN_SOCK is set, establish a connection
       to that address. Otherwise, run `watchman get-sockname` to start the
       daemon and retrieve its address. */
    const char *sockname_env = getenv("WATCHMAN_SOCK");
    if (sockname_env) {
        conn = watchman_sock_connect(sockname_env, timeout, error);
        goto done;
    }
    struct watchman_popen *p = watchman_popen_getsockname(error);
    if (p == NULL) {
        return NULL;
    }

    char buf[WATCHMAN_GET_SOCKNAME_MAX + 1];

    proto_t proto = read_with_timeout(p->fd, buf, WATCHMAN_GET_SOCKNAME_MAX, timeout);

    if (watchman_pclose(error, p)) {
        goto done;
    }
    if (proto_is_null(proto)) {
        watchman_err(error, WATCHMAN_ERR_WATCHMAN_BROKEN,
                     "Got bad or no JSON/BSER from watchman get-sockname");
        goto done;
    }
    if (!proto_is_object(proto)) {
        watchman_err(error, WATCHMAN_ERR_WATCHMAN_BROKEN,
                     "Got bad JSON/BSER from watchman get-sockname: object expected");
        goto bad_proto;
    }
    proto_t sockname_obj = proto_object_get(proto, "sockname");
    if (proto_is_null(sockname_obj)) {
        watchman_err(error, WATCHMAN_ERR_WATCHMAN_BROKEN,
                     "Got bad JSON/BSER from watchman get-sockname: "
                     "sockname element expected");
        goto bad_proto;
    }
    if (!proto_is_string(sockname_obj)) {
        watchman_err(error, WATCHMAN_ERR_WATCHMAN_BROKEN,
                     "Got bad JSON/BSER from watchman get-sockname:"
                     " sockname is not string");
        goto bad_proto;
    }
    const char *sockname = proto_strdup(sockname_obj);
    conn = watchman_sock_connect(sockname, timeout, error);
bad_proto:
    proto_free(proto);
done:
    return conn;
}
Пример #5
0
/* Release a reference to SA.  */
void
sa_release(struct sa *sa)
{
	struct cert_handler *handler;
	struct proto   *proto;

	LOG_DBG((LOG_SA, 80, "sa_release: SA %p had %d references",
	    sa, sa->refcnt));

	if (--sa->refcnt)
		return;

	LOG_DBG((LOG_SA, 60, "sa_release: freeing SA %p", sa));

	while ((proto = TAILQ_FIRST(&sa->protos)) != 0)
		proto_free(proto);
	if (sa->data) {
		if (sa->doi && sa->doi->free_sa_data)
			sa->doi->free_sa_data(sa->data);
		free(sa->data);
	}
	free(sa->id_i);
	free(sa->id_r);
	if (sa->recv_cert) {
		handler = cert_get(sa->recv_certtype);
		if (handler)
			handler->cert_free(sa->recv_cert);
	}
	if (sa->sent_cert) {
		handler = cert_get(sa->sent_certtype);
		if (handler)
			handler->cert_free(sa->sent_cert);
	}
	if (sa->recv_key)
		key_free(sa->recv_keytype, ISAKMP_KEYTYPE_PUBLIC,
		    sa->recv_key);
	free(sa->keynote_key);	/* This is just a string */
	if (sa->policy_id != -1)
		kn_close(sa->policy_id);
	free(sa->name);
	free(sa->keystate);
	if (sa->nat_t_keepalive)
		timer_remove_event(sa->nat_t_keepalive);
	if (sa->dpd_event)
		timer_remove_event(sa->dpd_event);
	if (sa->transport)
		transport_release(sa->transport);
	free(sa->tag);
	free(sa);
}
Пример #6
0
struct watchman_watch_list *
watchman_watch_list(struct watchman_connection *conn,
                    struct watchman_error *error)
{
    struct watchman_watch_list *res = NULL;
    struct watchman_watch_list *result = NULL;
    if (watchman_send_simple_command(conn, error, "watch-list", NULL)) {
        return NULL;
    }

    proto_t obj = watchman_read(conn, error);
    if (proto_is_null(obj)) {
        return NULL;
    }
    PROTO_ASSERT(proto_is_object, obj, "Got bogus value from watch-list %s");
    proto_t roots = proto_object_get(obj, "roots");
    PROTO_ASSERT(proto_is_array, roots, "Got bogus value from watch-list %s");

    res = malloc(sizeof(*res));
    int nr = proto_array_size(roots);
    res->nr = 0;
    res->roots = calloc(nr, sizeof(*res->roots));
    int i;
    for (i = 0; i < nr; ++i) {
        proto_t root = proto_array_get(roots, i);
        PROTO_ASSERT(proto_is_string, root,
                    "Got non-string root from watch-list %s");
        res->nr++;
        res->roots[i] = proto_strdup(root);
    }
    result = res;
    res = NULL;
done:
    if (res) {
        watchman_free_watch_list(res);
    }
    proto_free(obj);
    return result;
}
Пример #7
0
int
watchman_shutdown_server(struct watchman_connection *conn,
                         struct watchman_error *error)
{
    json_t *cmd = json_array();
    json_array_append_new(cmd, json_string("shutdown-server"));

    int ret = watchman_send(conn, cmd, error);
    json_decref(cmd);

    if (ret) {
        return -1;
    }

    proto_t obj = watchman_read(conn, error);
    if (proto_is_null(obj)) {
        return -1;
    }

    proto_free(obj);
    return 0;
}
Пример #8
0
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;
}