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); }
/* * 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); }
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; }
/* * 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); }
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; }
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); }
int Process::setDescriptor(int &std, int fd) { logTrace("Process::setDescriptor"); if (pid_ != -1) { logError("Process::setDescriptor", ESET(EPERM)); return -1; } std = fd; return 1; }
int Process::setPrivileged(int value) { logTrace("Process::setPrivileged"); if (pid_ != -1) { logError("Process::setPrivileged", ESET(EPERM)); return -1; } privileged_ = value; return 1; }
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; }
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); }
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; }
/* * 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 */ }
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); }
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; }
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; }
/* * 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); }
/* * 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); }
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); }
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); }
/* * 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); }
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; } } }
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; }
/* * 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); }