To aid in debugging problems with autopush, I've put together a
small program to dump out the autopush table (I still can't get
"autopush -g" to work and I'd be interested to know if anyone can.)
The advantage with this over "ifconfig -a modlist" is that it
should report unplumbed devices too :)
If it compiles without problem, it should "just work" if run as root.
cc dumpap.c -o dumpac -lkvm
gcc dumpap.c -o dumpac -lkvm
Darren
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/stream.h>
#define _KERNEL
#include <sys/sad.h>
#undef _KERNEL
#include <stdio.h>
#include <malloc.h>
#include <fcntl.h>
#include <kvm.h>
#include <nlist.h>
#include <string.h>
struct nlist names[] = {
{ "strpcache" },
{ "strpmask" },
{ "" }
};
struct majordevice {
char *name;
int major;
};
struct majordevice **majors;
void read_nametomajor(void);
void buildaplist(kvm_t *k, struct autopush **where);
void printap(struct autopush *a);
int
main(int argc, char *argv[])
{
struct autopush **base, **local, *a;
int apsize, i;
kvm_t *k;
read_nametomajor();
k = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0]);
if (k == NULL) {
perror("kvm_open");
exit(1);
}
if (kvm_nlist(k, names) == -1) {
fprintf(stderr, "kvm_nlist failed\n");
exit(1);
}
if (kvm_kread(k, names[0].n_value, &base, sizeof(base)) == -1) {
fprintf(stderr, "kvm_kread failed for strpcache\n");
exit(1);
}
if (kvm_kread(k, names[1].n_value, &apsize, sizeof(apsize)) == -1) {
fprintf(stderr, "kvm_kread failed for strpmsk\n");
exit(1);
}
local = calloc(apsize, sizeof(*local));
if (local == NULL) {
fprintf(stderr, "calloc failed for (%d,%u)\n",
apsize, sizeof(*local));
exit(1);
}
if (kvm_kread(k, (u_long)base, local, apsize * sizeof(*local)) == -1) {
fprintf(stderr, "kvm_kread failed to get strpcache\n");
exit(1);
}
for (i = 0; i < apsize; i++) {
if (local[i] == NULL)
continue;
buildaplist(k, local + i);
}
for (i = 0; i < apsize; i++) {
for (a = local[i]; a != NULL; a = a->ap_nextp)
printap(a);
}
exit(0);
}
void
buildaplist(kvm_t *k, struct autopush **where)
{
struct autopush *a, *n, **p;
for (p = where; (n = *p) != NULL; p = &a->ap_nextp) {
a = malloc(sizeof(*a));
if (a == NULL) {
fprintf(stderr, "malloc sizeof(%u) failed\n",
sizeof(*a));
break;
}
*p = a;
if (kvm_kread(k, (u_long)n, a, sizeof(*a)) == -1) {
fprintf(stderr, "kvm_kread n->a failed\n");
break;
}
}
*p = NULL;
}
void
printap(struct autopush *a)
{
int i;
if (a->ap_flags == APFREE)
return;
#if 0
switch (a->ap_common.apc_cmd)
{
case SAP_CLEAR :
printf("CLEAR");
break;
case SAP_ONE :
printf("ONE");
break;
case SAP_RANGE :
printf("RANGE");
break;
case SAP_ALL :
printf("ALL");
break;
default :
break;
}
#endif
printf("%s", majors[a->ap_common.apc_major]->name);
if (a->ap_common.apc_cmd == SAP_RANGE)
printf(" [%d-%d]", a->ap_common.apc_minor,
a->ap_common.apc_lastminor);
/* a->ap_common.apc_npush);*/
#if 0
printf("\tUse %d flags %x\n", a->ap_cnt, a->ap_flags);
#endif
putchar(':');
for (i = 0; i < a->ap_common.apc_npush; i++)
if (a->ap_list[i][0] != '\0')
printf(" %s", a->ap_list[i]);
else
printf(" ???");
putchar('\n');
}
void
read_nametomajor()
{
struct majordevice *maj, **all;
int ndevices, maxmajor, i;
char line[512], *s;
FILE *fp;
fp = fopen("/etc/name_to_major", "r");
if (fp == NULL)
return;
maxmajor = 0;
ndevices = 1;
all = malloc(sizeof(*all));
if (all == NULL)
return;
while (fgets(line, sizeof(line) - 1, fp) != NULL) {
s = strchr(line, '\n');
if (s != NULL)
*s = NULL;
else
continue;
s = strchr(line, ' ');
if (s == NULL)
continue;
*s++ = '\0';
if (!isdigit(*s))
continue;
maj = malloc(sizeof(*maj));
maj->name = strdup(line);
maj->major = atoi(s);
if (maj->major > maxmajor)
maxmajor = maj->major;
all[ndevices - 1] = maj;
ndevices++;
all = realloc(all, ndevices * sizeof(*all));
if (all == NULL)
return;
all[ndevices - 1] = NULL;
}
majors = calloc(maxmajor + 1, sizeof(*majors));
if (all == NULL)
return;
for (i = 0; i < ndevices; i++) {
maj = all[i];
if (maj == NULL)
continue;
majors[maj->major] = maj;
}
fclose(fp);
}