~ubuntu-branches/ubuntu/gutsy/net-snmp/gutsy-security

« back to all changes in this revision

Viewing changes to agent/mibgroup/host/hr_disk.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Host Resources MIB - disk device group implementation - hr_disk.c
 
3
 *
 
4
 */
 
5
 
 
6
#include <net-snmp/net-snmp-config.h>
 
7
#include "host_res.h"
 
8
#include "hr_disk.h"
 
9
#if HAVE_STRING_H
 
10
#include <string.h>
 
11
#else
 
12
#include <strings.h>
 
13
#endif
 
14
 
 
15
#include <fcntl.h>
 
16
#if HAVE_UNISTD_H
 
17
#include <unistd.h>
 
18
#endif
 
19
#if HAVE_KVM_H
 
20
#include <kvm.h>
 
21
#endif
 
22
#if HAVE_DIRENT_H
 
23
#include <dirent.h>
 
24
#else
 
25
# define dirent direct
 
26
# if HAVE_SYS_NDIR_H
 
27
#  include <sys/ndir.h>
 
28
# endif
 
29
# if HAVE_SYS_DIR_H
 
30
#  include <sys/dir.h>
 
31
# endif
 
32
# if HAVE_NDIR_H
 
33
#  include <ndir.h>
 
34
# endif
 
35
#endif
 
36
#if HAVE_SYS_IOCTL_H
 
37
#include <sys/ioctl.h>
 
38
#endif
 
39
 
 
40
#if HAVE_SYS_DKIO_H
 
41
#include <sys/dkio.h>
 
42
#endif
 
43
#if HAVE_SYS_DISKIO_H           /* HP-UX only ? */
 
44
#include <sys/diskio.h>
 
45
#endif
 
46
#if HAVE_LINUX_HDREG_H
 
47
#include <linux/hdreg.h>
 
48
#endif
 
49
#if HAVE_SYS_DISKLABEL_H
 
50
#define DKTYPENAMES
 
51
#include <sys/disklabel.h>
 
52
#endif
 
53
#if TIME_WITH_SYS_TIME
 
54
# include <sys/time.h>
 
55
# include <time.h>
 
56
#else
 
57
# if HAVE_SYS_TIME_H
 
58
#  include <sys/time.h>
 
59
# else
 
60
#  include <time.h>
 
61
# endif
 
62
#endif
 
63
 
 
64
#if HAVE_LIMITS_H
 
65
#include <limits.h>
 
66
#endif
 
67
 
 
68
#ifdef linux
 
69
/*
 
70
 * define BLKGETSIZE from <linux/fs.h>:
 
71
 * Note: cannot include this file completely due to errors with redefinition
 
72
 * of structures (at least with older linux versions) --jsf
 
73
 */
 
74
#define BLKGETSIZE _IO(0x12,96) /* return device size */
 
75
#endif
 
76
 
 
77
#include <net-snmp/agent/agent_read_config.h>
 
78
#include <net-snmp/library/read_config.h>
 
79
 
 
80
#define HRD_MONOTONICALLY_INCREASING
 
81
 
 
82
        /*********************
 
83
         *
 
84
         *  Kernel & interface information,
 
85
         *   and internal forward declarations
 
86
         *
 
87
         *********************/
 
88
 
 
89
void            Init_HR_Disk(void);
 
90
int             Get_Next_HR_Disk(void);
 
91
int             Get_Next_HR_Disk_Partition(char *, size_t, int);
 
92
static void     Add_HR_Disk_entry(const char *, int, int, int, int,
 
93
                                  const char *, int, int);
 
94
static void     Save_HR_Disk_General(void);
 
95
static void     Save_HR_Disk_Specific(void);
 
96
static int      Query_Disk(int, const char *);
 
97
static int      Is_It_Writeable(void);
 
98
static int      What_Type_Disk(void);
 
99
static int      Is_It_Removeable(void);
 
100
static const char *describe_disk(int);
 
101
 
 
102
int             header_hrdisk(struct variable *, oid *, size_t *, int,
 
103
                              size_t *, WriteMethod **);
 
104
 
 
105
static int      HRD_type_index;
 
106
static int      HRD_index;
 
107
static char     HRD_savedModel[40];
 
108
static long     HRD_savedCapacity = 1044;
 
109
static int      HRD_savedFlags;
 
110
static time_t   HRD_history[HRDEV_TYPE_MASK];
 
111
 
 
112
#ifdef DIOC_DESCRIBE
 
113
static disk_describe_type HRD_info;
 
114
static capacity_type HRD_cap;
 
115
 
 
116
static int      HRD_savedIntf_type;
 
117
static int      HRD_savedDev_type;
 
118
#endif
 
119
 
 
120
#ifdef DKIOCINFO
 
121
static struct dk_cinfo HRD_info;
 
122
static struct dk_geom HRD_cap;
 
123
 
 
124
static int      HRD_savedCtrl_type;
 
125
#endif
 
126
 
 
127
#ifdef HAVE_LINUX_HDREG_H
 
128
static struct hd_driveid HRD_info;
 
129
#endif
 
130
 
 
131
#ifdef DIOCGDINFO
 
132
static struct disklabel HRD_info;
 
133
#endif
 
134
 
 
135
static void     parse_disk_config(const char *, char *);
 
136
static void     free_disk_config(void);
 
137
 
 
138
        /*********************
 
139
         *
 
140
         *  Initialisation & common implementation functions
 
141
         *
 
142
         *********************/
 
143
 
 
144
#define HRDISK_ACCESS           1
 
145
#define HRDISK_MEDIA            2
 
146
#define HRDISK_REMOVEABLE       3
 
147
#define HRDISK_CAPACITY         4
 
148
 
 
149
struct variable4 hrdisk_variables[] = {
 
150
    {HRDISK_ACCESS, ASN_INTEGER, RONLY, var_hrdisk, 2, {1, 1}},
 
151
    {HRDISK_MEDIA, ASN_INTEGER, RONLY, var_hrdisk, 2, {1, 2}},
 
152
    {HRDISK_REMOVEABLE, ASN_INTEGER, RONLY, var_hrdisk, 2, {1, 3}},
 
153
    {HRDISK_CAPACITY, ASN_INTEGER, RONLY, var_hrdisk, 2, {1, 4}}
 
154
};
 
155
oid             hrdisk_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 3, 6 };
 
156
 
 
157
 
 
158
void
 
159
init_hr_disk(void)
 
160
{
 
161
    int             i;
 
162
 
 
163
    init_device[HRDEV_DISK] = Init_HR_Disk;
 
164
    next_device[HRDEV_DISK] = Get_Next_HR_Disk;
 
165
    save_device[HRDEV_DISK] = Save_HR_Disk_General;
 
166
#ifdef HRD_MONOTONICALLY_INCREASING
 
167
    dev_idx_inc[HRDEV_DISK] = 1;
 
168
#endif
 
169
 
 
170
#if defined(linux)
 
171
    Add_HR_Disk_entry("/dev/hd%c%d", -1, -1, 'a', 'l', "/dev/hd%c", 1, 15);
 
172
    Add_HR_Disk_entry("/dev/sd%c%d", -1, -1, 'a', 'p', "/dev/sd%c", 1, 15);
 
173
    Add_HR_Disk_entry("/dev/md%d", -1, -1, 0, 3, "/dev/md%d", 0, 0);
 
174
    Add_HR_Disk_entry("/dev/fd%d", -1, -1, 0, 1, "/dev/fd%d", 0, 0);
 
175
#elif defined(hpux)
 
176
#if defined(hpux10) || defined(hpux11)
 
177
    Add_HR_Disk_entry("/dev/rdsk/c%dt%xd%d", 0, 1, 0, 15,
 
178
                      "/dev/rdsk/c%dt%xd0", 0, 4);
 
179
#else                           /* hpux9 */
 
180
    Add_HR_Disk_entry("/dev/rdsk/c%dd%xs%d", 201, 201, 0, 15,
 
181
                      "/dev/rdsk/c%dd%xs0", 0, 4);
 
182
#endif
 
183
#elif defined(solaris2)
 
184
    Add_HR_Disk_entry("/dev/rdsk/c%dt%dd0s%d", 0, 1, 0, 15,
 
185
                      "/dev/rdsk/c%dt%dd0s0", 0, 7);
 
186
    Add_HR_Disk_entry("/dev/rdsk/c%dd%ds%d", 0, 1, 0, 15,
 
187
                      "/dev/rdsk/c%dd%ds0", 0, 7);
 
188
#elif defined(freebsd4) || defined(freebsd5)
 
189
    Add_HR_Disk_entry("/dev/ad%ds%d%c", 0, 1, 1, 4, "/dev/ad%ds%d", 'a', 'h');
 
190
    Add_HR_Disk_entry("/dev/da%ds%d%c", 0, 1, 1, 4, "/dev/da%ds%d", 'a', 'h');
 
191
#elif defined(freebsd3)
 
192
    Add_HR_Disk_entry("/dev/wd%ds%d%c", 0, 1, 1, 4, "/dev/wd%ds%d", 'a',
 
193
                      'h');
 
194
    Add_HR_Disk_entry("/dev/sd%ds%d%c", 0, 1, 1, 4, "/dev/sd%ds%d", 'a',
 
195
                      'h');
 
196
#elif defined(freebsd2)
 
197
    Add_HR_Disk_entry("/dev/wd%d%c", -1, -1, 0, 3, "/dev/wd%d", 'a', 'h');
 
198
    Add_HR_Disk_entry("/dev/sd%d%c", -1, -1, 0, 3, "/dev/sd%d", 'a', 'h');
 
199
#elif defined(netbsd1)
 
200
    Add_HR_Disk_entry("/dev/wd%d%c", -1, -1, 0, 3, "/dev/wd%dc", 'a', 'h');
 
201
    Add_HR_Disk_entry("/dev/sd%d%c", -1, -1, 0, 3, "/dev/sd%dc", 'a', 'h');
 
202
#endif
 
203
 
 
204
    device_descr[HRDEV_DISK] = describe_disk;
 
205
    HRD_savedModel[0] = '\0';
 
206
    HRD_savedCapacity = 0;
 
207
 
 
208
    for (i = 0; i < HRDEV_TYPE_MASK; ++i)
 
209
        HRD_history[i] = -1;
 
210
 
 
211
    REGISTER_MIB("host/hr_disk", hrdisk_variables, variable4,
 
212
                 hrdisk_variables_oid);
 
213
 
 
214
    snmpd_register_config_handler("ignoredisk", parse_disk_config,
 
215
                                  free_disk_config, "name");
 
216
}
 
217
 
 
218
#define ITEM_STRING     1
 
219
#define ITEM_SET        2
 
220
#define ITEM_STAR       3
 
221
#define ITEM_ANY        4
 
222
 
 
223
typedef unsigned char details_set[32];
 
224
 
 
225
typedef struct _conf_disk_item {
 
226
    int             item_type;  /* ITEM_STRING, ITEM_SET, ITEM_STAR, ITEM_ANY */
 
227
    void           *item_details;       /* content depends upon item_type */
 
228
    struct _conf_disk_item *item_next;
 
229
} conf_disk_item;
 
230
 
 
231
typedef struct _conf_disk_list {
 
232
    conf_disk_item *list_item;
 
233
    struct _conf_disk_list *list_next;
 
234
} conf_disk_list;
 
235
static conf_disk_list *conf_list;
 
236
 
 
237
static int      match_disk_config(const char *);
 
238
static int      match_disk_config_item(const char *, conf_disk_item *);
 
239
 
 
240
static void
 
241
parse_disk_config(const char *token, char *cptr)
 
242
{
 
243
    conf_disk_list *d_new;
 
244
    conf_disk_item *di_curr;
 
245
    details_set    *d_set;
 
246
    char           *name, *p, *d_str, c;
 
247
    unsigned int    i, neg, c1, c2;
 
248
 
 
249
    name = strtok(cptr, " \t");
 
250
    if (!name) {
 
251
        config_perror("Missing NAME parameter");
 
252
        return;
 
253
    }
 
254
    d_new = (conf_disk_list *) malloc(sizeof(conf_disk_list));
 
255
    if (!d_new) {
 
256
        config_perror("Out of memory");
 
257
        return;
 
258
    }
 
259
    di_curr = (conf_disk_item *) malloc(sizeof(conf_disk_item));
 
260
    if (!di_curr) {
 
261
        config_perror("Out of memory");
 
262
        return;
 
263
    }
 
264
    d_new->list_item = di_curr;
 
265
    for (;;) {
 
266
        if (*name == '?') {
 
267
            di_curr->item_type = ITEM_ANY;
 
268
            di_curr->item_details = (void *) 0;
 
269
            name++;
 
270
        } else if (*name == '*') {
 
271
            di_curr->item_type = ITEM_STAR;
 
272
            di_curr->item_details = (void *) 0;
 
273
            name++;
 
274
        } else if (*name == '[') {
 
275
            d_set = (details_set *) malloc(sizeof(details_set));
 
276
            if (!d_set) {
 
277
                config_perror("Out of memory");
 
278
                return;
 
279
            }
 
280
            for (i = 0; i < sizeof(details_set); i++)
 
281
                (*d_set)[i] = (unsigned char) 0;
 
282
            name++;
 
283
            if (*name == '^' || *name == '!') {
 
284
                neg = 1;
 
285
                name++;
 
286
            } else {
 
287
                neg = 0;
 
288
            }
 
289
            while (*name && *name != ']') {
 
290
                c1 = ((unsigned int) *name++) & 0xff;
 
291
                if (*name == '-' && *(name + 1) != ']') {
 
292
                    name++;
 
293
                    c2 = ((unsigned int) *name++) & 0xff;
 
294
                } else {
 
295
                    c2 = c1;
 
296
                }
 
297
                for (i = c1; i <= c2; i++)
 
298
                    (*d_set)[i / 8] |= (unsigned char) (1 << (i % 8));
 
299
            }
 
300
            if (*name != ']') {
 
301
                config_perror
 
302
                    ("Syntax error in NAME: invalid set specified");
 
303
                return;
 
304
            }
 
305
            if (neg) {
 
306
                for (i = 0; i < sizeof(details_set); i++)
 
307
                    (*d_set)[i] = (*d_set)[i] ^ (unsigned char) 0xff;
 
308
            }
 
309
            di_curr->item_type = ITEM_SET;
 
310
            di_curr->item_details = (void *) d_set;
 
311
            name++;
 
312
        } else {
 
313
            for (p = name;
 
314
                 *p != '\0' && *p != '?' && *p != '*' && *p != '['; p++);
 
315
            c = *p;
 
316
            *p = '\0';
 
317
            d_str = (char *) malloc(strlen(name) + 1);
 
318
            if (!d_str) {
 
319
                config_perror("Out of memory");
 
320
                return;
 
321
            }
 
322
            strcpy(d_str, name);
 
323
            *p = c;
 
324
            di_curr->item_type = ITEM_STRING;
 
325
            di_curr->item_details = (void *) d_str;
 
326
            name = p;
 
327
        }
 
328
        if (!*name) {
 
329
            di_curr->item_next = (conf_disk_item *) 0;
 
330
            break;
 
331
        }
 
332
        di_curr->item_next =
 
333
            (conf_disk_item *) malloc(sizeof(conf_disk_item));
 
334
        if (!di_curr->item_next) {
 
335
            config_perror("Out of memory");
 
336
            return;
 
337
        }
 
338
        di_curr = di_curr->item_next;
 
339
    }
 
340
    d_new->list_next = conf_list;
 
341
    conf_list = d_new;
 
342
}
 
343
 
 
344
static void
 
345
free_disk_config(void)
 
346
{
 
347
    conf_disk_list *d_ptr = conf_list, *d_next;
 
348
    conf_disk_item *di_ptr, *di_next;
 
349
 
 
350
    while (d_ptr) {
 
351
        d_next = d_ptr->list_next;
 
352
        di_ptr = d_ptr->list_item;
 
353
        while (di_ptr) {
 
354
            di_next = di_ptr->item_next;
 
355
            if (di_ptr->item_details)
 
356
                free(di_ptr->item_details);
 
357
            free((void *) di_ptr);
 
358
            di_ptr = di_next;
 
359
        }
 
360
        free((void *) d_ptr);
 
361
        d_ptr = d_next;
 
362
    }
 
363
    conf_list = (conf_disk_list *) 0;
 
364
}
 
365
 
 
366
static int
 
367
match_disk_config_item(const char *name, conf_disk_item * di_ptr)
 
368
{
 
369
    int             result = 0;
 
370
    size_t          len;
 
371
    details_set    *d_set;
 
372
    unsigned int    c;
 
373
 
 
374
    if (di_ptr) {
 
375
        switch (di_ptr->item_type) {
 
376
        case ITEM_STRING:
 
377
            len = strlen((const char *) di_ptr->item_details);
 
378
            if (!strncmp(name, (const char *) di_ptr->item_details, len))
 
379
                result = match_disk_config_item(name + len,
 
380
                                                di_ptr->item_next);
 
381
            break;
 
382
        case ITEM_SET:
 
383
            if (*name) {
 
384
                d_set = (details_set *) di_ptr->item_details;
 
385
                c = ((unsigned int) *name) & 0xff;
 
386
                if ((*d_set)[c / 8] & (unsigned char) (1 << (c % 8)))
 
387
                    result = match_disk_config_item(name + 1,
 
388
                                                    di_ptr->item_next);
 
389
            }
 
390
            break;
 
391
        case ITEM_STAR:
 
392
            if (di_ptr->item_next) {
 
393
                for (; !result && *name; name++)
 
394
                    result = match_disk_config_item(name,
 
395
                                                    di_ptr->item_next);
 
396
            } else {
 
397
                result = 1;
 
398
            }
 
399
            break;
 
400
        case ITEM_ANY:
 
401
            if (*name)
 
402
                result = match_disk_config_item(name + 1,
 
403
                                                di_ptr->item_next);
 
404
            break;
 
405
        }
 
406
    } else {
 
407
        if (*name == '\0')
 
408
            result = 1;
 
409
    }
 
410
 
 
411
    return result;
 
412
}
 
413
 
 
414
static int
 
415
match_disk_config(const char *name)
 
416
{
 
417
    conf_disk_list *d_ptr = conf_list;
 
418
 
 
419
    while (d_ptr) {
 
420
        if (match_disk_config_item(name, d_ptr->list_item))
 
421
            return 1;           /* match found in ignorelist */
 
422
        d_ptr = d_ptr->list_next;
 
423
    }
 
424
 
 
425
    /*
 
426
     * no match in ignorelist 
 
427
     */
 
428
    return 0;
 
429
}
 
430
 
 
431
/*
 
432
 * header_hrdisk(...
 
433
 * Arguments:
 
434
 * vp     IN      - pointer to variable entry that points here
 
435
 * name    IN/OUT  - IN/name requested, OUT/name found
 
436
 * length  IN/OUT  - length of IN/OUT oid's 
 
437
 * exact   IN      - TRUE if an exact match was requested
 
438
 * var_len OUT     - length of variable or 0 if function returned
 
439
 * write_method
 
440
 */
 
441
 
 
442
int
 
443
header_hrdisk(struct variable *vp,
 
444
              oid * name,
 
445
              size_t * length,
 
446
              int exact, size_t * var_len, WriteMethod ** write_method)
 
447
{
 
448
#define HRDISK_ENTRY_NAME_LENGTH        11
 
449
    oid             newname[MAX_OID_LEN];
 
450
    int             disk_idx, LowIndex = -1;
 
451
    int             result;
 
452
 
 
453
    DEBUGMSGTL(("host/hr_disk", "var_hrdisk: "));
 
454
    DEBUGMSGOID(("host/hr_disk", name, *length));
 
455
    DEBUGMSG(("host/hr_disk", " %d\n", exact));
 
456
 
 
457
    memcpy((char *) newname, (char *) vp->name,
 
458
           (int) vp->namelen * sizeof(oid));
 
459
    /*
 
460
     * Find "next" disk entry 
 
461
     */
 
462
 
 
463
    Init_HR_Disk();
 
464
    for (;;) {
 
465
        disk_idx = Get_Next_HR_Disk();
 
466
        if (disk_idx == -1)
 
467
            break;
 
468
        newname[HRDISK_ENTRY_NAME_LENGTH] = disk_idx;
 
469
        result =
 
470
            snmp_oid_compare(name, *length, newname,
 
471
                             (int) vp->namelen + 1);
 
472
        if (exact && (result == 0)) {
 
473
            LowIndex = disk_idx;
 
474
            Save_HR_Disk_Specific();
 
475
            break;
 
476
        }
 
477
        if ((!exact && (result < 0)) &&
 
478
            (LowIndex == -1 || disk_idx < LowIndex)) {
 
479
            LowIndex = disk_idx;
 
480
            Save_HR_Disk_Specific();
 
481
#ifdef HRD_MONOTONICALLY_INCREASING
 
482
            break;
 
483
#endif
 
484
        }
 
485
    }
 
486
 
 
487
    if (LowIndex == -1) {
 
488
        DEBUGMSGTL(("host/hr_disk", "... index out of range\n"));
 
489
        return (MATCH_FAILED);
 
490
    }
 
491
 
 
492
    newname[HRDISK_ENTRY_NAME_LENGTH] = LowIndex;
 
493
    memcpy((char *) name, (char *) newname,
 
494
           ((int) vp->namelen + 1) * sizeof(oid));
 
495
    *length = vp->namelen + 1;
 
496
    *write_method = 0;
 
497
    *var_len = sizeof(long);    /* default to 'long' results */
 
498
 
 
499
    DEBUGMSGTL(("host/hr_disk", "... get disk stats "));
 
500
    DEBUGMSGOID(("host/hr_disk", name, *length));
 
501
    DEBUGMSG(("host/hr_disk", "\n"));
 
502
 
 
503
    return LowIndex;
 
504
}
 
505
 
 
506
 
 
507
        /*********************
 
508
         *
 
509
         *  System specific implementation functions
 
510
         *
 
511
         *********************/
 
512
 
 
513
 
 
514
u_char         *
 
515
var_hrdisk(struct variable * vp,
 
516
           oid * name,
 
517
           size_t * length,
 
518
           int exact, size_t * var_len, WriteMethod ** write_method)
 
519
{
 
520
    int             disk_idx;
 
521
 
 
522
    disk_idx =
 
523
        header_hrdisk(vp, name, length, exact, var_len, write_method);
 
524
    if (disk_idx == MATCH_FAILED)
 
525
        return NULL;
 
526
 
 
527
 
 
528
    switch (vp->magic) {
 
529
    case HRDISK_ACCESS:
 
530
        long_return = Is_It_Writeable();
 
531
        return (u_char *) & long_return;
 
532
    case HRDISK_MEDIA:
 
533
        long_return = What_Type_Disk();
 
534
        return (u_char *) & long_return;
 
535
    case HRDISK_REMOVEABLE:
 
536
        long_return = Is_It_Removeable();
 
537
        return (u_char *) & long_return;
 
538
    case HRDISK_CAPACITY:
 
539
        long_return = HRD_savedCapacity;
 
540
        return (u_char *) & long_return;
 
541
    default:
 
542
        DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrdisk\n",
 
543
                    vp->magic));
 
544
    }
 
545
    return NULL;
 
546
}
 
547
 
 
548
 
 
549
        /*********************
 
550
         *
 
551
         *  Internal implementation functions
 
552
         *
 
553
         *********************/
 
554
 
 
555
#define MAX_NUMBER_DISK_TYPES   16      /* probably should be a variable */
 
556
#define MAX_DISKS_PER_TYPE      15      /* SCSI disks - not a hard limit */
 
557
#define HRDISK_TYPE_SHIFT       4       /* log2 (MAX_DISKS_PER_TYPE+1) */
 
558
 
 
559
typedef struct {
 
560
    const char     *disk_devpart_string;        /* printf() format disk part. name */
 
561
    short           disk_controller;    /* controller id or -1 if NA */
 
562
    short           disk_device_first;  /* first device id */
 
563
    short           disk_device_last;   /* last device id */
 
564
    const char     *disk_devfull_string;        /* printf() format full disk name */
 
565
    short           disk_partition_first;       /* first partition id */
 
566
    short           disk_partition_last;        /* last partition id */
 
567
} HRD_disk_t;
 
568
 
 
569
static HRD_disk_t disk_devices[MAX_NUMBER_DISK_TYPES];
 
570
static int      HR_number_disk_types = 0;
 
571
 
 
572
static void
 
573
Add_HR_Disk_entry(const char *devpart_string,
 
574
                  int first_ctl,
 
575
                  int last_ctl,
 
576
                  int first_dev,
 
577
                  int last_dev,
 
578
                  const char *devfull_string,
 
579
                  int first_partn, int last_partn)
 
580
{
 
581
    while (first_ctl <= last_ctl) {
 
582
        disk_devices[HR_number_disk_types].disk_devpart_string =
 
583
            devpart_string;
 
584
        disk_devices[HR_number_disk_types].disk_controller = first_ctl;
 
585
        disk_devices[HR_number_disk_types].disk_device_first = first_dev;
 
586
        disk_devices[HR_number_disk_types].disk_device_last = last_dev;
 
587
        disk_devices[HR_number_disk_types].disk_devfull_string =
 
588
            devfull_string;
 
589
        disk_devices[HR_number_disk_types].disk_partition_first =
 
590
            first_partn;
 
591
        disk_devices[HR_number_disk_types].disk_partition_last =
 
592
            last_partn;
 
593
 
 
594
        /*
 
595
         * Split long runs of disks into separate "types"
 
596
         */
 
597
        while (last_dev - first_dev > MAX_DISKS_PER_TYPE) {
 
598
            first_dev = first_dev + MAX_DISKS_PER_TYPE;
 
599
            disk_devices[HR_number_disk_types].disk_device_last =
 
600
                first_dev - 1;
 
601
            HR_number_disk_types++;
 
602
 
 
603
            disk_devices[HR_number_disk_types].disk_devpart_string =
 
604
                devpart_string;
 
605
            disk_devices[HR_number_disk_types].disk_controller = first_ctl;
 
606
            disk_devices[HR_number_disk_types].disk_device_first =
 
607
                first_dev;
 
608
            disk_devices[HR_number_disk_types].disk_device_last = last_dev;
 
609
            disk_devices[HR_number_disk_types].disk_devfull_string =
 
610
                devfull_string;
 
611
            disk_devices[HR_number_disk_types].disk_partition_first =
 
612
                first_partn;
 
613
            disk_devices[HR_number_disk_types].disk_partition_last =
 
614
                last_partn;
 
615
        }
 
616
 
 
617
        first_ctl++;
 
618
        HR_number_disk_types++;
 
619
    }
 
620
}
 
621
 
 
622
void
 
623
Init_HR_Disk(void)
 
624
{
 
625
    HRD_type_index = 0;
 
626
    HRD_index = -1;
 
627
    DEBUGMSGTL(("host/hr_disk", "Init_Disk\n"));
 
628
}
 
629
 
 
630
int
 
631
Get_Next_HR_Disk(void)
 
632
{
 
633
    char            string[1024];
 
634
    int             fd, result;
 
635
    int             iindex;
 
636
    int             max_disks;
 
637
    time_t          now;
 
638
 
 
639
    HRD_index++;
 
640
    (void *) time(&now);
 
641
    DEBUGMSGTL(("host/hr_disk", "Next_Disk type %d of %d\n",
 
642
                HRD_type_index, HR_number_disk_types));
 
643
    while (HRD_type_index < HR_number_disk_types) {
 
644
        max_disks = disk_devices[HRD_type_index].disk_device_last -
 
645
            disk_devices[HRD_type_index].disk_device_first + 1;
 
646
        DEBUGMSGTL(("host/hr_disk", "Next_Disk max %d of type %d\n",
 
647
                    max_disks, HRD_type_index));
 
648
 
 
649
        while (HRD_index < max_disks) {
 
650
            iindex = (HRD_type_index << HRDISK_TYPE_SHIFT) + HRD_index;
 
651
 
 
652
            /*
 
653
             * Check to see whether this device
 
654
             *   has been probed for 'recently'
 
655
             *   and skip if so.
 
656
             * This has a *major* impact on run
 
657
             *   times (by a factor of 10!)
 
658
             */
 
659
            if ((HRD_history[iindex] > 0) &&
 
660
                ((now - HRD_history[iindex]) < 60)) {
 
661
                HRD_index++;
 
662
                continue;
 
663
            }
 
664
 
 
665
            /*
 
666
             * Construct the full device name in "string" 
 
667
             */
 
668
            if (disk_devices[HRD_type_index].disk_controller != -1) {
 
669
                snprintf(string, sizeof(string),
 
670
                        disk_devices[HRD_type_index].disk_devfull_string,
 
671
                        disk_devices[HRD_type_index].disk_controller,
 
672
                        disk_devices[HRD_type_index].disk_device_first +
 
673
                        HRD_index);
 
674
            } else {
 
675
                snprintf(string, sizeof(string),
 
676
                        disk_devices[HRD_type_index].disk_devfull_string,
 
677
                        disk_devices[HRD_type_index].disk_device_first +
 
678
                        HRD_index);
 
679
            }
 
680
            string[ sizeof(string)-1 ] = 0;
 
681
 
 
682
            DEBUGMSGTL(("host/hr_disk", "Get_Next_HR_Disk: %s (%d/%d)\n",
 
683
                        string, HRD_type_index, HRD_index));
 
684
 
 
685
            if (HRD_history[iindex] == -1) {
 
686
                /*
 
687
                 * check whether this device is in the "ignoredisk" list in
 
688
                 * the config file. if yes this device will be marked as
 
689
                 * invalid for the future, i.e. it won't ever be checked
 
690
                 * again.
 
691
                 */
 
692
                if (match_disk_config(string)) {
 
693
                    /*
 
694
                     * device name matches entry in ignoredisk list 
 
695
                     */
 
696
                    DEBUGMSGTL(("host/hr_disk",
 
697
                                "Get_Next_HR_Disk: %s ignored\n", string));
 
698
                    HRD_history[iindex] = LONG_MAX;
 
699
                    HRD_index++;
 
700
                    continue;
 
701
                }
 
702
            }
 
703
 
 
704
            /*
 
705
             * use O_NDELAY to avoid CDROM spin-up and media detection
 
706
             * * (too slow) --okir 
 
707
             */
 
708
            /*
 
709
             * at least with HP-UX 11.0 this doesn't seem to work properly
 
710
             * * when accessing an empty CDROM device --jsf 
 
711
             */
 
712
#ifdef O_NDELAY                 /* I'm sure everything has it, but just in case...  --Wes */
 
713
            fd = open(string, O_RDONLY | O_NDELAY);
 
714
#else
 
715
            fd = open(string, O_RDONLY);
 
716
#endif
 
717
            if (fd != -1) {
 
718
                result = Query_Disk(fd, string);
 
719
                close(fd);
 
720
                if (result != -1) {
 
721
                    HRD_history[iindex] = 0;
 
722
                    return ((HRDEV_DISK << HRDEV_TYPE_SHIFT) + iindex);
 
723
                }
 
724
            }
 
725
            HRD_history[iindex] = now;
 
726
            HRD_index++;
 
727
        }
 
728
        HRD_type_index++;
 
729
        HRD_index = 0;
 
730
    }
 
731
    HRD_index = -1;
 
732
    return -1;
 
733
}
 
734
 
 
735
int
 
736
Get_Next_HR_Disk_Partition(char *string, size_t str_len, int HRP_index)
 
737
{
 
738
    DEBUGMSGTL(("host/hr_disk", "Next_Partition type %d/%d:%d\n",
 
739
                HRD_type_index, HRD_type_index, HRP_index));
 
740
 
 
741
    /*
 
742
     * no more partition names => return -1 
 
743
     */
 
744
    if (disk_devices[HRD_type_index].disk_partition_last -
 
745
        disk_devices[HRD_type_index].disk_partition_first + 1
 
746
        <= HRP_index) {
 
747
        return -1;
 
748
    }
 
749
 
 
750
    /*
 
751
     * Construct the partition name in "string" 
 
752
     */
 
753
    if (disk_devices[HRD_type_index].disk_controller != -1) {
 
754
        snprintf(string, str_len,
 
755
                disk_devices[HRD_type_index].disk_devpart_string,
 
756
                disk_devices[HRD_type_index].disk_controller,
 
757
                disk_devices[HRD_type_index].disk_device_first + HRD_index,
 
758
                disk_devices[HRD_type_index].disk_partition_first +
 
759
                HRP_index);
 
760
    } else {
 
761
        snprintf(string, str_len,
 
762
                disk_devices[HRD_type_index].disk_devpart_string,
 
763
                disk_devices[HRD_type_index].disk_device_first + HRD_index,
 
764
                disk_devices[HRD_type_index].disk_partition_first +
 
765
                HRP_index);
 
766
    }
 
767
    string[ str_len-1 ] = 0;
 
768
 
 
769
    DEBUGMSGTL(("host/hr_disk",
 
770
                "Get_Next_HR_Disk_Partition: %s (%d/%d:%d)\n", string,
 
771
                HRD_type_index, HRD_index, HRP_index));
 
772
 
 
773
    return 0;
 
774
}
 
775
 
 
776
static void
 
777
Save_HR_Disk_Specific(void)
 
778
{
 
779
#ifdef DIOC_DESCRIBE
 
780
    HRD_savedIntf_type = HRD_info.intf_type;
 
781
    HRD_savedDev_type = HRD_info.dev_type;
 
782
    HRD_savedFlags = HRD_info.flags;
 
783
    HRD_savedCapacity = HRD_cap.lba / 2;
 
784
#endif
 
785
#ifdef DKIOCINFO
 
786
    HRD_savedCtrl_type = HRD_info.dki_ctype;
 
787
    HRD_savedFlags = HRD_info.dki_flags;
 
788
    HRD_savedCapacity = HRD_cap.dkg_ncyl * HRD_cap.dkg_nhead * HRD_cap.dkg_nsect / 2;   /* ??? */
 
789
#endif
 
790
#ifdef HAVE_LINUX_HDREG_H
 
791
    HRD_savedCapacity = HRD_info.lba_capacity / 2;
 
792
    HRD_savedFlags = HRD_info.config;
 
793
#endif
 
794
#ifdef DIOCGDINFO
 
795
    HRD_savedCapacity = HRD_info.d_secperunit / 2;
 
796
#endif
 
797
}
 
798
 
 
799
static void
 
800
Save_HR_Disk_General(void)
 
801
{
 
802
#ifdef DIOC_DESCRIBE
 
803
    strncpy(HRD_savedModel, HRD_info.model_num, sizeof(HRD_savedModel)-1);
 
804
    HRD_savedModel[ sizeof(HRD_savedModel)-1 ] = 0;
 
805
#endif
 
806
#ifdef DKIOCINFO
 
807
    strncpy(HRD_savedModel, HRD_info.dki_dname, sizeof(HRD_savedModel)-1);
 
808
    HRD_savedModel[ sizeof(HRD_savedModel)-1 ] = 0;
 
809
#endif
 
810
#ifdef HAVE_LINUX_HDREG_H
 
811
    strncpy(HRD_savedModel, (const char *) HRD_info.model,
 
812
                    sizeof(HRD_savedModel)-1);
 
813
    HRD_savedModel[ sizeof(HRD_savedModel)-1 ] = 0;
 
814
#endif
 
815
#ifdef DIOCGDINFO
 
816
    strncpy(HRD_savedModel, dktypenames[HRD_info.d_type],
 
817
                    sizeof(HRD_savedModel)-1);
 
818
    HRD_savedModel[ sizeof(HRD_savedModel)-1 ] = 0;
 
819
#endif
 
820
}
 
821
 
 
822
static const char *
 
823
describe_disk(int idx)
 
824
{
 
825
    if (HRD_savedModel[0] == '\0')
 
826
        return ("some sort of disk");
 
827
    else
 
828
        return (HRD_savedModel);
 
829
}
 
830
 
 
831
 
 
832
static int
 
833
Query_Disk(int fd, const char *devfull)
 
834
{
 
835
    int             result = -1;
 
836
 
 
837
#ifdef DIOC_DESCRIBE
 
838
    result = ioctl(fd, DIOC_DESCRIBE, &HRD_info);
 
839
    if (result != -1)
 
840
        result = ioctl(fd, DIOC_CAPACITY, &HRD_cap);
 
841
#endif
 
842
 
 
843
#ifdef DKIOCINFO
 
844
    result = ioctl(fd, DKIOCINFO, &HRD_info);
 
845
    if (result != -1)
 
846
        result = ioctl(fd, DKIOCGGEOM, &HRD_cap);
 
847
#endif
 
848
 
 
849
#ifdef HAVE_LINUX_HDREG_H
 
850
    if (HRD_type_index == 0)    /* IDE hard disk */
 
851
        result = ioctl(fd, HDIO_GET_IDENTITY, &HRD_info);
 
852
    else if (HRD_type_index <= 2) {     /* SCSI hard disk and md devices */
 
853
        long            h;
 
854
        result = ioctl(fd, BLKGETSIZE, &h);
 
855
        if (result != -1 && HRD_type_index == 2 && h == 0L)
 
856
            result = -1;        /* ignore empty md devices */
 
857
        if (result != -1) {
 
858
            HRD_info.lba_capacity = h;
 
859
            if (HRD_type_index == 1)
 
860
                snprintf( HRD_info.model, sizeof(HRD_info.model)-1,
 
861
                         "SCSI disk (%s)", devfull);
 
862
            else
 
863
                snprintf( HRD_info.model, sizeof(HRD_info.model)-1,
 
864
                        "RAID disk (%s)", devfull);
 
865
            HRD_info.model[ sizeof(HRD_info.model)-1 ] = 0;
 
866
            HRD_info.config = 0;
 
867
        }
 
868
    }
 
869
#endif
 
870
 
 
871
#ifdef DIOCGDINFO
 
872
    result = ioctl(fd, DIOCGDINFO, &HRD_info);
 
873
#endif
 
874
 
 
875
    return (result);
 
876
}
 
877
 
 
878
 
 
879
static int
 
880
Is_It_Writeable(void)
 
881
{
 
882
#ifdef DIOC_DESCRIBE
 
883
    if ((HRD_savedFlags & WRITE_PROTECT_FLAG) ||
 
884
        (HRD_savedDev_type == CDROM_DEV_TYPE))
 
885
        return (2);             /* read only */
 
886
#endif
 
887
 
 
888
#ifdef DKIOCINFO
 
889
    if (HRD_savedCtrl_type == DKC_CDROM)
 
890
        return (2);             /* read only */
 
891
#endif
 
892
 
 
893
    return (1);                 /* read-write */
 
894
}
 
895
 
 
896
static int
 
897
What_Type_Disk(void)
 
898
{
 
899
#ifdef DIOC_DESCRIBE
 
900
    switch (HRD_savedDev_type) {
 
901
    case DISK_DEV_TYPE:
 
902
        if (HRD_savedIntf_type == PC_FDC_INTF)
 
903
            return (4);         /* Floppy Disk */
 
904
        else
 
905
            return (3);         /* Hard Disk */
 
906
        break;
 
907
    case CDROM_DEV_TYPE:
 
908
        return (5);             /* Optical RO */
 
909
        break;
 
910
    case WORM_DEV_TYPE:
 
911
        return (6);             /* Optical WORM */
 
912
        break;
 
913
    case MO_DEV_TYPE:
 
914
        return (7);             /* Optical R/W */
 
915
        break;
 
916
    default:
 
917
        return (2);             /* Unknown */
 
918
        break;
 
919
    }
 
920
#endif
 
921
 
 
922
#ifdef DKIOCINFO
 
923
    switch (HRD_savedCtrl_type) {
 
924
    case DKC_WDC2880:
 
925
    case DKC_DSD5215:
 
926
#ifdef DKC_XY450
 
927
    case DKC_XY450:
 
928
#endif
 
929
    case DKC_ACB4000:
 
930
    case DKC_MD21:
 
931
#ifdef DKC_XD7053
 
932
    case DKC_XD7053:
 
933
#endif
 
934
    case DKC_SCSI_CCS:
 
935
#ifdef DKC_PANTHER
 
936
    case DKC_PANTHER:
 
937
#endif
 
938
#ifdef DKC_CDC_9057
 
939
    case DKC_CDC_9057:
 
940
#endif
 
941
#ifdef DKC_FJ_M1060
 
942
    case DKC_FJ_M1060:
 
943
#endif
 
944
    case DKC_DIRECT:
 
945
    case DKC_PCMCIA_ATA:
 
946
        return (3);             /* Hard Disk */
 
947
        break;
 
948
    case DKC_NCRFLOPPY:
 
949
    case DKC_SMSFLOPPY:
 
950
    case DKC_INTEL82077:
 
951
        return (4);             /* Floppy Disk */
 
952
        break;
 
953
    case DKC_CDROM:
 
954
        return (5);             /* Optical RO */
 
955
        break;
 
956
    case DKC_PCMCIA_MEM:
 
957
        return (8);             /* RAM disk */
 
958
        break;
 
959
    case DKC_MD:               /* "meta-disk" driver */
 
960
        return (1);             /* Other */
 
961
        break;
 
962
    }
 
963
#endif
 
964
 
 
965
 
 
966
    return (2);                 /* Unknown */
 
967
}
 
968
 
 
969
static int
 
970
Is_It_Removeable(void)
 
971
{
 
972
#ifdef DIOC_DESCRIBE
 
973
    if ((HRD_savedIntf_type == PC_FDC_INTF) ||
 
974
        (HRD_savedDev_type == WORM_DEV_TYPE) ||
 
975
        (HRD_savedDev_type == MO_DEV_TYPE) ||
 
976
        (HRD_savedDev_type == CDROM_DEV_TYPE))
 
977
        return (1);             /* true */
 
978
#endif
 
979
 
 
980
#ifdef DKIOCINFO
 
981
    if ((HRD_savedCtrl_type == DKC_CDROM) ||
 
982
        (HRD_savedCtrl_type == DKC_NCRFLOPPY) ||
 
983
        (HRD_savedCtrl_type == DKC_SMSFLOPPY) ||
 
984
        (HRD_savedCtrl_type == DKC_INTEL82077) ||
 
985
        (HRD_savedCtrl_type == DKC_PCMCIA_MEM) ||
 
986
        (HRD_savedCtrl_type == DKC_PCMCIA_ATA))
 
987
        return (1);             /* true */
 
988
#endif
 
989
 
 
990
#ifdef HAVE_LINUX_HDREG_H
 
991
    if (HRD_savedFlags & 0x80)
 
992
        return (1);             /* true */
 
993
#endif
 
994
 
 
995
    return (2);                 /* false */
 
996
}