xenbus.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 762 行 · 第 1/2 页

C
762
字号
static char *errmsg(struct xsd_sockmsg *rep){    char *res;    if (!rep) {	char msg[] = "No reply";	size_t len = strlen(msg) + 1;	return memcpy(malloc(len), msg, len);    }    if (rep->type != XS_ERROR)	return NULL;    res = malloc(rep->len + 1);    memcpy(res, rep + 1, rep->len);    res[rep->len] = 0;    free(rep);    return res;}	/* Send a debug message to xenbus.  Can block. */static void xenbus_debug_msg(const char *msg){    int len = strlen(msg);    struct write_req req[] = {        { "print", sizeof("print") },        { msg, len },        { "", 1 }};    struct xsd_sockmsg *reply;    reply = xenbus_msg_reply(XS_DEBUG, 0, req, ARRAY_SIZE(req));    DEBUG("Got a reply, type %d, id %d, len %d.\n",            reply->type, reply->req_id, reply->len);}/* List the contents of a directory.  Returns a malloc()ed array of   pointers to malloc()ed strings.  The array is NULL terminated.  May   block. */char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents){    struct xsd_sockmsg *reply, *repmsg;    struct write_req req[] = { { pre, strlen(pre)+1 } };    int nr_elems, x, i;    char **res, *msg;    repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));    msg = errmsg(repmsg);    if (msg) {	*contents = NULL;	return msg;    }    reply = repmsg + 1;    for (x = nr_elems = 0; x < repmsg->len; x++)        nr_elems += (((char *)reply)[x] == 0);    res = malloc(sizeof(res[0]) * (nr_elems + 1));    for (x = i = 0; i < nr_elems; i++) {        int l = strlen((char *)reply + x);        res[i] = malloc(l + 1);        memcpy(res[i], (char *)reply + x, l + 1);        x += l + 1;    }    res[i] = NULL;    free(repmsg);    *contents = res;    return NULL;}char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value){    struct write_req req[] = { {path, strlen(path) + 1} };    struct xsd_sockmsg *rep;    char *res, *msg;    rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));    msg = errmsg(rep);    if (msg) {	*value = NULL;	return msg;    }    res = malloc(rep->len + 1);    memcpy(res, rep + 1, rep->len);    res[rep->len] = 0;    free(rep);    *value = res;    return NULL;}char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value){    struct write_req req[] = { 	{path, strlen(path) + 1},	{value, strlen(value)},    };    struct xsd_sockmsg *rep;    char *msg;    rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));    msg = errmsg(rep);    if (msg) return msg;    free(rep);    return NULL;}char* xenbus_watch_path_token( xenbus_transaction_t xbt, const char *path, const char *token, xenbus_event_queue *events){    struct xsd_sockmsg *rep;    struct write_req req[] = {         {path, strlen(path) + 1},	{token, strlen(token) + 1},    };    struct watch *watch = malloc(sizeof(*watch));    char *msg;    if (!events)        events = &xenbus_events;    watch->token = strdup(token);    watch->events = events;    watch->next = watches;    watches = watch;    rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));    msg = errmsg(rep);    if (msg) return msg;    free(rep);    return NULL;}char* xenbus_unwatch_path_token( xenbus_transaction_t xbt, const char *path, const char *token){    struct xsd_sockmsg *rep;    struct write_req req[] = {         {path, strlen(path) + 1},	{token, strlen(token) + 1},    };    struct watch *watch, **prev;    char *msg;    rep = xenbus_msg_reply(XS_UNWATCH, xbt, req, ARRAY_SIZE(req));    msg = errmsg(rep);    if (msg) return msg;    free(rep);    for (prev = &watches, watch = *prev; watch; prev = &watch->next, watch = *prev)        if (!strcmp(watch->token, token)) {            free(watch->token);            *prev = watch->next;            free(watch);            break;        }    return NULL;}char *xenbus_rm(xenbus_transaction_t xbt, const char *path){    struct write_req req[] = { {path, strlen(path) + 1} };    struct xsd_sockmsg *rep;    char *msg;    rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req));    msg = errmsg(rep);    if (msg)	return msg;    free(rep);    return NULL;}char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value){    struct write_req req[] = { {path, strlen(path) + 1} };    struct xsd_sockmsg *rep;    char *res, *msg;    rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req));    msg = errmsg(rep);    if (msg) {	*value = NULL;	return msg;    }    res = malloc(rep->len + 1);    memcpy(res, rep + 1, rep->len);    res[rep->len] = 0;    free(rep);    *value = res;    return NULL;}#define PERM_MAX_SIZE 32char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm){    char value[PERM_MAX_SIZE];    struct write_req req[] = { 	{path, strlen(path) + 1},	{value, 0},    };    struct xsd_sockmsg *rep;    char *msg;    snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);    req[1].len = strlen(value) + 1;    rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req));    msg = errmsg(rep);    if (msg)	return msg;    free(rep);    return NULL;}char *xenbus_transaction_start(xenbus_transaction_t *xbt){    /* xenstored becomes angry if you send a length 0 message, so just       shove a nul terminator on the end */    struct write_req req = { "", 1};    struct xsd_sockmsg *rep;    char *err;    rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);    err = errmsg(rep);    if (err)	return err;    sscanf((char *)(rep + 1), "%u", xbt);    free(rep);    return NULL;}char *xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry){    struct xsd_sockmsg *rep;    struct write_req req;    char *err;    *retry = 0;    req.data = abort ? "F" : "T";    req.len = 2;    rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);    err = errmsg(rep);    if (err) {	if (!strcmp(err, "EAGAIN")) {	    *retry = 1;	    free(err);	    return NULL;	} else {	    return err;	}    }    free(rep);    return NULL;}int xenbus_read_integer(char *path){    char *res, *buf;    int t;    res = xenbus_read(XBT_NIL, path, &buf);    if (res) {	printk("Failed to read %s.\n", path);	free(res);	return -1;    }    sscanf(buf, "%d", &t);    free(buf);    return t;}char* xenbus_printf(xenbus_transaction_t xbt,                                  char* node, char* path,                                  char* fmt, ...){#define BUFFER_SIZE 256    char fullpath[BUFFER_SIZE];    char val[BUFFER_SIZE];    va_list args;    BUG_ON(strlen(node) + strlen(path) + 1 >= BUFFER_SIZE);    sprintf(fullpath,"%s/%s", node, path);    va_start(args, fmt);    vsprintf(val, fmt, args);    va_end(args);    return xenbus_write(xbt,fullpath,val);}static void do_ls_test(const char *pre){    char **dirs, *msg;    int x;    DEBUG("ls %s...\n", pre);    msg = xenbus_ls(XBT_NIL, pre, &dirs);    if (msg) {	DEBUG("Error in xenbus ls: %s\n", msg);	free(msg);	return;    }    for (x = 0; dirs[x]; x++)     {        DEBUG("ls %s[%d] -> %s\n", pre, x, dirs[x]);        free(dirs[x]);    }    free(dirs);}static void do_read_test(const char *path){    char *res, *msg;    DEBUG("Read %s...\n", path);    msg = xenbus_read(XBT_NIL, path, &res);    if (msg) {	DEBUG("Error in xenbus read: %s\n", msg);	free(msg);	return;    }    DEBUG("Read %s -> %s.\n", path, res);    free(res);}static void do_write_test(const char *path, const char *val){    char *msg;    DEBUG("Write %s to %s...\n", val, path);    msg = xenbus_write(XBT_NIL, path, val);    if (msg) {	DEBUG("Result %s\n", msg);	free(msg);    } else {	DEBUG("Success.\n");    }}static void do_rm_test(const char *path){    char *msg;    DEBUG("rm %s...\n", path);    msg = xenbus_rm(XBT_NIL, path);    if (msg) {	DEBUG("Result %s\n", msg);	free(msg);    } else {	DEBUG("Success.\n");    }}/* Simple testing thing */void test_xenbus(void){    DEBUG("Doing xenbus test.\n");    xenbus_debug_msg("Testing xenbus...\n");    DEBUG("Doing ls test.\n");    do_ls_test("device");    do_ls_test("device/vif");    do_ls_test("device/vif/0");    DEBUG("Doing read test.\n");    do_read_test("device/vif/0/mac");    do_read_test("device/vif/0/backend");    DEBUG("Doing write test.\n");    do_write_test("device/vif/0/flibble", "flobble");    do_read_test("device/vif/0/flibble");    do_write_test("device/vif/0/flibble", "widget");    do_read_test("device/vif/0/flibble");    DEBUG("Doing rm test.\n");    do_rm_test("device/vif/0/flibble");    do_read_test("device/vif/0/flibble");    DEBUG("(Should have said ENOENT)\n");}/* * Local variables: * mode: C * c-basic-offset: 4 * End: */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?