Code

10095648f3bd9d14652056cedbd2e435dfbcca0e
[nagiosplug.git] / plugins / check_disk.c
1 /******************************************************************************
2 *
3 * Nagios check_disk plugin
4 *
5 * License: GPL
6 * Copyright (c) 1999-2006 nagios-plugins team
7 *
8 * Last Modified: $Date$
9 *
10 * Description:
11 *
12 * This file contains the check_disk plugin
13 *
14 * License Information:
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 * $Id$
31
32 *****************************************************************************/
34 const char *progname = "check_disk";
35 const char *program_name = "check_disk";  /* Required for coreutils libs */
36 const char *revision = "$Revision$";
37 const char *copyright = "1999-2006";
38 const char *email = "nagiosplug-devel@lists.sourceforge.net";
41 #include "common.h"
42 #ifdef HAVE_SYS_STAT_H
43 # include <sys/stat.h>
44 #endif
45 #if HAVE_INTTYPES_H
46 # include <inttypes.h>
47 #endif
48 #include <assert.h>
49 #include "popen.h"
50 #include "utils.h"
51 #include "utils_disk.h"
52 #include <stdarg.h>
53 #include "fsusage.h"
54 #include "mountlist.h"
55 #include "intprops.h"   /* necessary for TYPE_MAXIMUM */
56 #if HAVE_LIMITS_H
57 # include <limits.h>
58 #endif
61 /* If nonzero, show inode information. */
62 static int inode_format = 1;
64 /* If nonzero, show even filesystems with zero size or
65    uninteresting types. */
66 static int show_all_fs = 1;
68 /* If nonzero, show only local filesystems.  */
69 static int show_local_fs = 0;
71 /* If positive, the units to use when printing sizes;
72    if negative, the human-readable base.  */
73 /* static int output_block_size; */
75 /* If nonzero, invoke the `sync' system call before getting any usage data.
76    Using this option can make df very slow, especially with many or very
77    busy disks.  Note that this may make a difference on some systems --
78    SunOs4.1.3, for one.  It is *not* necessary on Linux.  */
79 /* static int require_sync = 0; */
81 /* Linked list of filesystem types to display.
82    If `fs_select_list' is NULL, list all types.
83    This table is generated dynamically from command-line options,
84    rather than hardcoding into the program what it thinks are the
85    valid filesystem types; let the user specify any filesystem type
86    they want to, and if there are any filesystems of that type, they
87    will be shown.
89    Some filesystem types:
90    4.2 4.3 ufs nfs swap ignore io vm efs dbg */
92 /* static struct parameter_list *fs_select_list; */
94 /* Linked list of filesystem types to omit.
95    If the list is empty, don't exclude any types.  */
97 static struct name_list *fs_exclude_list;
99 static struct name_list *dp_exclude_list;
101 static struct parameter_list *path_select_list = NULL;
103 /* Linked list of mounted filesystems. */
104 static struct mount_entry *mount_list;
106 /* For long options that have no equivalent short option, use a
107    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
108 enum
110   SYNC_OPTION = CHAR_MAX + 1,
111   NO_SYNC_OPTION,
112   BLOCK_SIZE_OPTION
113 };
115 #ifdef _AIX
116  #pragma alloca
117 #endif
119 /* Linked list of mounted filesystems. */
120 static struct mount_entry *mount_list;
122 int process_arguments (int, char **);
123 void print_path (const char *mypath);
124 void set_all_thresholds (struct parameter_list *path);
125 int validate_arguments (uintmax_t, uintmax_t, double, double, double, double, char *);
126 void print_help (void);
127 void print_usage (void);
128 double calculate_percent(uintmax_t, uintmax_t);
130 double w_dfp = -1.0;
131 double c_dfp = -1.0;
132 char *path;
133 char *exclude_device;
134 char *units;
135 uintmax_t mult = 1024 * 1024;
136 int verbose = 0;
137 int erronly = FALSE;
138 int display_mntp = FALSE;
139 int exact_match = FALSE;
140 char *warn_freespace_units = NULL;
141 char *crit_freespace_units = NULL;
142 char *warn_freespace_percent = NULL;
143 char *crit_freespace_percent = NULL;
144 char *warn_usedspace_units = NULL;
145 char *crit_usedspace_units = NULL;
146 char *warn_usedspace_percent = NULL;
147 char *crit_usedspace_percent = NULL;
148 char *warn_usedinodes_percent = NULL;
149 char *crit_usedinodes_percent = NULL;
150 char *warn_freeinodes_percent = NULL;
151 char *crit_freeinodes_percent = NULL;
152 bool path_selected = false;
153 char *group = NULL;
156 int
157 main (int argc, char **argv)
159   int result = STATE_UNKNOWN;
160   int disk_result = STATE_UNKNOWN;
161   char *output;
162   char *details;
163   char *perf;
164   char *preamble;
165   double inode_space_pct;
166   uintmax_t total, available, available_to_root, used;
167   double dfree_pct = -1, dused_pct = -1;
168   double dused_units, dfree_units, dtotal_units;
169   double dused_inodes_percent, dfree_inodes_percent;
170   double warning_high_tide;
171   double critical_high_tide;
172   int temp_result;
174   struct mount_entry *me;
175   struct fs_usage fsp, tmpfsp;
176   struct parameter_list *temp_list, *path;
177   struct name_list *seen = NULL;
179   preamble = strdup (" - free space:");
180   output = strdup ("");
181   details = strdup ("");
182   perf = strdup ("");
184   setlocale (LC_ALL, "");
185   bindtextdomain (PACKAGE, LOCALEDIR);
186   textdomain (PACKAGE);
188   mount_list = read_file_system_list (0);
190   if (process_arguments (argc, argv) == ERROR)
191     usage4 (_("Could not parse arguments"));
193   /* If a list of paths has not been selected, find entire
194      mount list and create list of paths
195    */
196   if (path_selected == false) { 
197     for (me = mount_list; me; me = me->me_next) {
198       if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) {
199         path = np_add_parameter(&path_select_list, me->me_mountdir);
200       }
201       path->best_match = me;
202       path->group = group;
203       set_all_thresholds(path);
204     }
205   }
206   np_set_best_match(path_select_list, mount_list, exact_match);
208   /* Error if no match found for specified paths */
209   temp_list = path_select_list;
210   while (temp_list) {
211     if (! temp_list->best_match) {
212       die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), temp_list->name);
213     }
214     temp_list = temp_list->name_next;
215   }
216   
218   /* Process for every path in list */
219   for (path = path_select_list; path; path=path->name_next) {
221     if (verbose > 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL)
222       printf("Thresholds(pct) for %s warn: %f crit %f\n",path->name, path->freespace_percent->warning->end,
223                                                          path->freespace_percent->critical->end);
225     if (verbose > 3 && path->group != NULL)
226       printf("Group of %s: %s\n",path->name,path->group);
228     /* reset disk result */
229     disk_result = STATE_UNKNOWN;
231     me = path->best_match;
233     /* Filters */
235     /* Remove filesystems already seen */
236     if (np_seen_name(seen, me->me_mountdir)) {
237       continue;
238     } else {
239       if (path->group != NULL) {
240         /* find all group members */
241         fsp.fsu_blocksize = 0;
242         fsp.fsu_blocks    = 0;
243         fsp.fsu_bfree     = 0;
244         fsp.fsu_bavail    = 0;
245         fsp.fsu_files     = 0;
246         fsp.fsu_ffree     = 0;
249         for (temp_list = path_select_list; temp_list; temp_list=temp_list->name_next) {
250           if (temp_list->group && ! (strcmp(temp_list->group, path->group))) {
251             
252             get_fs_usage (temp_list->best_match->me_mountdir, temp_list->best_match->me_devname, &tmpfsp);
254             /* possibly differing blocksizes if disks are grouped. Calculating average */
255             fsp.fsu_blocksize = (fsp.fsu_blocksize * fsp.fsu_blocks + tmpfsp.fsu_blocksize * tmpfsp.fsu_blocks) / \
256                                 (fsp.fsu_blocks + tmpfsp.fsu_blocks);  /* Size of a block.  */
257             fsp.fsu_blocks    += tmpfsp.fsu_blocks;     /* Total blocks. */
258             fsp.fsu_bfree     += tmpfsp.fsu_bfree;      /* Free blocks available to superuser. */
259             fsp.fsu_bavail    += tmpfsp.fsu_bavail;     /* Free blocks available to non-superuser. */
260             fsp.fsu_files     += tmpfsp.fsu_files;      /* Total file nodes. */
261             fsp.fsu_ffree     += tmpfsp.fsu_ffree;      /* Free file nodes. */
262             
263             if (verbose > 3)
264               printf("Group %s: add %llu blocks (%s) \n", path->group, tmpfsp.fsu_bavail, temp_list->name);
265              // printf("Group %s: add %u blocks (%s)\n", temp_list->name); // path->group, tmpfsp.fsu_bavail, temp_list->name);
267             np_add_name(&seen, temp_list->best_match->me_mountdir);
268           }
269         }
270         /* modify devname and mountdir for output */
271         me->me_mountdir = me->me_devname = path->group;
272       } else
273         np_add_name(&seen, me->me_mountdir);
274     }
276     if (path->group == NULL) {
277       /* Skip remote filesystems if we're not interested in them */
278       if (me->me_remote && show_local_fs) {
279         continue;
280       /* Skip pseudo fs's if we haven't asked for all fs's */
281       } else if (me->me_dummy && !show_all_fs) {
282         continue;
283       /* Skip excluded fstypes */
284       } else if (fs_exclude_list && np_find_name (fs_exclude_list, me->me_type)) {
285         continue;
286       /* Skip excluded fs's */  
287       } else if (dp_exclude_list && 
288                (np_find_name (dp_exclude_list, me->me_devname) ||
289                 np_find_name (dp_exclude_list, me->me_mountdir))) {
290         continue;
291       }
293       get_fs_usage (me->me_mountdir, me->me_devname, &fsp);
294     }
296     if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) {
297       total = fsp.fsu_blocks;
298       available = fsp.fsu_bavail;
299       available_to_root = fsp.fsu_bfree;
300       used = total - available_to_root;
302       dused_pct = calculate_percent( used, used + available );  /* used + available can never be > uintmax */
303      
304       dfree_pct = 100 - dused_pct;
305       dused_units = used*fsp.fsu_blocksize/mult;
306       dfree_units = available*fsp.fsu_blocksize/mult;
307       dtotal_units = total*fsp.fsu_blocksize/mult;
308       dused_inodes_percent = calculate_percent(fsp.fsu_files - fsp.fsu_ffree, fsp.fsu_files);
309       dfree_inodes_percent = 100 - dused_inodes_percent;
311       if (verbose >= 3) {
312         printf ("For %s, used_pct=%g free_pct=%g used_units=%g free_units=%g total_units=%g used_inodes_pct=%g free_inodes_pct=%g\n", 
313           me->me_mountdir, dused_pct, dfree_pct, dused_units, dfree_units, dtotal_units, dused_inodes_percent, dfree_inodes_percent);
314       }
316       /* Threshold comparisons */
318       temp_result = get_status(dfree_units, path->freespace_units);
319       if (verbose >=3) printf("Freespace_units result=%d\n", temp_result);
320       disk_result = max_state( disk_result, temp_result );
322       temp_result = get_status(dfree_pct, path->freespace_percent);
323       if (verbose >=3) printf("Freespace%% result=%d\n", temp_result);
324       disk_result = max_state( disk_result, temp_result );
326       temp_result = get_status(dused_units, path->usedspace_units);
327       if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result);
328       disk_result = max_state( disk_result, temp_result );
330       temp_result = get_status(dused_pct, path->usedspace_percent);
331       if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result);
332       disk_result = max_state( disk_result, temp_result );
334       temp_result = get_status(dused_inodes_percent, path->usedinodes_percent);
335       if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result);
336       disk_result = max_state( disk_result, temp_result );
338       temp_result = get_status(dfree_inodes_percent, path->freeinodes_percent);
339       if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result);
340       disk_result = max_state( disk_result, temp_result );
342       result = max_state(result, disk_result);
344       /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
345          Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
346          data. Assumption that start=0. Roll on new syntax...
347       */
349       /* *_high_tide must be reinitialized at each run */
350       warning_high_tide = UINT_MAX;
351       critical_high_tide = UINT_MAX;
353       if (path->freespace_units->warning != NULL) {
354         warning_high_tide = dtotal_units - path->freespace_units->warning->end;
355       }
356       if (path->freespace_percent->warning != NULL) {
357         warning_high_tide = abs( min( (double) warning_high_tide, (double) (1.0 - path->freespace_percent->warning->end/100)*dtotal_units ));
358       }
359       if (path->freespace_units->critical != NULL) {
360         critical_high_tide = dtotal_units - path->freespace_units->critical->end;
361       }
362       if (path->freespace_percent->critical != NULL) {
363         critical_high_tide = abs( min( (double) critical_high_tide, (double) (1.0 - path->freespace_percent->critical->end/100)*dtotal_units ));
364       }
366       asprintf (&perf, "%s %s", perf,
367                 perfdata ((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
368                           dused_units, units,
369                           (warning_high_tide != UINT_MAX ? TRUE : FALSE), warning_high_tide,
370                           (critical_high_tide != UINT_MAX ? TRUE : FALSE), critical_high_tide,
371                           TRUE, 0,
372                           TRUE, dtotal_units));
374       if (disk_result==STATE_OK && erronly && !verbose)
375         continue;
377       if (disk_result!=STATE_OK || verbose>=0) {
378         asprintf (&output, "%s %s %.0f %s (%.0f%%",
379                   output,
380                   (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
381                   dfree_units,
382                   units,
383                   dfree_pct);
384         if (dused_inodes_percent < 0) {
385           asprintf(&output, "%s inode=-);", output);
386         } else {
387           asprintf(&output, "%s inode=%.0f%%);", output, dfree_inodes_percent );
388         }
389       }
391       /* TODO: Need to do a similar debug line
392       asprintf (&details, _("%s\n\
393 %.0f of %.0f %s (%.0f%% inode=%.0f%%) free on %s (type %s mounted on %s) warn:%lu crit:%lu warn%%:%.0f%% crit%%:%.0f%%"),
394                 details, dfree_units, dtotal_units, units, dfree_pct, inode_space_pct,
395                 me->me_devname, me->me_type, me->me_mountdir,
396                 (unsigned long)w_df, (unsigned long)c_df, w_dfp, c_dfp);
397       */
399     }
401   }
403   if (verbose > 2)
404     asprintf (&output, "%s%s", output, details);
407   printf ("DISK %s%s%s|%s\n", state_text (result), (erronly && result==STATE_OK) ? "" : preamble, output, perf);
408   return result;
412 double calculate_percent(uintmax_t value, uintmax_t total) {
413   double pct = -1;
414   /* I don't understand the below, but it is taken from coreutils' df */
415   /* Seems to be calculating pct, in the best possible way */
416   if (value <= TYPE_MAXIMUM(uintmax_t) / 100 
417     && total != 0) {
418     uintmax_t u100 = value * 100;
419     pct = u100 / total + (u100 % total != 0);
420   } else {
421     /* Possible rounding errors - see coreutils' df for more explanation */
422     double u = value;
423     double t = total;
424     if (t) {
425       long int lipct = pct = u * 100 / t;
426       double ipct = lipct;
428       /* Like 'pct = ceil (dpct);', but without ceil - from coreutils again */
429       if (ipct - 1 < pct && pct <= ipct + 1)
430         pct = ipct + (ipct < pct);
431     }
432   }
433   return pct;
436 /* process command-line arguments */
437 int
438 process_arguments (int argc, char **argv)
440   int c;
441   struct parameter_list *se;
442   struct parameter_list *temp_list;
443   int result = OK;
444   struct stat *stat_buf;
446   int option = 0;
447   static struct option longopts[] = {
448     {"timeout", required_argument, 0, 't'},
449     {"warning", required_argument, 0, 'w'},
450     {"critical", required_argument, 0, 'c'},
451     {"iwarning", required_argument, 0, 'W'},
452     /* Dang, -C is taken. We might want to reshuffle this. */
453     {"icritical", required_argument, 0, 'K'},
454     {"local", required_argument, 0, 'l'},
455     {"kilobytes", required_argument, 0, 'k'},
456     {"megabytes", required_argument, 0, 'm'},
457     {"units", required_argument, 0, 'u'},
458     {"path", required_argument, 0, 'p'},
459     {"partition", required_argument, 0, 'p'},
460     {"exclude_device", required_argument, 0, 'x'},
461     {"exclude-type", required_argument, 0, 'X'},
462     {"group", required_argument, 0, 'g'},
463     {"mountpoint", no_argument, 0, 'M'},
464     {"errors-only", no_argument, 0, 'e'},
465     {"exact-match", no_argument, 0, 'E'},
466     {"verbose", no_argument, 0, 'v'},
467     {"quiet", no_argument, 0, 'q'},
468     {"clear", no_argument, 0, 'C'},
469     {"version", no_argument, 0, 'V'},
470     {"help", no_argument, 0, 'h'},
471     {0, 0, 0, 0}
472   };
474   if (argc < 2)
475     return ERROR;
477   np_add_name(&fs_exclude_list, "iso9660");
479   for (c = 1; c < argc; c++)
480     if (strcmp ("-to", argv[c]) == 0)
481       strcpy (argv[c], "-t");
483   while (1) {
484     c = getopt_long (argc, argv, "+?VqhveCt:c:w:K:W:u:p:x:X:mklg:ME", longopts, &option);
486     if (c == -1 || c == EOF)
487       break;
489     switch (c) {
490     case 't':                 /* timeout period */
491       if (is_integer (optarg)) {
492         timeout_interval = atoi (optarg);
493         break;
494       }
495       else {
496         usage2 (_("Timeout interval must be a positive integer"), optarg);
497       }
499     /* See comments for 'c' */
500     case 'w':                 /* warning threshold */
501       if (strstr(optarg, "%")) {
502         if (*optarg == '@') {
503           warn_freespace_percent = optarg;
504         } else {
505           asprintf(&warn_freespace_percent, "@%s", optarg);
506         }
507       } else {
508         if (*optarg == '@') {
509           warn_freespace_units = optarg;
510         } else {
511           asprintf(&warn_freespace_units, "@%s", optarg);
512         }
513       }
514       break;
516     /* Awful mistake where the range values do not make sense. Normally, 
517        you alert if the value is within the range, but since we are using
518        freespace, we have to alert if outside the range. Thus we artifically
519        force @ at the beginning of the range, so that it is backwards compatible
520     */
521     case 'c':                 /* critical threshold */
522       if (strstr(optarg, "%")) {
523         if (*optarg == '@') {
524           crit_freespace_percent = optarg;
525         } else {
526           asprintf(&crit_freespace_percent, "@%s", optarg);
527         }
528       } else {
529         if (*optarg == '@') {
530           crit_freespace_units = optarg;
531         } else {
532           asprintf(&crit_freespace_units, "@%s", optarg);
533         }
534       }
535       break;
537     case 'W':                   /* warning inode threshold */
538       if (*optarg == '@') {
539         warn_freeinodes_percent = optarg;
540       } else {
541         asprintf(&warn_freeinodes_percent, "@%s", optarg);
542       }
543       break;
544     case 'K':                   /* critical inode threshold */
545       if (*optarg == '@') {
546         crit_freeinodes_percent = optarg;
547       } else {
548         asprintf(&crit_freeinodes_percent, "@%s", optarg);
549       }
550       break;
551     case 'u':
552       if (units)
553         free(units);
554       if (! strcmp (optarg, "bytes")) {
555         mult = (uintmax_t)1;
556         units = strdup ("B");
557       } else if (! strcmp (optarg, "kB")) {
558         mult = (uintmax_t)1024;
559         units = strdup ("kB");
560       } else if (! strcmp (optarg, "MB")) {
561         mult = (uintmax_t)1024 * 1024;
562         units = strdup ("MB");
563       } else if (! strcmp (optarg, "GB")) {
564         mult = (uintmax_t)1024 * 1024 * 1024;
565         units = strdup ("GB");
566       } else if (! strcmp (optarg, "TB")) {
567         mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
568         units = strdup ("TB");
569       } else {
570         die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
571       }
572       if (units == NULL)
573         die (STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
574       break;
575     case 'k': /* display mountpoint */
576       mult = 1024;
577       if (units)
578         free(units);
579       units = strdup ("kB");
580       break;
581     case 'm': /* display mountpoint */
582       mult = 1024 * 1024;
583       if (units)
584         free(units);
585       units = strdup ("MB");
586       break;
587     case 'l':
588       show_local_fs = 1;      
589       break;
590     case 'p':                 /* select path */
591       if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent || 
592              crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
593              warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
594              crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) {
595         die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
596       }
598       /* add parameter if not found. overwrite thresholds if path has already been added  */
599       if (! (se = np_find_parameter(path_select_list, optarg))) {
600           se = np_add_parameter(&path_select_list, optarg);
601       }
602       se->group = group;
603       set_all_thresholds(se);
604       path_selected = true;
605       break;
606     case 'x':                 /* exclude path or partition */
607       np_add_name(&dp_exclude_list, optarg);
608       break;
609     case 'X':                 /* exclude file system type */
610       np_add_name(&fs_exclude_list, optarg);
611       break;
612     case 'v':                 /* verbose */
613       verbose++;
614       break;
615     case 'q':                 /* verbose */
616       verbose--;
617       break;
618     case 'e':
619       erronly = TRUE;
620       break;
621     case 'E':
622       exact_match = TRUE;
623       break;
624     case 'g':
625       if (path_selected)
626         die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before using -p\n"));
627       group = optarg;
628       break;
629     case 'M': /* display mountpoint */
630       display_mntp = TRUE;
631       break;
632     case 'C':
633        /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
634        if (path_selected == false) {
635          struct mount_entry *me;
636          struct parameter_list *path;
637          for (me = mount_list; me; me = me->me_next) {
638            if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) 
639              path = np_add_parameter(&path_select_list, me->me_mountdir);
640            path->best_match = me;
641            path->group = group;
642            set_all_thresholds(path);
643          }
644       }
645       warn_freespace_units = NULL;
646       crit_freespace_units = NULL;
647       warn_usedspace_units = NULL;
648       crit_usedspace_units = NULL;
649       warn_freespace_percent = NULL;
650       crit_freespace_percent = NULL;
651       warn_usedspace_percent = NULL;
652       crit_usedspace_percent = NULL;
653       warn_usedinodes_percent = NULL;
654       crit_usedinodes_percent = NULL;
655       warn_freeinodes_percent = NULL;
656       crit_freeinodes_percent = NULL;
657     
658       path_selected = false;
659       group = NULL;
660       break;
661     case 'V':                 /* version */
662       print_revision (progname, revision);
663       exit (STATE_OK);
664     case 'h':                 /* help */
665       print_help ();
666       exit (STATE_OK);
667     case '?':                 /* help */
668       usage (_("Unknown argument"));
669     }
670   }
672   /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
673   c = optind;
674   if (warn_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
675     warn_usedspace_percent = argv[c++];
677   if (crit_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
678     crit_usedspace_percent = argv[c++];
680   if (argc > c && path == NULL) {
681     se = np_add_parameter(&path_select_list, strdup(argv[c++]));
682     set_all_thresholds(se);
683   }
685   if (units == NULL) {
686     units = strdup ("MB");
687     mult = (uintmax_t)1024 * 1024;
688   }
690   if (path_select_list) {
691     temp_list = path_select_list;
692     stat_buf = malloc(sizeof *stat_buf);
693     while (temp_list) {
694       /* Stat each entry to check that dir exists */
695       if (stat (temp_list->name, &stat_buf[0])) {
696         printf("DISK %s - ", _("CRITICAL"));
697         die (STATE_CRITICAL, _("%s does not exist\n"), temp_list->name);
698       }
699       /* if (validate_arguments (temp_list->w_df,
700                               temp_list->c_df,
701                               temp_list->w_dfp,
702                               temp_list->c_dfp,
703                               temp_list->w_idfp,
704                               temp_list->c_idfp,
705                               temp_list->name) == ERROR)
706         result = ERROR;
707       */
708       temp_list = temp_list->name_next;
709     }
710     free(stat_buf);
711     return result;
712   } else {
713     return TRUE;
714     /* return validate_arguments (w_df, c_df, w_dfp, c_dfp, w_idfp, c_idfp, NULL); */
715   }
720 void
721 print_path (const char *mypath) 
723   if (mypath == NULL)
724     printf ("\n");
725   else
726     printf (_(" for %s\n"), mypath);
730 void
731 set_all_thresholds (struct parameter_list *path) 
733     set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
734     set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
735     set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
736     set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
737     set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
738     set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent);
741 /* TODO: Remove?
743 int
744 validate_arguments (uintmax_t w, uintmax_t c, double wp, double cp, double iwp, double icp, char *mypath)
746   if (w < 0 && c < 0 && wp < 0.0 && cp < 0.0) {
747     printf (_("INPUT ERROR: No thresholds specified"));
748     print_path (mypath);
749     return ERROR;
750   }
751   else if ((wp >= 0.0 || cp >= 0.0) &&
752            (wp < 0.0 || cp < 0.0 || wp > 100.0 || cp > 100.0 || cp > wp)) {
753     printf (_("\
754 INPUT ERROR: C_DFP (%f) should be less than W_DFP (%.1f) and both should be between zero and 100 percent, inclusive"),
755             cp, wp);
756     print_path (mypath);
757     return ERROR;
758   }
759   else if ((iwp >= 0.0 || icp >= 0.0) &&
760            (iwp < 0.0 || icp < 0.0 || iwp > 100.0 || icp > 100.0 || icp > iwp)) {
761     printf (_("\
762 INPUT ERROR: C_IDFP (%f) should be less than W_IDFP (%.1f) and both should be between zero and 100 percent, inclusive"),
763             icp, iwp);
764     print_path (mypath);
765     return ERROR;
766   }
767   else if ((w > 0 || c > 0) && (w == 0 || c == 0 || c > w)) {
768     printf (_("\
769 INPUT ERROR: C_DF (%lu) should be less than W_DF (%lu) and both should be greater than zero"),
770             (unsigned long)c, (unsigned long)w);
771     print_path (mypath);
772     return ERROR;
773   }
774   
775   return OK;
778 */
786 void
787 print_help (void)
789   print_revision (progname, revision);
791   printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
792   printf (COPYRIGHT, copyright, email);
794   printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
795   printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
797   printf ("\n\n");
799   print_usage ();
801   printf (_(UT_HELP_VRSN));
803   printf (" %s\n", "-w, --warning=INTEGER");
804   printf ("    %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
805   printf (" %s\n", "-w, --warning=PERCENT%");
806   printf ("    %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
807   printf (" %s\n", "-W, --iwarning=PERCENT%");
808   printf ("    %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
809   printf (" %s\n", "-K, --icritical=PERCENT%");
810   printf ("    %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
811   printf (" %s\n", "-c, --critical=INTEGER");
812   printf ("    %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
813   printf (" %s\n", "-c, --critical=PERCENT%");
814   printf ("    %s\n", _("Exit with CRITCAL status if less than PERCENT of disk space is free"));
815   printf (" %s\n", "-C, --clear");
816   printf ("    %s\n", _("Clear thresholds"));
817   printf (" %s\n", "-u, --units=STRING");
818   printf ("    %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
819   printf (" %s\n", "-k, --kilobytes");
820   printf ("    %s\n", _("Same as '--units kB'"));
821   printf (" %s\n", "-m, --megabytes");
822   printf ("    %s\n", _("Same as '--units MB'"));
823   printf (" %s\n", "-l, --local");
824   printf ("    %s\n", _("Only check local filesystems"));
825   printf (" %s\n", "-p, --path=PATH, --partition=PARTITION");
826   printf ("    %s\n", _("Path or partition (may be repeated)"));
827   printf (" %s\n", "-g, --group=NAME");
828   printf ("    %s\n", _("Group pathes. Thresholds apply to (free-)space of all partitions together"));
829   printf (" %s\n", "-x, --exclude_device=PATH <STRING>");
830   printf ("    %s\n", _("Ignore device (only works if -p unspecified)"));
831   printf (" %s\n", "-X, --exclude-type=TYPE <STRING>");
832   printf ("    %s\n", _("Ignore all filesystems of indicated type (may be repeated)"));
833   printf (" %s\n", "-M, --mountpoint");
834   printf ("    %s\n", _("Display the mountpoint instead of the partition"));
835   printf (" %s\n", "-E, --exact-match");
836   printf ("    %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
837   printf (" %s\n", "-e, --errors-only");
838   printf ("    %s\n", _("Display only devices/mountpoints with errors"));
839   printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
840   printf (_(UT_VERBOSE));
841   printf ("\n");
842   printf ("%s\n", _("Examples:"));
843   printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
844   printf ("    %s\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
845   printf (_(UT_SUPPORT));
850 void
851 print_usage (void)
853   printf (_("Usage:"));
854   printf (" %s -w limit -c limit [-p path | -x device] [-t timeout]", progname);
855   printf ("[-m] [-e] [-W limit] [-K limit] [-v] [-q] [-E]\n");