Example #1
0
static int
kvs_session_verify(WT_DATA_SOURCE *wtds,
    WT_SESSION *session, const char *uri, WT_CONFIG_ARG *config)
{
	DATA_SOURCE *ds;
	DB *db;
	WT_EXTENSION_API *wt_api;
	int ret = 0;
	const char *name;

	(void)config;				/* Unused parameters */

	ds = (DATA_SOURCE *)wtds;
	wt_api = ds->wt_api;
						/* Get the object name */
	if ((ret = uri2name(wt_api, session, uri, &name)) != 0)
		return (ret);

	if ((ret = single_thread(wtds, session, &ds->rwlock)) != 0)
		return (ret);

	if ((ret = db_create(&db, ds->dbenv, 0)) != 0)
		ESET(wt_api,
		    session, WT_ERROR, "db_create: %s", db_strerror(ret));
	else if ((ret = db->verify(db, name, NULL, NULL, 0)) != 0)
		ESET(wt_api, session, WT_ERROR,
		    "Db.verify: %s: %s", uri, db_strerror(ret));
	/* db handle is dead */

	ETRET(unlock(wt_api, session, &ds->rwlock));
	return (ret);
}
Example #2
0
/*
 * kvs_session_create --
 *	WT_SESSION::create method.
 */
static int
kvs_session_create(WT_DATA_SOURCE *dsrc,
    WT_SESSION *session, const char *uri, WT_CONFIG_ARG *config)
{
	struct kvs_config kvs_config;
	kvs_t kvs;
	int flags, ret;
	char **devices, *emsg;

	(void)dsrc;				/* Unused parameters */

	devices = NULL;
	emsg = NULL;

	/*
	 * Check if the object exists and drop it if we can.  What we really
	 * care about is if it's busy, we don't want to continue in the face
	 * of open cursors.
	 */
	if ((ret = drop_data_source(session, uri)) != 0)
		return (ret);

	/* Read the configuration. */
	if ((ret = kvs_config_read(
	    session, config, &devices, &kvs_config, &flags)) != 0)
		goto err;

	/* We require a list of devices underlying the URI. */
	if (devices[0] == NULL) {
		ESET(session, EINVAL,
		    "WT_SESSION.create: no devices specified");
		goto err;
	}

	/*
	 * Open the KVS handle (creating the underlying object), and then close
	 * it, we're done.
	 */
	if ((kvs =
	    kvs_open(devices, &kvs_config, flags | KVS_O_CREATE)) == NULL) {
		emsg = kvs_create_path_string(devices);
		ESET(session, WT_ERROR,
		    "WT_SESSION.create: kvs_open: %s: %s",
		    emsg == NULL ? devices[0] : emsg, kvs_strerror(os_errno()));
		goto err;
	}
	if ((ret = kvs_close(kvs)) != 0) {
		emsg = kvs_create_path_string(devices);
		ESET(session, WT_ERROR,
		    "%s: WT_SESSION.create: kvs_close: %s: %s",
		    emsg == NULL ? devices[0] : emsg, kvs_strerror(ret));
		goto err;
	}

err:	free(emsg);
	free(devices);
	return (ret);
}
Example #3
0
int Process::addParameter(const char *parameter)
{
  logTrace("Process::addParameter");

  if (function_ != NULL)
  {
    logTest("Process::addParameter", "Can't add a parameter "
                "to a function");

    logError("Process::addParameter", ESET(EPERM));

    return -1;
  }
  else if (nextParameter_ < 2)
  {
    logTest("Process::addParameter", "Can't add a parameter "
                "without a command");

    logError("Process::addParameter", ESET(EPERM));

    return -1;
  }

  if (nextParameter_ < parametersLimit_)
  {
    if (setValue(parameters_[nextParameter_], parameter) > 0)
    {
      nextParameter_++;

      return 1;
    }
  }
  else
  {
    logTest("Process::addParameter", "No space left in the "
                "parameter table");

    logError("Process::addParameter", ESET(ENOMEM));
  }

  return -1;
}
Example #4
0
/*
 * wiredtiger_extension_terminate --
 *	Shutdown the KVS connector code.
 */
int
wiredtiger_extension_terminate(WT_CONNECTION *connection)
{
	DATA_SOURCE *p;
	int ret, tret;

	(void)connection;			/* Unused parameters */

	ret = writelock(NULL, &global_lock);

	/* Start a flush on any open objects. */
	for (p = data_source_head; p != NULL; p = p->next)
		if ((tret = kvs_commit(p->kvs)) != 0)
			ESET(NULL, WT_ERROR,
			    "kvs_commit: %s: %s", p->uri, kvs_strerror(tret));

	/* Complain if any of the objects are in use. */
	for (p = data_source_head; p != NULL; p = p->next)
		if (p->open_cursors != 0)
			ESET(NULL, WT_ERROR,
			    "%s: has open cursors during close", p->uri);

	/* Close and discard the remaining objects. */
	while ((p = data_source_head) != NULL) {
		if ((tret = kvs_close(p->kvs)) != 0)
			ESET(NULL, WT_ERROR,
			    "kvs_close: %s: %s", p->uri, kvs_strerror(tret));
		data_source_head = p->next;
		free(p->uri);
		ETRET(lock_destroy(NULL, &p->lock));
		free(p);
	}

	ETRET(unlock(NULL, &global_lock));
	ETRET(lock_destroy(NULL, &global_lock));

	wt_ext = NULL;

	return (ret);
}
Example #5
0
static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)

{
    int i, len, total;
    char *base;

    ESET(0);
    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
	len = iov->iov_len;
	base = iov->iov_base;
	while (len > 0) {
	    register int nbytes;
	    nbytes = TRANS(Write) (ciptr, base, len);
	    if (nbytes < 0 && total == 0)  return -1;
	    if (nbytes <= 0)  return total;
	    ESET(0);
	    len   -= nbytes;
	    total += nbytes;
	    base  += nbytes;
	}
    }
    return total;
}
Example #6
0
static int
kvs_session_truncate(WT_DATA_SOURCE *wtds,
    WT_SESSION *session, const char *uri, WT_CONFIG_ARG *config)
{
	DATA_SOURCE *ds;
	DB *db;
	WT_EXTENSION_API *wt_api;
	int tret, ret = 0;
	const char *name;

	(void)config;				/* Unused parameters */

	ds = (DATA_SOURCE *)wtds;
	wt_api = ds->wt_api;
						/* Get the object name */
	if ((ret = uri2name(wt_api, session, uri, &name)) != 0)
		return (ret);

	if ((ret = single_thread(wtds, session, &ds->rwlock)) != 0)
		return (ret);

	if ((ret = db_create(&db, ds->dbenv, 0)) != 0)
		ESET(wt_api,
		    session, WT_ERROR, "db_create: %s", db_strerror(ret));
	else {
		if ((ret = db->open(db,
		    NULL, name, NULL, DB_UNKNOWN, DB_TRUNCATE, 0)) != 0)
			ESET(wt_api, session, WT_ERROR,
			    "Db.open: %s", db_strerror(ret));
		if ((tret = db->close(db, 0)) != 0)
			ESET(wt_api, session, WT_ERROR,
			    "Db.close: %s", db_strerror(tret));
	}

	ETRET(unlock(wt_api, session, &ds->rwlock));
	return (ret);
}
Example #7
0
int Process::setDescriptor(int &std, int fd)
{
  logTrace("Process::setDescriptor");

  if (pid_ != -1)
  {
    logError("Process::setDescriptor", ESET(EPERM));

    return -1;
  }

  std = fd;

  return 1;
}
Example #8
0
int Process::setPrivileged(int value)
{
  logTrace("Process::setPrivileged");

  if (pid_ != -1)
  {
    logError("Process::setPrivileged", ESET(EPERM));

    return -1;
  }

  privileged_ = value;
  
  return 1;
}
Example #9
0
int Process::wait(const T_timestamp timeout)
{
  logTrace("Process::wait");

  if (pid_ < 0)
  {
    logError("Process::wait", ESET(ECHILD));

    return 1;
  }

  //
  // Wait for the process until the timeout.
  //

  int status;

  int options = WUNTRACED;

  setTimer(timeout);

  int result;

  if ((result = waitpid(pid_, &status, options)) == -1)
  {
    if (EGET() == EINTR)
    {
      logTest("Process::wait", "Timeout raised waiting "
                  "for pid %d", pid_);

      return 0;
    }
    else
    {
      logError("Process::wait", EGET());

      return -1;      
    }
  }

  resetTimer();

  result = parseStatus(result, status);

  return result;
}
Example #10
0
int Process::wait()
{
  logTrace("Process::wait");

  if (pid_ < 0)
  {
    logError("Process::wait", ESET(ECHILD));

    return -1;
  }

  int status;

  int options = WUNTRACED;

  int result = waitpid(pid_, &status, options);

  return parseStatus(result, status);
}
Example #11
0
int Process::setFunction(int (*function)(void *), void *parameter)
{
  logTrace("Process::setFunction");

  if (function_ != NULL || parameters_[0] != NULL)
  {
    logError("Process::setFunction", ESET(EPERM));

    return -1;
  }

  function_ = function;

  parameters_[0] = (char *) parameter;

  nextParameter_ = 1;

  return 1;
}
Example #12
0
/*
 * kvs_session_truncate --
 *	WT_SESSION::truncate method.
 */
static int
kvs_session_truncate(WT_DATA_SOURCE *dsrc,
    WT_SESSION *session, const char *uri, WT_CONFIG_ARG *config)
{
	DATA_SOURCE *p;
	int ret, tret;

	(void)dsrc;				/* Unused parameters */

	/*
	 * Truncate should work even if the object is not yet opened: if we
	 * don't find it, open it.   We loop because we could theoretically
	 * race with other threads creating/deleting the object.
	 */
	for (;;) {
		if ((ret = writelock(session, &global_lock)) != 0)
			return (ret);

		/* Search our list of objects for a match. */
		for (p = data_source_head; p != NULL; p = p->next)
			if (strcmp(p->uri, uri) == 0)
				break;

		/* If we don't find the object, open it. */
		if (p == NULL) {
			if ((ret = unlock(session, &global_lock)) != 0)
				return (ret);
			if ((ret = open_data_source(session, uri, config)) != 0)
				return (ret);
			continue;
		}
		if (p->open_cursors == 0) {
			if ((tret = kvs_truncate(p->kvs)) != 0)
				ESET(NULL, WT_ERROR,
				    "kvs_truncate: %s: %s",
				    p->uri, kvs_strerror(tret));
		} else
			ret = EBUSY;
		ETRET(unlock(session, &global_lock));
		return (ret);
	}
	/* NOTREACHED */
}
Example #13
0
static int
kvs_terminate(WT_DATA_SOURCE *wtds, WT_SESSION *session)
{
	DB_ENV *dbenv;
	DATA_SOURCE *ds;
	WT_EXTENSION_API *wt_api;
	int ret = 0;

	ds = (DATA_SOURCE *)wtds;
	wt_api = ds->wt_api;
	dbenv = ds->dbenv;

	if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0)
		ESET(wt_api,
		    session, WT_ERROR, "DbEnv.close: %s", db_strerror(ret));

	ETRET(lock_destroy(wt_api, session, &ds->rwlock));

	return (ret);
}
Example #14
0
int Process::isSuccess()
{
  logTrace("Process::isSuccess");

  if (status_ == -1)
  {
    logTest("Process::isSuccess", "Child %d is "
                "still running", pid_);

    logWarning("Process::isSuccess", ESET(EPERM));

    return 0;
  }

  if (WIFEXITED(status_))
  {
    return (WEXITSTATUS(status_) == 0);
  }

  return 0;
}
Example #15
0
int Process::addEnvironment(const char *environment)
{
  logTrace("Process::addEnvironment");

  if (nextEnvironment_ < environmentLimit_)
  {
    if (setValue(environment_[nextEnvironment_], environment) > 0)
    {
      nextEnvironment_++;

      return 1;
    }
  }
  else
  {
    logTest("Process::addEnvironment", "No space left in the "
                "environment table");

    logError("Process::addEnvironment", ESET(ENOMEM));
  }

  return -1;
}
Example #16
0
/*
 * drop_data_source --
 *	Drop a data source from our list, closing any underlying KVS handle.
 */
static int
drop_data_source(WT_SESSION *session, const char *uri)
{
	DATA_SOURCE *p, **ref;
	int ret;

	if ((ret = writelock(session, &global_lock)) != 0)
		return (ret);

	/* Search our list of objects for a match. */
	for (ref = &data_source_head; (p = *ref) != NULL; p = p->next)
		if (strcmp(p->uri, uri) == 0)
			break;

	/*
	 * If we don't find the URI in our object list, we're done.
	 * If the object is in use (it has open cursors), we can't drop it.
	 * Otherwise, drop it.
	 */
	if (p == NULL || p->open_cursors != 0) {
		if (p != NULL)
			ret = EBUSY;
	} else {
		if ((ret = kvs_close(p->kvs)) != 0)
			ESET(session, WT_ERROR,
			    "kvs_close: %s: %s", uri, kvs_strerror(ret));
		*ref = p->next;

		free(p->uri);
		ETRET(lock_destroy(session, &p->lock));
		free(p);
	}

	ETRET(unlock(session, &global_lock));
	return (ret);
}
Example #17
0
/*
 * open_data_source --
 *	Open a new data source and insert it into the list.
 */
static int
open_data_source(WT_SESSION *session, const char *uri, WT_CONFIG_ARG *config)
{
	struct kvs_config kvs_config;
	DATA_SOURCE *data_source, *p;
	int ds_lockinit, flags, locked, ret;
	char **devices, *emsg;

	devices = NULL;
	emsg = NULL;
	ds_lockinit = locked = ret = 0;

	/*
	 * The first time we open a cursor on an object, allocate an underlying
	 * data source object.
	 */
	if ((data_source =
	    (DATA_SOURCE *)calloc(1, sizeof(DATA_SOURCE))) == NULL)
		return (os_errno());
	if ((data_source->uri = strdup(uri)) == NULL)
		goto err;
	if ((ret = lock_init(session, &data_source->lock)) != 0)
		goto err;
	ds_lockinit = 1;

	/* Read the configuration. */
	if ((ret = kvs_config_read(
	    session, config, &devices, &kvs_config, &flags)) != 0)
		goto err;

	/* We require a list of devices underlying the URI. */
	if (devices[0] == NULL) {
		ESET(
		    session, EINVAL, "WT_SESSION.create: no devices specified");
		goto err;
	}

	/*
	 * kvs_open isn't re-entrant: lock things down while we make sure we
	 * don't have more than a single handle at a time.
	 */
	if ((ret = writelock(session, &global_lock)) != 0)
		goto err;
	locked = 1;

	/*
	 * Check for a match: if we find one, we raced, but we return success,
	 * someone else did the work.
	 */
	for (p = data_source_head; p != NULL; p = p->next)
		if (strcmp(p->uri, uri) == 0)
			goto err;

	/* Open the KVS handle. */
	if ((data_source->kvs =
	    kvs_open(devices, &kvs_config, flags)) == NULL) {
		emsg = kvs_create_path_string(devices);
		ESET(session, WT_ERROR,
		    "WT_SESSION.create: kvs_open: %s: %s",
		    emsg == NULL ? devices[0] : emsg, kvs_strerror(os_errno()));
		goto err;
	}

	/* Insert the new entry at the head of the list. */
	data_source->next = data_source_head;
	data_source_head = data_source;
	data_source = NULL;

err:	if (locked)
		ETRET(unlock(session, &global_lock));

	if (data_source != NULL) {
		if (data_source->uri != NULL)
			free(data_source->uri);
		if (ds_lockinit)
			ETRET(lock_destroy(session, &data_source->lock));
		free(data_source);
	}
	free(devices);
	free(emsg);
	return (ret);
}
Example #18
0
static int
kvs_session_open_cursor(WT_DATA_SOURCE *wtds, WT_SESSION *session,
    const char *uri, WT_CONFIG_ARG *config, WT_CURSOR **new_cursor)
{
	CURSOR_SOURCE *cursor;
	DATA_SOURCE *ds;
	DB *db;
	WT_CONFIG_ITEM v;
	WT_EXTENSION_API *wt_api;
	int locked, ret;
	const char *name;

	ds = (DATA_SOURCE *)wtds;
	wt_api = ds->wt_api;
	locked = 0;
						/* Get the object name */
	if ((ret = uri2name(wt_api, session, uri, &name)) != 0)
		return (ret);
						/* Allocate the cursor */
	if ((cursor = calloc(1, sizeof(CURSOR_SOURCE))) == NULL)
		return (os_errno());
	cursor->ds = (DATA_SOURCE *)wtds;
	cursor->wt_api = wt_api;
						/* Parse configuration */
	if ((ret = wt_api->config_get(
	    wt_api, session, config, "append", &v)) != 0) {
		ESET(wt_api, session, ret,
		    "append configuration: %s",
		    wt_api->strerror(wt_api, session, ret));
		goto err;
	}
	cursor->config_append = v.val != 0;

	if ((ret = wt_api->config_get(
	    wt_api, session, config, "overwrite", &v)) != 0) {
		ESET(wt_api, session, ret,
		    "overwrite configuration: %s",
		    wt_api->strerror(wt_api, session, ret));
		goto err;
	}
	cursor->config_overwrite = v.val != 0;

	if ((ret = wt_api->config_get(
	    wt_api, session, config, "key_format", &v)) != 0) {
		ESET(wt_api, session, ret,
		    "key_format configuration: %s",
		    wt_api->strerror(wt_api, session, ret));
		goto err;
	}
	cursor->config_recno = v.len == 1 && v.str[0] == 'r';

	if ((ret = wt_api->config_get(
	    wt_api, session, config, "value_format", &v)) != 0) {
		ESET(wt_api, session, ret,
		    "value_format configuration: %s",
		    wt_api->strerror(wt_api, session, ret));
		goto err;
	}
	cursor->config_bitfield =
	    v.len == 2 && isdigit((u_char)v.str[0]) && v.str[1] == 't';

	if ((ret = writelock(wt_api, session, &ds->rwlock)) != 0)
		goto err;
	locked = 1;
				/* Open the Berkeley DB cursor */
	if ((ret = db_create(&cursor->db, ds->dbenv, 0)) != 0) {
		ESET(wt_api,
		    session, WT_ERROR, "db_create: %s", db_strerror(ret));
		goto err;
	}
	db = cursor->db;
	if ((ret = db->open(db, NULL, name, NULL,
	    cursor->config_recno ? DB_RECNO : DB_BTREE, DB_CREATE, 0)) != 0) {
		ESET(wt_api,
		    session, WT_ERROR, "Db.open: %s", db_strerror(ret));
		goto err;
	}
	if ((ret = db->cursor(db, NULL, &cursor->dbc, 0)) != 0) {
		ESET(wt_api,
		    session, WT_ERROR, "Db.cursor: %s", db_strerror(ret));
		goto err;
	}

				/* Initialize the methods */
	cursor->wtcursor.next = kvs_cursor_next;
	cursor->wtcursor.prev = kvs_cursor_prev;
	cursor->wtcursor.reset = kvs_cursor_reset;
	cursor->wtcursor.search = kvs_cursor_search;
	cursor->wtcursor.search_near = kvs_cursor_search_near;
	cursor->wtcursor.insert = kvs_cursor_insert;
	cursor->wtcursor.update = kvs_cursor_update;
	cursor->wtcursor.remove = kvs_cursor_remove;
	cursor->wtcursor.close = kvs_cursor_close;

	*new_cursor = (WT_CURSOR *)cursor;

	++ds->open_cursors;

	if (0) {
err:		free(cursor);
	}

	if (locked)
		ETRET(unlock(wt_api, session, &ds->rwlock));
	return (ret);
}
Example #19
0
int
wiredtiger_extension_init(WT_CONNECTION *connection, WT_CONFIG_ARG *config)
{
	/*
	 * List of the WT_DATA_SOURCE methods -- it's static so it breaks at
	 * compile-time should the structure changes underneath us.
	 */
	static WT_DATA_SOURCE wtds = {
		kvs_session_create,		/* session.create */
		NULL,				/* No session.compaction */
		kvs_session_drop,		/* session.drop */
		kvs_session_open_cursor,	/* session.open_cursor */
		kvs_session_rename,		/* session.rename */
		NULL,				/* No session.salvage */
		kvs_session_truncate,		/* session.truncate */
		NULL,				/* No range_truncate */
		kvs_session_verify,		/* session.verify */
		NULL,				/* session.checkpoint */
		kvs_terminate			/* termination */
	};
	DATA_SOURCE *ds;
	DB_ENV *dbenv;
	WT_EXTENSION_API *wt_api;
	size_t len;
	int ret = 0;
	const char *home;
	char *path;

	(void)config;				/* Unused parameters */

	ds = NULL;
	dbenv = NULL;
	path = NULL;
						/* Acquire the extension API */
	wt_api = connection->get_extension_api(connection);

	/* Allocate the local data-source structure. */
	if ((ds = calloc(1, sizeof(DATA_SOURCE))) == NULL)
		return (os_errno());
	ds->wt_api = wt_api;
						/* Configure the global lock */
	if ((ret = lock_init(wt_api, NULL, &ds->rwlock)) != 0)
		goto err;

	ds->wtds = wtds;			/* Configure the methods */

						/* Berkeley DB environment */
	if ((ret = db_env_create(&dbenv, 0)) != 0) {
		ESET(wt_api,
		    NULL, WT_ERROR, "db_env_create: %s", db_strerror(ret));
		goto err;
	}
	dbenv->set_errpfx(dbenv, "bdb");
	dbenv->set_errfile(dbenv, stderr);

	home = connection->get_home(connection);
	len = strlen(home) + 10;
	if ((path = malloc(len)) == NULL)
		goto err;
	(void)snprintf(path, len, "%s/KVS", home);
	if ((ret = dbenv->open(dbenv, path,
	    DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL | DB_PRIVATE, 0)) != 0) {
		ESET(wt_api,
		    NULL, WT_ERROR, "DbEnv.open: %s", db_strerror(ret));
		goto err;
	}
	ds->dbenv = dbenv;

	if ((ret =				/* Add the data source */
	    connection->add_data_source(
	    connection, "kvsbdb:", (WT_DATA_SOURCE *)ds, NULL)) != 0) {
		ESET(wt_api, NULL, ret, "WT_CONNECTION.add_data_source");
		goto err;
	}

	if (0) {
err:		if (dbenv != NULL)
			(void)dbenv->close(dbenv, 0);
		free(ds);
	}
	free(path);
	return (ret);
}
Example #20
0
/*
 * kvs_config_devices --
 *	Convert the device list into an argv[] array.
 */
static int
kvs_config_devices(WT_SESSION *session, WT_CONFIG_ITEM *orig, char ***devices)
{
	WT_CONFIG_ITEM k, v;
	WT_CONFIG_SCAN *scan;
	size_t len;
	u_int cnt, slots;
	int ret;
	char **argv, **p;

	ret = 0;
	argv = NULL;

	/* Set up the scan of the device list. */
	if ((ret = wt_ext->config_scan_begin(
	    wt_ext, session, orig->str, orig->len, &scan)) != 0) {
		ESET(session, ret,
		    "WT_EXTENSION_API::config_scan_begin: %s",
		    wt_ext->strerror(ret));
		return (ret);
	}

	for (cnt = slots = 0; (ret = wt_ext->
	    config_scan_next(wt_ext, scan, &k, &v)) == 0; ++cnt) {
		if (cnt + 1 >= slots) {		/* NULL-terminate the array */
			len = slots + 20 * sizeof(*argv);
			if ((p = realloc(argv, len)) == NULL) {
				ret = os_errno();
				goto err;
			}
			argv = p;
			slots += 20;
		}
		len = k.len + 1;
		if ((argv[cnt] = (char *)calloc(len, sizeof(**argv))) == NULL) {
			ret = os_errno();
			goto err;
		}
		argv[cnt + 1] = NULL;
		memcpy(argv[cnt], k.str, k.len);
	}
	if (ret != WT_NOTFOUND) {
		ESET(session, ret,
		    "WT_EXTENSION_API::config_scan_next: %s",
		    wt_ext->strerror(ret));
		return (ret);
	}
	if ((ret = wt_ext->config_scan_end(wt_ext, scan)) != 0) {
		ESET(session, ret,
		    "WT_EXTENSION_API::config_scan_end: %s",
		    wt_ext->strerror(ret));
		return (ret);
	}

	*devices = argv;
	return (0);

err:	if (argv != NULL) {
		for (p = argv; *p != NULL; ++p)
			free(*p);
		free(argv);
	}
	return (ret);
}
Example #21
0
int Process::start()
{
  logTrace("Process::start");

  int childIn[2]  = { -1, -1 };
  int childOut[2] = { -1, -1 };
  int childErr[2] = { -1, -1 };

  //
  // We either have 2 parameters and this process
  // will exec() a new command, or we have one or
  // none and this process will yield control to
  // a function.
  //

  if (function_ == NULL && (parameters_[0] == NULL ||
          parameters_[1] == NULL))
  {
    logTest("Process::start", "Can't start the process "
                "without a command or function");

    logError("Process::start", ESET(EPERM));

    return -1;
  }

  #ifdef TEST

  if (function_ == NULL)
  {
    logTest("Process::start", "Executing command '%s'",
                parameters_[0]);

    for (int i = 1; i < parametersLimit_ &&
             parameters_[i] != NULL; i++)
    {
      logTest("Process::start", "Parameter [%d] is '%s'",
                  i, parameters_[i]);
    }
  }
  else
  {
    logTest("Process::start", "Executing function at %p",
                function_);

    logTest("Process::start", "Passing data as %p",
                parameters_[0]);
  }

  for (int i = 0; i < environmentLimit_ &&
           environment_[i] != NULL; i++)
  {
    logTest("Process::start", "Environment [%d] is '%s'",
                i, environment_[i]);
  }

  #endif

  //
  // Create the pipes that will be used to replace
  // the standard descriptors.
  //

  if ((in_ == -1 && pipe(childIn) != 0) ||
          (out_ == -1 && pipe(childOut) != 0) ||
              (err_ == -1 && pipe(childErr) != 0))
  {
    logError("Process::start::pipe", EGET());

    return -1;
  }

  //
  // The fork() on Cygwin can show intermittent
  // failures. In this case we try again after
  // some time.
  //

  #ifdef __CYGWIN32__

  switch (pid_ = waitFork())

  #else

  switch (pid_ = fork())

  #endif

  {
    case -1:
    {
      //
      // An error was encountered.
      //

      logError("Process::start::fork", EGET());

      if (in_ == -1)
      {
        close(childIn[0]);
        close(childIn[1]);
      }

      if (out_ == -1)
      {
        close(childOut[0]);
        close(childOut[1]);
      }

      if (err_ == -1)
      {
        close(childErr[0]);
        close(childErr[1]);
      }

      return -1;
    }
    case 0:
    {
      //
      // We are the child process.
      //

      logTest("Process::start", "Child running with pid %d", getpid());

      //
      // Drop the privileges.
      //

      if (privileged_ != 1)
      {
        logTest("Process::start", "Child dropping the permissions");

        setgid(getgid());
        setuid(getuid());
      }

      //
      // Let the input descriptor inherited from the
      // parent replace the standard descriptors. The
      // descriptor can be either the one set by the
      // parent or our end of the pipe we created be-
      // fore forking.
      //
      // Handle the standard input.
      //

      if (in_ == -1)
      {
        logTest("Process::start", "Child replacing pipe "
                    "%d and %d for input", childIn[0], childIn[1]);

        if (childIn[0] != 0)
        {
          dup2(childIn[0], 0);

          close(childIn[0]);
        }

        close(childIn[1]);
      }
      else if (in_ != 0)
      {
        logTest("Process::start", "Child replacing input %d", in_);

        dup2(in_, 0);

        if (in_ != out_ && in_ != err_)
        {
          close(in_);
        }
      }
      else
      {
        logTest("Process::start", "Child inherited input");
      }

      in_ = 0;

      //
      // Handle the standard output.
      //

      if (out_ == -1)
      {
        logTest("Process::start", "Child replacing pipe "
                    "%d and %d for output", childOut[0], childOut[1]);

        if (childOut[1] != 1)
        {
          dup2(childOut[1], 1);

          close(childOut[1]);
        }

        close(childOut[0]);
      }
      else if (out_ != 1)
      {
        logTest("Process::start", "Child replacing output %d", out_);

        dup2(out_, 1);

        if (out_ != err_)
        {
          close(out_);
        }
      }
      else
      {
        logTest("Process::start", "Child inherited output");
      }

      out_ = 1;

      //
      // Handle the standard error.
      //

      if (err_ == -1)
      {
        logTest("Process::start", "Child replacing pipe "
                    "%d and %d for error", childErr[0], childErr[1]);

        if (childErr[1] != 2)
        {
          dup2(childErr[1], 2);

          close(childErr[1]);
        }

        close(childErr[0]);
      }
      else if (err_ != 2)
      {
        logTest("Process::start", "Child replacing error %d", err_);

        dup2(err_, 2);

        close(err_);
      }
      else
      {
        logTest("Process::start", "Child inherited error");
      }

      err_ = 2;

      //
      // Let the pid be our own pid.
      //

      pid_ = getpid();

      logTest("Process::start", "Child has descriptors "
                  "%d, %d, %d and pid %d", in_, out_, err_, pid_);

      //
      // Set the new environment for the process.
      //

      for (int i = 0; i < environmentLimit_ &&
               environment_[i] != NULL; i++)
      {
        putenv(environment_[i]);
      }

      //
      // Either execute the requested command or
      // yield control to the function.
      //

      if (parameters_[1] != NULL)
      {
        if (execvp(parameters_[0], parameters_ + 1) == -1)
        {
          logTest("Process::start", "Child failed to execute the command");

          logError("Process::start::execvp", EGET());
        }

        exitStatus(-1);
      }
      else
      {
        int result = function_((void *) parameters_[0]);

        exitStatus(result);
      }
    }
    default:
    {
      //
      // We are the parent process.
      //

      logTest("Process::start", "Parent started child with pid %d", pid_);

      if (in_ == -1)
      {
        close(childIn[0]);

        in_ = childIn[1];
      }

      if (out_ == -1)
      {
        close(childOut[1]);

        out_ = childOut[0];
      }

      if (err_ == -1)
      {
        close(childErr[1]);

        err_ = childErr[0];
      }

      logTest("Process::start", "Parent using descriptors %d, %d, %d",
                  in_, out_, err_);

      return 1;
    }
  }
}
Example #22
0
static int cb_iptables_rule_common(const struct filterent *ent, struct fg_misc *misc, sa_family_t family, const char *iptables)
{
    char *rulechain = NULL, *revchain = NULL, *natchain = NULL;
    char *ruletarget = NULL, *revtarget = NULL, *nattarget = NULL;
    char *natrule = NULL, *rule = NULL, *rule_r = NULL;
    char *forchain = NULL, *forrevchain = NULL;
    char *fortarget = NULL, *forrevtarget = NULL;
    char *subchain = NULL, *subtarget = NULL;
    int neednat = 0, needret = 0;
    int islocal = (ent->rtype != ROUTEDONLY);
    int isforward = (ent->rtype != LOCALONLY);
    long *feat = (long*)misc->misc;
    enum filtertype target = ent->target;
    int orules = 0;

    /* nat rule? */
    if((target == MASQ) || (target == REDIRECT)) {
        neednat = 1;
        if(family == AF_INET6) {
            fprintf(stderr, "can't NAT with IPv6\n");
            return -1;
        }
        if((target == MASQ) && (ent->direction == INPUT)) {
            fprintf(stderr, "can't masquerade on input\n");
            return -1;
        } else if((target == REDIRECT) && (ent->direction == OUTPUT)) {
            fprintf(stderr, "can't redirect on output\n");
            return -1;
        }
    }

    /* sub-stuff? */
    if(target == F_SUBGROUP) {
        subtarget = strapp(strdup(ent->subgroup), "-");
        needret = 1;
    } else subtarget = strdup("");

    if(ent->groupname) subchain = strapp(strdup(ent->groupname), "-");
    else subchain = strdup("");

    switch(ent->direction) {
    case INPUT:
        natchain = strdup("PREROUTING");
        rulechain = strdup("INPUT");
        revchain = strdup("OUTPUT");
        forchain = strdup("FORWARD");
        forrevchain = strdup("FORW_OUT");
        if(ent->iface && strcmp(ent->iface, "*")) {
            if(NEG(DIRECTION)) {
                APPS(natrule, "!");
                APPS(rule, "!");
                APPS(rule_r, "!");
            }
            APPSS2(natrule, "-i", ent->iface);
            APPSS2(rule, "-i", ent->iface);
            APPSS2(rule_r, "-o", ent->iface);
        }
        break;
    case OUTPUT:
        natchain = strdup("POSTROUTING");
        rulechain = strdup("OUTPUT");
        revchain = strdup("INPUT");
        forchain = strdup("FORW_OUT");
        forrevchain = strdup("FORWARD");
        if(ent->iface && strcmp(ent->iface, "*")) {
            if(NEG(DIRECTION)) {
                APPS(natrule, "!");
                APPS(rule, "!");
                APPS(rule_r, "!");
            }
            APPSS2(natrule, "-o", ent->iface);
            APPSS2(rule, "-o", ent->iface);
            APPSS2(rule_r, "-i", ent->iface);
        }
        break;
    default:
        fprintf(stderr, "unknown direction\n");
        abort();
    }

    /* state and reverse rules here */
    /* FIXME: state established on reverse for every rule, not just
     * specifically udp and tcp */
    if(ent->proto.name) {
        int needstate = 0;

        APPSS2(natrule, "-p", ent->proto.name);
        APPSS2(rule, "-p", ent->proto.name);
        APPSS2(rule_r, "-p", ent->proto.name);
        switch(ent->proto.num) {
        case IPPROTO_TCP:
            needret++;
            needstate++;
            *feat |= A_TCP;
            APPS(rule_r, "! --syn");
            break;
        case IPPROTO_UDP:
            needret++;
            needstate++;
            *feat |= A_UDP;
            break;
        }
        if(needstate) {
            APPS(rule, "-m state --state NEW,ESTABLISHED");
            APPS(rule_r, "-m state --state ESTABLISHED");
        }
    }

    if(ent->srcaddr.addrstr) {
        NEGA(natrule, SOURCE);
        NEGA(rule, SOURCE);
        NEGA(rule_r, SOURCE);
        APPIP2("-s", natrule, &ent->srcaddr);
        APPIP2("-s", rule, &ent->srcaddr);
        APPIP2("-d", rule_r, &ent->srcaddr);
    }
    if(ent->dstaddr.addrstr) {
        NEGA(natrule, DEST);
        NEGA(rule, DEST);
        NEGA(rule_r, DEST);
        APPIP2("-d", natrule, &ent->dstaddr);
        APPIP2("-d", rule, &ent->dstaddr);
        APPIP2("-s", rule_r, &ent->dstaddr);
    }

    switch(ent->proto.num) {
    case 0:
        break;
    case IPPROTO_UDP:
    case IPPROTO_TCP:
        if(ent->u.ports.src.minstr) {
            NEGA(natrule, SPORT);
            NEGA(rule, SPORT);
            NEGA(rule_r, SPORT);
            APPPORT2("--sport", natrule, &ent->u.ports.src);
            APPPORT2("--sport", rule, &ent->u.ports.src);
            APPPORT2("--dport", rule_r, &ent->u.ports.src);
        }
        if(ent->u.ports.dst.minstr) {
            NEGA(natrule, DPORT);
            NEGA(rule, DPORT);
            NEGA(rule_r, DPORT);
            APPPORT2("--dport", natrule, &ent->u.ports.dst);
            APPPORT2("--dport", rule, &ent->u.ports.dst);
            APPPORT2("--sport", rule_r, &ent->u.ports.dst);
        }
        break;
    case IPPROTO_ICMP:
        if(ent->u.icmp) {
            NEGA(natrule, ICMPTYPE);
            APPSS2(natrule, "--icmp-type", ent->u.icmp);
            NEGA(rule, ICMPTYPE);
            APPSS2(rule, "--icmp-type", ent->u.icmp);
        }
        break;
    default:
        ;
    }

    APPS(natrule, "-j");
    APPS(rule, "-j");
    APPS(rule_r, "-j");

    /* The "rule+1" in the printfs below are an ugly hack to
     * prevent a double-space in the output rule */

    /* Yuck, separate rules for logging packets.  Be still my
     * beating lunch.
     *
     * Logging and target rules have to be the last bits
     * before output, or this doesn't work.  This will also
     * fail if any mangling has been done above.
     */
    if(ESET(ent, LOG)) {
        char *lc, *la, *ls;
        if(ent->logmsg) {
            lc = strdup(" --log-prefix=");
            la = ent->logmsg;
            ls = strdup("\" \"");
        } else
            lc = la = ls = strdup("");
        if(islocal) orules++,oprintf("%s -A %s %s LOG%s%s%s\n", iptables, rulechain, rule+1, lc, la, ls);
        if(isforward) orules++,oprintf("%s -A %s %s LOG%s%s%s\n", iptables, forchain, rule+1, lc, la, ls);
    }

    /* Do this twice, once for NAT, once for filter */
    if(neednat) {
        switch(target) {
        case MASQ:
            nattarget = strdup("MASQUERADE");
            break;
        case REDIRECT:
            nattarget = strdup("REDIRECT");
            break;
        default:
            abort();
        }
    }

    switch(target) {
    case MASQ:
    case REDIRECT:
    case T_ACCEPT:
        ruletarget = revtarget =
                         fortarget = forrevtarget = strdup("ACCEPT");
        switch(ent->direction) {
        case INPUT:
            fortarget = strdup("FORW_OUT");
            break;
        case OUTPUT:
            forrevtarget = strdup("FORW_OUT");
            break;
        default:
            abort();
        }
        break;
    case DROP:
        ruletarget = fortarget = strdup("DROP");
        needret = 0;
        break;
    case T_REJECT:
        ruletarget = fortarget = strdup("REJECT");
        needret = 0;
        *feat |= T_REJECT;
        break;
    case F_SUBGROUP:
        switch(ent->direction) {
        case INPUT:
            ruletarget = strdup("INPUT");
            revtarget = strdup("OUTPUT");
            fortarget = strdup("FORWARD");
            forrevtarget = strdup("FORW_OUT");
            break;
        case OUTPUT:
            ruletarget = strdup("OUTPUT");
            revtarget = strdup("INPUT");
            fortarget = strdup("FORW_OUT");
            forrevtarget = strdup("FORWARD");
            break;
        default:
            abort();
        }
        break;
    default:
        abort();
    }

    if((misc->flags & FF_LSTATE) && (target != T_REJECT)) needret = 0;

    if(ent->oneway) needret = 0;

    if(neednat) orules++,oprintf("%s -t nat -A %s%s %s %s%s\n", iptables, subchain, natchain, natrule+1, subtarget, nattarget);
    if(islocal) orules++,oprintf("%s -A %s%s %s %s%s\n", iptables, subchain, rulechain, rule+1, subtarget, ruletarget);
    if(needret) orules++,oprintf("%s -I %s%s %s %s%s\n", iptables, subchain, revchain, rule_r+1, subtarget, revtarget);
    if(isforward) {
        orules++,oprintf("%s -A %s%s %s %s%s\n", iptables, subchain, forchain, rule+1, subtarget, fortarget);
        if(needret) orules++,oprintf("%s -I %s%s %s %s%s\n", iptables, subchain, forrevchain, rule_r+1, subtarget, forrevtarget);
    }

    free(natrule);
    free(rule);
    free(rule_r);
    free(subchain);
    free(subtarget);
    return orules;
}
Example #23
0
/*
 * kvs_session_open_cursor --
 *	WT_SESSION::open_cursor method.
 */
static int
kvs_session_open_cursor(WT_DATA_SOURCE *dsrc, WT_SESSION *session,
    const char *uri, WT_CONFIG_ARG *config, WT_CURSOR **new_cursor)
{
	CURSOR *cursor;
	DATA_SOURCE *p;
	WT_CONFIG_ITEM v;
	int ret;

	(void)dsrc;				/* Unused parameters */

	cursor = NULL;
	ret = 0;

	/* Allocate and initialize a cursor. */
	if ((cursor = (CURSOR *)calloc(1, sizeof(CURSOR))) == NULL)
		return (os_errno());

	cursor->session = session;
	cursor->record.key = cursor->key;
	if ((cursor->val = malloc(128)) == NULL)
		goto err;
	cursor->val_len = 128;
						/* Initialize the methods */
	cursor->wt_cursor.next = kvs_cursor_next;
	cursor->wt_cursor.prev = kvs_cursor_prev;
	cursor->wt_cursor.reset = kvs_cursor_reset;
	cursor->wt_cursor.search = kvs_cursor_search;
	cursor->wt_cursor.search_near = kvs_cursor_search_near;
	cursor->wt_cursor.insert = kvs_cursor_insert;
	cursor->wt_cursor.update = kvs_cursor_update;
	cursor->wt_cursor.remove = kvs_cursor_remove;
	cursor->wt_cursor.close = kvs_cursor_close;

						/* Parse configuration */
	if ((ret = wt_ext->config_get(
	    wt_ext, session, config, "append", &v)) != 0) {
		ESET(session, ret,
		    "append configuration: %s", wt_ext->strerror(ret));
		goto err;
	}
	cursor->config_append = v.val != 0;

	if ((ret = wt_ext->config_get(
	    wt_ext, session, config, "overwrite", &v)) != 0) {
		ESET(session, ret,
		    "overwrite configuration: %s", wt_ext->strerror(ret));
		goto err;
	}
	cursor->config_overwrite = v.val != 0;

	if ((ret = wt_ext->config_get(
	    wt_ext, session, config, "key_format", &v)) != 0) {
		ESET(session, ret,
		    "key_format configuration: %s", wt_ext->strerror(ret));
		goto err;
	}
	cursor->config_recno = v.len == 1 && v.str[0] == 'r';

	if ((ret = wt_ext->config_get(
	    wt_ext, session, config, "value_format", &v)) != 0) {
		ESET(session, ret,
		    "value_format configuration: %s", wt_ext->strerror(ret));
		goto err;
	}
	cursor->config_bitfield =
	    v.len == 2 && isdigit(v.str[0]) && v.str[1] == 't';

	/*
	 * See if the object already exists: if it does, increment the count of
	 * open cursors to pin it, and release the lock.
	 */
	for (;;) {
		if ((ret = writelock(session, &global_lock)) != 0)
			goto err;
		for (p = data_source_head; p != NULL; p = p->next)
			if (strcmp(p->uri, uri) == 0) {
				++p->open_cursors;
				break;
			}
		if ((ret = unlock(session, &global_lock)) != 0)
			goto err;
		if (p != NULL) {
			cursor->data_source = p;

			*new_cursor = (WT_CURSOR *)cursor;
			return (0);
		}

		/* Create the object. */
		if ((ret = open_data_source(session, uri, config)) != 0)
			goto err;

		/*
		 * We shouldn't loop more than once, but it's theoretically
		 * possible.
		 */
	}

err:	if (cursor != NULL) {
		if (cursor->val != NULL)
			free(cursor->val);
		free(cursor);
	}
	return (ret);
}