Esempio n. 1
0
/*
 * xenStoreDomainGetDiskID:
 * @conn: pointer to the connection.
 * @id: the domain id
 * @dev: the virtual block device name
 *
 * Get the reference (i.e. the string number) for the device on that domain
 * which uses the given virtual block device name
 *
 * The caller must hold the lock on the privateData
 * associated with the 'conn' parameter.
 *
 * Returns the new string or NULL in case of error, the string must be
 *         freed by the caller.
 */
char *
xenStoreDomainGetDiskID(virConnectPtr conn, int id, const char *dev)
{
    char dir[80], path[128], **list = NULL, *val = NULL;
    unsigned int devlen, len, num;
    size_t i;
    char *ret = NULL;
    xenUnifiedPrivatePtr priv = conn->privateData;

    if (id < 0 || priv->xshandle == NULL || dev == NULL)
        return NULL;
    devlen = strlen(dev);
    if (devlen <= 0)
        return NULL;

    snprintf(dir, sizeof(dir), "/local/domain/0/backend/vbd/%d", id);
    list = xs_directory(priv->xshandle, 0, dir, &num);
    if (list != NULL) {
        for (i = 0; i < num; i++) {
            snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev");
            val = xs_read(priv->xshandle, 0, path, &len);
            if (val == NULL)
                break;
            if ((devlen != len) || memcmp(val, dev, len)) {
                VIR_FREE(val);
            } else {
                ignore_value(VIR_STRDUP(ret, list[i]));

                VIR_FREE(val);
                VIR_FREE(list);
                return ret;
            }
        }
        VIR_FREE(list);
    }
    snprintf(dir, sizeof(dir), "/local/domain/0/backend/tap/%d", id);
    list = xs_directory(priv->xshandle, 0, dir, &num);
    if (list != NULL) {
        for (i = 0; i < num; i++) {
            snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev");
            val = xs_read(priv->xshandle, 0, path, &len);
            if (val == NULL)
                break;
            if ((devlen != len) || memcmp(val, dev, len)) {
                VIR_FREE(val);
            } else {
                ignore_value(VIR_STRDUP(ret, list[i]));

                VIR_FREE(val);
                VIR_FREE(list);
                return ret;
            }
        }
        VIR_FREE(list);
    }
    return NULL;
}
static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
{
    struct XenDevice *xendev;
    char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
    char **dev = NULL;
    unsigned int cdev, j;

    /* setup watch */
    snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
    snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
    if (!xs_watch(xenstore, path, token)) {
        xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
        return -1;
    }

    /* look for backends */
    dev = xs_directory(xenstore, 0, path, &cdev);
    if (!dev) {
        return 0;
    }
    for (j = 0; j < cdev; j++) {
        xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
        if (xendev == NULL) {
            continue;
        }
        xen_be_check_state(xendev);
    }
    free(dev);
    return 0;
}
Esempio n. 3
0
int setFullPerm(char *path){
  struct xs_permissions perms = {.id = 0, .perms = XS_PERM_READ|XS_PERM_WRITE}; // Full Permissions
  if(!xs_set_permissions(xsd, 0, path, &perms, 1)){
    printf("Could not set directory permissions.\n");
    return 3;
  }
  return 0;
}

int main(int argc, char **argv)
{
  unsigned int num, i;
  char **list;
  bool res;

  xsd = xs_open(0);
  
  mkdir("/rendezvous");
  mkdir("/transport");

  setFullPerm("/rendezvous");
  setFullPerm("/transport");
  setFullPerm("/local/domain");
    
  printf("Base directory added. New root directory:\n");
  list = xs_directory(xsd, 0, "/", &num);
  for(i = 0; i < num; i++)
    printf("  /%s\n", list[i]);

  return 0;
}
Esempio n. 4
0
/*
 * xenStoreDomainGetPCIID:
 * @conn: pointer to the connection.
 * @id: the domain id
 * @bdf: the PCI BDF
 *
 * Get the reference (i.e. the string number) for the device on that domain
 * which uses the given PCI address
 *
 * The caller must hold the lock on the privateData
 * associated with the 'conn' parameter.
 *
 * Returns the new string or NULL in case of error, the string must be
 *         freed by the caller.
 */
char *
xenStoreDomainGetPCIID(virConnectPtr conn, int id, const char *bdf)
{
    char dir[80], path[128], **list = NULL, *val = NULL;
    unsigned int len, num;
    size_t i;
    char *ret = NULL;
    xenUnifiedPrivatePtr priv = conn->privateData;

    if (id < 0 || priv->xshandle == NULL || bdf == NULL)
        return NULL;

    snprintf(dir, sizeof(dir), "/local/domain/0/backend/pci/%d", id);
    list = xs_directory(priv->xshandle, 0, dir, &num);
    if (list == NULL)
        return NULL;
    for (i = 0; i < num; i++) {
        snprintf(path, sizeof(path), "%s/%s/%s", dir, list[i], "dev-0");
        if ((val = xs_read(priv->xshandle, 0, path, &len)) == NULL)
            break;

        bool match = STREQ(val, bdf);

        VIR_FREE(val);

        if (match) {
            ignore_value(VIR_STRDUP(ret, list[i]));
            break;
        }
    }

    VIR_FREE(list);
    return ret;
}
Esempio n. 5
0
/**
 * xenStoreDoListDomains:
 * @conn: pointer to the hypervisor connection
 * @ids: array to collect the list of IDs of active domains
 * @maxids: size of @ids
 *
 * Internal API: collect the list of active domains, and store
 * their ID in @maxids. The driver lock must be held.
 *
 * Returns the number of domain found or -1 in case of error
 */
static int
xenStoreDoListDomains(virConnectPtr conn,
                      xenUnifiedPrivatePtr priv,
                      int *ids,
                      int maxids)
{
    char **idlist = NULL, *endptr;
    unsigned int num;
    size_t i;
    int ret = -1;
    long id;

    idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
    if (idlist == NULL)
        goto out;

    for (ret = 0, i = 0; (i < num) && (ret < maxids); i++) {
        id = strtol(idlist[i], &endptr, 10);
        if ((endptr == idlist[i]) || (*endptr != 0))
            goto out;

        /* Sometimes xenstore has stale domain IDs, so filter
           against the hypervisor's info */
        if (xenHypervisorHasDomain(conn, (int)id))
            ids[ret++] = (int) id;
    }

out:
    VIR_FREE(idlist);
    return ret;
}
Esempio n. 6
0
/**
 * xenStoreNumOfDomains:
 * @conn: pointer to the hypervisor connection
 *
 * Provides the number of active domains.
 *
 * Returns the number of domain found or -1 in case of error
 */
int
xenStoreNumOfDomains(virConnectPtr conn)
{
    unsigned int num;
    char **idlist = NULL, *endptr;
    size_t i;
    int ret = -1, realnum = 0;
    long id;
    xenUnifiedPrivatePtr priv = conn->privateData;

    idlist = xs_directory(priv->xshandle, 0, "/local/domain", &num);
    if (idlist) {
        for (i = 0; i < num; i++) {
            id = strtol(idlist[i], &endptr, 10);
            if ((endptr == idlist[i]) || (*endptr != 0))
                goto out;

            /* Sometimes xenstore has stale domain IDs, so filter
               against the hypervisor's info */
            if (xenHypervisorHasDomain(conn, (int)id))
                realnum++;
        }
out:
        VIR_FREE(idlist);
        ret = realnum;
    }
    return ret;
}
Esempio n. 7
0
/**
 * \brief Enumerate all devices of the given type on this bus.
 *
 * \param dev   NewBus device_t for this XenBus backend bus instance.
 * \param type  String indicating the device sub-tree (e.g. "vfb", "vif")
 *              to enumerate. 
 *
 * \return  On success, 0. Otherwise an errno value indicating the
 *          type of failure.
 *
 * Devices that are found are entered into the NewBus hierarchy via
 * xenbusb_add_device().  xenbusb_add_device() ignores duplicate detects
 * and ignores duplicate devices, so it can be called unconditionally
 * for any device found in the XenStore.
 *
 * The backend XenStore hierarchy has the following format:
 *
 *     backend/<device type>/<frontend vm id>/<device id>
 *
 */
static int
xenbusb_back_enumerate_type(device_t dev, const char *type)
{
	struct xenbusb_softc *xbs;
	const char **vms;
	u_int vm_idx;
	u_int vm_count;
	int error;

	xbs = device_get_softc(dev);
	error = xs_directory(XST_NIL, xbs->xbs_node, type, &vm_count, &vms);
	if (error)
		return (error);
	for (vm_idx = 0; vm_idx < vm_count; vm_idx++) {
		struct sbuf *vm_path;
		const char *vm;
		const char **devs;
		u_int dev_idx;
		u_int dev_count;

		vm = vms[vm_idx];

		vm_path = xs_join(type, vm);
		error = xs_directory(XST_NIL, xbs->xbs_node, sbuf_data(vm_path),
		    &dev_count, &devs);
		sbuf_delete(vm_path);
		if (error)
			break;

		for (dev_idx = 0; dev_idx < dev_count; dev_idx++) {
			const char *dev_num;
			struct sbuf *id;
			
			dev_num = devs[dev_idx];
			id = xs_join(vm, dev_num);
			xenbusb_add_device(dev, type, sbuf_data(id));
			sbuf_delete(id);
		}
		free(devs, M_XENSTORE);
	}

	free(vms, M_XENSTORE);

	return (0);
}
Esempio n. 8
0
static void
do_chmod(char *path, struct xs_permissions *perms, int nperms, int upto,
	 int recurse, struct xs_handle *xsh, xs_transaction_t xth)
{
    int ret;

    if (!path[0])
	return;

    ret = xs_set_permissions(xsh, xth, path, perms, nperms);
    if (!ret)
	err(1, "Error occurred setting permissions on '%s'", path);

    if (upto) {
	/* apply same permissions to all parent entries: */
	char *path_sep_ptr = strrchr(path, PATH_SEP);
	if (!path_sep_ptr)
	    errx(1, "Unable to locate path separator '%c' in '%s'",
		 PATH_SEP, path);
	
	*path_sep_ptr = '\0'; /* truncate path */
	
	do_chmod(path, perms, nperms, 1, 0, xsh, xth);

	*path_sep_ptr = PATH_SEP;
    }

    if (recurse) {
	char buf[MAX_PATH_LEN];

	/* apply same permissions to all child entries: */
	unsigned int xsval_n;
	char **xsval = xs_directory(xsh, xth, path, &xsval_n);

	if (xsval) {
	    int i;
	    for (i = 0; i < xsval_n; i++) {
		snprintf(buf, MAX_PATH_LEN, "%s/%s", path, xsval[i]);

		do_chmod(buf, perms, nperms, 0, 1, xsh, xth);
	    }

	    free(xsval);
	}
    }
}
Esempio n. 9
0
File: xslib.c Progetto: euanh/sm
int xs_exists(struct xs_handle *h, const char *path)
{
        char **d;
        unsigned int num;
        xs_transaction_t xth;

        if ((xth = xs_transaction_start(h)) == XBT_NULL) {
                printf("unable to start xs trasanction\n");
                return 0;
        }

        d = xs_directory(h, xth, path, &num);
        xs_transaction_end(h, xth, 0);
        if (!d)
                return 0;

        free(d);
        return 1;
}
Esempio n. 10
0
/**
 * \brief Enumerate all devices of the given type on this bus.
 *
 * \param dev   NewBus device_t for this XenBus front bus instance.
 * \param type  String indicating the device sub-tree (e.g. "vfb", "vif")
 *              to enumerate. 
 *
 * \return  On success, 0. Otherwise an errno value indicating the
 *          type of failure.
 *
 * Devices that are found are entered into the NewBus hierarchy via
 * xenbusb_add_device().  xenbusb_add_device() ignores duplicate detects
 * and ignores duplicate devices, so it can be called unconditionally
 * for any device found in the XenStore.
 */
int
xenbusb_front_enumerate_type(device_t dev, const char *type)
{
	struct xenbusb_softc *xbs;
	const char **dir;
	unsigned int i, count;
	int error;

	xbs = device_get_softc(dev);
	error = xs_directory(XST_NIL, xbs->xbs_node, type, &count, &dir);
	if (error)
		return (error);
	for (i = 0; i < count; i++)
		xenbusb_add_device(dev, type, dir[i]);

	free(dir, M_XENSTORE);

	return (0);
}
Esempio n. 11
0
/**
 * \brief Enumerate the devices on a XenBus bus and register them with
 *        the NewBus device tree.
 *
 * xenbusb_enumerate_bus() will create entries (in state DS_NOTPRESENT)
 * for nodes that appear in the XenStore, but will not invoke probe/attach
 * operations on drivers.  Probe/Attach processing must be separately
 * performed via an invocation of xenbusb_probe_children().  This is usually
 * done via the xbs_probe_children task.
 *
 * \param xbs  XenBus Bus device softc of the owner of the bus to enumerate.
 *
 * \return  On success, 0. Otherwise an errno value indicating the
 *          type of failure.
 */
static int
xenbusb_enumerate_bus(struct xenbusb_softc *xbs)
{
	const char **types;
	u_int type_idx;
	u_int type_count;
	int error;

	error = xs_directory(XST_NIL, xbs->xbs_node, "", &type_count, &types);
	if (error)
		return (error);

	for (type_idx = 0; type_idx < type_count; type_idx++)
		XENBUSB_ENUMERATE_TYPE(xbs->xbs_dev, types[type_idx]);

	free(types, M_XENSTORE);

	return (0);
}
Esempio n. 12
0
File: xslib.c Progetto: euanh/sm
char *dirlist(struct xs_handle *h, const char *path)
{
        char **d, *p, *ptr;
        xs_transaction_t xth;
	unsigned int num, j=0, count = 0;

	if ((p = calloc(1,MAXDIRBUF))==NULL) {
		printf("unable to allocate memory\n");
		return NULL;
	}
        if ((xth = xs_transaction_start(h)) == XBT_NULL) {
                printf("unable to start xs trasanction\n");
                return p;
        }

        d = xs_directory(h, xth, path, &num);
        xs_transaction_end(h, xth, 0);
        if (!d)
                return p;

	ptr = p;	
        while(j < num) {
		ptr = p + count;
		if ((count + strlen(d[j]) + 1) > MAXDIRBUF) {
			printf("Reached max dir entry\n");
			return p;
		}
		if (j) {
			*ptr = '|';
			*ptr++;
			count++;
		}
		count += sprintf(ptr, d[j]);
		j++;
	}

        free(d);
        return p;	
}
Esempio n. 13
0
static void
xs_ls_expected_error(unsigned code, const char *path, DWORD e)
{
    char **contents;
    unsigned count;
    DWORD err;

    contents = xs_directory(xs_handle, path, &count);
    if (contents) {
        fail_test(code, "managed to ls %s (%d)\n", path, count);
        free(contents);
    } else {
        err = GetLastError();
        if (e != err) {
            fail_test(code,
                      "ls %s failed with %d, should have failed with %d",
                      path,
                      err,
                      e);
        }
    }
}
Esempio n. 14
0
static void list_domain_devs(dominfo_t *domp)
{
  char xpath[256], **devs;
  int domid = domp->di_domid;
  int count,i;

  snprintf(xpath, sizeof(xpath), "/local/domain/0/backend/vusb/%d", domid);
  devs = xs_directory(xs_handle, XBT_NULL, xpath, &count);
  if (devs) {
    for (i = 0; i < count; ++i) {
      int virtid = atoi(devs[i]);
      int bus = virtid >> 12;
      int dev = virtid & 0xFFF;
      char *bepath = xs_dev_bepath(domp, "vusb", virtid);
      char *online = xs_get_keyval(bepath, "online");
      if (online && !strcmp(online, "1"))
        printf("%d %d\n", bus, dev);
      free(online);
      free(bepath);
    }
    free(devs);
  }
  fflush(stdout);
}
Esempio n. 15
0
main(
int argc, char **argv)
{

	vxt_db_start_arg_t         start_db_args;
	struct xs_handle *xs;
	char    token;
	char   **vec;
	char   *tail;
	int    ret;
	int    parse_result;
	int    num;
	int    domid;
	int    auth_dev;
	fd_set set;
	int    fd;
	char   target_uuid[MAX_VXT_UUID] = " ";
	int is_provision = 0;

	if (daemon(0, 0) < 0) {
		perror("daemon");
	}

	auth_dev = open(VXT_AUTH_DEVICE_NAME, O_RDWR);
	if(auth_dev < 0) {
		printf("main: Failed to open the Vxt authorization" 
		       " database device\n");
	}

	/*
	 * Start the database if it hasn't already been 
	 * started
	 */
	
	strncpy(start_db_args.db_file_name,
	        VXT_DB_DEFAULT_FILE_NAME, VXT_DB_NAME_MAX);
	
	ioctl(auth_dev, VXT_AUTH_DB_START, (void *)(long)&start_db_args);


	/* printf("The domain device %s\n", xs_domain_dev()); */
	xs = xs_domain_open();
	if (!xs) {
		perror("xs_domain_open failure");
		exit(1);
	}

	ret = xs_watch(xs,  "/vm", "vxtToken");
	if (ret == 0) {
		perror("xs_watch failed\n");
		exit(1);
	}

	fd = xs_fileno(xs);

	while (1) {

		FD_ZERO(&set);
		FD_SET(fd, &set);

		/* 
		 * Poll for data 
		 * printf("Poll for data, 0x%x\n", fd);
		 */
		if ((ret = select(fd+1, &set, NULL, NULL, NULL)) >= 0) {
			/* printf("Watch point triggered ret = 0x%x\n", ret); */
			vec = xs_read_watch(xs, &num);
			printf("\n after read watch ");
			if (!vec) error();

			parse_result =
			   xsd_vm_name(vec[XS_WATCH_PATH], target_uuid);

			if (parse_result == 1) {
				char **list;
			  	char path[64];
				int  entry_cnt;
				int  i;
				/*
				 * get a list of all the domain ids, 
				 * then check the name of each one
				 * to find the id for the specified domain
				 */
				list = xs_directory(xs, XBT_NULL,
				                    "/local/domain",
				                    &entry_cnt);
				for (i = (entry_cnt-1); i > 0; i--) {
					char *rec_uuid;
					sprintf(path,
					        "/local/domain/%s/vm",
						list[i]);
					rec_uuid = xs_read(xs, XBT_NULL,
					                   path, NULL);
					if ( rec_uuid == NULL ) {
						continue;
					}
					if (strcmp(&(rec_uuid[4]),
					           target_uuid) == 0) {
						free(rec_uuid);
						domid = atoi(list[i]);
						break;
					}
					free(rec_uuid);
				}
				free(list);
				if (i == 0) {
					free(vec);
					continue;
				}
	

				xsd_write_auth_record(auth_dev, target_uuid);
				/* 
				printf("main: call vxt_auth_db on uuid = %s\n",
				       target_uuid);
				*/

				xsd_provision_controller(xs, domid);
				is_provision = 1;
				update_vm_state(target_uuid, is_provision);

			} else if (parse_result == 2) {
				/* treating this case as deprovision */
				is_provision = 0;
				update_vm_state(target_uuid, is_provision);
			} else {
				/* target_uuid is undefined
				 * don't call update_vm_state
				 */
			}
			free(vec);
		} else {
			break;
		}
	}

	printf("returned from xs_watch, xenstore exited\n");

}
Esempio n. 16
0
static int check_sharing(struct xs_handle *h, struct backend_info *be)
{
	char *dom_uuid;
	char *cur_dom_uuid;
	char *path;
	char *mode;
	char *params;
	char **domains;
	char **devices;
	int i, j;
	unsigned int num_dom, num_dev;
	blkif_info_t *info = be->blkif->info;
	int ret = 0;
	const char *image_path[2];
	int be_domid = get_be_domid(be->backpath);

	image_path[0] = get_image_path(info->params);

	/* If the mode contains '!' or doesn't contain 'w' don't check anything */
	xs_gather(h, be->backpath, "mode", NULL, &mode, NULL);
	if (strchr(mode, '!'))
		goto out;
	if (strchr(mode, 'w') == NULL)
		goto out;

	/* Get the UUID of the domain we want to attach to */
	if (asprintf(&path, "/local/domain/%ld", be->frontend_id) == -1)
		goto fail;
	xs_gather(h, path, "vm", NULL, &dom_uuid, NULL);
	free(path);

	/* Iterate through the devices of all VMs */
	if (asprintf(&path, "/local/domain/%d/backend/tap", be_domid) == -1)
		goto fail;
	domains = xs_directory(h, XBT_NULL, path, &num_dom);
	free(path);
	if (domains == NULL)
		num_dom = 0;

	for (i = 0; !ret && (i < num_dom); i++) {

		/* If it's the same VM, no action needed */
		if (asprintf(&path, "/local/domain/%s", domains[i]) == -1) {
			ret = -1;
			break;
		}
		cur_dom_uuid = NULL;
		xs_gather(h, path, "vm", NULL, &cur_dom_uuid, NULL);
		free(path);
		if (!cur_dom_uuid)
			continue;

		if (!strcmp(cur_dom_uuid, dom_uuid)) {
			free(cur_dom_uuid);
			continue;
		}

		/* Check the devices */
		if (asprintf(&path, "/local/domain/%d/backend/tap/%s", be_domid, domains[i]) == -1) {
			ret = -1;
			free(cur_dom_uuid);
			break;
		}
		devices = xs_directory(h, XBT_NULL, path, &num_dev);
		if (devices == NULL)
			num_dev = 0;
		free(path);

		for (j = 0; !ret && (j < num_dev); j++) {
			if (asprintf(&path, "/local/domain/%d/backend/tap/%s/%s", be_domid, domains[i], devices[j]) == -1) {
				ret = -1;
				break;
			}
			params = NULL;
			xs_gather(h, path, "params", NULL, &params, NULL);
			free(path);
			if (!params)
				continue;

			image_path[1] = get_image_path(params);
			if (!strcmp(image_path[0], image_path[1])) {
				ret = -1;
			}

			free(params);
		}

		free(cur_dom_uuid);
		free(devices);
	}
	free(domains);
	free(dom_uuid);
	goto out;

fail:
	ret = -1;
out:
	free(mode);
	return ret;
}
Esempio n. 17
0
static int
perform(enum mode mode, int optind, int argc, char **argv, struct xs_handle *xsh,
        xs_transaction_t xth, int prefix, int tidy, int upto, int recurse, int nr_watches)
{
    switch (mode) {
    case MODE_ls:
	if (optind == argc)
	{
	    optind=0;
	    argc=1;
	    argv[0] = "/";
	}
	break;
    default:
	break;
    }

    while (optind < argc) {
        switch (mode) {
        case MODE_unknown:
            /* CANNOT BE REACHED */
            errx(1, "invalid mode %d", mode);
        case MODE_read: {
            static struct expanding_buffer ebuf;
            unsigned len;
            char *val = xs_read(xsh, xth, argv[optind], &len);
            if (val == NULL) {
                warnx("couldn't read path %s", argv[optind]);
                return 1;
            }
            if (prefix)
                output("%s: ", argv[optind]);
            output("%s\n", sanitise_value(&ebuf, val, len));
            free(val);
            optind++;
            break;
        }
        case MODE_write: {
            static struct expanding_buffer ebuf;
            char *val_spec = argv[optind + 1];
            unsigned len;
            expanding_buffer_ensure(&ebuf, strlen(val_spec)+1);
            unsanitise_value(ebuf.buf, &len, val_spec);
            if (!xs_write(xsh, xth, argv[optind], ebuf.buf, len)) {
                warnx("could not write path %s", argv[optind]);
                return 1;
            }
            optind += 2;
        } break;
        case MODE_rm: {
            /* Remove the specified path.  If the tidy flag is set, then also
               remove any containing directories that are both empty and have no
               value attached, and repeat, recursing all the way up to the root if
               necessary.
            */

            char *slash, *path = argv[optind];

            if (tidy) {
                /* Copy path, because we can't modify argv because we will need it
                   again if xs_transaction_end gives us EAGAIN. */
                char *p = malloc(strlen(path) + 1);
                strcpy(p, path);
                path = p;

            again:
                if (do_rm(path, xsh, xth)) {
                    return 1;
                }

                slash = strrchr(p, '/');
                if (slash) {
                    char *val;
                    unsigned len;
                    *slash = '\0';
                    val = xs_read(xsh, xth, p, &len);
                    if (val && len == 0) {
                        unsigned int num;
                        char ** list = xs_directory(xsh, xth, p, &num);

                        if (list) {
                            free(list);
                            if (num == 0)
                                goto again;
                        }
                    }
                }

                free(path);
            }
            else {
                if (do_rm(path, xsh, xth)) {
                    return 1;
                }
            }

            optind++;
            break;
        }
        case MODE_exists: {
            char *val = xs_read(xsh, xth, argv[optind], NULL);
            if (val == NULL) {
                return 1;
            }
            free(val);
            optind++;
            break;
        }
        case MODE_list: {
            unsigned int i, num;
            char **list = xs_directory(xsh, xth, argv[optind], &num);
            if (list == NULL) {
                warnx("could not list path %s", argv[optind]);
                return 1;
            }
            for (i = 0; i < num; i++) {
                if (prefix)
                    output("%s/", argv[optind]);
                output("%s\n", list[i]);
            }
            free(list);
            optind++;
            break;
        }
        case MODE_ls: {
            do_ls(xsh, argv[optind], 0, prefix);
            optind++;
            break;
        }
        case MODE_chmod: {
            /* save path pointer: */
            char *path = argv[optind++];
            int nperms = argc - optind;
            struct xs_permissions perms[nperms];
            int i;
            for (i = 0; argv[optind]; optind++, i++)
            {
                perms[i].id = atoi(argv[optind]+1);

                switch (argv[optind][0])
                {
                case 'n':
                    perms[i].perms = XS_PERM_NONE;
                    break;
                case 'r':
                    perms[i].perms = XS_PERM_READ;
                    break;
                case 'w':
                    perms[i].perms = XS_PERM_WRITE;
                    break;
                case 'b':
                    perms[i].perms = XS_PERM_READ | XS_PERM_WRITE;
                    break;
                default:
                    errx(1, "Invalid permission specification: '%c'",
                         argv[optind][0]);
                }
            }

            do_chmod(path, perms, nperms, upto, recurse, xsh, xth);
            break;
        }
        case MODE_watch: {
            for (; argv[optind]; optind++) {
                const char *w = argv[optind];

                if (!xs_watch(xsh, w, w))
                    errx(1, "Unable to add watch on %s\n", w);
            }
            do_watch(xsh, nr_watches);
        }
        }
    }

    return 0;
}
Esempio n. 18
0
void xenstore_parse_domain_config(int domid)
{
    char **e = NULL;
    char *buf = NULL, *path;
    char *fpath = NULL, *bpath = NULL,
        *dev = NULL, *params = NULL, *type = NULL, *drv = NULL;
    int i, is_scsi, is_hdN = 0;
    unsigned int len, num, hd_index;
    BlockDriverState *bs;

    for(i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++)
        media_filename[i] = NULL;

    xsh = xs_daemon_open();
    if (xsh == NULL) {
        fprintf(logfile, "Could not contact xenstore for domain config\n");
        return;
    }

    path = xs_get_domain_path(xsh, domid);
    if (path == NULL) {
        fprintf(logfile, "xs_get_domain_path() error\n");
        goto out;
    }

    if (pasprintf(&buf, "%s/device/vbd", path) == -1)
        goto out;

    e = xs_directory(xsh, XBT_NULL, buf, &num);
    if (e == NULL)
        goto out;

    for (i = 0; i < num; i++) {
        /* read the backend path */
        if (pasprintf(&buf, "%s/device/vbd/%s/backend", path, e[i]) == -1)
            continue;
        free(bpath);
        bpath = xs_read(xsh, XBT_NULL, buf, &len);
        if (bpath == NULL)
            continue;
        /* read the name of the device */
        if (pasprintf(&buf, "%s/dev", bpath) == -1)
            continue;
        free(dev);
        dev = xs_read(xsh, XBT_NULL, buf, &len);
        if (dev == NULL)
            continue;
        if (!strncmp(dev, "hd", 2)) {
            is_hdN = 1;
            break;
        }
    }
        
    for (i = 0; i < num; i++) {
        /* read the backend path */
        if (pasprintf(&buf, "%s/device/vbd/%s/backend", path, e[i]) == -1)
            continue;
        free(bpath);
        bpath = xs_read(xsh, XBT_NULL, buf, &len);
        if (bpath == NULL)
            continue;
        /* read the name of the device */
        if (pasprintf(&buf, "%s/dev", bpath) == -1)
            continue;
        free(dev);
        dev = xs_read(xsh, XBT_NULL, buf, &len);
        if (dev == NULL)
            continue;
        /* Change xvdN to look like hdN */
        if (!is_hdN && !strncmp(dev, "xvd", 3)) {
            fprintf(logfile, "Change xvd%c to look like hd%c\n",
                    dev[3], dev[3]);
            memmove(dev, dev+1, strlen(dev));
            dev[0] = 'h';
            dev[1] = 'd';
        }
        is_scsi = !strncmp(dev, "sd", 2);
        if ((strncmp(dev, "hd", 2) && !is_scsi) || strlen(dev) != 3 )
            continue;
        hd_index = dev[2] - 'a';
        if (hd_index >= (is_scsi ? MAX_SCSI_DISKS : MAX_DISKS))
            continue;
        /* read the type of the device */
        if (pasprintf(&buf, "%s/device/vbd/%s/device-type", path, e[i]) == -1)
            continue;
        free(type);
        type = xs_read(xsh, XBT_NULL, buf, &len);
        if (pasprintf(&buf, "%s/params", bpath) == -1)
            continue;
        free(params);
        params = xs_read(xsh, XBT_NULL, buf, &len);
        if (params == NULL)
            continue;
        /* read the name of the device */
        if (pasprintf(&buf, "%s/type", bpath) == -1)
            continue;
        free(drv);
        drv = xs_read(xsh, XBT_NULL, buf, &len);
        if (drv == NULL)
            continue;
        /* Strip off blktap sub-type prefix aio: - QEMU can autodetect this */
        if (!strcmp(drv, "tap") && params[0]) {
            char *offset = strchr(params, ':'); 
            if (!offset)
                continue ;
            memmove(params, offset+1, strlen(offset+1)+1 );
            fprintf(logfile, "Strip off blktap sub-type prefix to %s\n", params); 
        }
        /* Prefix with /dev/ if needed */
        if (!strcmp(drv, "phy") && params[0] != '/') {
            char *newparams = malloc(5 + strlen(params) + 1);
            sprintf(newparams, "/dev/%s", params);
            free(params);
            params = newparams;
        }

        /* 
         * check if device has a phantom vbd; the phantom is hooked
         * to the frontend device (for ease of cleanup), so lookup 
         * the frontend device, and see if there is a phantom_vbd
         * if there is, we will use resolution as the filename
         */
        if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1)
            continue;
        free(fpath);
        fpath = xs_read(xsh, XBT_NULL, buf, &len);
        if (fpath) {
            if (pasprintf(&buf, "%s/dev", fpath) == -1)
                continue;
            free(params);
            params = xs_read(xsh, XBT_NULL, buf , &len);
            if (params) {
                /* 
                 * wait for device, on timeout silently fail because we will 
                 * fail to open below
                 */
                waitForDevice(params);
            }
        }

        bs = bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)] = bdrv_new(dev);
        /* check if it is a cdrom */
        if (type && !strcmp(type, "cdrom")) {
            bdrv_set_type_hint(bs, BDRV_TYPE_CDROM);
            if (pasprintf(&buf, "%s/params", bpath) != -1)
                xs_watch(xsh, buf, dev);
        }

        /* open device now if media present */
        if (params[0]) {
            if (bdrv_open(bs, params, 0 /* snapshot */) < 0)
                fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
                        params);
        }
    }

    /* Set a watch for log-dirty requests from the migration tools */
    if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/next-active",
                  domid) != -1) {
        xs_watch(xsh, buf, "logdirty");
        fprintf(logfile, "Watching %s\n", buf);
    }

    /* Set a watch for suspend requests from the migration tools */
    if (pasprintf(&buf, 
                  "/local/domain/0/device-model/%u/command", domid) != -1) {
        xs_watch(xsh, buf, "dm-command");
        fprintf(logfile, "Watching %s\n", buf);
    }

 out:
    free(type);
    free(params);
    free(dev);
    free(bpath);
    free(buf);
    free(path);
    free(e);
    free(drv);
    return;
}
Esempio n. 19
0
static void do_ls(struct xs_handle *h, char *path, int cur_depth, int show_perms)
{
    static struct expanding_buffer ebuf;
    char **e;
    char newpath[STRING_MAX], *val;
    int newpath_len;
    int i;
    unsigned int num, len;

    e = xs_directory(h, XBT_NULL, path, &num);
    if (e == NULL)
        err(1, "xs_directory (%s)", path);

    for (i = 0; i<num; i++) {
        char buf[MAX_STRLEN(unsigned int)+1];
        struct xs_permissions *perms;
        unsigned int nperms;
        int linewid;

        /* Compose fullpath */
        newpath_len = snprintf(newpath, sizeof(newpath), "%s%s%s", path, 
                path[strlen(path)-1] == '/' ? "" : "/", 
                e[i]);

        /* Print indent and path basename */
        linewid = 0;
        if (show_whole_path) {
            fputs(newpath, stdout);
        } else {
            for (; linewid<cur_depth; linewid++) {
                putchar(' ');
            }
            linewid += printf("%.*s",
                              (int) (max_width - TAG_LEN - linewid), e[i]);
        }

	/* Fetch value */
        if ( newpath_len < sizeof(newpath) ) {
            val = xs_read(h, XBT_NULL, newpath, &len);
        }
        else {
            /* Path was truncated and thus invalid */
            val = NULL;
            len = 0;
        }

        /* Print value */
        if (val == NULL) {
            printf(":\n");
        }
        else {
            if (max_width < (linewid + len + TAG_LEN)) {
                printf(" = \"%.*s\\...\"",
                       (int)(max_width - TAG_LEN - linewid),
		       sanitise_value(&ebuf, val, len));
            }
            else {
                linewid += printf(" = \"%s\"",
				  sanitise_value(&ebuf, val, len));
                if (show_perms) {
                    putchar(' ');
                    for (linewid++;
                         linewid < MIN(desired_width, max_width);
                         linewid++)
                        putchar((linewid & 1)? '.' : ' ');
                }
            }
        }
        free(val);

        if (show_perms) {
            perms = xs_get_permissions(h, XBT_NULL, newpath, &nperms);
            if (perms == NULL) {
                warn("\ncould not access permissions for %s", e[i]);
            }
            else {
                int i;
                fputs("  (", stdout);
                for (i = 0; i < nperms; i++) {
                    if (i)
                        putchar(',');
                    xs_perm_to_string(perms+i, buf, sizeof(buf));
                    fputs(buf, stdout);
                }
                putchar(')');
            }
        }

        putchar('\n');
            
        do_ls(h, newpath, cur_depth+1, show_perms); 
    }
    free(e);
}
Esempio n. 20
0
int __cdecl
main()
{
    char *vm_path, *uuid, *t;
    size_t l;
    char **contents;
    unsigned count;
    HANDLE xs_handle2;
    HANDLE event;
    HANDLE event2;
    int watch_h;
    int watch_h2;
    int i;
    DWORD status;

    xs_handle = xs_domain_open();
    if (!xs_handle)
        win_err(1, "openning xenstore interface");

    /* Try to give ourselves a clean place to start */
    xs_remove(xs_handle, "data/test");

    /* Check basic xenstore reads with relative path... */
    vm_path = xs_read(xs_handle, "vm", NULL);
    if (!vm_path)
        win_err(1, "reading vm path");
    if (vm_path[0] != '/') {
        fail_test(__LINE__, "expected vm path to be absolute, got %s",
                  vm_path);
    }

    /* and with an absolute path. */
    uuid = gather_read(&l, vm_path, "uuid", NULL);
    if (!uuid)
        win_err(1, "reading uuid");
    if (l != 36) {
        fail_test(__LINE__, "uuid length was %d bytes, expected 36");
    }
    if (strlen(uuid) != 36) {
        fail_test(__LINE__,
                  "uuid was %s, not right length (%d, should be 36), returned length %d",
                  uuid,
                  strlen(uuid),
                  l);
    }

    /* Make sure read error sets a suitable code. */
    xs_read_expected_error(__LINE__, "non_existent", ERROR_FILE_NOT_FOUND);
    xs_read_expected_error(__LINE__, "invalid\\path",
                           ERROR_INVALID_PARAMETER);
    xs_read_expected_error(__LINE__, "/local/domain/0/name",
                           ERROR_ACCESS_DENIED);

    /* Test basic xs_write functionality. */
    if (!xs_write(xs_handle, "data/test/key1", "data1")) {
        fail_test(__LINE__, "write data/test/key1 failed with %lx",
                  GetLastError());
    } else {
        t = xs_read(xs_handle, "data/test/key1", &l);
        if (!t) {
            fail_test(__LINE__, "error reading from data/test/key1: %lx",
                      GetLastError());
        } else {
            if (l != 5) {
                fail_test(__LINE__,
                          "manifest length wrong reading data/test/key1: %d should be 5.",
                          l);
            }
            if (strcmp(t, "data1")) {
                fail_test(__LINE__,
                          "got wrong data reading data/test/key1: %s should be data1.",
                          t);
            }
            free(t);
        }
    }

    xs_write_expected_error(__LINE__, "foo", "bar", ERROR_ACCESS_DENIED);
    xs_write_expected_error(__LINE__, "/foo", "bar", ERROR_ACCESS_DENIED);

    /* Try a very large write and make sure that it fails in the
       expected way. */
    t = malloc(65536);
    memset(t, 'a', 65536);
    t[65535] = 0;
    xs_write_expected_error(__LINE__,"data/test/key1", t,
                            ERROR_DISK_FULL);
    free(t);

    /* Test that read and write work for keys containing nul bytes. */
    if (!xs_write_bin(xs_handle, "data/test/key1", "xxx\0yyy", 7)) {
        fail_test(__LINE__, "failed to write nul bytes (%d)",
                  GetLastError());
    }
    t = xs_read(xs_handle, "data/test/key1", &l);
    if (!t) {
        fail_test(__LINE__, "failed to read nul bytes (%d)",
                  GetLastError());
    } else {
        if (l != 7) {
            fail_test(__LINE__, "read with nuls: expected 7, got %d.\n", l);
        } else if (memcmp(t, "xxx\0yyy", 7)) {
            fail_test(__LINE__, "bad data from read with nuls: %s",
                      t);
        }
        free(t);
    }

    if (!xs_remove(xs_handle, "data/test/key1")) {
        fail_test(__LINE__, "failed to remove data/test/key1 (%d)",
                  GetLastError());
    }

    xs_read_expected_error(__LINE__, "data/test/key1", ERROR_FILE_NOT_FOUND);

    xs_ls_expected_error(__LINE__, "data/test/key1", ERROR_FILE_NOT_FOUND);

    if (!xs_write(xs_handle, "data/test/key1", "data1")) {
        fail_test(__LINE__, "failed to rewrite data/test/key1");
    }

    contents = xs_directory(xs_handle, "data/test/key1", &count);
    if (!contents) {
        fail_test(__LINE__, "failed to ls data/test/key1: %x",
                  GetLastError());
    } else if (count != 0) {
        fail_test(__LINE__, "ls data/test/key1 had %d items", count);
        free(contents);
    } else {
        free(contents);
    }

    if (!xs_write(xs_handle, "data/test/key1/key2", "data2")) {
        fail_test(__LINE__, "failed to rewrite data/test/key1/key2");
    }

    contents = xs_directory(xs_handle, "data/test/key1", &count);
    if (!contents) {
        fail_test(__LINE__, "failed to ls data/test/key1: %x",
                  GetLastError());
    } else if (count != 1) {
        fail_test(__LINE__, "ls data/test/key1 had %d items", count);
        free(contents);
    } else if (strcmp(contents[0], "key2")) {
        fail_test(__LINE__, "ls data/test/key1 gave unexpected result %s",
                  contents[0]);
    }

    xs_remove(xs_handle, "data/test");

    /* Looks like most of the basic functionality works.  Try
     * transactions. */
    xs_handle2 = xs_domain_open();
    if (!xs_handle2) win_err(1, "couldn't re-open domain interface");

    if (!xs_write(xs_handle, "data/test/key1", "before"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    if (!xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "failed to write to end transaction: %x",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "after"))
        fail_test(__LINE__, "transaction didn't stick");

    /* Now try aborting the transaction. */
    if (!xs_write(xs_handle, "data/test/key1", "before"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    if (!xs_transaction_end(xs_handle2, TRUE))
        fail_test(__LINE__, "failed to write to end transaction: %x",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "before"))
        fail_test(__LINE__, "transaction didn't abort");

    /* Try to arrange that the transaction fails. */
    if (!xs_write(xs_handle, "data/test/key1", "before"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    if (!xs_write(xs_handle, "data/test/key1", "other"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "transaction succeeded when it shouldn't",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "other"))
        fail_test(__LINE__, "transaction did something strange");


    if (!xs_write(xs_handle, "data/test/key1", "before1"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_write(xs_handle, "data/test/key2", "before2"))
        fail_test(__LINE__, "failed to write to data/test/key2: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    t = xs_read(xs_handle2, "data/test/key2", NULL);
    if (!t) {
        fail_test(__LINE__,
                  "failed to read data/test/key2 under transaction: %x",
                  GetLastError());
    } else {
        if (strcmp(t, "before2"))
            fail_test(__LINE__,
                      "got wrong thing reading dtaa/test/key2 (%s)",
                      t);
        free(t);
    }
    if (!xs_write(xs_handle, "data/test/key2", "other"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "transaction succeeded when it shouldn't",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "before1"))
        fail_test(__LINE__, "transaction did something strange");

    xs_daemon_close(xs_handle2);

    /* Try a couple of transaction error cases. */
    xs_handle2 = xs_domain_open();
    if (!xs_handle2) win_err(1, "couldn't re-open domain interface a second time");
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction for re-test");
    if (xs_transaction_start(xs_handle2)) {
        fail_test(__LINE__, "openned two transactions on same handle");
    }
    xs_daemon_close(xs_handle2);

    xs_handle2 = xs_domain_open();
    if (!xs_handle2) win_err(1, "couldn't re-open domain interface a third time");
    if (xs_transaction_end(xs_handle2, FALSE)) {
        fail_test(__LINE__, "ended transaction without starting it");
    }
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction for re-test");
    if (!xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "failed to end transaction");
    if (xs_transaction_end(xs_handle2, FALSE)) {
        fail_test(__LINE__, "double-ended transaction");
    }
    xs_daemon_close(xs_handle2);


    /* Transactions appear to be working, at least in their most basic
       form.  Have a go at watches. */
    event = CreateEvent(NULL, FALSE, FALSE, NULL);
    watch_h = xs_watch(xs_handle, "data/test/key1", event);
    if (watch_h < 0) {
        fail_test(__LINE__, "couldn't watch data/test/key1");
    } else {
        while (WaitForSingleObject(event, 100) != WAIT_TIMEOUT)
            ;
        xs_write(xs_handle, "data/test/key1", "foo");
        if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
            fail_test(__LINE__, "failed wait for data/test/key1: %x",
                      GetLastError());
        xs_write(xs_handle, "data/test/key1", "foo");
        if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
            fail_test(__LINE__, "failed wait for data/test/key1: %x",
                      GetLastError());
        xs_write(xs_handle, "data/test/key1", "foo");
        if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
            fail_test(__LINE__, "failed wait for data/test/key1: %x",
                      GetLastError());
        status = WaitForSingleObject(event, 2000);
        if (status != WAIT_TIMEOUT)
            fail_test(__LINE__,
                      "should have timed out waiting for data/test/key1 (%d, %d)",
                      status,
                      GetLastError());

        if (!xs_unwatch(xs_handle, watch_h))
            fail_test(__LINE__, "failed to unwatch");
    }

    /* Create two watches on the same key, kill one of them, and then
       make sure that the other one still works. */
    watch_h = xs_watch(xs_handle, "data/test/key1/subkey", event);
    if (watch_h < 0) {
        fail_test(__LINE__, "couldn't watch data/test/key1/subkey");
    } else {
        event2 = CreateEvent(NULL, FALSE, FALSE, NULL);
        watch_h2 = xs_watch(xs_handle, "data/test/key1/subkey", event);
        if (watch_h2 < 0) {
            fail_test(__LINE__, "couldn't double watch data/test/key1/subkey");
        } else {
            if (!xs_unwatch(xs_handle, watch_h2))
                fail_test(__LINE__, "failed to unwatch h2");
            ResetEvent(event);
            xs_remove(xs_handle, "data/test/key1");
            if (WaitForSingleObject(event, 5000) != WAIT_OBJECT_0)
                fail_test(__LINE__, "failed wait for data/test/key1: %x",
                          GetLastError());
            if (!xs_unwatch(xs_handle, watch_h))
                fail_test(__LINE__, "failed to unwatch");
        }
    }

    /* Watch a node, then modify it in a transaction, and check that
       the watch fires. */
    watch_h = xs_watch(xs_handle, "data/test/key1", event);
    if (watch_h < 0) {
        fail_test(__LINE__, "couldn't watch data/test/key1");
    } else {
        for (i = 0; i < 100; i++) {
            ResetEvent(event);
            do {
                if (!xs_transaction_start(xs_handle))
                    win_err(1, "couldn't open a transaction for watch test");
                xs_write(xs_handle, "data/test/key1", "foo");
            } while (!xs_transaction_end(xs_handle, FALSE));
            if (WaitForSingleObject(event, 5000) != WAIT_OBJECT_0)
                fail_test(__LINE__, "failed wait for data/test/key1(%d): %x",
                          i, GetLastError());
        }
        if (!xs_unwatch(xs_handle, watch_h))
            fail_test(__LINE__, "failed to unwatch");
    }

    /* Make a lot of watches, make sure they all work. */
    test_many_watches();

    /* Try some different sized requests */
    test_write_sizes(4096);

    xs_daemon_close(xs_handle);

    run_stress();

    if (failed) {
        printf("failed\n");
        return 1;
    } else {
        printf("passed\n");
        return 0;
    }
}