Code

Major fixes to check_disk. Now should return same data as df
[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);
125 double w_dfp = -1.0;
126 double c_dfp = -1.0;
127 char *path;
128 char *exclude_device;
129 char *units;
130 uintmax_t mult = 1024 * 1024;
131 int verbose = 0;
132 int erronly = FALSE;
133 int display_mntp = FALSE;
134 int exact_match = FALSE;
135 char *warn_freespace_units = NULL;
136 char *crit_freespace_units = NULL;
137 char *warn_freespace_percent = NULL;
138 char *crit_freespace_percent = NULL;
139 char *warn_usedspace_units = NULL;
140 char *crit_usedspace_units = NULL;
141 char *warn_usedspace_percent = NULL;
142 char *crit_usedspace_percent = NULL;
143 char *warn_usedinodes_percent = NULL;
144 char *crit_usedinodes_percent = NULL;
147 int
148 main (int argc, char **argv)
150   int result = STATE_UNKNOWN;
151   int disk_result = STATE_UNKNOWN;
152   char *output;
153   char *details;
154   char *perf;
155   float inode_space_pct;
156   uintmax_t total, available, available_to_root, used;
157   double dfree_pct = -1, dused_pct = -1;
158   double dused_units, dfree_units, dtotal_units;
159   double dused_inodes_percent;
160   int temp_result;
162   struct mount_entry *me;
163   struct fs_usage fsp;
164   struct parameter_list *temp_list, *path;
165   struct name_list *seen = NULL;
167   output = strdup (" - free space:");
168   details = strdup ("");
169   perf = strdup ("");
171   setlocale (LC_ALL, "");
172   bindtextdomain (PACKAGE, LOCALEDIR);
173   textdomain (PACKAGE);
175   mount_list = read_file_system_list (0);
177   if (process_arguments (argc, argv) == ERROR)
178     usage4 (_("Could not parse arguments"));
180   /* If a list of paths has not been selected, find entire
181      mount list and create list of paths
182    */
183   if (! path_select_list) {
184     for (me = mount_list; me; me = me->me_next) {
185       path = np_add_parameter(&path_select_list, me->me_mountdir);
186       path->best_match = me;
187       set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
188       set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
189       set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
190       set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
191       set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
192     }
193   } else {
194     np_set_best_match(path_select_list, mount_list, exact_match);
196     /* Error if no match found for specified paths */
197     temp_list = path_select_list;
198     while (temp_list) {
199       if (! temp_list->best_match) {
200         die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), temp_list->name);
201       }
202       temp_list = temp_list->name_next;
203     }
204   }
206   /* Process for every path in list */
207   for (path = path_select_list; path; path=path->name_next) {
208     me = path->best_match;
210     /* Filters */
212     /* Remove filesystems already seen */
213     if (np_seen_name(seen, me->me_mountdir)) {
214       continue;
215     } else {
216       np_add_name(&seen, me->me_mountdir);
217     }
218     /* Skip remote filesystems if we're not interested in them */
219     if (me->me_remote && show_local_fs) {
220       continue;
221     /* Skip pseudo fs's if we haven't asked for all fs's */
222     } else if (me->me_dummy && !show_all_fs) {
223       continue;
224     /* Skip excluded fstypes */
225     } else if (fs_exclude_list && np_find_name (fs_exclude_list, me->me_type)) {
226       continue;
227     /* Skip excluded fs's */  
228     } else if (dp_exclude_list && 
229              (np_find_name (dp_exclude_list, me->me_devname) ||
230               np_find_name (dp_exclude_list, me->me_mountdir))) {
231       continue;
232     }
234     get_fs_usage (me->me_mountdir, me->me_devname, &fsp);
236     if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) {
237       total = fsp.fsu_blocks;
238       available = fsp.fsu_bavail;
239       available_to_root = fsp.fsu_bfree;
240       used = total - available_to_root;
242       /* I don't understand the below, but it is taken from coreutils' df */
243       /* Is setting dused_pct, in the best possible way */
244       if (used <= TYPE_MAXIMUM(uintmax_t) / 100) {
245         uintmax_t u100 = used * 100;
246         uintmax_t nonroot_total = used + available;
247         dused_pct = u100 / nonroot_total + (u100 % nonroot_total != 0);
248       } else {
249         /* Possible rounding errors - see coreutils' df for more explanation */
250         double u = used;
251         double a = available;
252         double nonroot_total = u + a;
253         if (nonroot_total) {
254           long int lipct = dused_pct = u * 100 / nonroot_total;
255           double ipct = lipct;
257           /* Like 'pct = ceil (dpct);', but without ceil - from coreutils again */
258           if (ipct - 1 < dused_pct && dused_pct <= ipct + 1)
259             dused_pct = ipct + (ipct < dused_pct);
260         }
261       }
263       dfree_pct = 100 - dused_pct;
264       dused_units = used*fsp.fsu_blocksize/mult;
265       dfree_units = available*fsp.fsu_blocksize/mult;
266       dtotal_units = total*fsp.fsu_blocksize/mult;
267       dused_inodes_percent = (fsp.fsu_files - fsp.fsu_ffree) * 100 / fsp.fsu_files;
269       if (verbose >= 3) {
270         printf ("For %s, used_pct=%g free_pct=%g used_units=%g free_units=%g total_units=%g used_inodes_pct=%g\n", 
271           me->me_mountdir, dused_pct, dfree_pct, dused_units, dfree_units, dtotal_units, dused_inodes_percent);
272       }
274       /* Threshold comparisons */
276       temp_result = get_status(dfree_units, path->freespace_units);
277       if (verbose >=3) printf("Freespace_units result=%d\n", temp_result);
278       result = max_state( result, temp_result );
280       temp_result = get_status(dfree_pct, path->freespace_percent);
281       if (verbose >=3) printf("Freespace%% result=%d\n", temp_result);
282       result = max_state( result, temp_result );
284       temp_result = get_status(dused_units, path->usedspace_units);
285       if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result);
286       result = max_state( result, temp_result );
288       temp_result = get_status(dused_pct, path->usedspace_percent);
289       if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result);
290       result = max_state( result, temp_result );
292       temp_result = get_status(dused_inodes_percent, path->usedinodes_percent);
293       if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result);
294       result = max_state( result, temp_result );
296       
300                         /* Moved this computation up here so we can add it
301                          * to perf */
302                         inode_space_pct = (float)fsp.fsu_ffree*100/fsp.fsu_files;
305       asprintf (&perf, "%s %s", perf,
306                 perfdata ((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
307                           dused_units, units,
308                           FALSE, 0, /* min ((uintmax_t)dtotal_units-(uintmax_t)w_df, (uintmax_t)((1.0-w_dfp/100.0)*dtotal_units)), */
309                           FALSE, 0, /* min ((uintmax_t)dtotal_units-(uintmax_t)c_df, (uintmax_t)((1.0-c_dfp/100.0)*dtotal_units)), */
310                           FALSE, 0, /* inode_space_pct, */
311                           FALSE, 0));; /* dtotal_units)); */
313       if (disk_result==STATE_OK && erronly && !verbose)
314         continue;
316       if (disk_result!=STATE_OK || verbose>=0) {
317         asprintf (&output, ("%s %s %.0f %s (%.0f%% inode=%.0f%%);"),
318                   output,
319                   (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
320                   dfree_units,
321                   units,
322             dfree_pct,
323             inode_space_pct);
324       }
326       /* Need to do a similar one
327       asprintf (&details, _("%s\n\
328 %.0f of %.0f %s (%.0f%% inode=%.0f%%) free on %s (type %s mounted on %s) warn:%lu crit:%lu warn%%:%.0f%% crit%%:%.0f%%"),
329                 details, dfree_units, dtotal_units, units, dfree_pct, inode_space_pct,
330                 me->me_devname, me->me_type, me->me_mountdir,
331                 (unsigned long)w_df, (unsigned long)c_df, w_dfp, c_dfp);
332       */
334     }
336   }
338   if (verbose > 2)
339     asprintf (&output, "%s%s", output, details);
342   printf ("DISK %s%s|%s\n", state_text (result), output, perf);
343   return result;
348 /* process command-line arguments */
349 int
350 process_arguments (int argc, char **argv)
352   int c;
353   struct parameter_list *se;
354   struct parameter_list *temp_list;
355   int result = OK;
356   struct stat *stat_buf;
358   int option = 0;
359   static struct option longopts[] = {
360     {"timeout", required_argument, 0, 't'},
361     {"warning", required_argument, 0, 'w'},
362     {"critical", required_argument, 0, 'c'},
363     {"iwarning", required_argument, 0, 'W'},
364     /* Dang, -C is taken. We might want to reshuffle this. */
365     {"icritical", required_argument, 0, 'K'},
366     {"local", required_argument, 0, 'l'},
367     {"kilobytes", required_argument, 0, 'k'},
368     {"megabytes", required_argument, 0, 'm'},
369     {"units", required_argument, 0, 'u'},
370     {"path", required_argument, 0, 'p'},
371     {"partition", required_argument, 0, 'p'},
372     {"exclude_device", required_argument, 0, 'x'},
373     {"exclude-type", required_argument, 0, 'X'},
374     {"mountpoint", no_argument, 0, 'M'},
375     {"errors-only", no_argument, 0, 'e'},
376     {"exact-match", no_argument, 0, 'E'},
377     {"verbose", no_argument, 0, 'v'},
378     {"quiet", no_argument, 0, 'q'},
379     {"clear", no_argument, 0, 'C'},
380     {"version", no_argument, 0, 'V'},
381     {"help", no_argument, 0, 'h'},
382     {0, 0, 0, 0}
383   };
385   if (argc < 2)
386     return ERROR;
388   np_add_name(&fs_exclude_list, "iso9660");
390   for (c = 1; c < argc; c++)
391     if (strcmp ("-to", argv[c]) == 0)
392       strcpy (argv[c], "-t");
394   while (1) {
395     c = getopt_long (argc, argv, "+?VqhveCt:c:w:K:W:u:p:x:X:mklME", longopts, &option);
397     if (c == -1 || c == EOF)
398       break;
400     switch (c) {
401     case 't':                 /* timeout period */
402       if (is_integer (optarg)) {
403         timeout_interval = atoi (optarg);
404         break;
405       }
406       else {
407         usage2 (_("Timeout interval must be a positive integer"), optarg);
408       }
410     /* See comments for 'c' */
411     case 'w':                 /* warning threshold */
412       if (strstr(optarg, "%")) {
413         if (*optarg == '@') {
414           warn_freespace_percent = optarg;
415         } else {
416           asprintf(&warn_freespace_percent, "@%s", optarg);
417         }
418       } else {
419         if (*optarg == '@') {
420           warn_freespace_units = optarg;
421         } else {
422           asprintf(&warn_freespace_units, "@%s", optarg);
423         }
424       }
425       break;
427     /* Awful mistake where the range values do not make sense. Normally, 
428        you alert if the value is within the range, but since we are using
429        freespace, we have to alert if outside the range. Thus we artifically
430        force @ at the beginning of the range, so that it is backwards compatible
431     */
432     case 'c':                 /* critical threshold */
433       if (strstr(optarg, "%")) {
434         if (*optarg == '@') {
435           crit_freespace_percent = optarg;
436         } else {
437           asprintf(&crit_freespace_percent, "@%s", optarg);
438         }
439       } else {
440         if (*optarg == '@') {
441           crit_freespace_units = optarg;
442         } else {
443           asprintf(&crit_freespace_units, "@%s", optarg);
444         }
445       }
446       break;
448     case 'W':                   /* warning inode threshold */
449       warn_usedinodes_percent = optarg;
450       break;
451     case 'K':                   /* critical inode threshold */
452       crit_usedinodes_percent = optarg;
453       break;
454     case 'u':
455       if (units)
456         free(units);
457       if (! strcmp (optarg, "bytes")) {
458         mult = (uintmax_t)1;
459         units = strdup ("B");
460       } else if (! strcmp (optarg, "kB")) {
461         mult = (uintmax_t)1024;
462         units = strdup ("kB");
463       } else if (! strcmp (optarg, "MB")) {
464         mult = (uintmax_t)1024 * 1024;
465         units = strdup ("MB");
466       } else if (! strcmp (optarg, "GB")) {
467         mult = (uintmax_t)1024 * 1024 * 1024;
468         units = strdup ("GB");
469       } else if (! strcmp (optarg, "TB")) {
470         mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
471         units = strdup ("TB");
472       } else {
473         die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
474       }
475       if (units == NULL)
476         die (STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
477       break;
478     case 'k': /* display mountpoint */
479       mult = 1024;
480       if (units)
481         free(units);
482       units = strdup ("kB");
483       break;
484     case 'm': /* display mountpoint */
485       mult = 1024 * 1024;
486       if (units)
487         free(units);
488       units = strdup ("MB");
489       break;
490     case 'l':
491       show_local_fs = 1;      
492       break;
493     case 'p':                 /* select path */
494       if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent || 
495              crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
496              warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
497              crit_usedinodes_percent)) {
498         die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
499       }
500       se = np_add_parameter(&path_select_list, optarg);
501       set_thresholds(&se->freespace_units, warn_freespace_units, crit_freespace_units);
502       set_thresholds(&se->freespace_percent, warn_freespace_percent, crit_freespace_percent);
503       set_thresholds(&se->usedspace_units, warn_usedspace_units, crit_usedspace_units);
504       set_thresholds(&se->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
505       set_thresholds(&se->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
506       break;
507     case 'x':                 /* exclude path or partition */
508       np_add_name(&dp_exclude_list, optarg);
509       break;
510     case 'X':                 /* exclude file system type */
511       np_add_name(&fs_exclude_list, optarg);
512       break;
513     case 'v':                 /* verbose */
514       verbose++;
515       break;
516     case 'q':                 /* verbose */
517       verbose--;
518       break;
519     case 'e':
520       erronly = TRUE;
521       break;
522     case 'E':
523       exact_match = TRUE;
524       break;
525     case 'M': /* display mountpoint */
526       display_mntp = TRUE;
527       break;
528     case 'C':
529       warn_freespace_units = NULL;
530       crit_freespace_units = NULL;
531       warn_usedspace_units = NULL;
532       crit_usedspace_units = NULL;
533       warn_freespace_percent = NULL;
534       crit_freespace_percent = NULL;
535       warn_usedspace_percent = NULL;
536       crit_usedspace_percent = NULL;
537       warn_usedinodes_percent = NULL;
538       crit_usedinodes_percent = NULL;
539       break;
540     case 'V':                 /* version */
541       print_revision (progname, revision);
542       exit (STATE_OK);
543     case 'h':                 /* help */
544       print_help ();
545       exit (STATE_OK);
546     case '?':                 /* help */
547       usage (_("Unknown argument"));
548     }
549   }
551   /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
552   c = optind;
553   if (warn_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
554     warn_usedspace_percent = argv[c++];
556   if (crit_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
557     crit_usedspace_percent = argv[c++];
559   if (argc > c && path == NULL) {
560     se = np_add_parameter(&path_select_list, strdup(argv[c++]));
561     set_thresholds(&se->freespace_units, warn_freespace_units, crit_freespace_units);
562     set_thresholds(&se->freespace_percent, warn_freespace_percent, crit_freespace_percent);
563     set_thresholds(&se->usedspace_units, warn_usedspace_units, crit_usedspace_units);
564     set_thresholds(&se->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
565     set_thresholds(&se->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
566   }
568   if (units == NULL) {
569     units = strdup ("MB");
570     mult = (uintmax_t)1024 * 1024;
571   }
573   if (path_select_list) {
574     temp_list = path_select_list;
575     stat_buf = malloc(sizeof *stat_buf);
576     while (temp_list) {
577       /* Stat each entry to check that dir exists */
578       if (stat (temp_list->name, &stat_buf[0])) {
579         printf("DISK %s - ", _("CRITICAL"));
580         die (STATE_CRITICAL, _("%s does not exist\n"), temp_list->name);
581       }
582       /* if (validate_arguments (temp_list->w_df,
583                               temp_list->c_df,
584                               temp_list->w_dfp,
585                               temp_list->c_dfp,
586                               temp_list->w_idfp,
587                               temp_list->c_idfp,
588                               temp_list->name) == ERROR)
589         result = ERROR;
590       */
591       temp_list = temp_list->name_next;
592     }
593     free(stat_buf);
594     return result;
595   } else {
596     return TRUE;
597     /* return validate_arguments (w_df, c_df, w_dfp, c_dfp, w_idfp, c_idfp, NULL); */
598   }
603 void
604 print_path (const char *mypath) 
606   if (mypath == NULL)
607     printf ("\n");
608   else
609     printf (_(" for %s\n"), mypath);
611   //return;
616 /* TODO: Remove?
618 int
619 validate_arguments (uintmax_t w, uintmax_t c, double wp, double cp, double iwp, double icp, char *mypath)
621   if (w < 0 && c < 0 && wp < 0.0 && cp < 0.0) {
622     printf (_("INPUT ERROR: No thresholds specified"));
623     print_path (mypath);
624     return ERROR;
625   }
626   else if ((wp >= 0.0 || cp >= 0.0) &&
627            (wp < 0.0 || cp < 0.0 || wp > 100.0 || cp > 100.0 || cp > wp)) {
628     printf (_("\
629 INPUT ERROR: C_DFP (%f) should be less than W_DFP (%.1f) and both should be between zero and 100 percent, inclusive"),
630             cp, wp);
631     print_path (mypath);
632     return ERROR;
633   }
634   else if ((iwp >= 0.0 || icp >= 0.0) &&
635            (iwp < 0.0 || icp < 0.0 || iwp > 100.0 || icp > 100.0 || icp > iwp)) {
636     printf (_("\
637 INPUT ERROR: C_IDFP (%f) should be less than W_IDFP (%.1f) and both should be between zero and 100 percent, inclusive"),
638             icp, iwp);
639     print_path (mypath);
640     return ERROR;
641   }
642   else if ((w > 0 || c > 0) && (w == 0 || c == 0 || c > w)) {
643     printf (_("\
644 INPUT ERROR: C_DF (%lu) should be less than W_DF (%lu) and both should be greater than zero"),
645             (unsigned long)c, (unsigned long)w);
646     print_path (mypath);
647     return ERROR;
648   }
649   
650   return OK;
653 */
661 void
662 print_help (void)
664   print_revision (progname, revision);
666   printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
667   printf (COPYRIGHT, copyright, email);
669   printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
670   printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
672   printf ("\n\n");
674   print_usage ();
676   printf (_(UT_HELP_VRSN));
678   printf (" %s\n", "-w, --warning=INTEGER");
679   printf ("    %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
680   printf (" %s\n", "-w, --warning=PERCENT%");
681   printf ("    %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
682   printf (" %s\n", "-W, --iwarning=PERCENT%");
683   printf ("    %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
684   printf (" %s\n", "-K, --icritical=PERCENT%");
685   printf ("    %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
686   printf (" %s\n", "-c, --critical=INTEGER");
687   printf ("    %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
688   printf (" %s\n", "-c, --critical=PERCENT%");
689   printf ("    %s\n", _("Exit with CRITCAL status if less than PERCENT of disk space is free"));
690   printf (" %s\n", "-C, --clear");
691   printf ("    %s\n", _("Clear thresholds"));
692   printf (" %s\n", "-u, --units=STRING");
693   printf ("    %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
694   printf (" %s\n", "-k, --kilobytes");
695   printf ("    %s\n", _("Same as '--units kB'"));
696   printf (" %s\n", "-m, --megabytes");
697   printf ("    %s\n", _("Same as '--units MB'"));
698   printf (" %s\n", "-l, --local");
699   printf ("    %s\n", _("Only check local filesystems"));
700   printf (" %s\n", "-p, --path=PATH, --partition=PARTITION");
701   printf ("    %s\n", _("Path or partition (may be repeated)"));
702   printf (" %s\n", "-x, --exclude_device=PATH <STRING>");
703   printf ("    %s\n", _("Ignore device (only works if -p unspecified)"));
704   printf (" %s\n", _("-X, --exclude-type=TYPE <STRING>"));
705   printf ("    %s\n", _("Ignore all filesystems of indicated type (may be repeated)"));
706   printf (" %s\n", "-m, --mountpoint");
707   printf ("    %s\n", _("Display the mountpoint instead of the partition"));
708   printf (" %s\n", "-E, --exact-match");
709   printf ("    %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
710   printf (" %s\n", "-e, --errors-only");
711   printf ("    %s\n", _("Display only devices/mountpoints with errors"));
712   printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
713   printf (_(UT_VERBOSE));
714   printf ("\n");
715   printf ("%s\n", _("Examples:"));
716   printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
717   printf ("    %s\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
718   printf (_(UT_SUPPORT));
723 void
724 print_usage (void)
726   printf (_("Usage:"));
727   printf (" %s -w limit -c limit [-p path | -x device] [-t timeout]", progname);
728   printf ("[-m] [-e] [-W limit] [-K limit] [-v] [-q] [-E]\n");