10095648f3bd9d14652056cedbd2e435dfbcca0e
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
109 {
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)
158 {
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 }
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))) {
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. */
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 */
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;
409 }
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;
434 }
436 /* process command-line arguments */
437 int
438 process_arguments (int argc, char **argv)
439 {
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;
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 }
716 }
720 void
721 print_path (const char *mypath)
722 {
723 if (mypath == NULL)
724 printf ("\n");
725 else
726 printf (_(" for %s\n"), mypath);
727 }
730 void
731 set_all_thresholds (struct parameter_list *path)
732 {
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);
739 }
741 /* TODO: Remove?
743 int
744 validate_arguments (uintmax_t w, uintmax_t c, double wp, double cp, double iwp, double icp, char *mypath)
745 {
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 }
775 return OK;
776 }
778 */
786 void
787 print_help (void)
788 {
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));
846 }
850 void
851 print_usage (void)
852 {
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");
856 }