mongoc_cursor_t * _mongoc_cursor_clone (const mongoc_cursor_t *cursor) { mongoc_cursor_t *_clone; ENTRY; BSON_ASSERT (cursor); _clone = bson_malloc0 (sizeof *_clone); _clone->client = cursor->client; _clone->is_command = cursor->is_command; _clone->flags = cursor->flags; _clone->skip = cursor->skip; _clone->batch_size = cursor->batch_size; _clone->limit = cursor->limit; _clone->nslen = cursor->nslen; if (cursor->read_prefs) { _clone->read_prefs = mongoc_read_prefs_copy (cursor->read_prefs); } bson_copy_to (&cursor->query, &_clone->query); bson_copy_to (&cursor->fields, &_clone->fields); bson_strncpy (_clone->ns, cursor->ns, sizeof _clone->ns); _mongoc_buffer_init (&_clone->buffer, NULL, 0, NULL); mongoc_counter_cursors_active_inc (); RETURN (_clone); }
mongoc_database_t * _mongoc_database_new (mongoc_client_t *client, const char *name, const mongoc_read_prefs_t *read_prefs, const mongoc_write_concern_t *write_concern) { mongoc_database_t *db; ENTRY; bson_return_val_if_fail(client, NULL); bson_return_val_if_fail(name, NULL); db = bson_malloc0(sizeof *db); db->client = client; db->write_concern = write_concern ? mongoc_write_concern_copy(write_concern) : mongoc_write_concern_new(); db->read_prefs = read_prefs ? mongoc_read_prefs_copy(read_prefs) : mongoc_read_prefs_new(MONGOC_READ_PRIMARY); bson_strncpy (db->name, name, sizeof db->name); RETURN(db); }
static void mongoc_uri_append_host (mongoc_uri_t *uri, const char *host, uint16_t port) { mongoc_host_list_t *iter; mongoc_host_list_t *link_; link_ = bson_malloc0(sizeof *link_); bson_strncpy (link_->host, host, sizeof link_->host); if (strchr (host, ':')) { bson_snprintf (link_->host_and_port, sizeof link_->host_and_port, "[%s]:%hu", host, port); link_->family = AF_INET6; } else { bson_snprintf (link_->host_and_port, sizeof link_->host_and_port, "%s:%hu", host, port); link_->family = strstr (host, ".sock") ? AF_UNIX : AF_INET; } link_->host_and_port[sizeof link_->host_and_port - 1] = '\0'; link_->port = port; if ((iter = uri->hosts)) { for (; iter && iter->next; iter = iter->next) {} iter->next = link_; } else { uri->hosts = link_; } }
mongoc_database_t * _mongoc_database_new (mongoc_client_t *client, const char *name, const mongoc_read_prefs_t *read_prefs, const mongoc_read_concern_t *read_concern, const mongoc_write_concern_t *write_concern) { mongoc_database_t *db; ENTRY; BSON_ASSERT (client); BSON_ASSERT (name); db = (mongoc_database_t *)bson_malloc0(sizeof *db); db->client = client; db->write_concern = write_concern ? mongoc_write_concern_copy(write_concern) : mongoc_write_concern_new(); db->read_concern = read_concern ? mongoc_read_concern_copy(read_concern) : mongoc_read_concern_new(); db->read_prefs = read_prefs ? mongoc_read_prefs_copy(read_prefs) : mongoc_read_prefs_new(MONGOC_READ_PRIMARY); bson_strncpy (db->name, name, sizeof db->name); RETURN(db); }
char * bson_strerror_r (int err_code, /* IN */ char *buf, /* IN */ size_t buflen) /* IN */ { static const char *unknown_msg = "Unknown error"; char *ret = NULL; #if defined(_WIN32) if (strerror_s (buf, buflen, err_code) != 0) { ret = buf; } #elif defined(__GNUC__) && defined(_GNU_SOURCE) ret = strerror_r (err_code, buf, buflen); #else /* XSI strerror_r */ if (strerror_r (err_code, buf, buflen) == 0) { ret = buf; } #endif if (!ret) { bson_strncpy (buf, unknown_msg, buflen); ret = buf; } return ret; }
static void set_mongoc_test_host(void) { #ifdef _MSC_VER size_t buflen; if (0 != getenv_s (&buflen, MONGOC_TEST_HOST, sizeof MONGOC_TEST_HOST, "MONGOC_TEST_HOST")) { bson_strncpy (MONGOC_TEST_HOST, "localhost", sizeof MONGOC_TEST_HOST); } #else if (getenv("MONGOC_TEST_HOST")) { bson_strncpy (MONGOC_TEST_HOST, getenv("MONGOC_TEST_HOST"), sizeof MONGOC_TEST_HOST); } else { bson_strncpy (MONGOC_TEST_HOST, "localhost", sizeof MONGOC_TEST_HOST); } #endif }
void _mongoc_get_db_name (const char *ns, char *db /* OUT */) { size_t dblen; const char *dot; BSON_ASSERT (ns); dot = strstr (ns, "."); if (dot) { dblen = BSON_MIN (dot - ns + 1, MONGOC_NAMESPACE_MAX); bson_strncpy (db, ns, dblen); } else { bson_strncpy (db, ns, MONGOC_NAMESPACE_MAX); } }
mongoc_change_stream_t * _mongoc_change_stream_new_from_collection (const mongoc_collection_t *coll, const bson_t *pipeline, const bson_t *opts) { mongoc_change_stream_t *stream; BSON_ASSERT (coll); stream = (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t)); bson_strncpy (stream->db, coll->db, sizeof (stream->db)); bson_strncpy (stream->coll, coll->collection, sizeof (stream->coll)); stream->read_prefs = mongoc_read_prefs_copy (coll->read_prefs); stream->read_concern = mongoc_read_concern_copy (coll->read_concern); stream->client = coll->client; stream->change_stream_type = MONGOC_CHANGE_STREAM_COLLECTION; _change_stream_init (stream, pipeline, opts); return stream; }
bool _mongoc_host_list_from_string (mongoc_host_list_t *host_list, const char *host_and_port) { uint16_t port; const char *end_host; char *hostname = NULL; bson_return_val_if_fail(host_list, false); bson_return_val_if_fail(host_and_port, false); memset(host_list, 0, sizeof *host_list); if ((hostname = scan_to_unichar(host_and_port, ':', &end_host))) { end_host++; if (!isdigit(*end_host)) { bson_free(hostname); return false; } #ifdef _MSC_VER sscanf_s (end_host, "%hu", &port); #else sscanf (end_host, "%hu", &port); #endif } else { hostname = bson_strdup(host_and_port); port = MONGOC_DEFAULT_PORT; } bson_strncpy (host_list->host_and_port, host_and_port, sizeof host_list->host_and_port - 1); bson_strncpy (host_list->host, hostname, sizeof host_list->host - 1); host_list->port = port; host_list->family = AF_INET; bson_free(hostname); return true; }
static int _mongoc_openssl_password_cb (char *buf, int num, int rwflag, void *user_data) { char *pass = (char *) user_data; int pass_len = (int) strlen (pass); if (num < pass_len + 1) { return 0; } bson_strncpy (buf, pass, num); return pass_len; }
static char * _get_os_version (void) { char *ret = bson_malloc (METADATA_OS_VERSION_MAX); bool found = false; #ifdef _WIN32 OSVERSIONINFO osvi; ZeroMemory (&osvi, sizeof (OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (GetVersionEx (&osvi)) { bson_snprintf (ret, METADATA_OS_VERSION_MAX, "%d.%d (%d)", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber); found = true; } else { MONGOC_WARNING ("Error with GetVersionEx(): %d", GetLastError ()); } #elif defined (_POSIX_VERSION) struct utsname system_info; if (uname (&system_info) >= 0) { bson_strncpy (ret, system_info.release, METADATA_OS_VERSION_MAX); found = true; } else { MONGOC_WARNING ("Error with uname(): %d", errno); } #endif if (!found) { bson_free (ret); ret = NULL; } return ret; }
mongoc_change_stream_t * _mongoc_change_stream_new_from_client (mongoc_client_t *client, const bson_t *pipeline, const bson_t *opts) { mongoc_change_stream_t *stream; BSON_ASSERT (client); stream = (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t)); bson_strncpy (stream->db, "admin", sizeof (stream->db)); stream->coll[0] = '\0'; stream->read_prefs = mongoc_read_prefs_copy (client->read_prefs); stream->read_concern = mongoc_read_concern_copy (client->read_concern); stream->client = client; stream->change_stream_type = MONGOC_CHANGE_STREAM_CLIENT; _change_stream_init (stream, pipeline, opts); return stream; }
mongoc_change_stream_t * _mongoc_change_stream_new_from_database (const mongoc_database_t *db, const bson_t *pipeline, const bson_t *opts) { mongoc_change_stream_t *stream; BSON_ASSERT (db); stream = (mongoc_change_stream_t *) bson_malloc0 (sizeof (mongoc_change_stream_t)); bson_strncpy (stream->db, db->name, sizeof (stream->db)); stream->coll[0] = '\0'; stream->read_prefs = mongoc_read_prefs_copy (db->read_prefs); stream->read_concern = mongoc_read_concern_copy (db->read_concern); stream->client = db->client; stream->change_stream_type = MONGOC_CHANGE_STREAM_DATABASE; _change_stream_init (stream, pipeline, opts); return stream; }
mongoc_cursor_t * _mongoc_cursor_new (mongoc_client_t *client, const char *db_and_collection, mongoc_query_flags_t flags, uint32_t skip, uint32_t limit, uint32_t batch_size, bool is_command, const bson_t *query, const bson_t *fields, const mongoc_read_prefs_t *read_prefs) { mongoc_read_prefs_t *local_read_prefs = NULL; mongoc_read_mode_t mode; mongoc_cursor_t *cursor; const bson_t *tags; bson_iter_t iter; const char *key; const char *mode_str; bson_t child; bool found = false; int i; ENTRY; BSON_ASSERT (client); BSON_ASSERT (db_and_collection); BSON_ASSERT (query); if (!read_prefs) { read_prefs = client->read_prefs; } cursor = bson_malloc0 (sizeof *cursor); /* * CDRIVER-244: * * If this is a command, we need to verify we can send it to the location * specified by the read preferences. Otherwise, log a warning that we * are rerouting to the primary instance. */ if (is_command && read_prefs && (mongoc_read_prefs_get_mode (read_prefs) != MONGOC_READ_PRIMARY) && bson_iter_init (&iter, query) && bson_iter_next (&iter) && (key = bson_iter_key (&iter))) { for (i = 0; gSecondaryOkCommands [i]; i++) { if (0 == strcasecmp (key, gSecondaryOkCommands [i])) { found = true; break; } } if (!found) { cursor->redir_primary = true; local_read_prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY); read_prefs = local_read_prefs; MONGOC_INFO ("Database command \"%s\" rerouted to primary node", key); } } /* * Cursors execute their query lazily. This sadly means that we must copy * some extra data around between the bson_t structures. This should be * small in most cases, so it reduces to a pure memcpy. The benefit to this * design is simplified error handling by API consumers. */ cursor->client = client; bson_strncpy (cursor->ns, db_and_collection, sizeof cursor->ns); cursor->nslen = (uint32_t)strlen(cursor->ns); cursor->flags = flags; cursor->skip = skip; cursor->limit = limit; cursor->batch_size = batch_size; cursor->is_command = is_command; #define MARK_FAILED(c) \ do { \ (c)->failed = true; \ (c)->done = true; \ (c)->end_of_event = true; \ (c)->sent = true; \ } while (0) /* we can't have exhaust queries with limits */ if ((flags & MONGOC_QUERY_EXHAUST) && limit) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "Cannot specify MONGOC_QUERY_EXHAUST and set a limit."); MARK_FAILED (cursor); GOTO (finish); } /* we can't have exhaust queries with sharded clusters */ if ((flags & MONGOC_QUERY_EXHAUST) && (client->cluster.mode == MONGOC_CLUSTER_SHARDED_CLUSTER)) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "Cannot specify MONGOC_QUERY_EXHAUST with sharded cluster."); MARK_FAILED (cursor); GOTO (finish); } /* * Check types of various optional parameters. */ if (!is_command) { if (bson_iter_init_find (&iter, query, "$explain") && !(BSON_ITER_HOLDS_BOOL (&iter) || BSON_ITER_HOLDS_INT32 (&iter))) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "$explain must be a boolean."); MARK_FAILED (cursor); GOTO (finish); } if (bson_iter_init_find (&iter, query, "$snapshot") && !BSON_ITER_HOLDS_BOOL (&iter) && !BSON_ITER_HOLDS_INT32 (&iter)) { bson_set_error (&cursor->error, MONGOC_ERROR_CURSOR, MONGOC_ERROR_CURSOR_INVALID_CURSOR, "$snapshot must be a boolean."); MARK_FAILED (cursor); GOTO (finish); } } if (!cursor->is_command && !bson_has_field (query, "$query")) { bson_init (&cursor->query); bson_append_document (&cursor->query, "$query", 6, query); } else { bson_copy_to (query, &cursor->query); } if (read_prefs) { cursor->read_prefs = mongoc_read_prefs_copy (read_prefs); mode = mongoc_read_prefs_get_mode (read_prefs); tags = mongoc_read_prefs_get_tags (read_prefs); if (mode != MONGOC_READ_PRIMARY) { flags |= MONGOC_QUERY_SLAVE_OK; if ((mode != MONGOC_READ_SECONDARY_PREFERRED) || tags) { bson_append_document_begin (&cursor->query, "$readPreference", 15, &child); mode_str = _mongoc_cursor_get_read_mode_string (mode); bson_append_utf8 (&child, "mode", 4, mode_str, -1); if (tags) { bson_append_array (&child, "tags", 4, tags); } bson_append_document_end (&cursor->query, &child); } } } if (fields) { bson_copy_to(fields, &cursor->fields); } else { bson_init(&cursor->fields); } _mongoc_buffer_init(&cursor->buffer, NULL, 0, NULL); finish: mongoc_counter_cursors_active_inc(); if (local_read_prefs) { mongoc_read_prefs_destroy (local_read_prefs); } RETURN (cursor); }