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; }
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; }
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; }
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); }
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); }
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); }
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; }
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; }
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; }
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); }
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); }
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; }
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); }
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); }
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; }
/* * 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; }
/* * 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); }
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; }