#include <config.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
#include <isc/util.h>
#include <dns/sdb.h>
#include <named/globals.h>
#include "dirdb.h"
static dns_sdbimplementation_t *dirdb = NULL;
#define CHECK(op) \
do { result = (op); \
if (result != ISC_R_SUCCESS) return (result); \
} while (0)
#define CHECKN(op) \
do { n = (op); \
if (n < 0) return (ISC_R_FAILURE); \
} while (0)
static isc_result_t
dirdb_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup)
{
char filename[255];
char filename2[255];
char buf[1024];
struct stat statbuf;
isc_result_t result;
int n;
UNUSED(zone);
UNUSED(dbdata);
if (strcmp(name, "@") == 0)
snprintf(filename, sizeof(filename), "%s", (char *)dbdata);
else
snprintf(filename, sizeof(filename), "%s/%s",
(char *)dbdata, name);
CHECKN(lstat(filename, &statbuf));
if (S_ISDIR(statbuf.st_mode))
CHECK(dns_sdb_putrr(lookup, "txt", 3600, "dir"));
else if (S_ISCHR(statbuf.st_mode) || S_ISBLK(statbuf.st_mode)) {
CHECKN(snprintf(buf, sizeof(buf),
"\"%sdev\" \"major %d\" \"minor %d\"",
S_ISCHR(statbuf.st_mode) ? "chr" : "blk",
major(statbuf.st_rdev),
minor(statbuf.st_rdev)));
CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
} else if (S_ISFIFO(statbuf.st_mode))
CHECK(dns_sdb_putrr(lookup, "txt", 3600, "pipe"));
else if (S_ISSOCK(statbuf.st_mode))
CHECK(dns_sdb_putrr(lookup, "txt", 3600, "socket"));
else if (S_ISLNK(statbuf.st_mode)) {
CHECKN(readlink(filename, filename2, sizeof(filename2) - 1));
buf[n] = 0;
CHECKN(snprintf(buf, sizeof(buf), "\"symlink\" \"%s\"",
filename2));
CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
} else if (!S_ISREG(statbuf.st_mode))
CHECK(dns_sdb_putrr(lookup, "txt", 3600, "unknown"));
else {
CHECKN(snprintf(buf, sizeof(buf), "\"file\" \"size = %u\"",
(unsigned int)statbuf.st_size));
CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
}
return (ISC_R_SUCCESS);
}
static isc_result_t
dirdb_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
isc_result_t result;
UNUSED(zone);
UNUSED(dbdata);
result = dns_sdb_putsoa(lookup, "ns", "hostmaster", 0);
INSIST(result == ISC_R_SUCCESS);
result = dns_sdb_putrr(lookup, "ns", 86400, "ns1");
INSIST(result == ISC_R_SUCCESS);
result = dns_sdb_putrr(lookup, "ns", 86400, "ns2");
INSIST(result == ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
}
static isc_result_t
dirdb_create(const char *zone, int argc, char **argv,
void *driverdata, void **dbdata)
{
UNUSED(zone);
UNUSED(driverdata);
if (argc < 1)
return (ISC_R_FAILURE);
*dbdata = isc_mem_strdup((isc_mem_t *)driverdata, argv[0]);
if (*dbdata == NULL)
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
}
static void
dirdb_destroy(const char *zone, void *driverdata, void **dbdata) {
UNUSED(zone);
UNUSED(driverdata);
isc_mem_free((isc_mem_t *)driverdata, *dbdata);
}
static dns_sdbmethods_t dirdb_methods = {
dirdb_lookup,
dirdb_authority,
NULL,
dirdb_create,
dirdb_destroy
};
isc_result_t
dirdb_init(void) {
unsigned int flags;
flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA |
DNS_SDBFLAG_THREADSAFE;
return (dns_sdb_register("dir", &dirdb_methods, ns_g_mctx, flags,
ns_g_mctx, &dirdb));
}
void
dirdb_clear(void) {
if (dirdb != NULL)
dns_sdb_unregister(&dirdb);
}