Code

Fixed inode percent free output (Mike Emigh - 1531899)
[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 #if HAVE_INTTYPES_H
43 # include <inttypes.h>
44 #endif
45 #include <assert.h>
46 #include "popen.h"
47 #include "utils.h"
48 #include "utils_disk.h"
49 #include <stdarg.h>
50 #include "fsusage.h"
51 #include "mountlist.h"
52 #include "intprops.h"   /* necessary for TYPE_MAXIMUM */
53 #if HAVE_LIMITS_H
54 # include <limits.h>
55 #endif
58 /* If nonzero, show inode information. */
59 static int inode_format = 1;
61 /* If nonzero, show even filesystems with zero size or
62    uninteresting types. */
63 static int show_all_fs = 1;
65 /* If nonzero, show only local filesystems.  */
66 static int show_local_fs = 0;
68 /* If positive, the units to use when printing sizes;
69    if negative, the human-readable base.  */
70 /* static int output_block_size; */
72 /* If nonzero, invoke the `sync' system call before getting any usage data.
73    Using this option can make df very slow, especially with many or very
74    busy disks.  Note that this may make a difference on some systems --
75    SunOs4.1.3, for one.  It is *not* necessary on Linux.  */
76 /* static int require_sync = 0; */
78 /* Linked list of filesystem types to display.
79    If `fs_select_list' is NULL, list all types.
80    This table is generated dynamically from command-line options,
81    rather than hardcoding into the program what it thinks are the
82    valid filesystem types; let the user specify any filesystem type
83    they want to, and if there are any filesystems of that type, they
84    will be shown.
86    Some filesystem types:
87    4.2 4.3 ufs nfs swap ignore io vm efs dbg */
89 /* static struct parameter_list *fs_select_list; */
91 /* Linked list of filesystem types to omit.
92    If the list is empty, don't exclude any types.  */
94 static struct name_list *fs_exclude_list;
96 static struct name_list *dp_exclude_list;
98 static struct parameter_list *path_select_list = NULL;
100 /* Linked list of mounted filesystems. */
101 static struct mount_entry *mount_list;
103 /* For long options that have no equivalent short option, use a
104    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
105 enum
107   SYNC_OPTION = CHAR_MAX + 1,
108   NO_SYNC_OPTION,
109   BLOCK_SIZE_OPTION
110 };
112 #ifdef _AIX
113  #pragma alloca
114 #endif
116 /* Linked list of mounted filesystems. */
117 static struct mount_entry *mount_list;
119 int process_arguments (int, char **);
120 void print_path (const char *mypath);
121 int validate_arguments (uintmax_t, uintmax_t, double, double, double, double, char *);
122 void print_help (void);
123 void print_usage (void);
124 double calculate_percent(uintmax_t, uintmax_t);
126 double w_dfp = -1.0;
127 double c_dfp = -1.0;
128 char *path;
129 char *exclude_device;
130 char *units;
131 uintmax_t mult = 1024 * 1024;
132 int verbose = 0;
133 int erronly = FALSE;
134 int display_mntp = FALSE;
135 int exact_match = FALSE;
136 char *warn_freespace_units = NULL;
137 char *crit_freespace_units = NULL;
138 char *warn_freespace_percent = NULL;
139 char *crit_freespace_percent = NULL;
140 char *warn_usedspace_units = NULL;
141 char *crit_usedspace_units = NULL;
142 char *warn_usedspace_percent = NULL;
143 char *crit_usedspace_percent = NULL;
144 char *warn_usedinodes_percent = NULL;
145 char *crit_usedinodes_percent = NULL;
148 int
149 main (int argc, char **argv)
151   int result = STATE_UNKNOWN;
152   int disk_result = STATE_UNKNOWN;
153   char *output;
154   char *details;
155   char *perf;
156   double inode_space_pct;
157   uintmax_t total, available, available_to_root, used;
158   double dfree_pct = -1, dused_pct = -1;
159   double dused_units, dfree_units, dtotal_units;
160   double dused_inodes_percent, dfree_inodes_percent;
161   int temp_result;
163   struct mount_entry *me;
164   struct fs_usage fsp;
165   struct parameter_list *temp_list, *path;
166   struct name_list *seen = NULL;
168   output = strdup (" - free space:");
169   details = strdup ("");
170   perf = strdup ("");
172   setlocale (LC_ALL, "");
173   bindtextdomain (PACKAGE, LOCALEDIR);
174   textdomain (PACKAGE);
176   mount_list = read_file_system_list (0);
178   if (process_arguments (argc, argv) == ERROR)
179     usage4 (_("Could not parse arguments"));
181   /* If a list of paths has not been selected, find entire
182      mount list and create list of paths
183    */
184   if (! path_select_list) {
185     for (me = mount_list; me; me = me->me_next) {
186       path = np_add_parameter(&path_select_list, me->me_mountdir);
187       path->best_match = me;
188       set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
189       set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
190       set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
191       set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
192       set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
193     }
194   } else {
195     np_set_best_match(path_select_list, mount_list, exact_match);
197     /* Error if no match found for specified paths */
198     temp_list = path_select_list;
199     while (temp_list) {
200       if (! temp_list->best_match) {
201         die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), temp_list->name);
202       }
203       temp_list = temp_list->name_next;
204     }
205   }
207   /* Process for every path in list */
208   for (path = path_select_list; path; path=path->name_next) {
209     me = path->best_match;
211     /* Filters */
213     /* Remove filesystems already seen */
214     if (np_seen_name(seen, me->me_mountdir)) {
215       continue;
216     } else {
217       np_add_name(&seen, me->me_mountdir);
218     }
219     /* Skip remote filesystems if we're not interested in them */
220     if (me->me_remote && show_local_fs) {
221       continue;
222     /* Skip pseudo fs's if we haven't asked for all fs's */
223     } else if (me->me_dummy && !show_all_fs) {
224       continue;
225     /* Skip excluded fstypes */
226     } else if (fs_exclude_list && np_find_name (fs_exclude_list, me->me_type)) {
227       continue;
228     /* Skip excluded fs's */  
229     } else if (dp_exclude_list && 
230              (np_find_name (dp_exclude_list, me->me_devname) ||
231               np_find_name (dp_exclude_list, me->me_mountdir))) {
232       continue;
233     }
235     get_fs_usage (me->me_mountdir, me->me_devname, &fsp);
237     if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) {
238       total = fsp.fsu_blocks;
239       available = fsp.fsu_bavail;
240       available_to_root = fsp.fsu_bfree;
241       used = total - available_to_root;
243       dused_pct = calculate_percent( used, used + available );  /* used + available can never be > uintmax */
244      
245       dfree_pct = 100 - dused_pct;
246       dused_units = used*fsp.fsu_blocksize/mult;
247       dfree_units = available*fsp.fsu_blocksize/mult;
248       dtotal_units = total*fsp.fsu_blocksize/mult;
249       dused_inodes_percent = calculate_percent(fsp.fsu_files - fsp.fsu_ffree, fsp.fsu_files);
250       dfree_inodes_percent = 100 - dused_inodes_percent;
252       if (verbose >= 3) {
253         printf ("For %s, used_pct=%g free_pct=%g used_units=%g free_units=%g total_units=%g used_inodes_pct=%g\n", 
254           me->me_mountdir, dused_pct, dfree_pct, dused_units, dfree_units, dtotal_units, dused_inodes_percent);
255       }
257       /* Threshold comparisons */
259       temp_result = get_status(dfree_units, path->freespace_units);
260       if (verbose >=3) printf("Freespace_units result=%d\n", temp_result);
261       result = max_state( result, temp_result );
263       temp_result = get_status(dfree_pct, path->freespace_percent);
264       if (verbose >=3) printf("Freespace%% result=%d\n", temp_result);
265       result = max_state( result, temp_result );
267       temp_result = get_status(dused_units, path->usedspace_units);
268       if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result);
269       result = max_state( result, temp_result );
271       temp_result = get_status(dused_pct, path->usedspace_percent);
272       if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result);
273       result = max_state( result, temp_result );
275       temp_result = get_status(dused_inodes_percent, path->usedinodes_percent);
276       if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result);
277       result = max_state( result, temp_result );
279       asprintf (&perf, "%s %s", perf,
280                 perfdata ((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
281                           dused_units, units,
282                           FALSE, 0, /* min ((uintmax_t)dtotal_units-(uintmax_t)w_df, (uintmax_t)((1.0-w_dfp/100.0)*dtotal_units)), */
283                           FALSE, 0, /* min ((uintmax_t)dtotal_units-(uintmax_t)c_df, (uintmax_t)((1.0-c_dfp/100.0)*dtotal_units)), */
284                           FALSE, 0, /* inode_space_pct - this is not meant to be here???, */
285                           FALSE, 0));; /* dtotal_units)); */
287       if (disk_result==STATE_OK && erronly && !verbose)
288         continue;
290       if (disk_result!=STATE_OK || verbose>=0) {
291         asprintf (&output, "%s %s %.0f %s (%.0f%%",
292                   output,
293                   (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
294                   dfree_units,
295                   units,
296                   dfree_pct);
297         if (dused_inodes_percent < 0) {
298           asprintf(&output, "%s inode=-);", output);
299         } else {
300           asprintf(&output, "%s inode=%.0f%%);", output, dfree_inodes_percent );
301         }
302       }
304       /* TODO: Need to do a similar debug line
305       asprintf (&details, _("%s\n\
306 %.0f of %.0f %s (%.0f%% inode=%.0f%%) free on %s (type %s mounted on %s) warn:%lu crit:%lu warn%%:%.0f%% crit%%:%.0f%%"),
307                 details, dfree_units, dtotal_units, units, dfree_pct, inode_space_pct,
308                 me->me_devname, me->me_type, me->me_mountdir,
309                 (unsigned long)w_df, (unsigned long)c_df, w_dfp, c_dfp);
310       */
312     }
314   }
316   if (verbose > 2)
317     asprintf (&output, "%s%s", output, details);
320   printf ("DISK %s%s|%s\n", state_text (result), output, perf);
321   return result;
325 double calculate_percent(uintmax_t value, uintmax_t total) {
326   double pct = -1;
327   /* I don't understand the below, but it is taken from coreutils' df */
328   /* Seems to be calculating pct, in the best possible way */
329   if (value <= TYPE_MAXIMUM(uintmax_t) / 100 
330     && total != 0) {
331     uintmax_t u100 = value * 100;
332     pct = u100 / total + (u100 % total != 0);
333   } else {
334     /* Possible rounding errors - see coreutils' df for more explanation */
335     double u = value;
336     double t = total;
337     if (t) {
338       long int lipct = pct = u * 100 / t;
339       double ipct = lipct;
341       /* Like 'pct = ceil (dpct);', but without ceil - from coreutils again */
342       if (ipct - 1 < pct && pct <= ipct + 1)
343         pct = ipct + (ipct < pct);
344     }
345   }
346   return pct;
349 /* process command-line arguments */
350 int
351 process_arguments (int argc, char **argv)
353   int c;
354   struct parameter_list *se;
355   struct parameter_list *temp_list;
356   int result = OK;
357   struct stat *stat_buf;
359   int option = 0;
360   static struct option longopts[] = {
361     {"timeout", required_argument, 0, 't'},
362     {"warning", required_argument, 0, 'w'},
363     {"critical", required_argument, 0, 'c'},
364     {"iwarning", required_argument, 0, 'W'},
365     /* Dang, -C is taken. We might want to reshuffle this. */
366     {"icritical", required_argument, 0, 'K'},
367     {"local", required_argument, 0, 'l'},
368     {"kilobytes", required_argument, 0, 'k'},
369     {"megabytes", required_argument, 0, 'm'},
370     {"units", required_argument, 0, 'u'},
371     {"path", required_argument, 0, 'p'},
372     {"partition", required_argument, 0, 'p'},
373     {"exclude_device", required_argument, 0, 'x'},
374     {"exclude-type", required_argument, 0, 'X'},
375     {"mountpoint", no_argument, 0, 'M'},
376     {"errors-only", no_argument, 0, 'e'},
377     {"exact-match", no_argument, 0, 'E'},
378     {"verbose", no_argument, 0, 'v'},
379     {"quiet", no_argument, 0, 'q'},
380     {"clear", no_argument, 0, 'C'},
381     {"version", no_argument, 0, 'V'},
382     {"help", no_argument, 0, 'h'},
383     {0, 0, 0, 0}
384   };
386   if (argc < 2)
387     return ERROR;
389   np_add_name(&fs_exclude_list, "iso9660");
391   for (c = 1; c < argc; c++)
392     if (strcmp ("-to", argv[c]) == 0)
393       strcpy (argv[c], "-t");
395   while (1) {
396     c = getopt_long (argc, argv, "+?VqhveCt:c:w:K:W:u:p:x:X:mklME", longopts, &option);
398     if (c == -1 || c == EOF)
399       break;
401     switch (c) {
402     case 't':                 /* timeout period */
403       if (is_integer (optarg)) {
404         timeout_interval = atoi (optarg);
405         break;
406       }
407       else {
408         usage2 (_("Timeout interval must be a positive integer"), optarg);
409       }
411     /* See comments for 'c' */
412     case 'w':                 /* warning threshold */
413       if (strstr(optarg, "%")) {
414         if (*optarg == '@') {
415           warn_freespace_percent = optarg;
416         } else {
417           asprintf(&warn_freespace_percent, "@%s", optarg);
418         }
419       } else {
420         if (*optarg == '@') {
421           warn_freespace_units = optarg;
422         } else {
423           asprintf(&warn_freespace_units, "@%s", optarg);
424         }
425       }
426       break;
428     /* Awful mistake where the range values do not make sense. Normally, 
429        you alert if the value is within the range, but since we are using
430        freespace, we have to alert if outside the range. Thus we artifically
431        force @ at the beginning of the range, so that it is backwards compatible
432     */
433     case 'c':                 /* critical threshold */
434       if (strstr(optarg, "%")) {
435         if (*optarg == '@') {
436           crit_freespace_percent = optarg;
437         } else {
438           asprintf(&crit_freespace_percent, "@%s", optarg);
439         }
440       } else {
441         if (*optarg == '@') {
442           crit_freespace_units = optarg;
443         } else {
444           asprintf(&crit_freespace_units, "@%s", optarg);
445         }
446       }
447       break;
449     case 'W':                   /* warning inode threshold */
450       warn_usedinodes_percent = optarg;
451       break;
452     case 'K':                   /* critical inode threshold */
453       crit_usedinodes_percent = optarg;
454       break;
455     case 'u':
456       if (units)
457         free(units);
458       if (! strcmp (optarg, "bytes")) {
459         mult = (uintmax_t)1;
460         units = strdup ("B");
461       } else if (! strcmp (optarg, "kB")) {
462         mult = (uintmax_t)1024;
463         units = strdup ("kB");
464       } else if (! strcmp (optarg, "MB")) {
465         mult = (uintmax_t)1024 * 1024;
466         units = strdup ("MB");
467       } else if (! strcmp (optarg, "GB")) {
468         mult = (uintmax_t)1024 * 1024 * 1024;
469         units = strdup ("GB");
470       } else if (! strcmp (optarg, "TB")) {
471         mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
472         units = strdup ("TB");
473       } else {
474         die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
475       }
476       if (units == NULL)
477         die (STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
478       break;
479     case 'k': /* display mountpoint */
480       mult = 1024;
481       if (units)
482         free(units);
483       units = strdup ("kB");
484       break;
485     case 'm': /* display mountpoint */
486       mult = 1024 * 1024;
487       if (units)
488         free(units);
489       units = strdup ("MB");
490       break;
491     case 'l':
492       show_local_fs = 1;      
493       break;
494     case 'p':                 /* select path */
495       if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent || 
496              crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
497              warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
498              crit_usedinodes_percent)) {
499         die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
500       }
501       se = np_add_parameter(&path_select_list, optarg);
502       set_thresholds(&se->freespace_units, warn_freespace_units, crit_freespace_units);
503       set_thresholds(&se->freespace_percent, warn_freespace_percent, crit_freespace_percent);
504       set_thresholds(&se->usedspace_units, warn_usedspace_units, crit_usedspace_units);
505       set_thresholds(&se->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
506       set_thresholds(&se->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
507       break;
508     case 'x':                 /* exclude path or partition */
509       np_add_name(&dp_exclude_list, optarg);
510       break;
511     case 'X':                 /* exclude file system type */
512       np_add_name(&fs_exclude_list, optarg);
513       break;
514     case 'v':                 /* verbose */
515       verbose++;
516       break;
517     case 'q':                 /* verbose */
518       verbose--;
519       break;
520     case 'e':
521       erronly = TRUE;
522       break;
523     case 'E':
524       exact_match = TRUE;
525       break;
526     case 'M': /* display mountpoint */
527       display_mntp = TRUE;
528       break;
529     case 'C':
530       warn_freespace_units = NULL;
531       crit_freespace_units = NULL;
532       warn_usedspace_units = NULL;
533       crit_usedspace_units = NULL;
534       warn_freespace_percent = NULL;
535       crit_freespace_percent = NULL;
536       warn_usedspace_percent = NULL;
537       crit_usedspace_percent = NULL;
538       warn_usedinodes_percent = NULL;
539       crit_usedinodes_percent = NULL;
540       break;
541     case 'V':                 /* version */
542       print_revision (progname, revision);
543       exit (STATE_OK);
544     case 'h':                 /* help */
545       print_help ();
546       exit (STATE_OK);
547     case '?':                 /* help */
548       usage (_("Unknown argument"));
549     }
550   }
552   /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
553   c = optind;
554   if (warn_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
555     warn_usedspace_percent = argv[c++];
557   if (crit_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
558     crit_usedspace_percent = argv[c++];
560   if (argc > c && path == NULL) {
561     se = np_add_parameter(&path_select_list, strdup(argv[c++]));
562     set_thresholds(&se->freespace_units, warn_freespace_units, crit_freespace_units);
563     set_thresholds(&se->freespace_percent, warn_freespace_percent, crit_freespace_percent);
564     set_thresholds(&se->usedspace_units, warn_usedspace_units, crit_usedspace_units);
565     set_thresholds(&se->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
566     set_thresholds(&se->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
567   }
569   if (units == NULL) {
570     units = strdup ("MB");
571     mult = (uintmax_t)1024 * 1024;
572   }
574   if (path_select_list) {
575     temp_list = path_select_list;
576     stat_buf = malloc(sizeof *stat_buf);
577     while (temp_list) {
578       /* Stat each entry to check that dir exists */
579       if (stat (temp_list->name, &stat_buf[0])) {
580         printf("DISK %s - ", _("CRITICAL"));
581         die (STATE_CRITICAL, _("%s does not exist\n"), temp_list->name);
582       }
583       /* if (validate_arguments (temp_list->w_df,
584                               temp_list->c_df,
585                               temp_list->w_dfp,
586                               temp_list->c_dfp,
587                               temp_list->w_idfp,
588                               temp_list->c_idfp,
589                               temp_list->name) == ERROR)
590         result = ERROR;
591       */
592       temp_list = temp_list->name_next;
593     }
594     free(stat_buf);
595     return result;
596   } else {
597     return TRUE;
598     /* return validate_arguments (w_df, c_df, w_dfp, c_dfp, w_idfp, c_idfp, NULL); */
599   }
604 void
605 print_path (const char *mypath) 
607   if (mypath == NULL)
608     printf ("\n");
609   else
610     printf (_(" for %s\n"), mypath);
612   //return;
617 /* TODO: Remove?
619 int
620 validate_arguments (uintmax_t w, uintmax_t c, double wp, double cp, double iwp, double icp, char *mypath)
622   if (w < 0 && c < 0 && wp < 0.0 && cp < 0.0) {
623     printf (_("INPUT ERROR: No thresholds specified"));
624     print_path (mypath);
625     return ERROR;
626   }
627   else if ((wp >= 0.0 || cp >= 0.0) &&
628            (wp < 0.0 || cp < 0.0 || wp > 100.0 || cp > 100.0 || cp > wp)) {
629     printf (_("\
630 INPUT ERROR: C_DFP (%f) should be less than W_DFP (%.1f) and both should be between zero and 100 percent, inclusive"),
631             cp, wp);
632     print_path (mypath);
633     return ERROR;
634   }
635   else if ((iwp >= 0.0 || icp >= 0.0) &&
636            (iwp < 0.0 || icp < 0.0 || iwp > 100.0 || icp > 100.0 || icp > iwp)) {
637     printf (_("\
638 INPUT ERROR: C_IDFP (%f) should be less than W_IDFP (%.1f) and both should be between zero and 100 percent, inclusive"),
639             icp, iwp);
640     print_path (mypath);
641     return ERROR;
642   }
643   else if ((w > 0 || c > 0) && (w == 0 || c == 0 || c > w)) {
644     printf (_("\
645 INPUT ERROR: C_DF (%lu) should be less than W_DF (%lu) and both should be greater than zero"),
646             (unsigned long)c, (unsigned long)w);
647     print_path (mypath);
648     return ERROR;
649   }
650   
651   return OK;
654 */
662 void
663 print_help (void)
665   print_revision (progname, revision);
667   printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
668   printf (COPYRIGHT, copyright, email);
670   printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
671   printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
673   printf ("\n\n");
675   print_usage ();
677   printf (_(UT_HELP_VRSN));
679   printf (" %s\n", "-w, --warning=INTEGER");
680   printf ("    %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
681   printf (" %s\n", "-w, --warning=PERCENT%");
682   printf ("    %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
683   printf (" %s\n", "-W, --iwarning=PERCENT%");
684   printf ("    %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
685   printf (" %s\n", "-K, --icritical=PERCENT%");
686   printf ("    %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
687   printf (" %s\n", "-c, --critical=INTEGER");
688   printf ("    %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
689   printf (" %s\n", "-c, --critical=PERCENT%");
690   printf ("    %s\n", _("Exit with CRITCAL status if less than PERCENT of disk space is free"));
691   printf (" %s\n", "-C, --clear");
692   printf ("    %s\n", _("Clear thresholds"));
693   printf (" %s\n", "-u, --units=STRING");
694   printf ("    %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
695   printf (" %s\n", "-k, --kilobytes");
696   printf ("    %s\n", _("Same as '--units kB'"));
697   printf (" %s\n", "-m, --megabytes");
698   printf ("    %s\n", _("Same as '--units MB'"));
699   printf (" %s\n", "-l, --local");
700   printf ("    %s\n", _("Only check local filesystems"));
701   printf (" %s\n", "-p, --path=PATH, --partition=PARTITION");
702   printf ("    %s\n", _("Path or partition (may be repeated)"));
703   printf (" %s\n", "-x, --exclude_device=PATH <STRING>");
704   printf ("    %s\n", _("Ignore device (only works if -p unspecified)"));
705   printf (" %s\n", _("-X, --exclude-type=TYPE <STRING>"));
706   printf ("    %s\n", _("Ignore all filesystems of indicated type (may be repeated)"));
707   printf (" %s\n", "-m, --mountpoint");
708   printf ("    %s\n", _("Display the mountpoint instead of the partition"));
709   printf (" %s\n", "-E, --exact-match");
710   printf ("    %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
711   printf (" %s\n", "-e, --errors-only");
712   printf ("    %s\n", _("Display only devices/mountpoints with errors"));
713   printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
714   printf (_(UT_VERBOSE));
715   printf ("\n");
716   printf ("%s\n", _("Examples:"));
717   printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
718   printf ("    %s\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
719   printf (_(UT_SUPPORT));
724 void
725 print_usage (void)
727   printf (_("Usage:"));
728   printf (" %s -w limit -c limit [-p path | -x device] [-t timeout]", progname);
729   printf ("[-m] [-e] [-W limit] [-K limit] [-v] [-q] [-E]\n");