Beispiel #1
0
int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx,
				uint64_t dev,
				uint64_t ino,
				uint64_t extid,
				const struct smb_share_mode_entry *set_entry,
				const struct smb_share_mode_entry *new_entry)
{
	TDB_DATA db_data;
	struct locking_key lk;
	TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
	int num_share_modes = 0;
	struct locking_data *ld = NULL; /* internal samba db state. */
	struct share_mode_entry *shares = NULL;
	size_t i;
	int found_entry = 0;

	db_data = tdb_fetch_compat(db_ctx->smb_tdb, locking_key);
	if (!db_data.dptr) {
		return -1; /* Error - missing entry ! */
	}

	ld = (struct locking_data *)db_data.dptr;
	num_share_modes = ld->u.s.num_share_mode_entries;
	shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));

	for (i = 0; i < num_share_modes; i++) {
		struct share_mode_entry *share = &shares[i];
		struct server_id pid = share->pid;

		/* Check this process really exists. */
		if (kill(sharemodes_procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
			continue; /* No longer exists. */
		}

		if (share_mode_entry_equal(set_entry, share)) {
			create_share_mode_entry(share, new_entry, share->name_hash);
			found_entry = 1;
			break;
		}
	}

	if (!found_entry) {
		free(db_data.dptr);
		return -1;
	}

	/* Save modified data. */
	if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) != 0) {
		free(db_data.dptr);
		return -1;
	}
	free(db_data.dptr);
	return 0;
}
Beispiel #2
0
bool tdb_fetch_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, uint32_t *value)
{
	TDB_DATA data;

	data = tdb_fetch_compat(tdb, key);
	if (!data.dptr || data.dsize != sizeof(uint32_t)) {
		SAFE_FREE(data.dptr);
		return false;
	}

	*value = IVAL(data.dptr,0);
	SAFE_FREE(data.dptr);
	return true;
}
Beispiel #3
0
int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, TDB_DATA key)
{
	TDB_DATA data;
	int32_t ret;

	data = tdb_fetch_compat(tdb, key);
	if (!data.dptr || data.dsize != sizeof(int32_t)) {
		SAFE_FREE(data.dptr);
		return -1;
	}

	ret = IVAL(data.dptr,0);
	SAFE_FREE(data.dptr);
	return ret;
}
Beispiel #4
0
/**
 * fetch a record from the tdb, separating out the header
 * information and returning the body of the record.
 */
static NTSTATUS db_ctdb_ltdb_fetch(struct db_ctdb_ctx *db,
				   TDB_DATA key,
				   struct ctdb_ltdb_header *header,
				   TALLOC_CTX *mem_ctx,
				   TDB_DATA *data)
{
	TDB_DATA rec;
	NTSTATUS status;

	rec = tdb_fetch_compat(db->wtdb->tdb, key);
	if (rec.dsize < sizeof(struct ctdb_ltdb_header)) {
		status = NT_STATUS_NOT_FOUND;
		if (data) {
			ZERO_STRUCTP(data);
		}
		if (header) {
			header->dmaster = (uint32_t)-1;
			header->rsn = 0;
		}
		goto done;
	}

	if (header) {
		*header = *(struct ctdb_ltdb_header *)rec.dptr;
	}

	if (data) {
		data->dsize = rec.dsize - sizeof(struct ctdb_ltdb_header);
		if (data->dsize == 0) {
			data->dptr = NULL;
		} else {
			data->dptr = (unsigned char *)talloc_memdup(mem_ctx,
					rec.dptr
					 + sizeof(struct ctdb_ltdb_header),
					data->dsize);
			if (data->dptr == NULL) {
				status = NT_STATUS_NO_MEMORY;
				goto done;
			}
		}
	}

	status = NT_STATUS_OK;

done:
	SAFE_FREE(rec.dptr);
	return status;
}
Beispiel #5
0
int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
				uint64_t dev,
				uint64_t ino,
				uint64_t extid,
				const struct smb_share_mode_entry *del_entry)
{
	TDB_DATA db_data;
	struct locking_key lk;
	TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
	int orig_num_share_modes = 0;
	struct locking_data *ld = NULL; /* internal samba db state. */
	struct share_mode_entry *shares = NULL;
	uint8 *new_data_p = NULL;
	size_t remaining_size = 0;
	size_t i, num_share_modes;
	const uint8 *remaining_ptr = NULL;

	db_data = tdb_fetch_compat(db_ctx->smb_tdb, locking_key);
	if (!db_data.dptr) {
		return -1; /* Error - missing entry ! */
	}

	ld = (struct locking_data *)db_data.dptr;
	orig_num_share_modes = ld->u.s.num_share_mode_entries;
	shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));

	if (orig_num_share_modes == 1) {
		/* Only one entry - better be ours... */
		if (!share_mode_entry_equal(del_entry, shares)) {
			/* Error ! We can't delete someone else's entry ! */
			free(db_data.dptr);
			return -1;
		}
		/* It's ours - just remove the entire record. */
		free(db_data.dptr);
		return tdb_delete(db_ctx->smb_tdb, locking_key) ? -1 : 0;
	}

	/* More than one - allocate a new record minus the one we'll delete. */
	new_data_p = (uint8 *)malloc(
		db_data.dsize - sizeof(struct share_mode_entry));
	if (!new_data_p) {
		free(db_data.dptr);
		return -1;
	}

	/* Copy the header. */
	memcpy(new_data_p, db_data.dptr, sizeof(struct locking_data));

	num_share_modes = 0;
	for (i = 0; i < orig_num_share_modes; i++) {
		struct share_mode_entry *share = &shares[i];
		struct server_id pid = share->pid;

		/* Check this process really exists. */
		if (kill(sharemodes_procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
			continue; /* No longer exists. */
		}

		if (share_mode_entry_equal(del_entry, share)) {
			continue; /* This is our delete taget. */
		}

		memcpy(new_data_p + sizeof(struct locking_data) +
				(num_share_modes * sizeof(struct share_mode_entry)),
			share, sizeof(struct share_mode_entry) );

		num_share_modes++;
	}

	if (num_share_modes == 0) {
		/* None left after pruning. Delete record. */
		free(db_data.dptr);
		free(new_data_p);
		return tdb_delete(db_ctx->smb_tdb, locking_key) ? -1 : 0;
	}

	/* Copy any delete tokens plus the terminating filenames. */
	remaining_ptr = db_data.dptr + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry));
	remaining_size = db_data.dsize - (remaining_ptr - db_data.dptr);

	memcpy(new_data_p + sizeof(struct locking_data) + (num_share_modes * sizeof(struct share_mode_entry)),
		remaining_ptr,
		remaining_size);

	free(db_data.dptr);

	db_data.dptr = new_data_p;

	/* Re-save smaller record. */
	ld = (struct locking_data *)db_data.dptr;
	ld->u.s.num_share_mode_entries = num_share_modes;

	db_data.dsize = sizeof(struct locking_data) + (num_share_modes * sizeof(struct share_mode_entry)) + remaining_size;

	if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) != 0) {
		free(db_data.dptr);
		return -1;
	}
	free(db_data.dptr);
	return 0;
}
Beispiel #6
0
int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
				uint64_t dev,
				uint64_t ino,
				uint64_t extid,
				const struct smb_share_mode_entry *new_entry,
				const char *sharepath, /* Must be absolute utf8 path. */
				const char *filename) /* Must be relative utf8 path. */
{
	TDB_DATA db_data;
	struct locking_key lk;
	TDB_DATA locking_key =  get_locking_key(&lk, dev, ino, extid);
	int orig_num_share_modes = 0;
	struct locking_data *ld = NULL; /* internal samba db state. */
	struct share_mode_entry *shares = NULL;
	uint8 *new_data_p = NULL;
	size_t new_data_size = 0;
	int err = 0;
	uint32_t name_hash = smb_name_hash(sharepath, filename, &err);

	if (err) {
		return -1;
	}

	db_data = tdb_fetch_compat(db_ctx->smb_tdb, locking_key);
	if (!db_data.dptr) {
		/* We must create the entry. */
		db_data.dptr = (uint8 *)malloc(
			sizeof(struct locking_data) +
			sizeof(struct share_mode_entry) +
			strlen(sharepath) + 1 +
			strlen(filename) + 1);
		if (!db_data.dptr) {
			return -1;
		}
		ld = (struct locking_data *)db_data.dptr;
		memset(ld, '\0', sizeof(struct locking_data));
		ld->u.s.num_share_mode_entries = 1;
		ld->u.s.num_delete_token_entries = 0;
		shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));
		create_share_mode_entry(shares, new_entry, name_hash);

		memcpy(db_data.dptr + sizeof(struct locking_data) + sizeof(struct share_mode_entry),
			sharepath,
			strlen(sharepath) + 1);
		memcpy(db_data.dptr + sizeof(struct locking_data) + sizeof(struct share_mode_entry) +
			strlen(sharepath) + 1,
			filename,
			strlen(filename) + 1);

		db_data.dsize = sizeof(struct locking_data) + sizeof(struct share_mode_entry) +
					strlen(sharepath) + 1 +
					strlen(filename) + 1;
		if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_INSERT) != 0) {
			free(db_data.dptr);
			return -1;
		}
		free(db_data.dptr);
		return 0;
	}

	/* Entry exists, we must add a new entry. */
	new_data_p = (uint8 *)malloc(
		db_data.dsize + sizeof(struct share_mode_entry));
	if (!new_data_p) {
		free(db_data.dptr);
		return -1;
	}

	ld = (struct locking_data *)db_data.dptr;
	orig_num_share_modes = ld->u.s.num_share_mode_entries;

	/* Copy the original data. */
	memcpy(new_data_p, db_data.dptr, sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry)));

	/* Add in the new share mode */
	shares = (struct share_mode_entry *)(new_data_p + sizeof(struct locking_data) +
			(orig_num_share_modes * sizeof(struct share_mode_entry)));

	create_share_mode_entry(shares, new_entry, name_hash);

	ld = (struct locking_data *)new_data_p;
	ld->u.s.num_share_mode_entries++;

	/* Append the original delete_tokens and filenames. */
	memcpy(new_data_p + sizeof(struct locking_data) + (ld->u.s.num_share_mode_entries * sizeof(struct share_mode_entry)),
		db_data.dptr + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry)),
		db_data.dsize - sizeof(struct locking_data) - (orig_num_share_modes * sizeof(struct share_mode_entry)));

	new_data_size = db_data.dsize + sizeof(struct share_mode_entry);

	free(db_data.dptr);

	db_data.dptr = new_data_p;
	db_data.dsize = new_data_size;

	if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) != 0) {
		free(db_data.dptr);
		return -1;
	}
	free(db_data.dptr);
	return 0;
}
Beispiel #7
0
int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
				uint64_t dev,
				uint64_t ino,
				uint64_t extid,
				struct smb_share_mode_entry **pp_list,
				unsigned char *p_delete_on_close)
{
	struct locking_key lk;
	TDB_DATA db_data;
	struct smb_share_mode_entry *list = NULL;
	int num_share_modes = 0;
	struct locking_data *ld = NULL; /* internal samba db state. */
	struct share_mode_entry *shares = NULL;
	size_t i;
	int list_num;

	*pp_list = NULL;
	*p_delete_on_close = 0;

	db_data = tdb_fetch_compat(db_ctx->smb_tdb,
				   get_locking_key(&lk, dev, ino, extid));
	if (!db_data.dptr) {
		return 0;
	}

	ld = (struct locking_data *)db_data.dptr;
	num_share_modes = ld->u.s.num_share_mode_entries;

	if (!num_share_modes) {
		free(db_data.dptr);
		return 0;
	}

	list = (struct smb_share_mode_entry *)malloc(sizeof(struct smb_share_mode_entry)*num_share_modes);
	if (!list) {
		free(db_data.dptr);
		return -1;
	}

	memset(list, '\0', num_share_modes * sizeof(struct smb_share_mode_entry));

	shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));

	list_num = 0;
	for (i = 0; i < num_share_modes; i++) {
		struct share_mode_entry *share = &shares[i];
		struct smb_share_mode_entry *sme = &list[list_num];
		struct server_id pid = share->pid;

		/* Check this process really exists. */
		if (kill(sharemodes_procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
			continue; /* No longer exists. */
		}

		/* Ignore deferred open entries. */
		if (share->op_type == DEFERRED_OPEN_ENTRY) {
			continue;
		}

		/* Copy into the external list. */
		sme->dev = share->id.devid;
		sme->ino = share->id.inode;
		sme->extid = share->id.extid;
		sme->share_access = (uint32_t)share->share_access;
		sme->access_mask = (uint32_t)share->access_mask;
		sme->open_time.tv_sec = share->time.tv_sec;
		sme->open_time.tv_usec = share->time.tv_usec;
        	sme->file_id = (uint32_t)share->share_file_id;
		sme->pid = share->pid;
		list_num++;
	}

	if (list_num == 0) {
		free(db_data.dptr);
		free(list);
		return 0;
	}

	*p_delete_on_close = ld->u.s.num_delete_token_entries != 0;
	*pp_list = list;
	free(db_data.dptr);
	return list_num;
}
Beispiel #8
0
TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr)
{
	TDB_DATA key = string_term_tdb_data(keystr);

	return tdb_fetch_compat(tdb, key);
}
Beispiel #9
0
/*
  modify a record - internal interface

  yuck - this is O(n^2). Luckily n is usually small so we probably
  get away with it, but if we ever have really large attribute lists
  then we'll need to look at this again

  'req' is optional, and is used to specify controls if supplied
*/
int ltdb_modify_internal(struct ldb_module *module,
			 const struct ldb_message *msg,
			 struct ldb_request *req)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	void *data = ldb_module_get_private(module);
	struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
	TDB_DATA tdb_key, tdb_data;
	struct ldb_message *msg2;
	unsigned int i, j, k;
	int ret = LDB_SUCCESS, idx;
	struct ldb_control *control_permissive = NULL;

	if (req) {
		control_permissive = ldb_request_get_control(req,
					LDB_CONTROL_PERMISSIVE_MODIFY_OID);
	}

	tdb_key = ltdb_key(module, msg->dn);
	if (!tdb_key.dptr) {
		return LDB_ERR_OTHER;
	}

	tdb_data = tdb_fetch_compat(ltdb->tdb, tdb_key);
	if (!tdb_data.dptr) {
		talloc_free(tdb_key.dptr);
		return ltdb_err_map(tdb_error(ltdb->tdb));
	}

	msg2 = ldb_msg_new(tdb_key.dptr);
	if (msg2 == NULL) {
		free(tdb_data.dptr);
		ret = LDB_ERR_OTHER;
		goto done;
	}

	ret = ltdb_unpack_data(module, &tdb_data, msg2);
	free(tdb_data.dptr);
	if (ret == -1) {
		ret = LDB_ERR_OTHER;
		goto done;
	}

	if (!msg2->dn) {
		msg2->dn = msg->dn;
	}

	for (i=0; i<msg->num_elements; i++) {
		struct ldb_message_element *el = &msg->elements[i], *el2;
		struct ldb_val *vals;
		const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
		const char *dn;

		switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
		case LDB_FLAG_MOD_ADD:

			if (el->num_values == 0) {
				ldb_asprintf_errstring(ldb,
						       "attribute '%s': attribute on '%s' specified, but with 0 values (illegal)",
						       el->name, ldb_dn_get_linearized(msg2->dn));
				ret = LDB_ERR_CONSTRAINT_VIOLATION;
				goto done;
			}

			/* make a copy of the array so that a permissive
			 * control can remove duplicates without changing the
			 * original values, but do not copy data as we do not
			 * need to keep it around once the operation is
			 * finished */
			if (control_permissive) {
				el = talloc(msg2, struct ldb_message_element);
				if (!el) {
					ret = LDB_ERR_OTHER;
					goto done;
				}
				*el = msg->elements[i];
				el->values = talloc_array(el, struct ldb_val, el->num_values);
				if (el->values == NULL) {
					ret = LDB_ERR_OTHER;
					goto done;
				}
				for (j = 0; j < el->num_values; j++) {
					el->values[j] = msg->elements[i].values[j];
				}
			}

			if (el->num_values > 1 && ldb_tdb_single_valued(a, el)) {
				ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
						       el->name, ldb_dn_get_linearized(msg2->dn));
				ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
				goto done;
			}

			/* Checks if element already exists */
			idx = find_element(msg2, el->name);
			if (idx == -1) {
				if (ltdb_msg_add_element(ldb, msg2, el) != 0) {
					ret = LDB_ERR_OTHER;
					goto done;
				}
				ret = ltdb_index_add_element(module, msg2->dn,
							     el);
				if (ret != LDB_SUCCESS) {
					goto done;
				}
			} else {
				j = (unsigned int) idx;
				el2 = &(msg2->elements[j]);

				/* We cannot add another value on a existing one
				   if the attribute is single-valued */
				if (ldb_tdb_single_valued(a, el)) {
					ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
						               el->name, ldb_dn_get_linearized(msg2->dn));
					ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
					goto done;
				}

				/* Check that values don't exist yet on multi-
				   valued attributes or aren't provided twice */
				for (j = 0; j < el->num_values; j++) {
					if (ldb_msg_find_val(el2, &el->values[j]) != NULL) {
						if (control_permissive) {
							/* remove this one as if it was never added */
							el->num_values--;
							for (k = j; k < el->num_values; k++) {
								el->values[k] = el->values[k + 1];
							}
							j--; /* rewind */

							continue;
						}

						ldb_asprintf_errstring(ldb,
								       "attribute '%s': value #%u on '%s' already exists",
								       el->name, j, ldb_dn_get_linearized(msg2->dn));
						ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
						goto done;
					}
					if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
						ldb_asprintf_errstring(ldb,
								       "attribute '%s': value #%u on '%s' provided more than once",
								       el->name, j, ldb_dn_get_linearized(msg2->dn));
						ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
						goto done;
					}
				}

				/* Now combine existing and new values to a new
				   attribute record */
				vals = talloc_realloc(msg2->elements,
						      el2->values, struct ldb_val,
						      el2->num_values + el->num_values);
				if (vals == NULL) {
					ldb_oom(ldb);
					ret = LDB_ERR_OTHER;
					goto done;
				}

				for (j=0; j<el->num_values; j++) {
					vals[el2->num_values + j] =
						ldb_val_dup(vals, &el->values[j]);
				}

				el2->values = vals;
				el2->num_values += el->num_values;

				ret = ltdb_index_add_element(module, msg2->dn, el);
				if (ret != LDB_SUCCESS) {
					goto done;
				}
			}

			break;

		case LDB_FLAG_MOD_REPLACE:

			if (el->num_values > 1 && ldb_tdb_single_valued(a, el)) {
				ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
						       el->name, ldb_dn_get_linearized(msg2->dn));
				ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
				goto done;
			}

			/* TODO: This is O(n^2) - replace with more efficient check */
			for (j=0; j<el->num_values; j++) {
				if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
					ldb_asprintf_errstring(ldb,
							       "attribute '%s': value #%u on '%s' provided more than once",
							       el->name, j, ldb_dn_get_linearized(msg2->dn));
					ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
					goto done;
				}
			}

			/* Checks if element already exists */
			idx = find_element(msg2, el->name);
			if (idx != -1) {
				j = (unsigned int) idx;
				el2 = &(msg2->elements[j]);
				if (ldb_msg_element_compare(el, el2) == 0) {
					/* we are replacing with the same values */
					continue;
				}
			
				/* Delete the attribute if it exists in the DB */
				if (msg_delete_attribute(module, ldb, msg2,
							 el->name) != 0) {
					ret = LDB_ERR_OTHER;
					goto done;
				}
			}

			/* Recreate it with the new values */
			if (ltdb_msg_add_element(ldb, msg2, el) != 0) {
				ret = LDB_ERR_OTHER;
				goto done;
			}

			ret = ltdb_index_add_element(module, msg2->dn, el);
			if (ret != LDB_SUCCESS) {
				goto done;
			}

			break;

		case LDB_FLAG_MOD_DELETE:
			dn = ldb_dn_get_linearized(msg2->dn);
			if (dn == NULL) {
				ret = LDB_ERR_OTHER;
				goto done;
			}

			if (msg->elements[i].num_values == 0) {
				/* Delete the whole attribute */
				ret = msg_delete_attribute(module, ldb, msg2,
							   msg->elements[i].name);
				if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE &&
				    control_permissive) {
					ret = LDB_SUCCESS;
				} else {
					ldb_asprintf_errstring(ldb,
							       "attribute '%s': no such attribute for delete on '%s'",
							       msg->elements[i].name, dn);
				}
				if (ret != LDB_SUCCESS) {
					goto done;
				}
			} else {
				/* Delete specified values from an attribute */
				for (j=0; j < msg->elements[i].num_values; j++) {
					ret = msg_delete_element(module,
							         msg2,
							         msg->elements[i].name,
							         &msg->elements[i].values[j]);
					if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE &&
					    control_permissive) {
						ret = LDB_SUCCESS;
					} else {
						ldb_asprintf_errstring(ldb,
								       "attribute '%s': no matching attribute value while deleting attribute on '%s'",
								       msg->elements[i].name, dn);
					}
					if (ret != LDB_SUCCESS) {
						goto done;
					}
				}
			}
			break;
		default:
			ldb_asprintf_errstring(ldb,
					       "attribute '%s': invalid modify flags on '%s': 0x%x",
					       msg->elements[i].name, ldb_dn_get_linearized(msg->dn),
					       msg->elements[i].flags & LDB_FLAG_MOD_MASK);
			ret = LDB_ERR_PROTOCOL_ERROR;
			goto done;
		}
	}

	ret = ltdb_store(module, msg2, TDB_MODIFY);
	if (ret != LDB_SUCCESS) {
		goto done;
	}

	ret = ltdb_modified(module, msg2->dn);
	if (ret != LDB_SUCCESS) {
		goto done;
	}

done:
	talloc_free(tdb_key.dptr);
	return ret;
}
Beispiel #10
0
/*
  test tdb speed
*/
static bool test_tdb_speed(struct torture_context *torture, const void *_data)
{
	struct timeval tv;
	struct tdb_wrap *tdbw;
	int timelimit = torture_setting_int(torture, "timelimit", 10);
	int i, count;
	TALLOC_CTX *tmp_ctx = talloc_new(torture);

	unlink("test.tdb");

	torture_comment(torture, "Testing tdb speed for sidmap\n");

	tdbw = tdb_wrap_open(tmp_ctx, "test.tdb", 
			     10000, 0, O_RDWR|O_CREAT|O_TRUNC, 0600);
	if (!tdbw) {
		torture_result(torture, TORTURE_FAIL, "Failed to open test.tdb");
		goto failed;
	}

	torture_comment(torture, "Adding %d SID records\n", torture_entries);

	for (i=0;i<torture_entries;i++) {
		if (!tdb_add_record(tdbw, 
				    "S-1-5-21-53173311-3623041448-2049097239-%u",
				    "UID %u", i)) {
			torture_result(torture, TORTURE_FAIL, "Failed to add SID %d!", i);
			goto failed;
		}
		if (!tdb_add_record(tdbw, 
				    "UID %u",
				    "S-1-5-21-53173311-3623041448-2049097239-%u", i)) {
			torture_result(torture, TORTURE_FAIL, "Failed to add UID %d!", i);
			goto failed;
		}
	}

	torture_comment(torture, "Testing for %d seconds\n", timelimit);

	tv = timeval_current();

	for (count=0;timeval_elapsed(&tv) < timelimit;count++) {
		TDB_DATA key, data;
		i = random() % torture_entries;
		key.dptr = (uint8_t *)talloc_asprintf(tmp_ctx, "S-1-5-21-53173311-3623041448-2049097239-%u", i);
		key.dsize = strlen((char *)key.dptr)+1;
		data = tdb_fetch_compat(tdbw->tdb, key);
		talloc_free(key.dptr);
		if (data.dptr == NULL) {
			torture_result(torture, TORTURE_FAIL, "Failed to find SID %d!", i);
			goto failed;
		}
		free(data.dptr);
		key.dptr = (uint8_t *)talloc_asprintf(tmp_ctx, "UID %u", i);
		key.dsize = strlen((char *)key.dptr)+1;
		data = tdb_fetch_compat(tdbw->tdb, key);
		talloc_free(key.dptr);
		if (data.dptr == NULL) {
			torture_result(torture, TORTURE_FAIL, "Failed to find UID %d!", i);
			goto failed;
		}
		free(data.dptr);
	}

	tdb_speed = count/timeval_elapsed(&tv);
	torture_comment(torture, "tdb speed %.2f ops/sec\n", tdb_speed);
	
	talloc_free(tmp_ctx);
	unlink("test.tdb");
	return true;

failed:
	talloc_free(tmp_ctx);
	unlink("test.tdb");
	return false;
}
static NTSTATUS migrate_internal(TALLOC_CTX *mem_ctx,
				 const char *tdb_path,
				 struct rpc_pipe_client *winreg_pipe)
{
	const char *backup_suffix = ".bak";
	TDB_DATA kbuf, dbuf;
	TDB_CONTEXT *tdb;
	NTSTATUS status;
	int rc;

	tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0600);
	if (tdb == NULL && errno == ENOENT) {
		/* if we have no printers database then migration is
		   considered successful */
		DEBUG(4, ("No printers database to migrate in %s\n", tdb_path));
		return NT_STATUS_OK;
	}
	if (tdb == NULL) {
		DEBUG(2, ("Failed to open tdb file: %s\n", tdb_path));
		return NT_STATUS_NO_SUCH_FILE;
	}

	for (kbuf = tdb_firstkey_compat(tdb);
	     kbuf.dptr;
	     kbuf = tdb_nextkey_compat(tdb, kbuf))
	{
		dbuf = tdb_fetch_compat(tdb, kbuf);
		if (!dbuf.dptr) {
			continue;
		}

		if (strncmp((const char *) kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
			status = printing_tdb_migrate_form(mem_ctx,
					      winreg_pipe,
					      (const char *) kbuf.dptr + strlen(FORMS_PREFIX),
					      dbuf.dptr,
					      dbuf.dsize);
			SAFE_FREE(dbuf.dptr);
			if (!NT_STATUS_IS_OK(status)) {
				tdb_close(tdb);
				return status;
			}
			continue;
		}

		if (strncmp((const char *) kbuf.dptr, DRIVERS_PREFIX, strlen(DRIVERS_PREFIX)) == 0) {
			status = printing_tdb_migrate_driver(mem_ctx,
						winreg_pipe,
						(const char *) kbuf.dptr + strlen(DRIVERS_PREFIX),
						dbuf.dptr,
						dbuf.dsize,
						false);
			SAFE_FREE(dbuf.dptr);
			if (!NT_STATUS_IS_OK(status)) {
				tdb_close(tdb);
				return status;
			}
			continue;
		}

		if (strncmp((const char *) kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
			const char *printer_name = (const char *)(kbuf.dptr
						    + strlen(PRINTERS_PREFIX));
			status = printing_tdb_migrate_printer(mem_ctx,
						 winreg_pipe,
						 printer_name,
						 dbuf.dptr,
						 dbuf.dsize,
						 false);
			SAFE_FREE(dbuf.dptr);
			if (!NT_STATUS_IS_OK(status)) {
				tdb_close(tdb);
				return status;
			}
			continue;
		}
		SAFE_FREE(dbuf.dptr);
	}

	for (kbuf = tdb_firstkey_compat(tdb);
	     kbuf.dptr;
	     kbuf = tdb_nextkey_compat(tdb, kbuf))
	{
		dbuf = tdb_fetch_compat(tdb, kbuf);
		if (!dbuf.dptr) {
			continue;
		}

		if (strncmp((const char *) kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
			const char *secdesc_name = (const char *)(kbuf.dptr
						    + strlen(SECDESC_PREFIX));
			status = printing_tdb_migrate_secdesc(mem_ctx,
						 winreg_pipe,
						 secdesc_name,
						 dbuf.dptr,
						 dbuf.dsize);
			SAFE_FREE(dbuf.dptr);
			if (NT_STATUS_EQUAL(status, werror_to_ntstatus(WERR_BADFILE))) {
				DEBUG(2, ("Skipping secdesc migration for non-existent "
						"printer: %s\n", secdesc_name));
			} else if (!NT_STATUS_IS_OK(status)) {
				tdb_close(tdb);
				return status;
			}
			continue;
		}
		SAFE_FREE(dbuf.dptr);
	}

	tdb_close(tdb);

	rc = rename_file_with_suffix(mem_ctx, tdb_path, backup_suffix);
	if (rc != 0) {
		DEBUG(0, ("Error moving tdb to '%s%s'\n",
			  tdb_path, backup_suffix));
	}

	return NT_STATUS_OK;
}