[BACK]Return to dkstats.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / vmstat

Annotation of src/usr.bin/vmstat/dkstats.c, Revision 1.23

1.23    ! millert     1: /*     $OpenBSD: dkstats.c,v 1.22 2002/12/16 01:57:04 tdeval Exp $     */
1.2       deraadt     2: /*     $NetBSD: dkstats.c,v 1.1 1996/05/10 23:19:27 thorpej Exp $      */
1.1       tholo       3:
                      4: /*
1.2       deraadt     5:  * Copyright (c) 1996 John M. Vinopal
1.1       tholo       6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *      This product includes software developed for the NetBSD Project
                     19:  *      by John M. Vinopal.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     28:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     29:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     30:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     31:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
1.10      angelos    36: #include <sys/param.h>
1.1       tholo      37: #include <sys/dkstat.h>
                     38: #include <sys/time.h>
                     39: #include <sys/disk.h>
1.10      angelos    40: #include <sys/sysctl.h>
                     41: #include <sys/tty.h>
1.1       tholo      42:
                     43: #include <err.h>
                     44: #include <fcntl.h>
                     45: #include <kvm.h>
                     46: #include <limits.h>
                     47: #include <nlist.h>
                     48: #include <stdio.h>
                     49: #include <stdlib.h>
                     50: #include <string.h>
                     51: #include <unistd.h>
                     52: #include "dkstats.h"
                     53:
1.16      deraadt    54: #if !defined(NOKVM)
1.1       tholo      55: static struct nlist namelist[] = {
1.18      deraadt    56: #define        X_TK_NIN        0               /* sysctl */
                     57:        { "_tk_nin" },
                     58: #define        X_TK_NOUT       1               /* sysctl */
                     59:        { "_tk_nout" },
                     60: #define        X_CP_TIME       2               /* sysctl */
                     61:        { "_cp_time" },
                     62: #define        X_HZ            3               /* sysctl */
                     63:        { "_hz" },
                     64: #define        X_STATHZ        4               /* sysctl */
1.1       tholo      65:        { "_stathz" },
1.18      deraadt    66: #define X_DISK_COUNT   5               /* sysctl */
                     67:        { "_disk_count" },
                     68: #define X_DISKLIST     6               /* sysctl */
                     69:        { "_disklist" },
1.1       tholo      70:        { NULL },
                     71: };
1.16      deraadt    72: #define        KVM_ERROR(_string) {                                            \
                     73:        warnx("%s", (_string));                                         \
                     74:        errx(1, "%s", kvm_geterr(kd));                                  \
                     75: }
                     76:
                     77: /*
                     78:  * Dereference the namelist pointer `v' and fill in the local copy
                     79:  * 'p' which is of size 's'.
                     80:  */
                     81: #define deref_nl(v, p, s) deref_kptr((void *)namelist[(v)].n_value, (p), (s));
                     82: static void deref_kptr(void *, void *, size_t);
                     83: #endif /* !defined(NOKVM) */
1.1       tholo      84:
                     85: /* Structures to hold the statistics. */
                     86: struct _disk   cur, last;
                     87:
                     88: /* Kernel pointers: nlistf and memf defined in calling program. */
1.19      deraadt    89: #if !defined(NOKVM)
1.20      deraadt    90: extern kvm_t   *kd;
1.19      deraadt    91: #endif
1.1       tholo      92: extern char    *nlistf;
                     93: extern char    *memf;
                     94:
1.19      deraadt    95: #if !defined(NOKVM)
1.1       tholo      96: /* Pointer to list of disks. */
                     97: static struct disk     *dk_drivehead = NULL;
1.19      deraadt    98: #endif
1.1       tholo      99:
                    100: /* Backward compatibility references. */
                    101: int            dk_ndrive = 0;
                    102: int            *dk_select;
                    103: char           **dr_name;
                    104:
                    105: /* Missing from <sys/time.h> */
1.16      deraadt   106: #define timerset(tvp, uvp) \
                    107:        ((uvp)->tv_sec = (tvp)->tv_sec);                \
                    108:        ((uvp)->tv_usec = (tvp)->tv_usec)
                    109:
                    110: #define SWAP(fld)      tmp = cur.fld;                          \
                    111:                        cur.fld -= last.fld;                    \
                    112:                        last.fld = tmp
1.1       tholo     113:
                    114: /*
                    115:  * Take the delta between the present values and the last recorded
                    116:  * values, storing the present values in the 'last' structure, and
                    117:  * the delta values in the 'cur' structure.
                    118:  */
                    119: void
1.21      deraadt   120: dkswap(void)
1.1       tholo     121: {
                    122:        u_int64_t tmp;
                    123:        int     i;
                    124:
1.22      tdeval    125:        for (i = 0; i < cur.dk_ndrive; i++) {
1.1       tholo     126:                struct timeval  tmp_timer;
                    127:
                    128:                if (!cur.dk_select[i])
                    129:                        continue;
                    130:
                    131:                /* Delta Values. */
                    132:                SWAP(dk_xfer[i]);
                    133:                SWAP(dk_seek[i]);
                    134:                SWAP(dk_bytes[i]);
                    135:
                    136:                /* Delta Time. */
                    137:                timerclear(&tmp_timer);
                    138:                timerset(&(cur.dk_time[i]), &tmp_timer);
                    139:                timersub(&tmp_timer, &(last.dk_time[i]), &(cur.dk_time[i]));
                    140:                timerclear(&(last.dk_time[i]));
                    141:                timerset(&tmp_timer, &(last.dk_time[i]));
                    142:        }
                    143:        for (i = 0; i < CPUSTATES; i++) {
                    144:                SWAP(cp_time[i]);
                    145:        }
                    146:        SWAP(tk_nin);
                    147:        SWAP(tk_nout);
                    148:
                    149: #undef SWAP
                    150: }
                    151:
                    152: /*
                    153:  * Read the disk statistics for each disk in the disk list.
                    154:  * Also collect statistics for tty i/o and cpu ticks.
                    155:  */
                    156: void
1.21      deraadt   157: dkreadstats(void)
1.1       tholo     158: {
1.19      deraadt   159: #if !defined(NOKVM)
1.1       tholo     160:        struct disk     cur_disk, *p;
1.19      deraadt   161: #endif
1.22      tdeval    162:        int             i, j, mib[3];
1.10      angelos   163:        size_t          size;
1.22      tdeval    164:        char            *disknames, *name, *bufpp, **dk_name;
1.13      angelos   165:        struct diskstats *q;
1.1       tholo     166:
1.22      tdeval    167:        last.dk_ndrive = cur.dk_ndrive;
                    168:
1.10      angelos   169:        if (nlistf == NULL && memf == NULL) {
1.22      tdeval    170:                /* Get the number of attached drives. */
                    171:                mib[0] = CTL_HW;
                    172:                mib[1] = HW_DISKCOUNT;
                    173:                size = sizeof(dk_ndrive);
                    174:                if (sysctl(mib, 2, &dk_ndrive, &size, NULL, 0) < 0 ) {
                    175:                        warn("could not read hw.diskcount");
                    176:                        dk_ndrive = 0;
                    177:                }
                    178:
                    179:                if (cur.dk_ndrive != dk_ndrive) {
                    180:                        /* Re-read the disk names. */
                    181:                        dk_name = calloc(dk_ndrive, sizeof(char *));
                    182:                        if (dk_name == NULL)
                    183:                                err(1, NULL);
                    184:                        mib[0] = CTL_HW;
                    185:                        mib[1] = HW_DISKNAMES;
                    186:                        size = 0;
                    187:                        if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0)
                    188:                                err(1, "can't get hw.disknames");
                    189:                        disknames = malloc(size);
                    190:                        if (disknames == NULL)
                    191:                                err(1, NULL);
                    192:                        if (sysctl(mib, 2, disknames, &size, NULL, 0) < 0)
                    193:                                err(1, "can't get hw.disknames");
                    194:                        bufpp = disknames;
1.23    ! millert   195:                        for (i = 0; i < dk_ndrive && (name = strsep(&bufpp, ",")) != NULL; i++)
        !           196:                                dk_name[i] = name;
1.22      tdeval    197:                        disknames = cur.dk_name[0];     /* To free old names. */
                    198:
                    199:                        if (dk_ndrive < cur.dk_ndrive) {
                    200:                                for (i = 0, j = 0; i < dk_ndrive; i++, j++) {
                    201:                                        while (j < cur.dk_ndrive &&
                    202:                                            strcmp(cur.dk_name[j], dk_name[i]))
                    203:                                                j++;
                    204:                                        if (i == j) continue;
                    205:
                    206:                                        if (j >= cur.dk_ndrive) {
                    207:                                                cur.dk_select[i] = 1;
                    208:                                                last.dk_xfer[i] = 0;
                    209:                                                last.dk_seek[i] = 0;
                    210:                                                last.dk_bytes[i] = 0;
                    211:                                                bzero(&last.dk_time[i],
                    212:                                                    sizeof(struct timeval));
                    213:                                                continue;
                    214:                                        }
                    215:
                    216:                                        cur.dk_select[i] = cur.dk_select[j];
                    217:                                        last.dk_xfer[i] = last.dk_xfer[j];
                    218:                                        last.dk_seek[i] = last.dk_seek[j];
                    219:                                        last.dk_bytes[i] = last.dk_bytes[j];
                    220:                                        last.dk_time[i] = last.dk_time[j];
                    221:                                }
                    222:
                    223:                                cur.dk_select = realloc(cur.dk_select,
                    224:                                    dk_ndrive * sizeof(*cur.dk_select));
                    225:                                cur.dk_xfer = realloc(cur.dk_xfer,
                    226:                                    dk_ndrive * sizeof(*cur.dk_xfer));
                    227:                                cur.dk_seek = realloc(cur.dk_seek,
                    228:                                    dk_ndrive * sizeof(*cur.dk_seek));
                    229:                                cur.dk_bytes = realloc(cur.dk_bytes,
                    230:                                    dk_ndrive * sizeof(*cur.dk_bytes));
                    231:                                cur.dk_time = realloc(cur.dk_time,
                    232:                                    dk_ndrive * sizeof(*cur.dk_time));
                    233:                                last.dk_xfer = realloc(last.dk_xfer,
                    234:                                    dk_ndrive * sizeof(*last.dk_xfer));
                    235:                                last.dk_seek = realloc(last.dk_seek,
                    236:                                    dk_ndrive * sizeof(*last.dk_seek));
                    237:                                last.dk_bytes = realloc(last.dk_bytes,
                    238:                                    dk_ndrive * sizeof(*last.dk_bytes));
                    239:                                last.dk_time = realloc(last.dk_time,
                    240:                                    dk_ndrive * sizeof(*last.dk_time));
                    241:                        } else {
                    242:                                cur.dk_select = realloc(cur.dk_select,
                    243:                                    dk_ndrive * sizeof(*cur.dk_select));
                    244:                                cur.dk_xfer = realloc(cur.dk_xfer,
                    245:                                    dk_ndrive * sizeof(*cur.dk_xfer));
                    246:                                cur.dk_seek = realloc(cur.dk_seek,
                    247:                                    dk_ndrive * sizeof(*cur.dk_seek));
                    248:                                cur.dk_bytes = realloc(cur.dk_bytes,
                    249:                                    dk_ndrive * sizeof(*cur.dk_bytes));
                    250:                                cur.dk_time = realloc(cur.dk_time,
                    251:                                    dk_ndrive * sizeof(*cur.dk_time));
                    252:                                last.dk_xfer = realloc(last.dk_xfer,
                    253:                                    dk_ndrive * sizeof(*last.dk_xfer));
                    254:                                last.dk_seek = realloc(last.dk_seek,
                    255:                                    dk_ndrive * sizeof(*last.dk_seek));
                    256:                                last.dk_bytes = realloc(last.dk_bytes,
                    257:                                    dk_ndrive * sizeof(*last.dk_bytes));
                    258:                                last.dk_time = realloc(last.dk_time,
                    259:                                    dk_ndrive * sizeof(*last.dk_time));
                    260:
                    261:                                for (i = dk_ndrive - 1, j = cur.dk_ndrive - 1;
                    262:                                     i >= 0; i--) {
                    263:
                    264:                                        if (j < 0 ||
                    265:                                            strcmp(cur.dk_name[j], dk_name[i]))
                    266:                                        {
                    267:                                                cur.dk_select[i] = 1;
                    268:                                                last.dk_xfer[i] = 0;
                    269:                                                last.dk_seek[i] = 0;
                    270:                                                last.dk_bytes[i] = 0;
                    271:                                                bzero(&last.dk_time[i],
                    272:                                                    sizeof(struct timeval));
                    273:                                                continue;
                    274:                                        }
                    275:
                    276:                                        if (i > j) {
                    277:                                                cur.dk_select[i] =
                    278:                                                    cur.dk_select[j];
                    279:                                                last.dk_xfer[i] =
                    280:                                                    last.dk_xfer[j];
                    281:                                                last.dk_seek[i] =
                    282:                                                    last.dk_seek[j];
                    283:                                                last.dk_bytes[i] =
                    284:                                                    last.dk_bytes[j];
                    285:                                                last.dk_time[i] =
                    286:                                                    last.dk_time[j];
                    287:                                        }
                    288:                                        j--;
                    289:                                }
                    290:                        }
                    291:
                    292:                        cur.dk_ndrive = dk_ndrive;
                    293:                        free(disknames);
                    294:                        cur.dk_name = dk_name;
                    295:                        dr_name = cur.dk_name;
                    296:                        dk_select = cur.dk_select;
                    297:                }
                    298:
                    299:                size = cur.dk_ndrive * sizeof(struct diskstats);
1.10      angelos   300:                mib[0] = CTL_HW;
                    301:                mib[1] = HW_DISKSTATS;
1.13      angelos   302:                q = malloc(size);
                    303:                if (q == NULL)
1.10      angelos   304:                        err(1, NULL);
1.13      angelos   305:                if (sysctl(mib, 2, q, &size, NULL, 0) < 0) {
1.22      tdeval    306: #ifdef DEBUG
1.10      angelos   307:                        warn("could not read hw.diskstats");
1.22      tdeval    308: #endif /* DEBUG */
                    309:                        bzero(q, cur.dk_ndrive * sizeof(struct diskstats));
1.10      angelos   310:                }
                    311:
1.22      tdeval    312:                for (i = 0; i < cur.dk_ndrive; i++)     {
1.13      angelos   313:                        cur.dk_xfer[i] = q[i].ds_xfer;
                    314:                        cur.dk_seek[i] = q[i].ds_seek;
                    315:                        cur.dk_bytes[i] = q[i].ds_bytes;
                    316:                        timerset(&(q[i].ds_time), &(cur.dk_time[i]));
1.10      angelos   317:                }
1.14      deraadt   318:                free(q);
1.10      angelos   319:
                    320:                size = sizeof(cur.cp_time);
                    321:                mib[0] = CTL_KERN;
                    322:                mib[1] = KERN_CPTIME;
                    323:                if (sysctl(mib, 2, cur.cp_time, &size, NULL, 0) < 0) {
1.11      angelos   324:                        warn("could not read kern.cp_time");
1.10      angelos   325:                        bzero(cur.cp_time, sizeof(cur.cp_time));
                    326:                }
                    327:                size = sizeof(cur.tk_nin);
                    328:                mib[0] = CTL_KERN;
                    329:                mib[1] = KERN_TTY;
                    330:                mib[2] = KERN_TTY_TKNIN;
                    331:                if (sysctl(mib, 3, &cur.tk_nin, &size, NULL, 0) < 0) {
1.11      angelos   332:                        warn("could not read kern.tty.tk_nin");
1.10      angelos   333:                        cur.tk_nin = 0;
                    334:                }
                    335:                size = sizeof(cur.tk_nin);
                    336:                mib[0] = CTL_KERN;
                    337:                mib[1] = KERN_TTY;
                    338:                mib[2] = KERN_TTY_TKNOUT;
                    339:                if (sysctl(mib, 3, &cur.tk_nout, &size, NULL, 0) < 0) {
1.11      angelos   340:                        warn("could not read kern.tty.tk_nout");
1.10      angelos   341:                        cur.tk_nout = 0;
                    342:                }
                    343:        } else {
1.16      deraadt   344: #if !defined(NOKVM)
1.10      angelos   345:                p = dk_drivehead;
                    346:
1.22      tdeval    347:                for (i = 0; i < cur.dk_ndrive; i++) {
1.10      angelos   348:                        deref_kptr(p, &cur_disk, sizeof(cur_disk));
                    349:                        cur.dk_xfer[i] = cur_disk.dk_xfer;
                    350:                        cur.dk_seek[i] = cur_disk.dk_seek;
                    351:                        cur.dk_bytes[i] = cur_disk.dk_bytes;
                    352:                        timerset(&(cur_disk.dk_time), &(cur.dk_time[i]));
                    353:                        p = cur_disk.dk_link.tqe_next;
                    354:                }
                    355:                deref_nl(X_CP_TIME, cur.cp_time, sizeof(cur.cp_time));
                    356:                deref_nl(X_TK_NIN, &cur.tk_nin, sizeof(cur.tk_nin));
                    357:                deref_nl(X_TK_NOUT, &cur.tk_nout, sizeof(cur.tk_nout));
1.16      deraadt   358: #endif /* !defined(NOKVM) */
1.1       tholo     359:        }
                    360: }
                    361:
                    362: /*
                    363:  * Perform all of the initialization and memory allocation needed to
                    364:  * track disk statistics.
                    365:  */
                    366: int
1.21      deraadt   367: dkinit(int select)
1.1       tholo     368: {
1.19      deraadt   369: #if !defined(NOKVM)
1.1       tholo     370:        struct disklist_head disk_head;
                    371:        struct disk     cur_disk, *p;
                    372:         char           errbuf[_POSIX2_LINE_MAX];
1.19      deraadt   373: #endif
1.1       tholo     374:        static int      once = 0;
                    375:        extern int      hz;
1.10      angelos   376:        int             i, mib[2];
                    377:        size_t          size;
                    378:        struct clockinfo clkinfo;
                    379:        char            *disknames, *name, *bufpp;
1.1       tholo     380:
                    381:        if (once)
                    382:                return(1);
                    383:
1.10      angelos   384:        if (nlistf != NULL || memf != NULL) {
1.16      deraadt   385: #if !defined(NOKVM)
1.20      deraadt   386:                if (memf != NULL) {
                    387:                        setegid(getgid());
                    388:                        setgid(getgid());
                    389:                }
                    390:
1.10      angelos   391:                /* Open the kernel. */
1.20      deraadt   392:                if (kd == NULL &&
                    393:                    (kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY,
1.10      angelos   394:                    errbuf)) == NULL)
                    395:                        errx(1, "kvm_openfiles: %s", errbuf);
1.20      deraadt   396:
                    397:                setegid(getgid());
                    398:                setgid(getgid());
1.10      angelos   399:
                    400:                /* Obtain the namelist symbols from the kernel. */
                    401:                if (kvm_nlist(kd, namelist))
                    402:                        KVM_ERROR("kvm_nlist failed to read symbols.");
                    403:
                    404:                /* Get the number of attached drives. */
1.22      tdeval    405:                deref_nl(X_DISK_COUNT, &cur.dk_ndrive, sizeof(cur.dk_ndrive));
1.10      angelos   406:
1.22      tdeval    407:                if (cur.dk_ndrive < 0)
                    408:                        errx(1, "invalid _disk_count %d.", cur.dk_ndrive);
1.10      angelos   409:
1.1       tholo     410:                /* Get a pointer to the first disk. */
                    411:                deref_nl(X_DISKLIST, &disk_head, sizeof(disk_head));
                    412:                dk_drivehead = disk_head.tqh_first;
1.10      angelos   413:
                    414:                /* Get ticks per second. */
                    415:                deref_nl(X_STATHZ, &hz, sizeof(hz));
                    416:                if (!hz)
                    417:                  deref_nl(X_HZ, &hz, sizeof(hz));
1.16      deraadt   418: #endif /* !defined(NOKVM) */
1.10      angelos   419:        } else {
                    420:                /* Get the number of attached drives. */
                    421:                mib[0] = CTL_HW;
                    422:                mib[1] = HW_DISKCOUNT;
1.22      tdeval    423:                size = sizeof(cur.dk_ndrive);
                    424:                if (sysctl(mib, 2, &cur.dk_ndrive, &size, NULL, 0) < 0 ) {
1.11      angelos   425:                        warn("could not read hw.diskcount");
1.22      tdeval    426:                        cur.dk_ndrive = 0;
1.10      angelos   427:                }
                    428:
                    429:                /* Get ticks per second. */
                    430:                mib[0] = CTL_KERN;
                    431:                mib[1] = KERN_CLOCKRATE;
                    432:                size = sizeof(clkinfo);
                    433:                if (sysctl(mib, 2, &clkinfo, &size, NULL, 0) < 0) {
1.11      angelos   434:                        warn("could not read kern.clockrate");
1.10      angelos   435:                        hz = 0;
                    436:                } else
                    437:                        hz = clkinfo.stathz;
1.1       tholo     438:        }
                    439:
                    440:        /* allocate space for the statistics */
1.22      tdeval    441:        cur.dk_time = calloc(cur.dk_ndrive, sizeof(struct timeval));
                    442:        cur.dk_xfer = calloc(cur.dk_ndrive, sizeof(u_int64_t));
                    443:        cur.dk_seek = calloc(cur.dk_ndrive, sizeof(u_int64_t));
                    444:        cur.dk_bytes = calloc(cur.dk_ndrive, sizeof(u_int64_t));
                    445:        last.dk_time = calloc(cur.dk_ndrive, sizeof(struct timeval));
                    446:        last.dk_xfer = calloc(cur.dk_ndrive, sizeof(u_int64_t));
                    447:        last.dk_seek = calloc(cur.dk_ndrive, sizeof(u_int64_t));
                    448:        last.dk_bytes = calloc(cur.dk_ndrive, sizeof(u_int64_t));
                    449:        cur.dk_select = calloc(cur.dk_ndrive, sizeof(int));
                    450:        cur.dk_name = calloc(cur.dk_ndrive, sizeof(char *));
1.1       tholo     451:
1.9       deraadt   452:        if (!cur.dk_time || !cur.dk_xfer || !cur.dk_seek || !cur.dk_bytes ||
                    453:            !last.dk_time || !last.dk_xfer || !last.dk_seek ||
                    454:            !last.dk_bytes || !cur.dk_select || !cur.dk_name)
1.1       tholo     455:                errx(1, "Memory allocation failure.");
                    456:
                    457:        /* Set up the compatibility interfaces. */
1.22      tdeval    458:        dk_ndrive = cur.dk_ndrive;
1.1       tholo     459:        dk_select = cur.dk_select;
                    460:        dr_name = cur.dk_name;
                    461:
1.22      tdeval    462:        /* Read the disk names and set initial selection. */
1.10      angelos   463:        if (nlistf == NULL && memf == NULL) {
                    464:                mib[0] = CTL_HW;
                    465:                mib[1] = HW_DISKNAMES;
                    466:                size = 0;
                    467:                if (sysctl(mib, 2, NULL, &size, NULL, 0) < 0)
                    468:                        err(1, "can't get hw.disknames");
1.12      angelos   469:                disknames = malloc(size);
1.10      angelos   470:                if (disknames == NULL)
                    471:                        err(1, NULL);
                    472:                if (sysctl(mib, 2, disknames, &size, NULL, 0) < 0)
                    473:                        err(1, "can't get hw.disknames");
                    474:                bufpp = disknames;
1.23    ! millert   475:                for (i = 0; i < dk_ndrive && (name = strsep(&bufpp, ",")) != NULL; i++) {
        !           476:                        cur.dk_name[i] = name;
        !           477:                        cur.dk_select[i] = select;
1.10      angelos   478:                }
                    479:        } else {
1.16      deraadt   480: #if !defined(NOKVM)
1.10      angelos   481:                p = dk_drivehead;
1.22      tdeval    482:                for (i = 0; i < cur.dk_ndrive; i++) {
1.10      angelos   483:                        char    buf[10];
1.16      deraadt   484:
1.10      angelos   485:                        deref_kptr(p, &cur_disk, sizeof(cur_disk));
                    486:                        deref_kptr(cur_disk.dk_name, buf, sizeof(buf));
                    487:                        cur.dk_name[i] = strdup(buf);
                    488:                        if (!cur.dk_name[i])
                    489:                                errx(1, "Memory allocation failure.");
                    490:                        cur.dk_select[i] = select;
1.1       tholo     491:
1.10      angelos   492:                        p = cur_disk.dk_link.tqe_next;
                    493:                }
1.16      deraadt   494: #endif /* !defined(NOKVM) */
1.1       tholo     495:        }
                    496:
                    497:        /* Never do this initalization again. */
                    498:        once = 1;
                    499:        return(1);
                    500: }
                    501:
1.16      deraadt   502: #if !defined(NOKVM)
1.1       tholo     503: /*
                    504:  * Dereference the kernel pointer `kptr' and fill in the local copy
                    505:  * pointed to by `ptr'.  The storage space must be pre-allocated,
                    506:  * and the size of the copy passed in `len'.
                    507:  */
                    508: static void
1.21      deraadt   509: deref_kptr(void *kptr, void *ptr, size_t len)
1.1       tholo     510: {
                    511:        char buf[128];
                    512:
1.6       art       513:        if (kvm_read(kd, (u_long)kptr, ptr, len) != len) {
1.1       tholo     514:                bzero(buf, sizeof(buf));
                    515:                snprintf(buf, (sizeof(buf) - 1),
1.2       deraadt   516:                     "can't dereference kptr 0x%lx", (u_long)kptr);
1.1       tholo     517:                KVM_ERROR(buf);
                    518:        }
                    519: }
1.17      drahn     520: #endif /* !defined(NOKVM) */