static bool test_sids2unixids1(TALLOC_CTX *memctx, struct idmap_domain *dom)
{
	NTSTATUS status;
	struct id_map uid_map, gid_map, **test_maps;

	ZERO_STRUCT(uid_map);
	ZERO_STRUCT(gid_map);

	/* create two mappings for a UID and GID */

	uid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID4 "-1000");
	uid_map.xid.type = ID_TYPE_UID;

	gid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID4 "-1001");
	gid_map.xid.type = ID_TYPE_GID;

	status = idmap_tdb_common_new_mapping(dom, &uid_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_sids2unixids1: could not create uid map!\n"));
		return false;
	}

	status = idmap_tdb_common_new_mapping(dom, &gid_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_sids2unixids1: could not create gid map!\n"));
		return false;
	}

	/* now read them back  */
	test_maps = talloc_zero_array(memctx, struct id_map*, 3);

	test_maps[0] = talloc(test_maps, struct id_map);
	test_maps[1] = talloc(test_maps, struct id_map);
	test_maps[2] = NULL;

	test_maps[0]->sid = talloc(test_maps, struct dom_sid);
	test_maps[1]->sid = talloc(test_maps, struct dom_sid);
	sid_copy(test_maps[0]->sid, uid_map.sid);
	sid_copy(test_maps[1]->sid, gid_map.sid);

	status = idmap_tdb_common_sids_to_unixids(dom, test_maps);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_sids2sunixids1: sids2unixids failed!\n"));
		talloc_free(test_maps);
		return false;
	}

	if(test_maps[0]->xid.id!=uid_map.xid.id ||
	    test_maps[1]->xid.id!=gid_map.xid.id ) {
		DEBUG(0, ("test_sids2unixids1: sid2unixid returned wrong xid!\n"));
		talloc_free(test_maps);
		return false;
	}

	DEBUG(0, ("test_sids2unixids1: PASSED!\n"));

	talloc_free(test_maps);

	return true;
}
static NTSTATUS idmap_tdb_common_sids_to_unixids_action(struct db_context *db,
							void *private_data)
{
	struct idmap_tdb_common_sids_to_unixids_context *state;
	int i, num_mapped = 0;
	NTSTATUS ret = NT_STATUS_OK;

	state = (struct idmap_tdb_common_sids_to_unixids_context *)private_data;

	DEBUG(10, ("idmap_tdb_common_sids_to_unixids: "
		   " domain: [%s], allocate: %s\n",
		   state->dom->name, state->allocate_unmapped ? "yes" : "no"));

	for (i = 0; state->ids[i]; i++) {
		if ((state->ids[i]->status == ID_UNKNOWN) ||
		    /* retry if we could not map in previous run: */
		    (state->ids[i]->status == ID_UNMAPPED)) {
			NTSTATUS ret2;

			ret2 = state->sid_to_unixid_fn(state->dom,
					state->ids[i]);

			if (!NT_STATUS_IS_OK(ret2)) {

				/* if it is just a failed mapping, continue */
				if (NT_STATUS_EQUAL
				    (ret2, NT_STATUS_NONE_MAPPED)) {

					/* make sure it is marked as unmapped */
					state->ids[i]->status = ID_UNMAPPED;
					ret = STATUS_SOME_UNMAPPED;
				} else {
					/*
					 * some fatal error occurred,
					 * return immediately
					 */
					ret = ret2;
					goto done;
				}
			} else {
				/* all ok, id is mapped */
				state->ids[i]->status = ID_MAPPED;
			}
		}

		if (state->ids[i]->status == ID_MAPPED) {
			num_mapped += 1;
		}

		if ((state->ids[i]->status == ID_UNMAPPED) &&
		    state->allocate_unmapped) {
			ret =
			    idmap_tdb_common_new_mapping(state->dom,
							 state->ids[i]);
			if (!NT_STATUS_IS_OK(ret)) {
				goto done;
			}
			num_mapped += 1;
		}
	}

done:

	if (NT_STATUS_IS_OK(ret) ||
	    NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED)) {
		if (i == 0 || num_mapped == 0) {
			ret = NT_STATUS_NONE_MAPPED;
		} else if (num_mapped < i) {
			ret = STATUS_SOME_UNMAPPED;
		} else {
			ret = NT_STATUS_OK;
		}
	}

	return ret;
}
static bool test_unixids2sids3(TALLOC_CTX *memctx, struct idmap_domain *dom)
{
	NTSTATUS status;
	struct id_map uid_map, gid_map, **test_maps;
	bool retval = true;

	ZERO_STRUCT(uid_map);
	ZERO_STRUCT(gid_map);

	/* create two mappings for a UID and GID */
	uid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID6 "-1000");
	uid_map.xid.type = ID_TYPE_UID;

	gid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID6 "-1001");
	gid_map.xid.type = ID_TYPE_GID;

	status = idmap_tdb_common_new_mapping(dom, &uid_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_unixids2sids3: could not create uid map!\n"));
		return false;
	}

	status = idmap_tdb_common_new_mapping(dom, &gid_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_unixids2sids3: could not create gid map!\n"));
		return false;
	}

	/*
	 * check the mapping states:
	 * NONE_MAPPED, SOME_UNMAPPED, OK (all mapped)
	 */
	test_maps = talloc_zero_array(memctx, struct id_map*, 3);

	test_maps[0] = talloc(test_maps, struct id_map);
	test_maps[1] = talloc(test_maps, struct id_map);
	test_maps[2] = NULL;

	/* NONE_MAPPED first */
	test_maps[0]->sid = talloc(test_maps, struct dom_sid);
	test_maps[1]->sid = talloc(test_maps, struct dom_sid);

	test_maps[0]->xid.id = HIGH_ID - 1;
	test_maps[0]->xid.type = ID_TYPE_UID;

	test_maps[1]->xid.id = HIGH_ID - 1;
	test_maps[1]->xid.type = ID_TYPE_GID;

	status = idmap_tdb_common_unixids_to_sids(dom, test_maps);
	if(!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
		DEBUG(0, ("test_unixids2sids3: incorrect status "
			  "(%s), expected NT_STATUS_NONE_MAPPED!\n",
			   nt_errstr(status)));
		retval = false;
		goto out;
	}

	/* SOME_UNMAPPED */
	test_maps[0]->sid = talloc(test_maps, struct dom_sid);
	test_maps[1]->sid = talloc(test_maps, struct dom_sid);
	test_maps[0]->xid = uid_map.xid;
	test_maps[1]->xid.id = HIGH_ID - 1;
	test_maps[1]->xid.type = ID_TYPE_GID;

	status = idmap_tdb_common_unixids_to_sids(dom, test_maps);
	if(!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
		DEBUG(0, ("test_unixids2sids3: incorrect status "
			  "(%s), expected STATUS_SOME_UNMAPPED!\n",
			   nt_errstr(status)));
		retval = false;
		goto out;
	}

	/* OK */
	test_maps[0]->sid = talloc(test_maps, struct dom_sid);
	test_maps[1]->sid = talloc(test_maps, struct dom_sid);
	test_maps[0]->xid = uid_map.xid;
	test_maps[1]->xid = gid_map.xid;

	status = idmap_tdb_common_unixids_to_sids(dom, test_maps);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_unixids2sids3: incorrect status "
			  "(%s), expected NT_STATUS_OK!\n",
			   nt_errstr(status)));
		retval = false;
		goto out;
	}

	DEBUG(0, ("test_unixids2sids3: PASSED!\n"));

out:
	talloc_free(test_maps);
	return retval;
}
static bool test_unixid2sid3(TALLOC_CTX *memctx, struct idmap_domain *dom)
{
	NTSTATUS status;
	struct id_map uid_map, gid_map, test_map;
	struct dom_sid testsid;

	ZERO_STRUCT(uid_map);
	ZERO_STRUCT(gid_map);

	/* create two mappings for a UID and GID */
	uid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID3 "-1000");
	uid_map.xid.type = ID_TYPE_UID;

	gid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID3 "-1001");
	gid_map.xid.type = ID_TYPE_GID;

	status = idmap_tdb_common_new_mapping(dom, &uid_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_unixid2sid3: could not create uid map!\n"));
		return false;
	}

	status = idmap_tdb_common_new_mapping(dom, &gid_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_unixid2sid3: could not create gid map!\n"));
		return false;
	}

	/* now read them back */
	ZERO_STRUCT(test_map);
	test_map.xid.id = uid_map.xid.id;
	test_map.xid.type = ID_TYPE_UID;
	test_map.sid = &testsid;

	status = idmap_tdb_common_unixid_to_sid(dom, &test_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_unixid2sid3: unixid2sid failed for uid!\n"));
		return false;
	}

	if(test_map.xid.type!=uid_map.xid.type) {
		DEBUG(0, ("test_unixid2sid3: unixid2sid returned wrong type!\n"));
		return false;
	}

	if(!dom_sid_equal(test_map.sid, uid_map.sid)) {
		DEBUG(0, ("test_unixid2sid3: unixid2sid returned wrong SID!\n"));
		return false;
	}

	ZERO_STRUCT(test_map);
	test_map.xid.id = gid_map.xid.id;
	test_map.xid.type = ID_TYPE_GID;
	test_map.sid = &testsid;

	status = idmap_tdb_common_unixid_to_sid(dom, &test_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_unixid2sid3: unixid2sid failed for gid!\n"));
		return false;
	}

	if(test_map.xid.type!=gid_map.xid.type) {
		DEBUG(0, ("test_unixid2sid3: unixid2sid returned wrong type!\n"));
		return false;
	}

	if(!dom_sid_equal(test_map.sid,gid_map.sid)) {
		DEBUG(0, ("test_unixid2sid3: unixid2sid returned wrong SID!\n"));
		return false;
	}

	DEBUG(0, ("test_unixid2sid3: PASSED!\n"));

	return true;
}
static bool test_sid2unixid2(TALLOC_CTX *memctx, struct idmap_domain *dom)
{
	NTSTATUS status;
	struct id_map uid_map, gid_map, test_map;
	bool doagain = true;

	ZERO_STRUCT(uid_map);
	ZERO_STRUCT(gid_map);

	/* create two mappings for a UID and GID */

again:

	uid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID2 "-1000");
	uid_map.xid.type = ID_TYPE_UID;

	gid_map.sid = dom_sid_parse_talloc(memctx, DOM_SID2 "-1001");
	gid_map.xid.type = ID_TYPE_GID;

	status = idmap_tdb_common_new_mapping(dom, &uid_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_sid2unixid1: could not create uid map!\n"));
		return false;
	}

	status = idmap_tdb_common_new_mapping(dom, &gid_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_sid2unixid1: could not create gid map!\n"));
		return false;
	}

	/* now read them back */
	ZERO_STRUCT(test_map);
	test_map.sid = uid_map.sid;

	status = idmap_tdb_common_sid_to_unixid(dom, &test_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_sid2unixid1: sid2unixid failed for uid!\n"));
		return false;
	}

	if(test_map.xid.id!=uid_map.xid.id) {
		DEBUG(0, ("test_sid2unixid1: sid2unixid returned wrong uid!\n"));
		return false;
	}

	test_map.sid = gid_map.sid;

	status = idmap_tdb_common_sid_to_unixid(dom, &test_map);
	if(!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("test_sid2unixid1: sid2unixid failed for gid!\n"));
		return false;
	}

	if(test_map.xid.id!=gid_map.xid.id) {
		DEBUG(0, ("test_sid2unixid1: sid2unixid returned wrong gid!\n"));
		return false;
	}

	/*
	 * Go through the same tests again once to see if trying to recreate
	 * a mapping that was already created will work or not
	 */
	if(doagain) {
		doagain = false;
		goto again;
	}

	DEBUG(0, ("test_sid2unixid1: PASSED!\n"));

	return true;
}