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 <net-snmp/utilities.h>
15 #include <sys/mntent.h>
18 #include <sys/mnttab.h>
20 #if HAVE_SYS_STATVFS_H
21 #include <sys/statvfs.h>
26 #ifdef HAVE_SYS_PARAM_H
27 #include <sys/param.h>
29 #ifdef HAVE_SYS_MOUNT_H
30 #include <sys/mount.h>
41 #if defined(bsdi4) || defined(freebsd3) || defined(freebsd4) || defined(freebsd5)
43 #if defined(MFSNAMELEN)
44 #define MOUNT_NFS "nfs"
45 #define MNTTYPE_UFS "ufs"
47 #define MNTTYPE_FFS "ffs"
48 #define MNTTYPE_NFS "nfs"
49 #define MNTTYPE_NFS3 "nfs"
50 #define MNTTYPE_MFS "mfs"
51 #define MNTTYPE_MSDOS "msdos"
52 #define MNTTYPE_LFS "lfs"
53 #define MNTTYPE_FDESC "fdesc"
54 #define MNTTYPE_PORTAL "portal"
55 #define MNTTYPE_NULL "null"
56 #define MNTTYPE_UMAP "umap"
57 #define MNTTYPE_KERNFS "kernfs"
58 #define MNTTYPE_PROCFS "procfs"
59 #define MNTTYPE_AFS "afs"
60 #define MNTTYPE_CD9660 "cd9660"
61 #define MNTTYPE_UNION "union"
62 #define MNTTYPE_ADOSFS "adosfs"
63 #define MNTTYPE_EXT2FS "ext2fs"
64 #define MNTTYPE_CFS "coda"
65 #define MNTTYPE_NTFS "ntfs"
70 #define HRFS_MONOTONICALLY_INCREASING
72 /*********************
74 * Kernel & interface information,
75 * and internal forward declarations
77 *********************/
81 struct mnttab HRFS_entry_struct;
82 struct mnttab *HRFS_entry = &HRFS_entry_struct;
83 #define HRFS_name mnt_special
84 #define HRFS_mount mnt_mountp
85 #define HRFS_type mnt_fstype
86 #define HRFS_statfs statvfs
88 #elif defined(HAVE_GETFSSTAT)
89 static struct statfs *fsstats = 0;
91 struct statfs *HRFS_entry;
92 #define HRFS_statfs statfs
94 #define HRFS_type f_fstypename
96 #define HRFS_type f_type
98 #define HRFS_mount f_mntonname
99 #define HRFS_name f_mntfromname
103 struct mntent *HRFS_entry;
104 #define HRFS_name mnt_fsname
105 #define HRFS_mount mnt_dir
106 #define HRFS_type mnt_type
107 #define HRFS_statfs statvfs
111 struct mntent *HRFS_entry;
112 #define HRFS_name mnt_fsname
113 #define HRFS_mount mnt_dir
114 #define HRFS_type mnt_type
115 #define HRFS_statfs statfs
118 #define MNTTYPE_CD9660 "iso9660"
119 #define MNTTYPE_EXT2FS "ext2"
120 #define MNTTYPE_EXT3FS "ext3"
121 #define MNTTYPE_SMBFS "smbfs"
122 #define MNTTYPE_MSDOS "msdos"
123 #define MNTTYPE_FAT32 "vfat"
124 #define MNTTYPE_NTFS "ntfs"
133 extern void Init_HR_FileSys(void);
134 extern int Get_Next_HR_FileSys(void);
135 char *cook_device(char *);
136 static u_char *when_dumped(char *filesys, int level, size_t * length);
137 int header_hrfilesys(struct variable *, oid *, size_t *, int,
138 size_t *, WriteMethod **);
140 /*********************
142 * Initialisation & common implementation functions
144 *********************/
146 #define HRFSYS_INDEX 1
147 #define HRFSYS_MOUNT 2
148 #define HRFSYS_RMOUNT 3
149 #define HRFSYS_TYPE 4
150 #define HRFSYS_ACCESS 5
151 #define HRFSYS_BOOT 6
152 #define HRFSYS_STOREIDX 7
153 #define HRFSYS_FULLDUMP 8
154 #define HRFSYS_PARTDUMP 9
156 struct variable4 hrfsys_variables[] = {
157 {HRFSYS_INDEX, ASN_INTEGER, RONLY, var_hrfilesys, 2, {1, 1}},
158 {HRFSYS_MOUNT, ASN_OCTET_STR, RONLY, var_hrfilesys, 2, {1, 2}},
159 {HRFSYS_RMOUNT, ASN_OCTET_STR, RONLY, var_hrfilesys, 2, {1, 3}},
160 {HRFSYS_TYPE, ASN_OBJECT_ID, RONLY, var_hrfilesys, 2, {1, 4}},
161 {HRFSYS_ACCESS, ASN_INTEGER, RONLY, var_hrfilesys, 2, {1, 5}},
162 {HRFSYS_BOOT, ASN_INTEGER, RONLY, var_hrfilesys, 2, {1, 6}},
163 {HRFSYS_STOREIDX, ASN_INTEGER, RONLY, var_hrfilesys, 2, {1, 7}},
164 {HRFSYS_FULLDUMP, ASN_OCTET_STR, RONLY, var_hrfilesys, 2, {1, 8}},
165 {HRFSYS_PARTDUMP, ASN_OCTET_STR, RONLY, var_hrfilesys, 2, {1, 9}},
167 oid hrfsys_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 3, 8 };
170 init_hr_filesys(void)
172 REGISTER_MIB("host/hr_filesys", hrfsys_variables, variable4,
173 hrfsys_variables_oid);
177 * header_hrfilesys(...
179 * vp IN - pointer to variable entry that points here
180 * name IN/OUT - IN/name requested, OUT/name found
181 * length IN/OUT - length of IN/OUT oid's
182 * exact IN - TRUE if an exact match was requested
183 * var_len OUT - length of variable or 0 if function returned
189 header_hrfilesys(struct variable *vp,
192 int exact, size_t * var_len, WriteMethod ** write_method)
194 #define HRFSYS_ENTRY_NAME_LENGTH 11
195 oid newname[MAX_OID_LEN];
196 int fsys_idx, LowIndex = -1;
199 DEBUGMSGTL(("host/hr_filesys", "var_hrfilesys: "));
200 DEBUGMSGOID(("host/hr_filesys", name, *length));
201 DEBUGMSG(("host/hr_filesys", " %d\n", exact));
203 memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid));
205 * Find "next" file system entry
210 fsys_idx = Get_Next_HR_FileSys();
213 newname[HRFSYS_ENTRY_NAME_LENGTH] = fsys_idx;
214 result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
215 if (exact && (result == 0)) {
219 if ((!exact && (result < 0)) &&
220 (LowIndex == -1 || fsys_idx < LowIndex)) {
222 #ifdef HRFS_MONOTONICALLY_INCREASING
228 if (LowIndex == -1) {
229 DEBUGMSGTL(("host/hr_filesys", "... index out of range\n"));
230 return (MATCH_FAILED);
233 memcpy((char *) name, (char *) newname,
234 (vp->namelen + 1) * sizeof(oid));
235 *length = vp->namelen + 1;
237 *var_len = sizeof(long); /* default to 'long' results */
239 DEBUGMSGTL(("host/hr_filesys", "... get filesys stats "));
240 DEBUGMSGOID(("host/hr_filesys", name, *length));
241 DEBUGMSG(("host/hr_filesys", "\n"));
247 oid fsys_type_id[] = { 1, 3, 6, 1, 2, 1, 25, 3, 9, 1 }; /* hrFSOther */
249 sizeof(fsys_type_id) / sizeof(fsys_type_id[0]);
251 /*********************
253 * System specific implementation functions
255 *********************/
259 var_hrfilesys(struct variable *vp,
262 int exact, size_t * var_len, WriteMethod ** write_method)
265 static char string[100];
269 header_hrfilesys(vp, name, length, exact, var_len, write_method);
270 if (fsys_idx == MATCH_FAILED)
276 long_return = fsys_idx;
277 return (u_char *) & long_return;
279 snprintf(string, sizeof(string), HRFS_entry->HRFS_mount);
280 string[ sizeof(string)-1 ] = 0;
281 *var_len = strlen(string);
282 return (u_char *) string;
284 if (Check_HR_FileSys_NFS()) {
285 snprintf(string, sizeof(string), HRFS_entry->HRFS_name);
286 string[ sizeof(string)-1 ] = 0;
289 *var_len = strlen(string);
290 return (u_char *) string;
293 if (Check_HR_FileSys_NFS())
294 fsys_type_id[fsys_type_len - 1] = 14;
297 * Not sufficient to identity the file
298 * type precisely, but it's a start.
300 #if HAVE_GETFSSTAT && !defined(MFSNAMELEN)
301 switch (HRFS_entry->HRFS_type) {
303 fsys_type_id[fsys_type_len - 1] = 3;
306 fsys_type_id[fsys_type_len - 1] = 14;
309 fsys_type_id[fsys_type_len - 1] = 8;
312 fsys_type_id[fsys_type_len - 1] = 5;
315 fsys_type_id[fsys_type_len - 1] = 1;
318 fsys_type_id[fsys_type_len - 1] = 1;
321 fsys_type_id[fsys_type_len - 1] = 1;
324 fsys_type_id[fsys_type_len - 1] = 1;
327 fsys_type_id[fsys_type_len - 1] = 1;
330 fsys_type_id[fsys_type_len - 1] = 1;
333 fsys_type_id[fsys_type_len - 1] = 1;
336 fsys_type_id[fsys_type_len - 1] = 1;
339 fsys_type_id[fsys_type_len - 1] = 16;
342 fsys_type_id[fsys_type_len - 1] = 12;
345 fsys_type_id[fsys_type_len - 1] = 1;
348 fsys_type_id[fsys_type_len - 1] = 1;
352 fsys_type_id[fsys_type_len - 1] = 23;
357 fsys_type_id[fsys_type_len - 1] = 15;
362 mnt_type = HRFS_entry->HRFS_type;
363 if (mnt_type == NULL)
364 fsys_type_id[fsys_type_len - 1] = 2; /* unknown */
366 else if (!strcmp(mnt_type, MNTTYPE_HFS))
368 fsys_type_id[fsys_type_len - 1] = 3;
370 fsys_type_id[fsys_type_len - 1] = 4;
374 else if (!strcmp(mnt_type, MNTTYPE_UFS))
375 #if defined(BerkelyFS) && !defined(MNTTYPE_HFS)
376 fsys_type_id[fsys_type_len - 1] = 3;
378 fsys_type_id[fsys_type_len - 1] = 4; /* or 3? XXX */
382 else if (!strcmp(mnt_type, MNTTYPE_SYSV))
383 fsys_type_id[fsys_type_len - 1] = 4;
386 else if (!strcmp(mnt_type, MNTTYPE_PC))
387 fsys_type_id[fsys_type_len - 1] = 5;
390 else if (!strcmp(mnt_type, MNTTYPE_MSDOS))
391 fsys_type_id[fsys_type_len - 1] = 5;
394 else if (!strcmp(mnt_type, MNTTYPE_FAT32))
395 fsys_type_id[fsys_type_len - 1] = 22;
398 else if (!strcmp(mnt_type, MNTTYPE_CDFS))
400 fsys_type_id[fsys_type_len - 1] = 13;
402 fsys_type_id[fsys_type_len - 1] = 12;
405 #ifdef MNTTYPE_ISO9660
406 else if (!strcmp(mnt_type, MNTTYPE_ISO9660))
407 fsys_type_id[fsys_type_len - 1] = 12;
409 #ifdef MNTTYPE_CD9660
410 else if (!strcmp(mnt_type, MNTTYPE_CD9660))
411 fsys_type_id[fsys_type_len - 1] = 12;
414 else if (!strcmp(mnt_type, MNTTYPE_SMBFS))
415 fsys_type_id[fsys_type_len - 1] = 1;
418 else if (!strcmp(mnt_type, MNTTYPE_NFS))
419 fsys_type_id[fsys_type_len - 1] = 14;
422 else if (!strcmp(mnt_type, MNTTYPE_NFS3))
423 fsys_type_id[fsys_type_len - 1] = 14;
426 else if (!strcmp(mnt_type, MNTTYPE_MFS))
427 fsys_type_id[fsys_type_len - 1] = 8;
429 #ifdef MNTTYPE_EXT2FS
430 else if (!strcmp(mnt_type, MNTTYPE_EXT2FS))
431 fsys_type_id[fsys_type_len - 1] = 23;
433 #ifdef MNTTYPE_EXT3FS
434 else if (!strcmp(mnt_type, MNTTYPE_EXT3FS))
435 fsys_type_id[fsys_type_len - 1] = 23;
438 else if (!strcmp(mnt_type, MNTTYPE_NTFS))
439 fsys_type_id[fsys_type_len - 1] = 9;
442 fsys_type_id[fsys_type_len - 1] = 1; /* Other */
443 #endif /* HAVE_GETFSSTAT */
446 *var_len = sizeof(fsys_type_id);
447 return (u_char *) fsys_type_id;
451 long_return = HRFS_entry->f_flags & MNT_RDONLY ? 2 : 1;
452 #elif defined(cygwin)
455 if (hasmntopt(HRFS_entry, "ro") != NULL)
456 long_return = 2; /* Read Only */
458 long_return = 1; /* Read-Write */
460 return (u_char *) & long_return;
462 if (HRFS_entry->HRFS_mount[0] == '/' &&
463 HRFS_entry->HRFS_mount[1] == 0)
464 long_return = 1; /* root is probably bootable! */
466 long_return = 2; /* others probably aren't */
467 return (u_char *) & long_return;
468 case HRFSYS_STOREIDX:
469 long_return = fsys_idx; /* Use the same indices */
470 return (u_char *) & long_return;
471 case HRFSYS_FULLDUMP:
472 return when_dumped(HRFS_entry->HRFS_name, FULL_DUMP, var_len);
473 case HRFSYS_PARTDUMP:
474 return when_dumped(HRFS_entry->HRFS_name, PART_DUMP, var_len);
476 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrfilesys\n",
483 /*********************
485 * Internal implementation functions
487 *********************/
489 static int HRFS_index;
490 #ifndef HAVE_GETFSSTAT
495 Init_HR_FileSys(void)
498 fscount = getfsstat(NULL, 0, MNT_NOWAIT);
500 free((char *) fsstats);
502 fsstats = malloc(fscount * sizeof(*fsstats));
503 getfsstat(fsstats, fscount * sizeof(*fsstats), MNT_NOWAIT);
509 fp = fopen(ETC_MNTTAB, "r");
513 const char *HRFS_ignores[] = {
514 #ifdef MNTTYPE_IGNORE
523 #ifdef MNTTYPE_AUTOFS
541 Get_Next_HR_FileSys(void)
544 if (HRFS_index >= fscount)
546 HRFS_entry = fsstats + HRFS_index;
551 * XXX - According to RFC 1514, hrFSIndex must
552 * "remain constant at least from one re-initialization
553 * of the agent to the next re-initialization."
555 * This simple-minded counter doesn't handle filesystems
556 * being un-mounted and re-mounted.
557 * Options for fixing this include:
558 * - keeping a history of previous indices used
559 * - calculating the index from filesystem
560 * specific information
562 * Note: this index is also used as hrStorageIndex
563 * which is assumed to be less than HRS_TYPE_FS_MAX
564 * This assumption may well be broken if the second
565 * option above is followed. Consider indexing the
566 * non-filesystem-based storage entries first in this
567 * case, and assume hrStorageIndex > HRS_TYPE_FS_MIN
568 * (for file-system based storage entries)
570 * But at least this gets us started.
577 if (getmntent(fp, HRFS_entry) != 0)
580 HRFS_entry = getmntent(fp);
581 if (HRFS_entry == NULL)
583 #endif /* solaris2 */
585 for (cpp = HRFS_ignores; *cpp != NULL; ++cpp)
586 if (!strcmp(HRFS_entry->HRFS_type, *cpp))
587 return Get_Next_HR_FileSys();
590 #endif /* HAVE_GETFSSTAT */
594 * this function checks whether the current file system (info can be found
595 * in HRFS_entry) is a Network file system
596 * HRFS_entry must be valid prior to calling this function
597 * returns 1 if Network file system, 0 otherwise
600 Check_HR_FileSys_NFS (void)
603 #if defined(MFSNAMELEN)
604 if (!strcmp(HRFS_entry->HRFS_type, MOUNT_NFS))
606 if (HRFS_entry->HRFS_type == MOUNT_NFS)
608 #else /* HAVE_GETFSSTAT */
609 if ( HRFS_entry->HRFS_type != NULL && (
610 #if defined(MNTTYPE_NFS)
611 !strcmp( HRFS_entry->HRFS_type, MNTTYPE_NFS) ||
613 !strcmp( HRFS_entry->HRFS_type, "nfs") ||
615 #if defined(MNTTYPE_NFS3)
616 !strcmp( HRFS_entry->HRFS_type, MNTTYPE_NFS3) ||
618 #if defined(MNTTYPE_SMBFS)
619 !strcmp( HRFS_entry->HRFS_type, MNTTYPE_SMBFS) ||
621 #if defined(MNTTYPE_LOFS)
622 !strcmp( HRFS_entry->HRFS_type, MNTTYPE_LOFS) ||
625 * MVFS is Rational ClearCase's view file system
626 * it is similiar to NFS file systems in that it is mounted
627 * locally or remotely from the ClearCase server
629 !strcmp( HRFS_entry->HRFS_type, "mvfs")))
630 #endif /* HAVE_GETFSSTAT */
631 return 1; /* Network file system */
633 return 0; /* no Network file system */
639 #ifdef HAVE_GETFSSTAT
641 free((char *) fsstats);
652 when_dumped(char *filesys, int level, size_t * length)
654 time_t dumpdate = 0, tmp;
657 char *cp1, *cp2, *cp3;
660 * Look for the relevent entries in /etc/dumpdates
662 * This is complicated by the fact that disks are
663 * mounted using block devices, but dumps are
664 * done via the raw character devices.
665 * Thus the device names in /etc/dumpdates and
666 * /etc/mnttab don't match.
667 * These comparisons are therefore made using the
668 * final portion of the device name only.
671 if (*filesys == '\0') /* No filesystem name? */
672 return date_n_time(NULL, length);
673 cp1 = strrchr(filesys, '/'); /* Find the last element of the current FS */
678 if ((dump_fp = fopen("/etc/dumpdates", "r")) == NULL)
679 return date_n_time(NULL, length);
681 while (fgets(line, sizeof(line), dump_fp) != NULL) {
682 cp2 = strchr(line, ' '); /* Start by looking at the device name only */
685 cp3 = strrchr(line, '/'); /* and find the last element */
689 if (strcmp(cp1, cp3) != 0) /* Wrong FS */
693 while (isspace(*cp2))
694 ++cp2; /* Now find the dump level */
696 if (level == FULL_DUMP) {
698 continue; /* Not interested in partial dumps */
699 while (isspace(*cp2))
702 dumpdate = ctime_to_timet(cp2);
704 return date_n_time(&dumpdate, length);
705 } else { /* Partial Dump */
707 continue; /* Not interested in full dumps */
708 while (isspace(*cp2))
711 tmp = ctime_to_timet(cp2);
713 dumpdate = tmp; /* Remember the 'latest' partial dump */
720 return date_n_time(&dumpdate, length);
724 #define RAW_DEVICE_PREFIX "/dev/rdsk"
725 #define COOKED_DEVICE_PREFIX "/dev/dsk"
728 cook_device(char *dev)
730 static char cooked_dev[SNMP_MAXPATH+1];
732 if (!strncmp(dev, RAW_DEVICE_PREFIX, strlen(RAW_DEVICE_PREFIX))) {
733 strncpy(cooked_dev, COOKED_DEVICE_PREFIX, sizeof(cooked_dev)-1);
734 cooked_dev[ sizeof(cooked_dev)-1 ] = 0;
735 strncat(cooked_dev, dev + strlen(RAW_DEVICE_PREFIX),
736 sizeof(cooked_dev)-strlen(cooked_dev)-1);
737 cooked_dev[ sizeof(cooked_dev)-1 ] = 0;
739 strncpy(cooked_dev, dev, sizeof(cooked_dev)-1);
740 cooked_dev[ sizeof(cooked_dev)-1 ] = 0;
748 Get_FSIndex(char *dev)
754 while ((iindex = Get_Next_HR_FileSys()) != -1)
755 if (!strcmp(HRFS_entry->HRFS_name, cook_device(dev))) {
765 Get_FSSize(char *dev)
767 struct HRFS_statfs statfs_buf;
771 while (Get_Next_HR_FileSys() != -1)
772 if (!strcmp(HRFS_entry->HRFS_name, cook_device(dev))) {
775 if (HRFS_statfs(HRFS_entry->HRFS_mount, &statfs_buf) != -1)
777 * with large file systems the following calculation produces
779 * (statfs_buf.f_blocks*statfs_buf.f_bsize)/1024
781 * assumption: f_bsize is either 512 or a multiple of 1024
782 * in case of 512 (f_blocks/2) is returned
783 * otherwise (f_blocks*(f_bsize/1024)) is returned
785 if (statfs_buf.f_bsize == 512)
786 return (statfs_buf.f_blocks/2);
788 return (statfs_buf.f_blocks*(statfs_buf.f_bsize/1024));