disk.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:21k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * disk.c
  3.  */
  4. #include <net-snmp/net-snmp-config.h>
  5. #include <stdio.h>
  6. #if HAVE_STDLIB_H
  7. #include <stdlib.h>
  8. #endif
  9. #if HAVE_UNISTD_H
  10. #include <unistd.h>
  11. #endif
  12. #if HAVE_FCNTL_H
  13. #include <fcntl.h>
  14. #endif
  15. #include <signal.h>
  16. #if HAVE_MACHINE_PARAM_H
  17. #include <machine/param.h>
  18. #endif
  19. #if HAVE_SYS_VMMETER_H
  20. #if !(defined(bsdi2) || defined(netbsd1))
  21. #include <sys/vmmeter.h>
  22. #endif
  23. #endif
  24. #if HAVE_SYS_PARAM_H
  25. #include <sys/param.h>
  26. #endif
  27. #if HAVE_SYS_CONF_H
  28. #include <sys/conf.h>
  29. #endif
  30. #if HAVE_ASM_PAGE_H
  31. #include <asm/page.h>
  32. #endif
  33. #if HAVE_SYS_SWAP_H
  34. #include <sys/swap.h>
  35. #endif
  36. #if HAVE_SYS_FS_H
  37. #include <sys/fs.h>
  38. #else
  39. #if HAVE_UFS_FS_H
  40. #include <ufs/fs.h>
  41. #else
  42. #ifdef HAVE_SYS_STAT_H
  43. #include <sys/stat.h>
  44. #endif
  45. #ifdef HAVE_SYS_VNODE_H
  46. #include <sys/vnode.h>
  47. #endif
  48. #ifdef HAVE_UFS_UFS_QUOTA_H
  49. #include <ufs/ufs/quota.h>
  50. #endif
  51. #ifdef HAVE_UFS_UFS_INODE_H
  52. #include <ufs/ufs/inode.h>
  53. #endif
  54. #if HAVE_UFS_FFS_FS_H
  55. #include <ufs/ffs/fs.h>
  56. #endif
  57. #endif
  58. #endif
  59. #if HAVE_MTAB_H
  60. #include <mtab.h>
  61. #endif
  62. #include <sys/stat.h>
  63. #include <errno.h>
  64. #if HAVE_SYS_STATFS_H
  65. #include <sys/statfs.h>
  66. #endif
  67. #if HAVE_SYS_STATVFS_H
  68. #include <sys/statvfs.h>
  69. #endif
  70. #if HAVE_SYS_VFS_H
  71. #include <sys/vfs.h>
  72. #endif
  73. #if defined(HAVE_STATFS)
  74. #if HAVE_SYS_MOUNT_H
  75. #include <sys/mount.h>
  76. #endif
  77. #if HAVE_SYS_SYSCTL_H
  78. #include <sys/sysctl.h>
  79. #endif
  80. #if !defined(HAVE_STATVFS)
  81. #define statvfs statfs
  82. #endif
  83. #endif
  84. #if HAVE_VM_VM_H
  85. #include <vm/vm.h>
  86. #endif
  87. #if HAVE_VM_SWAP_PAGER_H
  88. #include <vm/swap_pager.h>
  89. #endif
  90. #if HAVE_SYS_FIXPOINT_H
  91. #include <sys/fixpoint.h>
  92. #endif
  93. #if HAVE_MALLOC_H
  94. #include <malloc.h>
  95. #endif
  96. #if HAVE_STRING_H
  97. #include <string.h>
  98. #endif
  99. #if HAVE_FSTAB_H
  100. #include <fstab.h>
  101. #endif
  102. #if HAVE_MNTENT_H
  103. #include <mntent.h>
  104. #endif
  105. #if HAVE_SYS_MNTTAB_H
  106. #include <sys/mnttab.h>
  107. #endif
  108. #if HAVE_NETINET_IN_H
  109. #include <netinet/in.h>
  110. #endif
  111. #if TIME_WITH_SYS_TIME
  112. # ifdef WIN32
  113. #  include <sys/timeb.h>
  114. # else
  115. #  include <sys/time.h>
  116. # endif
  117. # include <time.h>
  118. #else
  119. # if HAVE_SYS_TIME_H
  120. #  include <sys/time.h>
  121. # else
  122. #  include <time.h>
  123. # endif
  124. #endif
  125. #if HAVE_WINSOCK_H
  126. #include <winsock.h>
  127. #endif
  128. #if HAVE_DMALLOC_H
  129. #include <dmalloc.h>
  130. #endif
  131. #include <net-snmp/net-snmp-includes.h>
  132. #include <net-snmp/agent/net-snmp-agent-includes.h>
  133. #include <net-snmp/agent/auto_nlist.h>
  134. #include "struct.h"
  135. #include "disk.h"
  136. #include "util_funcs.h"
  137. #if USING_UCD_SNMP_ERRORMIB_MODULE
  138. #include "errormib.h"
  139. #else
  140. #define setPerrorstatus(x) snmp_log_perror(x)
  141. #endif
  142. /*
  143.  *  * config file parsing routines
  144.  *   */
  145. static void       disk_free_config(void);
  146. static void       disk_parse_config(const char *, char *);
  147. static void       disk_parse_config_all(const char *, char *);
  148. static void       find_and_add_allDisks(int minpercent);
  149. static void       add_device(char *path, char *device,
  150.                      int minspace, int minpercent, int override);
  151. static void       modify_disk_parameters(int index, int minspace,
  152.                                  int minpercent);
  153. static int        disk_exists(char *path);
  154. static u_char    *find_device(char *path);
  155. struct diskpart {
  156.     char            device[STRMAX];
  157.     char            path[STRMAX];
  158.     int             minimumspace;
  159.     int             minpercent;
  160. };
  161. int             numdisks;
  162. int             allDisksIncluded = 0;
  163. struct diskpart disks[MAXDISKS];
  164. struct variable2 extensible_disk_variables[] = {
  165.   {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_disk, 1, {MIBINDEX}},
  166.   {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_disk, 1, {ERRORNAME}},
  167.   {DISKDEVICE, ASN_OCTET_STR, RONLY, var_extensible_disk, 1,
  168.    {DISKDEVICE}},
  169.   {DISKMINIMUM, ASN_INTEGER, RONLY, var_extensible_disk, 1,
  170.    {DISKMINIMUM}},
  171.   {DISKMINPERCENT, ASN_INTEGER, RONLY, var_extensible_disk, 1,
  172.    {DISKMINPERCENT}},
  173.   {DISKTOTAL, ASN_INTEGER, RONLY, var_extensible_disk, 1, {DISKTOTAL}},
  174.   {DISKAVAIL, ASN_INTEGER, RONLY, var_extensible_disk, 1, {DISKAVAIL}},
  175.   {DISKUSED, ASN_INTEGER, RONLY, var_extensible_disk, 1, {DISKUSED}},
  176.   {DISKPERCENT, ASN_INTEGER, RONLY, var_extensible_disk, 1,
  177.    {DISKPERCENT}},
  178.   {DISKPERCENTNODE, ASN_INTEGER, RONLY, var_extensible_disk, 1,
  179.    {DISKPERCENTNODE}},
  180.   {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_disk, 1, {ERRORFLAG}},
  181.   {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_disk, 1, {ERRORMSG}}
  182. };
  183. /*
  184.  * Define the OID pointer to the top of the mib tree that we're
  185.  * registering underneath 
  186.  */
  187. oid             disk_variables_oid[] = { UCDAVIS_MIB, DISKMIBNUM, 1 };
  188. void
  189. init_disk(void)
  190. {
  191.   /*
  192.    * register ourselves with the agent to handle our mib tree 
  193.    */
  194.   REGISTER_MIB("ucd-snmp/disk", extensible_disk_variables, variable2,
  195.        disk_variables_oid);
  196.   snmpd_register_config_handler("disk", disk_parse_config,
  197. disk_free_config,
  198. "path [ minspace | minpercent% ]");
  199.   snmpd_register_config_handler("includeAllDisks", disk_parse_config_all,
  200. disk_free_config,
  201. "minpercent%");
  202.   allDisksIncluded = 0;
  203. }
  204. static void
  205. disk_free_config(void)
  206. {
  207.   int             i;
  208.   numdisks = 0;
  209.   for (i = 0; i < MAXDISKS; i++) {    /* init/erase disk db */
  210.     disks[i].device[0] = 0;
  211.     disks[i].path[0] = 0;
  212.     disks[i].minimumspace = -1;
  213.     disks[i].minpercent = -1;
  214.   }
  215. }
  216. static void 
  217. disk_parse_config(const char *token, char *cptr)
  218. {
  219. #if HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS
  220.   char            tmpbuf[1024];
  221.   char            path[STRMAX];
  222.   int             minpercent;
  223.   int             minspace;
  224.   if (numdisks == MAXDISKS) {
  225.     config_perror("Too many disks specified.");
  226.     snprintf(tmpbuf, sizeof(tmpbuf), "tignoring:  %s", cptr);
  227.     tmpbuf[ sizeof(tmpbuf)-1 ] = 0;
  228.     config_perror(tmpbuf);
  229.   } else {
  230.     /*
  231.      * read disk path (eg, /1 or /usr) 
  232.      */
  233.     copy_nword(cptr, path, sizeof(path));
  234.     cptr = skip_not_white(cptr);
  235.     cptr = skip_white(cptr);
  236.     /*
  237.      * read optional minimum disk usage spec 
  238.      */
  239.     if(cptr != NULL) {
  240.       if(strchr(cptr, '%') == 0) {
  241. minspace = atoi(cptr);
  242. minpercent = -1;
  243.       }
  244.       else {
  245. minspace = -1;
  246. minpercent = atoi(cptr);
  247.       }
  248.     } else {
  249.       minspace = DEFDISKMINIMUMSPACE;
  250.       minpercent = -1;
  251.     }
  252.     /*
  253.      * check if the disk already exists, if so then modify its
  254.      * parameters. if it does not exist then add it
  255.      */
  256.     add_device(path, find_device(path), minspace, minpercent, 1);
  257.   }
  258. #endif /* HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS */
  259. }
  260. static void 
  261. disk_parse_config_all(const char *token, char *cptr)
  262. {
  263. #if HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS
  264.   char            tmpbuf[1024];
  265.   int             minpercent = DISKMINPERCENT;
  266.     
  267.   if (numdisks == MAXDISKS) {
  268.     config_perror("Too many disks specified.");
  269.     sprintf(tmpbuf, "tignoring:  %s", cptr);
  270.     config_perror(tmpbuf);
  271.   } else {
  272.     /*
  273.      * read the minimum disk usage percent
  274.      */
  275.     if(cptr != NULL) {
  276.       if(strchr(cptr, '%') != 0) {
  277. minpercent = atoi(cptr);
  278.       }
  279.     }
  280.     /*
  281.      * if we have already seen the "includeAllDisks" directive
  282.      * then search for the disk in the "disks" array and modify
  283.      * the values. if we havent seen the "includeAllDisks"
  284.      * directive then include this disk
  285.      */
  286.     if(allDisksIncluded) {
  287.       config_perror("includeAllDisks already specified.");
  288.       sprintf(tmpbuf, "tignoring: includeAllDisks %s", cptr);
  289.       config_perror(tmpbuf);
  290.     }
  291.     else {
  292.       allDisksIncluded = 1;
  293.       find_and_add_allDisks(minpercent);
  294.     }
  295.   }
  296. #endif /* HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS */
  297. }
  298. static void
  299. add_device(char *path, char *device, int minspace, int minpercent, int override) 
  300. {
  301.   int index;
  302.   if (numdisks == MAXDISKS) {
  303.     char tmpbuf[1024];
  304.     config_perror("Too many disks specified.");
  305.     snprintf(tmpbuf, sizeof(tmpbuf), "tignoring:  %s", device);
  306.     tmpbuf[ sizeof(tmpbuf)-1 ] = 0;
  307.     config_perror(tmpbuf);
  308.     return;
  309.   }
  310.   index = disk_exists(path);
  311.   if((index != -1) && (index < MAXDISKS) && (override==1)) {
  312.     modify_disk_parameters(index, minspace, minpercent);
  313.   }
  314.   else if(index == -1){
  315.     /* add if and only if the device was found */
  316.     if(device[0] != 0) {
  317.       copy_nword(path, disks[numdisks].path, 
  318.  sizeof(disks[numdisks].path));
  319.       copy_nword(device, disks[numdisks].device, 
  320.  sizeof(disks[numdisks].device));
  321.       disks[numdisks].minimumspace = minspace;
  322.       disks[numdisks].minpercent   = minpercent;
  323.       numdisks++;  
  324.     }
  325.     else {
  326.       disks[numdisks].minimumspace = -1;
  327.       disks[numdisks].minpercent = -1;
  328.       disks[numdisks].path[0] = 0;
  329.       disks[numdisks].device[0] = 0;
  330.     }
  331.   }
  332. }
  333. void
  334. modify_disk_parameters(int index, int minspace, int minpercent)
  335. {
  336.   disks[index].minimumspace = minspace;
  337.   disks[index].minpercent   = minpercent;
  338. }
  339. int disk_exists(char *path) 
  340. {
  341.   int index;
  342.   for(index = 0; index < numdisks; index++) {
  343.     DEBUGMSGTL(("ucd-snmp/disk:", "Checking for %s. Found %s at %d ", path, disks[index].path, index));
  344.     if(strcmp(path, disks[index].path) == 0) {
  345.       return index;
  346.     }
  347.   }
  348.   return -1;
  349. }
  350. static void 
  351. find_and_add_allDisks(int minpercent)
  352. {
  353. #if HAVE_GETMNTENT
  354. #if HAVE_SYS_MNTTAB_H
  355.   struct mnttab   mnttab;
  356. #else
  357.   struct mntent  *mntent;
  358. #endif
  359.   FILE           *mntfp;
  360. #elif HAVE_FSTAB_H
  361.   struct fstab   *fstab1;
  362. #elif HAVE_STATFS
  363.   struct statfs   statf;
  364. #endif
  365. #if defined(HAVE_GETMNTENT) && !defined(HAVE_SETMNTENT)
  366.   int             i;
  367. #endif
  368.   int dummy = 0;
  369.   char            tmpbuf[1024];
  370.   /* 
  371.    * find the device for the path and copy the device into the
  372.    * string declared above and at the end of the routine return it
  373.    * to the caller 
  374.    */
  375. #if HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS   
  376. #if HAVE_GETMNTENT
  377. #if HAVE_SETMNTENT
  378.   mntfp = setmntent(ETC_MNTTAB, "r");
  379.   while (NULL != (mntent = getmntent(mntfp))) {
  380.     add_device(mntent->mnt_dir, mntent->mnt_fsname, -1, minpercent, 0);
  381.     dummy = 1;
  382.   }
  383.   if (mntfp)
  384.     endmntent(mntfp);
  385.   if(dummy != 0) {
  386.     /*
  387.      * dummy clause for else below
  388.      */
  389.   }
  390. #else                           /* getmentent but not setmntent */
  391.   mntfp = fopen(ETC_MNTTAB, "r");
  392.   while ((i = getmntent(mntfp, &mnttab)) == 0) {
  393.     add_device(mnttab.mnt_mountp, mnttab.mnt_special, -1, minpercent, 0);
  394.     dummy = 1;
  395.   }
  396.   fclose(mntfp);
  397.   if(dummy != 0) {
  398.     /*
  399.      * dummy clause for else below
  400.      */
  401.   }
  402. #endif /* HAVE_SETMNTENT */
  403. #elif HAVE_FSTAB_H
  404.   setfsent(); /* open /etc/fstab */
  405.   while((fstab1 = getfsent()) != NULL) {
  406.     add_device(fstab1->fs_file, fstab1->fs_spec, -1, minpercent, 0);
  407.     dummy = 1;
  408.   }
  409.   endfsent(); /* close /etc/fstab */
  410.   if(dummy != 0) {
  411.     /*
  412.      * dummy clause for else below
  413.      */
  414.   }
  415. #elif HAVE_STATFS
  416.   /*
  417.    * since there is no way to get all the mounted systems with just
  418.    * statfs we default to the root partition "/"
  419.    */
  420.   if (statfs("/", &statf) == 0) {
  421.     add_device("/", statf.f_mntfromname, -1, minpercent, 0);
  422.   }
  423. #endif
  424.   else {
  425.     if (numdisks == MAXDISKS) {
  426.       return;
  427.     }
  428.     snprintf(tmpbuf, sizeof(tmpbuf),
  429.              "Couldn't find device for disk %s",
  430.              disks[numdisks].path);
  431.     tmpbuf[ sizeof(tmpbuf)-1 ] = 0;
  432.     config_pwarn(tmpbuf);
  433.     disks[numdisks].minimumspace = -1;
  434.     disks[numdisks].minpercent = -1;
  435.     disks[numdisks].path[0] = 0;
  436.   }
  437. #else
  438.   config_perror("'disk' checks not supported on this architecture.");
  439. #endif                   /* HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS */  
  440.  
  441. }
  442. static u_char *
  443. find_device(char *path)
  444. {
  445. #if HAVE_GETMNTENT
  446. #if HAVE_SYS_MNTTAB_H
  447.   struct mnttab   mnttab;
  448. #else
  449.   struct mntent  *mntent;
  450. #endif
  451.   FILE           *mntfp;
  452. #elif HAVE_FSTAB_H
  453.   struct fstab   *fstab;
  454.   struct stat     stat1;
  455. #elif HAVE_STATFS
  456.   struct statfs   statf;
  457. #endif
  458.   char            tmpbuf[1024];
  459.   static char     device[STRMAX];
  460. #if defined(HAVE_GETMNTENT) && !defined(HAVE_SETMNTENT)
  461.   int             i;
  462. #endif
  463.   device[0] = ''; /* null terminate the device */
  464.   /* find the device for the path and copy the device into the
  465.    * string declared above and at the end of the routine return it
  466.    * to the caller 
  467.    */
  468. #if HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS   
  469. #if HAVE_GETMNTENT
  470. #if HAVE_SETMNTENT
  471.   mntfp = setmntent(ETC_MNTTAB, "r");
  472.   while (NULL != (mntent = getmntent(mntfp)))
  473.     if (strcmp(path, mntent->mnt_dir) == 0) {
  474.       copy_nword(mntent->mnt_fsname, device,
  475.  sizeof(device));
  476.       DEBUGMSGTL(("ucd-snmp/disk", "Disk:  %sn",
  477.   mntent->mnt_fsname));
  478.       break;
  479.     } else {
  480.       DEBUGMSGTL(("ucd-snmp/disk", "  %s != %sn",
  481.   path, mntent->mnt_dir));
  482.     }
  483.   if (mntfp)
  484.     endmntent(mntfp);
  485. #else                           /* getmentent but not setmntent */
  486.   mntfp = fopen(ETC_MNTTAB, "r");
  487.   while ((i = getmntent(mntfp, &mnttab)) == 0)
  488.     if (strcmp(path, mnttab.mnt_mountp) == 0)
  489.       break;
  490.     else {
  491.       DEBUGMSGTL(("ucd-snmp/disk", "  %s != %sn",
  492.   path, mnttab.mnt_mountp));
  493.     }
  494.   fclose(mntfp);
  495.   if (i == 0) {
  496.     copy_nword(mnttab.mnt_special, device,
  497.        sizeof(device));
  498.   }
  499. #endif /* HAVE_SETMNTENT */
  500. #elif HAVE_FSTAB_H
  501.   stat(path, &stat1);
  502.   setfsent();
  503.   if ((fstab = getfsfile(path))) {
  504.     copy_nword(fstab->fs_spec, device,
  505.        sizeof(device));
  506.   }
  507.   endfsent();
  508.   if (device[0] != '') {
  509.      /*
  510.       * dummy clause for else below
  511.       */
  512.    }
  513. #elif HAVE_STATFS
  514.   if (statfs(path, &statf) == 0) {
  515.     copy_word(statf.f_mntfromname, device);
  516.     DEBUGMSGTL(("ucd-snmp/disk", "Disk:  %sn",
  517. statf.f_mntfromname));
  518.   }
  519. #endif
  520.   else {
  521.     sprintf(tmpbuf, "Couldn't find device for disk %s",
  522.     path);
  523.     config_pwarn(tmpbuf);
  524.   }
  525. #else
  526.   config_perror("'disk' checks not supported on this architecture.");
  527. #endif                   /* HAVE_FSTAB_H || HAVE_GETMNTENT || HAVE_STATFS */  
  528.   return device;
  529. }
  530. /*
  531.  * var_extensible_disk(...
  532.  * Arguments:
  533.  * vp     IN      - pointer to variable entry that points here
  534.  * name    IN/OUT  - IN/name requested, OUT/name found
  535.  * length  IN/OUT  - length of IN/OUT oid's 
  536.  * exact   IN      - TRUE if an exact match was requested
  537.  * var_len OUT     - length of variable or 0 if function returned
  538.  * write_method
  539.  * 
  540.  */
  541. u_char         *
  542. var_extensible_disk(struct variable *vp,
  543.                     oid * name,
  544.                     size_t * length,
  545.                     int exact,
  546.                     size_t * var_len, WriteMethod ** write_method)
  547. {
  548.     int             percent, iserror, disknum = 0;
  549. #if !defined(HAVE_SYS_STATVFS_H) && !defined(HAVE_STATFS)
  550.     double          totalblks, free, used, avail, availblks;
  551. #else
  552.     static long     avail;
  553. #if defined(STRUCT_STATVFS_HAS_F_FILES) || defined(STRUCT_STATFS_HAS_F_FILES)
  554.     int             percent_inode;
  555. #endif
  556. #endif
  557.     static long     long_ret;
  558.     static char     errmsg[300];
  559.     float           multiplier;
  560. #if defined(HAVE_STATVFS) || defined(HAVE_STATFS)
  561. #ifdef STAT_STATFS_FS_DATA
  562.     struct fs_data  fsd;
  563.     struct {
  564.         u_int           f_blocks, f_bfree, f_bavail, f_bsize;
  565.     } vfs;
  566. #else
  567.     struct statvfs  vfs;
  568. #endif
  569. #else
  570. #if HAVE_FSTAB_H
  571.     int             file;
  572.     union {
  573.         struct fs       iu_fs;
  574.         char            dummy[SBSIZE];
  575.     } sb;
  576. #define filesys sb.iu_fs
  577. #endif
  578. #endif
  579.     if (header_simple_table
  580.         (vp, name, length, exact, var_len, write_method, numdisks))
  581.         return (NULL);
  582.     disknum = name[*length - 1] - 1;
  583.     switch (vp->magic) {
  584.     case MIBINDEX:
  585.         long_ret = disknum + 1;
  586.         return ((u_char *) (&long_ret));
  587.     case ERRORNAME:            /* DISKPATH */
  588.         *var_len = strlen(disks[disknum].path);
  589.         return ((u_char *) disks[disknum].path);
  590.     case DISKDEVICE:
  591.         *var_len = strlen(disks[disknum].device);
  592.         return ((u_char *) disks[disknum].device);
  593.     case DISKMINIMUM:
  594.         long_ret = disks[disknum].minimumspace;
  595.         return ((u_char *) (&long_ret));
  596.     case DISKMINPERCENT:
  597.         long_ret = disks[disknum].minpercent;
  598.         return ((u_char *) (&long_ret));
  599.     }
  600. #if defined(HAVE_STATVFS) || defined(HAVE_STATFS)
  601. #ifdef STAT_STATFS_FS_DATA
  602.     if (statvfs(disks[disknum].path, &fsd) == -1)
  603. #else
  604.     if (statvfs(disks[disknum].path, &vfs) == -1)
  605. #endif
  606.     {
  607.         snmp_log(LOG_ERR, "Couldn't open device %sn",
  608.                  disks[disknum].device);
  609.         setPerrorstatus("statvfs dev/disk");
  610.         return NULL;
  611.     }
  612. #ifdef STAT_STATFS_FS_DATA
  613.     vfs.f_blocks = fsd.fd_btot;
  614.     vfs.f_bfree = fsd.fd_bfree;
  615.     vfs.f_bavail = fsd.fd_bfreen;
  616.     vfs.f_bsize = 1024;         /*  Ultrix f_bsize is a VM parameter apparently.  */
  617. #endif
  618. #if defined(HAVE_ODS)
  619.     vfs.f_blocks = vfs.f_spare[0];
  620.     vfs.f_bfree = vfs.f_spare[1];
  621.     vfs.f_bavail = vfs.f_spare[2];
  622. #endif
  623.     percent = vfs.f_bavail <= 0 ? 100 :
  624.         (int) ((double) (vfs.f_blocks - vfs.f_bfree) /
  625.                (double) (vfs.f_blocks -
  626.                          (vfs.f_bfree - vfs.f_bavail)) * 100.0 + 0.5);
  627.     multiplier = (float)vfs.f_bsize / (float)1024.0;
  628. #ifdef STRUCT_STATVFS_HAS_F_FRSIZE
  629.     if (vfs.f_frsize > 255)
  630.         multiplier = (float)vfs.f_frsize / (float)1024.0;
  631. #endif
  632.     avail = (long)(vfs.f_bavail * multiplier);
  633.     iserror = (disks[disknum].minimumspace >= 0 ?
  634.                avail < disks[disknum].minimumspace :
  635.                100 - percent <= disks[disknum].minpercent) ? 1 : 0;
  636. #if defined(STRUCT_STATVFS_HAS_F_FILES) || defined STRUCT_STATFS_HAS_F_FAVAIL
  637.     percent_inode = vfs.f_favail <= 0 ? 100 :
  638.         (int) ((double) (vfs.f_files - vfs.f_ffree) /
  639.                (double) (vfs.f_files -
  640.                          (vfs.f_ffree - vfs.f_favail)) * 100.0 + 0.5);
  641. #else
  642. #if defined(STRUCT_STATFS_HAS_F_FILES) && defined(STRUCT_STATFS_HAS_F_FFREE)
  643.    percent_inode = vfs.f_files == 0 ? 100.0 :
  644.       (int) ((double) (vfs.f_files - vfs.f_ffree) /
  645.           (double) (vfs.f_files) * 100.0 + 0.5);
  646. #endif 
  647. #endif /* defined(STRUCT_STATVFS_HAS_F_FILES) */ 
  648.     switch (vp->magic) {
  649.     case DISKTOTAL:
  650.         long_ret = (long)(vfs.f_blocks * multiplier);
  651.         return ((u_char *) (&long_ret));
  652.     case DISKAVAIL:
  653.         return ((u_char *) (&avail));
  654.     case DISKUSED:
  655.         long_ret = (long)((vfs.f_blocks - vfs.f_bfree) * multiplier);
  656.         return ((u_char *) (&long_ret));
  657.     case DISKPERCENT:
  658.         long_ret = percent;
  659.         return ((u_char *) (&long_ret));
  660. #if defined(STRUCT_STATVFS_HAS_F_FILES) || defined (STRUCT_STATFS_HAS_F_FILES)
  661.     case DISKPERCENTNODE:
  662.         long_ret = percent_inode;
  663.         return ((u_char *) (&long_ret));
  664. #endif
  665.     case ERRORFLAG:
  666.         long_ret = iserror;
  667.         return ((u_char *) (&long_ret));
  668.     case ERRORMSG:
  669.         if (iserror) {
  670.             if (disks[disknum].minimumspace >= 0)
  671.                 snprintf(errmsg, sizeof(errmsg),
  672.                         "%s: less than %d free (= %d)",
  673.                         disks[disknum].path, disks[disknum].minimumspace,
  674.                         (int) avail);
  675.             else
  676.                 snprintf(errmsg, sizeof(errmsg),
  677.                         "%s: less than %d%% free (= %d%%)",
  678.                         disks[disknum].path, disks[disknum].minpercent,
  679.                         percent);
  680.             errmsg[ sizeof(errmsg)-1 ] = 0;
  681.         } else
  682.             errmsg[0] = 0;
  683.         *var_len = strlen(errmsg);
  684.         return ((u_char *) (errmsg));
  685.     }
  686. #else
  687. #if HAVE_FSTAB_H
  688.     /*
  689.      * read the disk information 
  690.      */
  691.     if ((file = open(disks[disknum].device, 0)) < 0) {
  692.         snmp_log(LOG_ERR, "Couldn't open device %sn",
  693.                  disks[disknum].device);
  694.         setPerrorstatus("open dev/disk");
  695.         return (NULL);
  696.     }
  697.     lseek(file, (long) (SBLOCK * DEV_BSIZE), 0);
  698.     if (read(file, (char *) &filesys, SBSIZE) != SBSIZE) {
  699.         setPerrorstatus("open dev/disk");
  700.         snmp_log(LOG_ERR, "Error reading device %sn",
  701.                  disks[disknum].device);
  702.         close(file);
  703.         return (NULL);
  704.     }
  705.     close(file);
  706.     totalblks = filesys.fs_dsize;
  707.     free = filesys.fs_cstotal.cs_nbfree * filesys.fs_frag +
  708.         filesys.fs_cstotal.cs_nffree;
  709.     used = totalblks - free;
  710.     availblks = totalblks * (100 - filesys.fs_minfree) / 100;
  711.     avail = availblks > used ? availblks - used : 0;
  712.     percent =
  713.         availblks ==
  714.         0 ? 100 : (int) ((double) used / (double) totalblks * 100.0 + 0.5);
  715.     multiplier = (float)filesys.fs_fsize / (float)1024.0;
  716.     iserror =
  717.         (disks[disknum].minimumspace >= 0
  718.             ? avail * multiplier < disks[disknum].minimumspace
  719.             : 100 - percent <= disks[disknum].minpercent) ? 1 : 0;
  720.     switch (vp->magic) {
  721.     case DISKTOTAL:
  722.         long_ret = (long)(totalblks * multiplier);
  723.         return ((u_char *) (&long_ret));
  724.     case DISKAVAIL:
  725.         long_ret = (long)(avail * multiplier);
  726.         return ((u_char *) (&long_ret));
  727.     case DISKUSED:
  728.         long_ret = (long)(used * multiplier);
  729.         return ((u_char *) (&long_ret));
  730.     case DISKPERCENT:
  731.         long_ret = percent;
  732.         return ((u_char *) (&long_ret));
  733.     case ERRORFLAG:
  734.         long_ret = iserror;
  735.         return ((u_char *) (&long_ret));
  736.     case ERRORMSG:
  737.         if (iserror) {
  738.             if (disks[disknum].minimumspace >= 0)
  739.                 snprintf(errmsg, sizeof(errmsg),
  740.                         "%s: less than %d free (= %d)",
  741.                         disks[disknum].path, disks[disknum].minimumspace,
  742.                         avail * filesys.fs_fsize / 1024);
  743.             else
  744.                 snprintf(errmsg, sizeof(errmsg),
  745.                         "%s: less than %d%% free (= %d%%)",
  746.                         disks[disknum].path, disks[disknum].minpercent,
  747.                         percent);
  748.             errmsg[ sizeof(errmsg)-1 ] = 0;
  749.         } else
  750.             errmsg[0] = 0;
  751.         *var_len = strlen(errmsg);
  752.         return ((u_char *) (errmsg));
  753.     }
  754. #endif
  755. #endif
  756.     return NULL;
  757. }