#include <stdio.h>
#include <string.h>
#include <NetInfo/dsutil.h>
#include <NetInfo/dsengine.h>
#include <NetInfo/syslock.h>
#include <NetInfo/system_log.h>
#include <NetInfo/DynaAPI.h>
#define DEFAULT_STORE_DIR "/var/db/sysinfo"
typedef struct
{
dsengine *engine;
syslock *threadLock;
dynainfo *dyna;
} agent_private;
static char *pathForCategory[] =
{
"/users",
"/groups",
"/machines",
"/networks",
"/services",
"/protocols",
"/rpcs",
"/mounts",
"/printers",
"/machines",
"/machines",
"/aliases",
"/netdomains",
NULL,
NULL,
NULL,
NULL
};
static dsengine *
SI_open(char *store)
{
dsstatus status;
char *path;
int flags;
dsengine *engine;
path = NULL;
if (store[0] == '/')
{
path = copyString(store);
}
else
{
path = malloc(strlen(DEFAULT_STORE_DIR) + strlen(store) + 2);
sprintf(path, "%s/%s", DEFAULT_STORE_DIR, store);
}
flags = 0;
flags |= DSSTORE_FLAGS_ACCESS_READONLY;
flags |= DSENGINE_FLAGS_NETINFO_NAMING;
status = dsengine_open(&engine, path, flags);
if (status != DSStatusOK)
{
system_log(LOG_ERR, "SysInfo open datastore %s failed: %s", path, dsstatus_message(status));
free(path);
return NULL;
}
free(path);
return engine;
}
u_int32_t
SI_new(void **c, char *args, dynainfo *d)
{
agent_private *ap;
if (c == NULL) return 1;
ap = (agent_private *)malloc(sizeof(agent_private));
*c = ap;
if (args == NULL) ap->engine = SI_open("local");
else ap->engine = SI_open(args);
if (ap->engine == NULL)
{
free(ap);
*c = NULL;
return 1;
}
ap->threadLock = syslock_new(0);
ap->dyna = d;
system_log(LOG_DEBUG, "Allocated SI 0x%08x\n", (int)ap);
return 0;
}
u_int32_t
SI_free(void *c)
{
agent_private *ap;
if (c == NULL) return 0;
ap = (agent_private *)c;
if (ap->engine != NULL) dsengine_close(ap->engine);
ap->engine = NULL;
syslock_free(ap->threadLock);
ap->threadLock = NULL;
system_log(LOG_DEBUG, "Deallocated SI 0x%08x\n", (int)ap);
free(ap);
c = NULL;
return 0;
}
static void
add_validation(dsrecord *r)
{
char str[64];
dsdata *d;
dsattribute *a;
if (r == NULL) return;
d = cstring_to_dsdata("lookup_validation");
dsrecord_remove_key(r, d, SELECT_META_ATTRIBUTE);
a = dsattribute_new(d);
dsrecord_append_attribute(r, a, SELECT_META_ATTRIBUTE);
dsdata_release(d);
sprintf(str, "%lu %lu %lu", (unsigned long)r->dsid, (unsigned long)r->serial, (unsigned long)r->vers);
d = cstring_to_dsdata(str);
dsattribute_append(a, d);
dsdata_release(d);
dsattribute_release(a);
}
u_int32_t
SI_query(void *c, dsrecord *pattern, dsrecord **list)
{
dsstatus status;
agent_private *ap;
char *path;
u_int32_t pdsid;
u_int32_t *match, count, i, cat;
dsattribute *a;
dsdata *k;
dsrecord **lp;
int single_item = 0;
if (c == NULL) return 1;
if (pattern == NULL) return 1;
if (list == NULL) return 1;
*list = NULL;
ap = (agent_private *)c;
k = cstring_to_dsdata(CATEGORY_KEY);
a = dsrecord_attribute(pattern, k, SELECT_META_ATTRIBUTE);
dsdata_release(k);
if (a == NULL) return 1;
if (a->count == 0) return 1;
dsrecord_remove_attribute(pattern, a, SELECT_META_ATTRIBUTE);
cat = atoi(dsdata_to_cstring(a->value[0]));
dsattribute_release(a);
path = pathForCategory[cat];
if (path == NULL) return 1;
k = cstring_to_dsdata(SINGLE_KEY);
a = dsrecord_attribute(pattern, k, SELECT_META_ATTRIBUTE);
dsdata_release(k);
if (a != NULL)
{
dsrecord_remove_attribute(pattern, a, SELECT_META_ATTRIBUTE);
dsattribute_release(a);
single_item = 1;
}
status = dsengine_netinfo_string_pathmatch(ap->engine, 0, path, &pdsid);
if (status != DSStatusOK) return 1;
match = NULL;
count = 0;
status = dsengine_search_pattern(ap->engine, pdsid, pattern, 1, 1, &match, &count);
if (status != DSStatusOK) return 1;
if (match == NULL) return 0;
if (single_item == 1) count = 1;
status = dsengine_fetch_list(ap->engine, count, match, &lp);
free(match);
if (status != DSStatusOK) return 1;
if (lp == NULL) return 0;
*list = lp[0];
if (lp != NULL) add_validation(lp[0]);
for (i = 1; i < count; i++)
{
add_validation(lp[i]);
lp[i-1]->next = lp[i];
}
return 0;
}
u_int32_t
SI_validate(void *c, char *v)
{
agent_private *ap;
int n;
u_int32_t dsid, vers, serial;
u_int32_t evers, eserial, esuper;
dsstatus status;
if (c == NULL) return 0;
if (v == NULL) return 0;
ap = (agent_private *)c;
n = sscanf(v, "%u %u %u", &dsid, &serial, &vers);
if (n != 3) return 0;
status = dsengine_vital_statistics(ap->engine, dsid, &evers, &eserial, &esuper);
if (status != DSStatusOK) return 0;
if (evers != vers) return 0;
return 1;
}