2
* Host Resources MIB - File System device group implementation - hr_filesys.c
6
#include <net-snmp/net-snmp-config.h>
8
#include "hr_filesys.h"
9
#include "hr_storage.h"
10
#include <net-snmp/utilities.h>
16
#include <sys/mntent.h>
19
#include <sys/mnttab.h>
21
#if HAVE_SYS_STATVFS_H
22
#include <sys/statvfs.h>
27
#ifdef HAVE_SYS_PARAM_H
28
#include <sys/param.h>
30
#ifdef HAVE_SYS_MOUNT_H
31
#include <sys/mount.h>
42
#if defined(bsdi4) || defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
44
#if defined(MFSNAMELEN)
45
#define MOUNT_NFS "nfs"
46
#define MNTTYPE_UFS "ufs"
48
#define MNTTYPE_FFS "ffs"
49
#define MNTTYPE_NFS "nfs"
50
#define MNTTYPE_NFS3 "nfs"
51
#define MNTTYPE_MFS "mfs"
52
#define MNTTYPE_MSDOS "msdos"
53
#define MNTTYPE_LFS "lfs"
54
#define MNTTYPE_FDESC "fdesc"
55
#define MNTTYPE_PORTAL "portal"
56
#define MNTTYPE_NULL "null"
57
#define MNTTYPE_UMAP "umap"
58
#define MNTTYPE_KERNFS "kernfs"
59
#define MNTTYPE_PROCFS "procfs"
60
#define MNTTYPE_AFS "afs"
61
#define MNTTYPE_CD9660 "cd9660"
62
#define MNTTYPE_UNION "union"
63
#define MNTTYPE_ADOSFS "adosfs"
64
#define MNTTYPE_EXT2FS "ext2fs"
65
#define MNTTYPE_CFS "coda"
66
#define MNTTYPE_NTFS "ntfs"
71
#define HRFS_MONOTONICALLY_INCREASING
73
/*********************
75
* Kernel & interface information,
76
* and internal forward declarations
78
*********************/
82
struct mnttab HRFS_entry_struct;
83
struct mnttab *HRFS_entry = &HRFS_entry_struct;
84
#define HRFS_name mnt_special
85
#define HRFS_mount mnt_mountp
86
#define HRFS_type mnt_fstype
87
#define HRFS_statfs statvfs
89
#elif defined(HAVE_GETFSSTAT)
90
static struct statfs *fsstats = 0;
92
struct statfs *HRFS_entry;
93
#define HRFS_statfs statfs
95
#define HRFS_type f_fstypename
97
#define HRFS_type f_type
99
#define HRFS_mount f_mntonname
100
#define HRFS_name f_mntfromname
104
struct mntent *HRFS_entry;
105
#define HRFS_name mnt_fsname
106
#define HRFS_mount mnt_dir
107
#define HRFS_type mnt_type
108
#define HRFS_statfs statvfs
112
struct mntent *HRFS_entry;
113
#define HRFS_name mnt_fsname
114
#define HRFS_mount mnt_dir
115
#define HRFS_type mnt_type
116
#define HRFS_statfs statfs
119
#define MNTTYPE_CD9660 "iso9660"
120
#define MNTTYPE_EXT2FS "ext2"
121
#define MNTTYPE_EXT3FS "ext3"
122
#define MNTTYPE_SMBFS "smbfs"
123
#define MNTTYPE_MSDOS "msdos"
124
#define MNTTYPE_FAT32 "vfat"
125
#define MNTTYPE_NTFS "ntfs"
134
extern void Init_HR_FileSys(void);
135
extern int Get_Next_HR_FileSys(void);
136
char *cook_device(char *);
137
static u_char *when_dumped(char *filesys, int level, size_t * length);
138
int header_hrfilesys(struct variable *, oid *, size_t *, int,
139
size_t *, WriteMethod **);
141
/*********************
143
* Initialisation & common implementation functions
145
*********************/
147
#define HRFSYS_INDEX 1
148
#define HRFSYS_MOUNT 2
149
#define HRFSYS_RMOUNT 3
150
#define HRFSYS_TYPE 4
151
#define HRFSYS_ACCESS 5
152
#define HRFSYS_BOOT 6
153
#define HRFSYS_STOREIDX 7
154
#define HRFSYS_FULLDUMP 8
155
#define HRFSYS_PARTDUMP 9
157
struct variable4 hrfsys_variables[] = {
158
{HRFSYS_INDEX, ASN_INTEGER, RONLY, var_hrfilesys, 2, {1, 1}},
159
{HRFSYS_MOUNT, ASN_OCTET_STR, RONLY, var_hrfilesys, 2, {1, 2}},
160
{HRFSYS_RMOUNT, ASN_OCTET_STR, RONLY, var_hrfilesys, 2, {1, 3}},
161
{HRFSYS_TYPE, ASN_OBJECT_ID, RONLY, var_hrfilesys, 2, {1, 4}},
162
{HRFSYS_ACCESS, ASN_INTEGER, RONLY, var_hrfilesys, 2, {1, 5}},
163
{HRFSYS_BOOT, ASN_INTEGER, RONLY, var_hrfilesys, 2, {1, 6}},
164
{HRFSYS_STOREIDX, ASN_INTEGER, RONLY, var_hrfilesys, 2, {1, 7}},
165
{HRFSYS_FULLDUMP, ASN_OCTET_STR, RONLY, var_hrfilesys, 2, {1, 8}},
166
{HRFSYS_PARTDUMP, ASN_OCTET_STR, RONLY, var_hrfilesys, 2, {1, 9}},
168
oid hrfsys_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 3, 8 };
171
init_hr_filesys(void)
173
REGISTER_MIB("host/hr_filesys", hrfsys_variables, variable4,
174
hrfsys_variables_oid);
178
* header_hrfilesys(...
180
* vp IN - pointer to variable entry that points here
181
* name IN/OUT - IN/name requested, OUT/name found
182
* length IN/OUT - length of IN/OUT oid's
183
* exact IN - TRUE if an exact match was requested
184
* var_len OUT - length of variable or 0 if function returned
190
header_hrfilesys(struct variable *vp,
193
int exact, size_t * var_len, WriteMethod ** write_method)
195
#define HRFSYS_ENTRY_NAME_LENGTH 11
196
oid newname[MAX_OID_LEN];
197
int fsys_idx, LowIndex = -1;
200
DEBUGMSGTL(("host/hr_filesys", "var_hrfilesys: "));
201
DEBUGMSGOID(("host/hr_filesys", name, *length));
202
DEBUGMSG(("host/hr_filesys", " %d\n", exact));
204
memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid));
206
* Find "next" file system entry
211
fsys_idx = Get_Next_HR_FileSys();
214
newname[HRFSYS_ENTRY_NAME_LENGTH] = fsys_idx;
215
result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
216
if (exact && (result == 0)) {
220
if ((!exact && (result < 0)) &&
221
(LowIndex == -1 || fsys_idx < LowIndex)) {
223
#ifdef HRFS_MONOTONICALLY_INCREASING
229
if (LowIndex == -1) {
230
DEBUGMSGTL(("host/hr_filesys", "... index out of range\n"));
231
return (MATCH_FAILED);
234
memcpy((char *) name, (char *) newname,
235
(vp->namelen + 1) * sizeof(oid));
236
*length = vp->namelen + 1;
238
*var_len = sizeof(long); /* default to 'long' results */
240
DEBUGMSGTL(("host/hr_filesys", "... get filesys stats "));
241
DEBUGMSGOID(("host/hr_filesys", name, *length));
242
DEBUGMSG(("host/hr_filesys", "\n"));
248
oid fsys_type_id[] = { 1, 3, 6, 1, 2, 1, 25, 3, 9, 1 }; /* hrFSOther */
250
sizeof(fsys_type_id) / sizeof(fsys_type_id[0]);
252
/*********************
254
* System specific implementation functions
256
*********************/
260
var_hrfilesys(struct variable *vp,
263
int exact, size_t * var_len, WriteMethod ** write_method)
266
static char string[1024];
270
header_hrfilesys(vp, name, length, exact, var_len, write_method);
271
if (fsys_idx == MATCH_FAILED)
277
long_return = fsys_idx;
278
return (u_char *) & long_return;
280
snprintf(string, sizeof(string), HRFS_entry->HRFS_mount);
281
string[ sizeof(string)-1 ] = 0;
282
*var_len = strlen(string);
283
return (u_char *) string;
285
if (Check_HR_FileSys_NFS()) {
286
snprintf(string, sizeof(string), HRFS_entry->HRFS_name);
287
string[ sizeof(string)-1 ] = 0;
290
*var_len = strlen(string);
291
return (u_char *) string;
294
if (Check_HR_FileSys_NFS())
295
fsys_type_id[fsys_type_len - 1] = 14;
298
* Not sufficient to identity the file
299
* type precisely, but it's a start.
301
#if HAVE_GETFSSTAT && !defined(MFSNAMELEN)
302
switch (HRFS_entry->HRFS_type) {
304
fsys_type_id[fsys_type_len - 1] = 3;
307
fsys_type_id[fsys_type_len - 1] = 14;
310
fsys_type_id[fsys_type_len - 1] = 8;
313
fsys_type_id[fsys_type_len - 1] = 5;
316
fsys_type_id[fsys_type_len - 1] = 1;
319
fsys_type_id[fsys_type_len - 1] = 1;
322
fsys_type_id[fsys_type_len - 1] = 1;
325
fsys_type_id[fsys_type_len - 1] = 1;
328
fsys_type_id[fsys_type_len - 1] = 1;
331
fsys_type_id[fsys_type_len - 1] = 1;
334
fsys_type_id[fsys_type_len - 1] = 1;
337
fsys_type_id[fsys_type_len - 1] = 1;
340
fsys_type_id[fsys_type_len - 1] = 16;
343
fsys_type_id[fsys_type_len - 1] = 12;
346
fsys_type_id[fsys_type_len - 1] = 1;
349
fsys_type_id[fsys_type_len - 1] = 1;
353
fsys_type_id[fsys_type_len - 1] = 23;
358
fsys_type_id[fsys_type_len - 1] = 15;
363
mnt_type = HRFS_entry->HRFS_type;
364
if (mnt_type == NULL)
365
fsys_type_id[fsys_type_len - 1] = 2; /* unknown */
367
else if (!strcmp(mnt_type, MNTTYPE_HFS))
369
fsys_type_id[fsys_type_len - 1] = 3;
371
fsys_type_id[fsys_type_len - 1] = 4;
375
else if (!strcmp(mnt_type, MNTTYPE_UFS))
376
#if (defined(BerkelyFS) && !defined(MNTTYPE_HFS)) || defined(solaris2)
377
fsys_type_id[fsys_type_len - 1] = 3;
379
fsys_type_id[fsys_type_len - 1] = 4; /* or 3? XXX */
383
else if (!strcmp(mnt_type, MNTTYPE_SYSV))
384
fsys_type_id[fsys_type_len - 1] = 4;
387
else if (!strcmp(mnt_type, MNTTYPE_PC))
388
fsys_type_id[fsys_type_len - 1] = 5;
391
else if (!strcmp(mnt_type, MNTTYPE_MSDOS))
392
fsys_type_id[fsys_type_len - 1] = 5;
395
else if (!strcmp(mnt_type, MNTTYPE_FAT32))
396
fsys_type_id[fsys_type_len - 1] = 22;
399
else if (!strcmp(mnt_type, MNTTYPE_CDFS))
401
fsys_type_id[fsys_type_len - 1] = 13;
403
fsys_type_id[fsys_type_len - 1] = 12;
407
else if (!strcmp(mnt_type, MNTTYPE_HSFS))
408
fsys_type_id[fsys_type_len - 1] = 13;
410
#ifdef MNTTYPE_ISO9660
411
else if (!strcmp(mnt_type, MNTTYPE_ISO9660))
412
fsys_type_id[fsys_type_len - 1] = 12;
414
#ifdef MNTTYPE_CD9660
415
else if (!strcmp(mnt_type, MNTTYPE_CD9660))
416
fsys_type_id[fsys_type_len - 1] = 12;
419
else if (!strcmp(mnt_type, MNTTYPE_SMBFS))
420
fsys_type_id[fsys_type_len - 1] = 14;
423
else if (!strcmp(mnt_type, MNTTYPE_NFS))
424
fsys_type_id[fsys_type_len - 1] = 14;
427
else if (!strcmp(mnt_type, MNTTYPE_NFS3))
428
fsys_type_id[fsys_type_len - 1] = 14;
431
else if (!strcmp(mnt_type, MNTTYPE_MFS))
432
fsys_type_id[fsys_type_len - 1] = 8;
434
#ifdef MNTTYPE_EXT2FS
435
else if (!strcmp(mnt_type, MNTTYPE_EXT2FS))
436
fsys_type_id[fsys_type_len - 1] = 23;
438
#ifdef MNTTYPE_EXT3FS
439
else if (!strcmp(mnt_type, MNTTYPE_EXT3FS))
440
fsys_type_id[fsys_type_len - 1] = 23;
443
else if (!strcmp(mnt_type, MNTTYPE_NTFS))
444
fsys_type_id[fsys_type_len - 1] = 9;
447
fsys_type_id[fsys_type_len - 1] = 1; /* Other */
448
#endif /* HAVE_GETFSSTAT */
451
*var_len = sizeof(fsys_type_id);
452
return (u_char *) fsys_type_id;
456
long_return = HRFS_entry->f_flags & MNT_RDONLY ? 2 : 1;
457
#elif defined(cygwin)
460
if (hasmntopt(HRFS_entry, "ro") != NULL)
461
long_return = 2; /* Read Only */
463
long_return = 1; /* Read-Write */
465
return (u_char *) & long_return;
467
if (HRFS_entry->HRFS_mount[0] == '/' &&
468
HRFS_entry->HRFS_mount[1] == 0)
469
long_return = 1; /* root is probably bootable! */
471
long_return = 2; /* others probably aren't */
472
return (u_char *) & long_return;
473
case HRFSYS_STOREIDX:
474
long_return = fsys_idx + HRS_TYPE_FIXED_MAX;
475
return (u_char *) & long_return;
476
case HRFSYS_FULLDUMP:
477
return when_dumped(HRFS_entry->HRFS_name, FULL_DUMP, var_len);
478
case HRFSYS_PARTDUMP:
479
return when_dumped(HRFS_entry->HRFS_name, PART_DUMP, var_len);
481
DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrfilesys\n",
488
/*********************
490
* Internal implementation functions
492
*********************/
494
static int HRFS_index;
495
#ifndef HAVE_GETFSSTAT
500
Init_HR_FileSys(void)
503
fscount = getfsstat(NULL, 0, MNT_NOWAIT);
505
free((char *) fsstats);
507
fsstats = malloc(fscount * sizeof(*fsstats));
508
getfsstat(fsstats, fscount * sizeof(*fsstats), MNT_NOWAIT);
514
fp = fopen(ETC_MNTTAB, "r");
518
const char *HRFS_ignores[] = {
519
#ifdef MNTTYPE_IGNORE
528
#ifdef MNTTYPE_PROCFS
531
#ifdef MNTTYPE_AUTOFS
552
Get_Next_HR_FileSys(void)
555
if (HRFS_index >= fscount)
557
HRFS_entry = fsstats + HRFS_index;
562
* XXX - According to RFC 1514, hrFSIndex must
563
* "remain constant at least from one re-initialization
564
* of the agent to the next re-initialization."
566
* This simple-minded counter doesn't handle filesystems
567
* being un-mounted and re-mounted.
568
* Options for fixing this include:
569
* - keeping a history of previous indices used
570
* - calculating the index from filesystem
571
* specific information
573
* Note: this index is also used as hrStorageIndex
574
* which is assumed to be less than HRS_TYPE_FS_MAX
575
* This assumption may well be broken if the second
576
* option above is followed. Consider indexing the
577
* non-filesystem-based storage entries first in this
578
* case, and assume hrStorageIndex > HRS_TYPE_FS_MIN
579
* (for file-system based storage entries)
581
* But at least this gets us started.
588
if (getmntent(fp, HRFS_entry) != 0)
591
HRFS_entry = getmntent(fp);
592
if (HRFS_entry == NULL)
594
#endif /* solaris2 */
596
for (cpp = HRFS_ignores; *cpp != NULL; ++cpp)
597
if (!strcmp(HRFS_entry->HRFS_type, *cpp))
598
return Get_Next_HR_FileSys();
601
#endif /* HAVE_GETFSSTAT */
605
* this function checks whether the current file system (info can be found
606
* in HRFS_entry) is a NFS file system
607
* HRFS_entry must be valid prior to calling this function
608
* returns 1 if NFS file system, 0 otherwise
611
Check_HR_FileSys_NFS (void)
614
#if defined(MFSNAMELEN)
615
if (!strcmp(HRFS_entry->HRFS_type, MOUNT_NFS))
617
if (HRFS_entry->HRFS_type == MOUNT_NFS)
619
#else /* HAVE_GETFSSTAT */
620
if ( HRFS_entry->HRFS_type != NULL && (
621
#if defined(MNTTYPE_NFS)
622
!strcmp( HRFS_entry->HRFS_type, MNTTYPE_NFS) ||
624
!strcmp( HRFS_entry->HRFS_type, "nfs") ||
626
#if defined(MNTTYPE_NFS3)
627
!strcmp( HRFS_entry->HRFS_type, MNTTYPE_NFS3) ||
629
#if defined(MNTTYPE_SMBFS)
630
!strcmp( HRFS_entry->HRFS_type, MNTTYPE_SMBFS) ||
632
#if defined(MNTTYPE_LOFS)
633
!strcmp( HRFS_entry->HRFS_type, MNTTYPE_LOFS) ||
636
* MVFS is Rational ClearCase's view file system
637
* it is similiar to NFS file systems in that it is mounted
638
* locally or remotely from the ClearCase server
640
!strcmp( HRFS_entry->HRFS_type, "mvfs")))
641
#endif /* HAVE_GETFSSTAT */
642
return 1; /* NFS file system */
644
return 0; /* no NFS file system */
650
#ifdef HAVE_GETFSSTAT
652
free((char *) fsstats);
663
when_dumped(char *filesys, int level, size_t * length)
665
time_t dumpdate = 0, tmp;
668
char *cp1, *cp2, *cp3;
671
* Look for the relevent entries in /etc/dumpdates
673
* This is complicated by the fact that disks are
674
* mounted using block devices, but dumps are
675
* done via the raw character devices.
676
* Thus the device names in /etc/dumpdates and
677
* /etc/mnttab don't match.
678
* These comparisons are therefore made using the
679
* final portion of the device name only.
682
if (*filesys == '\0') /* No filesystem name? */
683
return date_n_time(NULL, length);
684
cp1 = strrchr(filesys, '/'); /* Find the last element of the current FS */
689
if ((dump_fp = fopen("/etc/dumpdates", "r")) == NULL)
690
return date_n_time(NULL, length);
692
while (fgets(line, sizeof(line), dump_fp) != NULL) {
693
cp2 = strchr(line, ' '); /* Start by looking at the device name only */
696
cp3 = strrchr(line, '/'); /* and find the last element */
700
if (strcmp(cp1, cp3) != 0) /* Wrong FS */
704
while (isspace(*cp2))
705
++cp2; /* Now find the dump level */
707
if (level == FULL_DUMP) {
709
continue; /* Not interested in partial dumps */
710
while (isspace(*cp2))
713
dumpdate = ctime_to_timet(cp2);
715
return date_n_time(&dumpdate, length);
716
} else { /* Partial Dump */
718
continue; /* Not interested in full dumps */
719
while (isspace(*cp2))
722
tmp = ctime_to_timet(cp2);
724
dumpdate = tmp; /* Remember the 'latest' partial dump */
731
return date_n_time(&dumpdate, length);
735
#define RAW_DEVICE_PREFIX "/dev/rdsk"
736
#define COOKED_DEVICE_PREFIX "/dev/dsk"
739
cook_device(char *dev)
741
static char cooked_dev[SNMP_MAXPATH+1];
743
if (!strncmp(dev, RAW_DEVICE_PREFIX, strlen(RAW_DEVICE_PREFIX))) {
744
strncpy(cooked_dev, COOKED_DEVICE_PREFIX, sizeof(cooked_dev)-1);
745
cooked_dev[ sizeof(cooked_dev)-1 ] = 0;
746
strncat(cooked_dev, dev + strlen(RAW_DEVICE_PREFIX),
747
sizeof(cooked_dev)-strlen(cooked_dev)-1);
748
cooked_dev[ sizeof(cooked_dev)-1 ] = 0;
750
strncpy(cooked_dev, dev, sizeof(cooked_dev)-1);
751
cooked_dev[ sizeof(cooked_dev)-1 ] = 0;
759
Get_FSIndex(char *dev)
765
while ((iindex = Get_Next_HR_FileSys()) != -1)
766
if (!strcmp(HRFS_entry->HRFS_name, cook_device(dev))) {
776
Get_FSSize(char *dev)
778
struct HRFS_statfs statfs_buf;
782
while (Get_Next_HR_FileSys() != -1)
783
if (!strcmp(HRFS_entry->HRFS_name, cook_device(dev))) {
786
if (HRFS_statfs(HRFS_entry->HRFS_mount, &statfs_buf) != -1)
788
* with large file systems the following calculation produces
790
* (statfs_buf.f_blocks*statfs_buf.f_bsize)/1024
792
* assumption: f_bsize is either 512 or a multiple of 1024
793
* in case of 512 (f_blocks/2) is returned
794
* otherwise (f_blocks*(f_bsize/1024)) is returned
796
if (statfs_buf.f_bsize == 512)
797
return (statfs_buf.f_blocks/2);
799
return (statfs_buf.f_blocks*(statfs_buf.f_bsize/1024));