示例#1
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_mergedirprop(void *domain, ni_id *dir, const ni_name key, ni_namelist values)
{
    /* mergeprop given a directory rather than a pathname */

    ni_status ret;
    ni_property p;
    ni_namelist nl;
    ni_index where, whereval;
    int i;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* check for existing property with this key */
    where = ni_namelist_match(nl, key);
    ni_namelist_free(&nl);

    /* if property doesn't exist, create it */
    if (where == NI_INDEX_NULL) {
        NI_INIT(&p);
        p.nip_name = ni_name_dup(key);
        p.nip_val = ni_namelist_dup(values);
        ret = ni_createprop(domain, dir, p, NI_INDEX_NULL);
        ni_prop_free(&p);
        return ret;
    }


    /* property exists: replace the existing values */
    /* fetch existing namelist for this property */
    NI_INIT(&nl);
    ret = ni_readprop(domain, dir, where, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* merge new values */
    for (i = 0; i < values.ni_namelist_len; i++) {
        whereval = ni_namelist_match(nl, values.ni_namelist_val[i]);
        if (whereval == NI_INDEX_NULL) {
            ni_namelist_insert(&nl, values.ni_namelist_val[i], NI_INDEX_NULL);
        }
    }

    /* write the new list back */
    ret = ni_writeprop(domain, dir, where, nl);
    ni_namelist_free(&nl);
    return ret;
}
示例#2
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_copydirtoparentdir(void *srcdomain, ni_id *srcdir, void*dstdomain, ni_id *dstdir , bool recursive)
{
    ni_status ret;
    ni_idlist children;
    int i, len;
    ni_proplist p;
    ni_id dir, newdstdir;

    NI_INIT(&p);
    
    /* get proplist from src dir */
    ret = ni_read(srcdomain, srcdir, &p);
    if (ret != NI_OK) {
        return ret;
    }

    /* create the destination dir */
    ret = ni_create(dstdomain, dstdir, p, &newdstdir, NI_INDEX_NULL);
    if (ret != NI_OK) {
        ni_proplist_free(&p);
        return ret;
    }
    
    ni_proplist_free(&p);

    if (recursive) {
        NI_INIT(&children);

        /* get list of children */
        ret = ni_children(srcdomain, srcdir, &children);
        if (ret != NI_OK) {
            return ret;
        }

        len = children.ni_idlist_len;
        for (i = 0; i < len; i++) {
            dir.nii_object = children.ni_idlist_val[i];
            ret = ni_self(srcdomain, &dir);
            if (ret != NI_OK) {
                ni_idlist_free(&children);
                return ret;
            }
            ret = ni2_copydirtoparentdir(srcdomain,&dir,dstdomain, &newdstdir,recursive);
        }
    
        ni_idlist_free(&children);
    }

    return NI_OK;
}
示例#3
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_destroydirval(void *domain, ni_id *dir, const ni_name key, ni_namelist values)
{
    /* destroyval given a directory rather than a pathname */

    ni_status ret;
    ni_namelist nl;
    ni_index where, whereval;
    int i;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* check for existing property with this key */
    where = ni_namelist_match(nl, key);
    ni_namelist_free(&nl);

    /* if property doesn't exist, nothing to do */
    if (where == NI_INDEX_NULL) {
        return NI_OK;
    }

    /* fetch existing namelist for this property */
    NI_INIT(&nl);
    ret = ni_readprop(domain, dir, where, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* delete values */
    for (i = 0; i < values.ni_namelist_len; i++) {
        whereval = ni_namelist_match(nl, values.ni_namelist_val[i]);
        while (whereval != NI_INDEX_NULL) {
            ni_namelist_delete(&nl, whereval);
            whereval = ni_namelist_match(nl, values.ni_namelist_val[i]);
        }
    }

    /* write the new list back */
    ret = ni_writeprop(domain, dir, where, nl);
    ni_namelist_free(&nl);

    return ret;
}
示例#4
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_renamedirprop(void *domain, ni_id *dir, const ni_name oldname, const ni_name newname)
{
    /* renameprop given a directory rather than a pathname */

    ni_status ret;
    ni_index where;
    ni_namelist nl;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* look up old name */
    where = ni_namelist_match(nl, oldname);
    ni_namelist_free(&nl);

    /* if it's not there, return an error */
    if (where == NI_INDEX_NULL) {
        return NI_NOPROP;
    }

    return ni_renameprop(domain, dir, where, newname);
}
示例#5
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_destroydir(void *domain, ni_id *dir, ni_id *parent)
{
    /* destroy a directory and all it's subdirectories */
    /* this is the recursive workhorse */

    ni_status ret;
    int i;
    ni_idlist children;
    ni_id child;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* get a list of all my children */
    NI_INIT(&children);
    ret = ni_children(domain, dir, &children);
    if (ret != NI_OK) return ret;

    /* destroy each child */
    for (i = 0; i < children.ni_idlist_len; i++) {
        child.nii_object = children.ni_idlist_val[i];
        ret = ni_self(domain, &child);
        if (ret != NI_OK) return ret;
        ret = ni2_destroydir(domain, &child, dir);
        if (ret != NI_OK) return ret;
    }

    /* free list of child ids */
    ni_idlist_free(&children);

    /* destroy myself */
    return ni_destroy(domain, parent, *dir);
}
示例#6
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_reapdir(void *domain, char *pathname)
{
    /* destroy a directory if it has nothing but a name */

    ni_status ret;
    ni_id dir;
    ni_namelist nl;

    /* see if the directory exists */
    ret = ni2_pathsearch(domain, &dir, pathname);
    if (ret != NI_OK) return ret;

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, &dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* if more than one property, leave it alone */
    if (nl.ni_namelist_len > 1) {
        ni_namelist_free(&nl);
        return NI_OK;
    }

    /* directory is empty (except for name), delete it */
    ni_namelist_free(&nl);
    return ni2_destroy(domain, pathname);
}
示例#7
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_statpropdir(void *domain, ni_id *dir, const ni_name key, ni_index *where)
{
    /* statprop given a directory rather than a pathname */

    ni_status ret;
    ni_namelist nl;

    /* assume there's no match */
    *where = NI_INDEX_NULL;

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* check for property with this key */
    *where = ni_namelist_match(nl, key);
    ni_namelist_free(&nl);

    /* if property doesn't exist, no match */
    if (*where == NI_INDEX_NULL) {
        return NI_NOPROP;
    }

    return NI_OK;
}
示例#8
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_statvaldir(void *domain, ni_id *dir, const ni_name key, const ni_name value, ni_index *where)
{
    /* statval given a directory rather than a pathname */

    ni_status ret;
    ni_namelist nl;
    ni_index wh;

    /* assume there's no match */
    *where = NI_INDEX_NULL;

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* check for property with this key */
    wh = ni_namelist_match(nl, key);
    ni_namelist_free(&nl);

    /* if property doesn't exist, no match */
    if (wh == NI_INDEX_NULL) {
        return NI_NOPROP;
    }

    /* fetch existing namelist for this property */
    NI_INIT(&nl);
    ret = ni_readprop(domain, dir, wh, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* check for this value */
    wh = ni_namelist_match(nl, value);
    ni_namelist_free(&nl);

    /* if value doesn't exist, no match */
    if (wh == NI_INDEX_NULL) {
        return NI_NONAME;
    }

    *where = wh;
    return NI_OK;
}
示例#9
0
static u_int32_t
NI_checksum_for_index(agent_private *ap, u_int32_t i)
{
	struct timeval now;
	u_int32_t age;
	ni_status status;
	ni_proplist pl;
	u_int32_t sum;
	ni_index where;

	if (ap == NULL) return 0;

	if (i >= ap->domain_count) return 0;

	gettimeofday(&now, (struct timezone *)NULL);
	age = now.tv_sec - ap->domain[i].checksum_time;
	if (age <= ap->latency) return ap->domain[i].checksum;

	NI_INIT(&pl);

	syslock_lock(rpcLock);
	status = sa_statistics(ap->domain[i].handle, &pl);
	syslock_unlock(rpcLock);

	if (status != NI_OK)
	{
		system_log(LOG_ERR, "ni_statistics: %s", ni_error(status));
		ni_proplist_free(&pl);
		return 0;
	}

	/* checksum should be first (and only!) property */
	where = NI_INDEX_NULL;
	if (pl.ni_proplist_len > 0)
	{
		if (strcmp(pl.ni_proplist_val[0].nip_name, "checksum"))
			where = 0;
		else
			where = ni_proplist_match(pl, "checksum", NULL);
	}

	if (where == NI_INDEX_NULL)
	{
		system_log(LOG_ERR, "ap->domain %lu: can't get checksum", i);
		ni_proplist_free(&pl);
		return 0;
	}

	sscanf(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], "%lu", (unsigned long *)&sum);
	ni_proplist_free(&pl);

	ap->domain[i].checksum_time = now.tv_sec;
	ap->domain[i].checksum = sum;

	return sum;
}
示例#10
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_reappropdir(void *domain, ni_id *dir, const ni_name key)
{
    /* reapprop given a directory rather than a pathname */

    ni_status ret;
    ni_namelist nl;
    ni_index where;

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* check for property with this key */
    where = ni_namelist_match(nl, key);
    ni_namelist_free(&nl);

    /* if property doesn't exist, return */
    if (where == NI_INDEX_NULL) {
        return NI_OK;
    }

    /* fetch existing namelist for this property */
    NI_INIT(&nl);
    ret = ni_readprop(domain, dir, where, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* if the property contains any values, leave it alone */
    if (nl.ni_namelist_len > 0) {
        ni_namelist_free(&nl);
        return NI_OK;
    }

    /* property is empty, delete it */
    ni_namelist_free(&nl);
    return ni_destroyprop(domain, dir, where);
}
示例#11
0
文件: nilib2.c 项目: 9crk/EasyDarwin
void nipl_createprop(ni_proplist *l, const ni_name n)
{
    /* property list utility */
    /* add a name property to a property list */

    ni_property p;

    NI_INIT(&p);
    p.nip_name = ni_name_dup(n);
    p.nip_val.ninl_len = 0;
    p.nip_val.ninl_val = NULL;
    ni_proplist_insert(l, p, NI_INDEX_NULL);
    ni_prop_free(&p);
}
示例#12
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_createdirprop(void *domain, ni_id *dir, const ni_name key, ni_namelist values)
{
    /* createprop given a directory rather than a pathname */

    ni_status ret;
    ni_property p;
    ni_namelist nl;
    ni_index where;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* check for existing property with this key */
    where = ni_namelist_match(nl, key);
    ni_namelist_free(&nl);

    /* if property doesn't exist, create it */
    if (where == NI_INDEX_NULL) {
        NI_INIT(&p);
        p.nip_name = ni_name_dup(key);
        p.nip_val = ni_namelist_dup(values);
        ret = ni_createprop(domain, dir, p, NI_INDEX_NULL);
        ni_prop_free(&p);
        return ret;
    }

    /* property exists: replace the existing values */
    ret = ni_writeprop(domain, dir, where, values);
    return ret;
}
示例#13
0
文件: netinfo.c 项目: aosm/bootp
void
ni_namelist_free(
	      ni_namelist *nl
	      )
{
	ni_index i;

	if (nl->ninl_val == NULL) {
		return;
	}
	for (i = 0; i < nl->ninl_len; i++) {
		ni_name_free(&nl->ninl_val[i]);
	}
	MM_FREE_ARRAY(nl->ninl_val, nl->ninl_len);
	NI_INIT(nl);
}
示例#14
0
文件: netinfo.c 项目: aosm/bootp
void
ni_proplist_free(
		 ni_proplist *pl
		 )
{
	ni_index i;

	if (pl->nipl_val == NULL) {
		return;
	}
	for (i = 0; i < pl->nipl_len; i++) {
		ni_prop_free(&pl->nipl_val[i]);
	}
	MM_FREE_ARRAY(pl->nipl_val, pl->nipl_len);
	NI_INIT(pl);
}
示例#15
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_destroydirprop(void *domain, ni_id *dir, ni_namelist keys)
{
    /* destroyprop given a directory rather than a pathname */

    ni_status ret;
    ni_index where;
    ni_namelist nl;
    int i;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* destroy all occurrences of each key */
    for (i = 0; i < keys.ni_namelist_len; i++) {

        where = ni_namelist_match(nl, keys.ni_namelist_val[i]);

        /* keep looking for all occurrences */
        while (where != NI_INDEX_NULL) {
            ret = ni_destroyprop(domain, dir, where);
            if (ret != NI_OK) {
                ni_namelist_free(&nl);
                return ret;
            }

            /* update the namelist */  
            ni_namelist_delete(&nl, where);
            where = ni_namelist_match(nl, keys.ni_namelist_val[i]);
        }
    }
    ni_namelist_free(&nl);
    return NI_OK;
}
示例#16
0
/*
 * Use ni_lookup to match key=value, 
 * Fetch matching subdirectories and append those that match the pattern to the list.
 */
static u_int32_t
NI_query_lookup(agent_private *ap, char *path, int single_item, u_int32_t where, dsrecord *pattern, dsrecord **list)
{
	ni_idlist idl;
	ni_proplist pl;
	ni_id dir;
	int dx, i, try_realname;
	ni_status status;
	dsrecord *r, *lastrec;
	char *key, *val;
	dsattribute *a;

	lastrec = NULL;

	a = dsattribute_retain(pattern->attribute[where]);
	key = dsdata_to_cstring(a->key);
	val = dsdata_to_cstring(a->value[0]);
	dsrecord_remove_attribute(pattern, a, SELECT_ATTRIBUTE);

	/*
	 * SPECIAL CASE For category user, key "name":
	 * if no matches for "name", try "realname".
	 */
	try_realname = 0;
	if ((!strcmp(path, "/users")) && (!strcmp(key, "name"))) try_realname = 1;

	for (dx = 0; dx < ap->domain_count; dx++)
	{
		NI_INIT(&dir);
		syslock_lock(rpcLock);
		status = sa_pathsearch(ap->domain[dx].handle, &dir, path);
		syslock_unlock(rpcLock);
		if (status != NI_OK) continue;

		NI_INIT(&idl);
		syslock_lock(rpcLock);

		status = sa_lookup(ap->domain[dx].handle, &dir, key, val, &idl);

		if ((idl.ni_idlist_len == 0) && (try_realname == 1))
		{
			status = sa_lookup(ap->domain[dx].handle, &dir, "realname", val, &idl);
		}

		syslock_unlock(rpcLock);
		if (status != NI_OK) continue;
		
		for (i = 0; i < idl.ni_idlist_len; i++)
		{
			dir.nii_object = idl.ni_idlist_val[i];
			dir.nii_instance = 0;

			NI_INIT(&pl);
			syslock_lock(rpcLock);
			status = sa_read(ap->domain[dx].handle, &dir, &pl);
			syslock_unlock(rpcLock);
			if (status != NI_OK) continue;

			r = nitods(&pl);
			NI_add_validation(ap, r, dx);
			ni_proplist_free(&pl);
			if (r == NULL) continue;

			if (dsrecord_match(r, pattern))
			{
				if (*list == NULL) *list = r;
				else lastrec->next = r;
				lastrec = r;

				if (single_item == 1)
				{
					ni_idlist_free(&idl);
					dsattribute_release(a);
					return 0;
				}

			}
			else
			{
				dsrecord_release(r);
			}
		}

		ni_idlist_free(&idl);
	}
	
	dsattribute_release(a);
	return 0;
}
示例#17
0
/*
 * Fetch all subdirectories and append those that match the pattern to the list.
 */
static u_int32_t
NI_query_all(agent_private *ap, char *path, int single_item, int stamp, dsrecord *pattern, dsrecord **list)
{
	ni_idlist idl;
	ni_proplist pl;
	ni_id dir;
	int dx, i;
	ni_status status;
	dsrecord *r, *lastrec;

	lastrec = NULL;

	for (dx = 0; dx < ap->domain_count; dx++)
	{
		if (stamp == 1)
		{
			r = dsrecord_new();
			NI_add_validation(ap, r, dx);
			if (*list == NULL) *list = r;
			else lastrec->next = r;
			lastrec = r;
			continue;
		}
	
		NI_INIT(&dir);
		syslock_lock(rpcLock);
		status = sa_pathsearch(ap->domain[dx].handle, &dir, path);
		syslock_unlock(rpcLock);
		if (status != NI_OK) continue;

		NI_INIT(&idl);
		syslock_lock(rpcLock);
		status = sa_children(ap->domain[dx].handle, &dir, &idl);
		syslock_unlock(rpcLock);
		if (status != NI_OK) continue;
		
		for (i = 0; i < idl.ni_idlist_len; i++)
		{
			dir.nii_object = idl.ni_idlist_val[i];
			dir.nii_instance = 0;

			NI_INIT(&pl);
			syslock_lock(rpcLock);
			status = sa_read(ap->domain[dx].handle, &dir, &pl);
			syslock_unlock(rpcLock);
			if (status != NI_OK) continue;

			r = nitods(&pl);
			NI_add_validation(ap, r, dx);
			ni_proplist_free(&pl);
			if (r == NULL) continue;

			if (dsrecord_match(r, pattern))
			{
				if (*list == NULL) *list = r;
				else lastrec->next = r;
				lastrec = r;

				if (single_item == 1)
				{
					ni_idlist_free(&idl);
					return 0;
				}

			}
			else
			{
				dsrecord_release(r);
			}
		}

		ni_idlist_free(&idl);
	}
	
	return 0;
}
boolean_t
PLCache_read(PLCache_t * cache, const char * filename)
{
    FILE *	file = NULL;
    int		line_number = 0;
    char	line[1024];
    ni_proplist	pl;
    enum { 
	nowhere_e,
	start_e, 
	body_e, 
	end_e 
    }		where = nowhere_e;

    NI_INIT(&pl);
    file = fopen(filename, "r");
    if (file == NULL) {
	perror(filename);
	goto failed;
    }

    while (1) {
	if (my_fgets(line, sizeof(line), file) != line) {
	    if (where == start_e || where == body_e) {
		fprintf(stderr, "file ends prematurely\n");
	    }
	    break;
	}
	line_number++;
	if (strcmp(line, "{\n") == 0) {
	    if (where != end_e && where != nowhere_e) {
		fprintf(stderr, "unexpected '{' at line %d\n", 
			line_number);
		goto failed;
	    }
	    where = start_e;
	}
	else if (strcmp(line, "}\n") == 0) {
	    if (where != start_e && where != body_e) {
		fprintf(stderr, "unexpected '}' at line %d\n", 
			line_number);
		goto failed;
	    }
	    if (pl.nipl_len > 0) {
		PLCache_append(cache, PLCacheEntry_create(pl));
		ni_proplist_free(&pl);
	    }
	    where = end_e;
	}
	else {
	    char	propname[128];
	    char	propval[768] = "";
	    int 	len = strlen(line);
	    char *	sep = strchr(line, '=');
	    int 	whitespace_len = strspn(line, " \t\n");

	    if (whitespace_len == len) {
		continue;
	    }
	    if (sep) {
		int nlen = (sep - line) - whitespace_len;
		int vlen = len - whitespace_len - nlen - 2;

		if (nlen >= sizeof(propname)) {
		    fprintf(stderr,
			    "property name truncated to %d bytes at line %d\n",
			    (int)sizeof(propname) - 1,
			    line_number);
		    nlen = sizeof(propname) - 1;
		}
		if (vlen >= sizeof(propval)) {
		    fprintf(stderr, 
			    "value truncated to %d bytes at line %d\n",
			    (int)sizeof(propval) - 1,
			    line_number);
		    vlen = sizeof(propval) - 1;
		}
		strncpy(propname, line + whitespace_len, nlen);
		propname[nlen] = '\0';
		strncpy(propval, sep + 1, vlen);
		propval[vlen] = '\0';
		ni_proplist_insertprop(&pl, propname, propval, NI_INDEX_NULL);
	    }
	    else {
		int nlen = len - whitespace_len - 1;

		if (nlen >= sizeof(propname)) {
		    fprintf(stderr,
			    "property name truncated to %d bytes at line %d\n",
			    (int)sizeof(propname) - 1,
			    line_number);
		    nlen = sizeof(propname) - 1;
		}
		strncpy(propname, line + whitespace_len, nlen);
		propname[nlen] = '\0';
		ni_proplist_insertprop(&pl, propname, NULL, NI_INDEX_NULL);
	    }
	    where = body_e;
	}
    }

 failed:
    if (file)
	fclose(file);
    ni_proplist_free(&pl);
    return (TRUE);
}
示例#19
0
文件: nilib2.c 项目: 9crk/EasyDarwin
ni_status ni2_createchild(void *domain, ni_id *dir, const ni_name dirname)
{
    /* make a child directory with the given name */

    ni_status ret;
    ni_proplist p;
    ni_id child;
    int i, j, k, len;
    char *key = NULL;
    char *value = NULL;

    /* if the name contains "=", then we've got "foo=bar" */
    /* property key is "foo", not "name" */

    len = 0;
    for (i = 0; dirname[i] != '\0' && dirname[i] != '='; i++);
    if (dirname[i] == '=') len = i;

    if (len > 0) {
        key = malloc(len + 1);
        /* check for backslashes in property key */
        for (i = 0, j = 0; i < len; i++, j++) {
            if (dirname[i] == '\\' && dirname[i+1] == '/') i++;
            key[j] = dirname[i];
        }
        key[j] = '\0';
        i = len + 1;
    }
    else {
        key = malloc(5);
        strcpy(key, "name");
        i = 0;
    }

    /* compress out backslashes in value */
    j = strlen(dirname);
    len = j - i;
    value = malloc(len + 1);
    for (k = 0; i < j; k++, i++) {
        if (dirname[i] == '\\' && dirname[i+1] == '/') i++;
        value[k] = dirname[i];
    }
    value[k] = '\0';
        
    /* set up the new directory */
    NI_INIT(&p);
    nipl_createprop(&p, key);
    nipl_appendprop(&p, key, value);

    /* create it */
    ret = ni_create(domain, dir, p, &child, NI_INDEX_NULL);
    if (ret != NI_OK) {
        ni_proplist_free(&p);
        return ret;
    }

    ni_proplist_free(&p);
    free(key);
    free(value);
    *dir = child;
    return NI_OK;
}