X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=plugins%2Fcheck_disk.c;h=f2ed983bfb97320f3666b3f011a60eef58b8a3e9;hb=884aee06674755ef44e4042803ae84a0faac5b10;hp=c758530e71c33ac5a307ef481d149791186b2903;hpb=b07cec408f61acd3c34ad1c03b212bba9b66c454;p=nagiosplug.git diff --git a/plugins/check_disk.c b/plugins/check_disk.c index c758530..f2ed983 100644 --- a/plugins/check_disk.c +++ b/plugins/check_disk.c @@ -1,116 +1,60 @@ -/****************************************************************************** -* -* This program is free software; you can redistribute it and/or modify +/***************************************************************************** +* +* Nagios check_disk plugin +* +* License: GPL +* Copyright (c) 1999-2008 Nagios Plugins Development Team +* +* Description: +* +* This file contains the check_disk plugin +* +* +* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or +* the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* +* along with this program. If not, see . +* +* *****************************************************************************/ const char *progname = "check_disk"; -const char *revision = "$Revision$"; -const char *copyright = "1999-2003"; +const char *program_name = "check_disk"; /* Required for coreutils libs */ +const char *copyright = "1999-2008"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; + #include "common.h" +#ifdef HAVE_SYS_STAT_H +# include +#endif #if HAVE_INTTYPES_H # include #endif #include #include "popen.h" #include "utils.h" +#include "utils_disk.h" #include -#include "../lib/fsusage.h" -#include "../lib/mountlist.h" +#include "fsusage.h" +#include "mountlist.h" +#include "intprops.h" /* necessary for TYPE_MAXIMUM */ #if HAVE_LIMITS_H # include #endif +#include "regex.h" -void -print_usage (void) -{ - printf (_("\ -Usage: %s -w limit -c limit [-p path | -x device] [-t timeout] [-m] [-e]\n\ - [-v] [-q]\n\ - %s (-h|--help)\n\ - %s (-V|--version)\n"), - progname, progname, progname); -} - -void -print_help (void) -{ - print_revision (progname, revision); - - printf (_(COPYRIGHT), copyright, email); - - printf (_("\ -This plugin checks the amount of used disk space on a mounted file system\n\ -and generates an alert if free space is less than one of the threshold values.")); - - print_usage (); - - printf (_(UT_HELP_VRSN)); - - printf (_("\ - -w, --warning=INTEGER\n\ - Exit with WARNING status if less than INTEGER kilobytes of disk are free\n\ - -w, --warning=PERCENT%%\n\ - Exit with WARNING status if less than PERCENT of disk space is free\n\ - -c, --critical=INTEGER\n\ - Exit with CRITICAL status if less than INTEGER kilobytes of disk are free\n\ - -c, --critical=PERCENT%%\n\ - Exit with CRITCAL status if less than PERCENT of disk space is free\n\ - -C, --clear\n\ - Clear thresholds\n")); - - printf (_("\ - -u, --units=STRING\n\ - Choose bytes, kB, MB, GB, TB (default: MB)\n\ - -k, --kilobytes\n\ - Same as '--units kB'\n\ - -m, --megabytes\n\ - Same as '--units MB'\n")); - - printf (_("\ - -l, --local\n\ - Only check local filesystems\n\ - -p, --path=PATH, --partition=PARTITION\n\ - Path or partition (may be repeated)\n\ - -x, --exclude_device=PATH \n\ - Ignore device (only works if -p unspecified)\n\ - -X, --exclude-type=TYPE \n\ - Ignore all filesystems of indicated type (may be repeated)\n\ - -M, --mountpoint\n\ - Display the mountpoint instead of the partition\n\ - -e, --errors-only\n\ - Display only devices/mountpoints with errors\n")); - - printf (_(UT_WARN_CRIT)); - - printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT); - - printf (_(UT_VERBOSE)); - - printf ("%s", _("Examples:\n\ - check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /\n\ - Checks /tmp and /var at 10%,5% and / at 100MB, 50MB\n")); - - support (); -} - /* If nonzero, show inode information. */ -/* static int inode_format; */ +static int inode_format = 1; /* If nonzero, show even filesystems with zero size or uninteresting types. */ @@ -119,6 +63,9 @@ static int show_all_fs = 1; /* If nonzero, show only local filesystems. */ static int show_local_fs = 0; +/* If nonzero, show only local filesystems but call stat() on remote ones. */ +static int stat_remote_fs = 0; + /* If positive, the units to use when printing sizes; if negative, the human-readable base. */ /* static int output_block_size; */ @@ -129,19 +76,6 @@ static int show_local_fs = 0; SunOs4.1.3, for one. It is *not* necessary on Linux. */ /* static int require_sync = 0; */ -/* A filesystem type to display. */ - -struct name_list -{ - char *name; - int found; - int w_df; - int c_df; - double w_dfp; - double c_dfp; - struct name_list *name_next; -}; - /* Linked list of filesystem types to display. If `fs_select_list' is NULL, list all types. This table is generated dynamically from command-line options, @@ -153,7 +87,7 @@ struct name_list Some filesystem types: 4.2 4.3 ufs nfs swap ignore io vm efs dbg */ -/* static struct name_list *fs_select_list; */ +/* static struct parameter_list *fs_select_list; */ /* Linked list of filesystem types to omit. If the list is empty, don't exclude any types. */ @@ -162,9 +96,7 @@ static struct name_list *fs_exclude_list; static struct name_list *dp_exclude_list; -static struct name_list *path_select_list; - -static struct name_list *dev_select_list; +static struct parameter_list *path_select_list = NULL; /* Linked list of mounted filesystems. */ static struct mount_entry *mount_list; @@ -183,407 +115,884 @@ enum #endif int process_arguments (int, char **); -int validate_arguments (int, int, double, double, char *); -int check_disk (int usp, int free_disk); -int walk_name_list (struct name_list *list, const char *name); +void print_path (const char *mypath); +void set_all_thresholds (struct parameter_list *path); +int validate_arguments (uintmax_t, uintmax_t, double, double, double, double, char *); +void print_help (void); +void print_usage (void); +double calculate_percent(uintmax_t, uintmax_t); +void stat_path (struct parameter_list *p); -int w_df = -1; -int c_df = -1; double w_dfp = -1.0; double c_dfp = -1.0; -char *path = ""; -char *exclude_device = ""; -char *units = "MB"; -unsigned long mult = 1024 * 1024; +char *path; +char *exclude_device; +char *units; +uintmax_t mult = 1024 * 1024; int verbose = 0; int erronly = FALSE; int display_mntp = FALSE; +int exact_match = FALSE; +char *warn_freespace_units = NULL; +char *crit_freespace_units = NULL; +char *warn_freespace_percent = NULL; +char *crit_freespace_percent = NULL; +char *warn_usedspace_units = NULL; +char *crit_usedspace_units = NULL; +char *warn_usedspace_percent = NULL; +char *crit_usedspace_percent = NULL; +char *warn_usedinodes_percent = NULL; +char *crit_usedinodes_percent = NULL; +char *warn_freeinodes_percent = NULL; +char *crit_freeinodes_percent = NULL; +int path_selected = FALSE; +char *group = NULL; +struct stat *stat_buf; -/* Linked list of mounted filesystems. */ -static struct mount_entry *mount_list; int main (int argc, char **argv) { - int usp = -1; - int result = STATE_UNKNOWN; - int disk_result = STATE_UNKNOWN; - char file_system[MAX_INPUT_BUFFER]; - char *output = ""; - char *details = ""; - float free_space, free_space_pct, total_space; - - struct mount_entry *me; - struct fs_usage fsp; - struct name_list *temp_list; - - mount_list = read_filesystem_list (0); - - if (process_arguments (argc, argv) != OK) - usage (_("Could not parse arguments\n")); - - for (me = mount_list; me; me = me->me_next) { - - if (path_select_list && - (walk_name_list (path_select_list, me->me_mountdir) || - walk_name_list (path_select_list, me->me_devname) ) ) - get_fs_usage (me->me_mountdir, me->me_devname, &fsp); - else if (dev_select_list || path_select_list) - continue; - else if (me->me_remote && show_local_fs) - continue; - else if (me->me_dummy && !show_all_fs) - continue; - else if (fs_exclude_list && walk_name_list (fs_exclude_list, me->me_type)) - continue; - else if (dp_exclude_list && - (walk_name_list (dp_exclude_list, me->me_devname) || - walk_name_list (dp_exclude_list, me->me_mountdir))) - continue; - else - get_fs_usage (me->me_mountdir, me->me_devname, &fsp); - - if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { - usp = (fsp.fsu_blocks - fsp.fsu_bavail) * 100 / fsp.fsu_blocks; - disk_result = check_disk (usp, fsp.fsu_bavail); - result = max_state (disk_result, result); - if (disk_result==STATE_OK && erronly && !verbose) - continue; - - free_space = (float)fsp.fsu_bavail*fsp.fsu_blocksize/mult; - free_space_pct = (float)fsp.fsu_bavail*100/fsp.fsu_blocks; - total_space = (float)fsp.fsu_blocks*fsp.fsu_blocksize/mult; - if (disk_result!=STATE_OK || verbose>=0) - asprintf (&output, ("%s [%.0f %s (%.0f%%) free on %s]"), - output, - free_space, - units, - free_space_pct, - (!strcmp(file_system, "none") || display_mntp) ? me->me_devname : me->me_mountdir); - asprintf (&details, _("%s\n%.0f of %.0f %s (%.0f%%) free on %s (type %s mounted on %s) warn:%d crit:%d warn%%:%.0f%% crit%%:%.0f%%"), - details, - free_space, - total_space, - units, - free_space_pct, - me->me_devname, - me->me_type, - me->me_mountdir, - w_df, c_df, w_dfp, c_dfp); - } - - } - - if (verbose > 2) - asprintf (&output, "%s%s", output, details); - - /* Override result if paths specified and not found */ - temp_list = path_select_list; - while (temp_list) { - if (temp_list->found != TRUE) { - asprintf (&output, _("%s [%s not found]"), output, temp_list->name); - result = STATE_CRITICAL; - } - temp_list = temp_list->name_next; - } - - terminate (result, "DISK %s%s\n", state_text (result), output, details); - return STATE_UNKNOWN; + int result = STATE_UNKNOWN; + int disk_result = STATE_UNKNOWN; + char *output; + char *details; + char *perf; + char *preamble; + double inode_space_pct; + uintmax_t total, available, available_to_root, used; + double dfree_pct = -1, dused_pct = -1; + double dused_units, dfree_units, dtotal_units; + double dused_inodes_percent, dfree_inodes_percent; + double warning_high_tide; + double critical_high_tide; + int temp_result; + + struct mount_entry *me; + struct fs_usage fsp, tmpfsp; + struct parameter_list *temp_list, *path; + struct name_list *seen = NULL; + + preamble = strdup (" - free space:"); + output = strdup (""); + details = strdup (""); + perf = strdup (""); + stat_buf = malloc(sizeof *stat_buf); + + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + mount_list = read_file_system_list (0); + + /* Parse extra opts if any */ + argv = np_extra_opts (&argc, argv, progname); + + if (process_arguments (argc, argv) == ERROR) + usage4 (_("Could not parse arguments")); + + /* If a list of paths has not been selected, find entire + mount list and create list of paths + */ + if (path_selected == FALSE) { + for (me = mount_list; me; me = me->me_next) { + if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) { + path = np_add_parameter(&path_select_list, me->me_mountdir); + } + path->best_match = me; + path->group = group; + set_all_thresholds(path); + } + } + np_set_best_match(path_select_list, mount_list, exact_match); + + /* Error if no match found for specified paths */ + temp_list = path_select_list; + + while (temp_list) { + if (! temp_list->best_match) { + die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), temp_list->name); + } + + temp_list = temp_list->name_next; + } + + /* Process for every path in list */ + for (path = path_select_list; path; path=path->name_next) { + + if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) + printf("Thresholds(pct) for %s warn: %f crit %f\n",path->name, path->freespace_percent->warning->end, + path->freespace_percent->critical->end); + + if (verbose >= 3 && path->group != NULL) + printf("Group of %s: %s\n",path->name,path->group); + + /* reset disk result */ + disk_result = STATE_UNKNOWN; + + me = path->best_match; + + /* Filters */ + + /* Remove filesystems already seen */ + if (np_seen_name(seen, me->me_mountdir)) { + continue; + } else { + if (path->group != NULL) { + /* find all group members */ + fsp.fsu_blocksize = 0; + fsp.fsu_blocks = 0; + fsp.fsu_bfree = 0; + fsp.fsu_bavail = 0; + fsp.fsu_files = 0; + fsp.fsu_ffree = 0; + + + for (temp_list = path_select_list; temp_list; temp_list=temp_list->name_next) { + if (temp_list->group && ! (strcmp(temp_list->group, path->group))) { + + stat_path(path); + get_fs_usage (temp_list->best_match->me_mountdir, temp_list->best_match->me_devname, &tmpfsp); + + /* possibly differing blocksizes if disks are grouped. Calculating average */ + fsp.fsu_blocksize = (fsp.fsu_blocksize * fsp.fsu_blocks + tmpfsp.fsu_blocksize * tmpfsp.fsu_blocks) / \ + (fsp.fsu_blocks + tmpfsp.fsu_blocks); /* Size of a block. */ + fsp.fsu_blocks += tmpfsp.fsu_blocks; /* Total blocks. */ + fsp.fsu_bfree += tmpfsp.fsu_bfree; /* Free blocks available to superuser. */ + /* Gnulib workaround - see comment about it a few lines below */ + fsp.fsu_bavail += (tmpfsp.fsu_bavail > tmpfsp.fsu_bfree ? 0 : tmpfsp.fsu_bavail); /* Free blocks available to non-superuser. */ + fsp.fsu_files += tmpfsp.fsu_files; /* Total file nodes. */ + fsp.fsu_ffree += tmpfsp.fsu_ffree; /* Free file nodes. */ + + if (verbose >= 3) + printf("Group %s: add %llu blocks (%s) \n", path->group, tmpfsp.fsu_bavail, temp_list->name); + /* printf("Group %s: add %u blocks (%s)\n", temp_list->name); *//* path->group, tmpfsp.fsu_bavail, temp_list->name); */ + + np_add_name(&seen, temp_list->best_match->me_mountdir); + } + } + /* modify devname and mountdir for output */ + me->me_mountdir = me->me_devname = path->group; + } else + np_add_name(&seen, me->me_mountdir); + } + + if (path->group == NULL) { + /* Skip remote filesystems if we're not interested in them */ + if (me->me_remote && show_local_fs) { + if (stat_remote_fs) + stat_path(path); + continue; + /* Skip pseudo fs's if we haven't asked for all fs's */ + } else if (me->me_dummy && !show_all_fs) { + continue; + /* Skip excluded fstypes */ + } else if (fs_exclude_list && np_find_name (fs_exclude_list, me->me_type)) { + continue; + /* Skip excluded fs's */ + } else if (dp_exclude_list && + (np_find_name (dp_exclude_list, me->me_devname) || + np_find_name (dp_exclude_list, me->me_mountdir))) { + continue; + } + + stat_path(path); + get_fs_usage (me->me_mountdir, me->me_devname, &fsp); + } + + if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { + total = fsp.fsu_blocks; + /* 2007-12-08 - Workaround for Gnulib reporting insanely high available + * space on BSD (the actual value should be negative but fsp.fsu_bavail + * is unsigned) */ + available = fsp.fsu_bavail > fsp.fsu_bfree ? 0 : fsp.fsu_bavail; + available_to_root = fsp.fsu_bfree; + used = total - available_to_root; + + if (verbose >= 3) + printf ("For %s, total=%llu, available=%llu, available_to_root=%llu, used=%llu, fsp.fsu_files=%llu, fsp.fsu_ffree=%llu\n", + me->me_mountdir, total, available, available_to_root, used, fsp.fsu_files, fsp.fsu_ffree); + + dused_pct = calculate_percent( used, used + available ); /* used + available can never be > uintmax */ + + dfree_pct = 100 - dused_pct; + dused_units = used*fsp.fsu_blocksize/mult; + dfree_units = available*fsp.fsu_blocksize/mult; + dtotal_units = total*fsp.fsu_blocksize/mult; + dused_inodes_percent = calculate_percent(fsp.fsu_files - fsp.fsu_ffree, fsp.fsu_files); + dfree_inodes_percent = 100 - dused_inodes_percent; + + if (verbose >= 3) { + 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 fsp.fsu_blocksize=%llu mult=%llu\n", + me->me_mountdir, dused_pct, dfree_pct, dused_units, dfree_units, dtotal_units, dused_inodes_percent, dfree_inodes_percent, fsp.fsu_blocksize, mult); + } + + /* Threshold comparisons */ + + temp_result = get_status(dfree_units, path->freespace_units); + if (verbose >=3) printf("Freespace_units result=%d\n", temp_result); + disk_result = max_state( disk_result, temp_result ); + + temp_result = get_status(dfree_pct, path->freespace_percent); + if (verbose >=3) printf("Freespace%% result=%d\n", temp_result); + disk_result = max_state( disk_result, temp_result ); + + temp_result = get_status(dused_units, path->usedspace_units); + if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result); + disk_result = max_state( disk_result, temp_result ); + + temp_result = get_status(dused_pct, path->usedspace_percent); + if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result); + disk_result = max_state( disk_result, temp_result ); + + temp_result = get_status(dused_inodes_percent, path->usedinodes_percent); + if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result); + disk_result = max_state( disk_result, temp_result ); + + temp_result = get_status(dfree_inodes_percent, path->freeinodes_percent); + if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result); + disk_result = max_state( disk_result, temp_result ); + + result = max_state(result, disk_result); + + /* What a mess of units. The output shows free space, the perf data shows used space. Yikes! + Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf + data. Assumption that start=0. Roll on new syntax... + */ + + /* *_high_tide must be reinitialized at each run */ + warning_high_tide = UINT_MAX; + critical_high_tide = UINT_MAX; + + if (path->freespace_units->warning != NULL) { + warning_high_tide = dtotal_units - path->freespace_units->warning->end; + } + if (path->freespace_percent->warning != NULL) { + warning_high_tide = abs( min( (double) warning_high_tide, (double) (1.0 - path->freespace_percent->warning->end/100)*dtotal_units )); + } + if (path->freespace_units->critical != NULL) { + critical_high_tide = dtotal_units - path->freespace_units->critical->end; + } + if (path->freespace_percent->critical != NULL) { + critical_high_tide = abs( min( (double) critical_high_tide, (double) (1.0 - path->freespace_percent->critical->end/100)*dtotal_units )); + } + + /* Nb: *_high_tide are unset when == UINT_MAX */ + asprintf (&perf, "%s %s", perf, + perfdata ((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, + dused_units, units, + (warning_high_tide != UINT_MAX ? TRUE : FALSE), warning_high_tide, + (critical_high_tide != UINT_MAX ? TRUE : FALSE), critical_high_tide, + TRUE, 0, + TRUE, dtotal_units)); + + if (disk_result==STATE_OK && erronly && !verbose) + continue; + + asprintf (&output, "%s %s %.0f %s (%.0f%%", + output, + (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, + dfree_units, + units, + dfree_pct); + if (dused_inodes_percent < 0) { + asprintf(&output, "%s inode=-);", output); + } else { + asprintf(&output, "%s inode=%.0f%%);", output, dfree_inodes_percent ); + } + + /* TODO: Need to do a similar debug line + asprintf (&details, _("%s\n\ +%.0f of %.0f %s (%.0f%% inode=%.0f%%) free on %s (type %s mounted on %s) warn:%lu crit:%lu warn%%:%.0f%% crit%%:%.0f%%"), + details, dfree_units, dtotal_units, units, dfree_pct, inode_space_pct, + me->me_devname, me->me_type, me->me_mountdir, + (unsigned long)w_df, (unsigned long)c_df, w_dfp, c_dfp); + */ + + } + + } + + if (verbose >= 2) + asprintf (&output, "%s%s", output, details); + + + printf ("DISK %s%s%s|%s\n", state_text (result), (erronly && result==STATE_OK) ? "" : preamble, output, perf); + return result; } +double calculate_percent(uintmax_t value, uintmax_t total) { + double pct = -1; + /* I don't understand the below, but it is taken from coreutils' df */ + /* Seems to be calculating pct, in the best possible way */ + if (value <= TYPE_MAXIMUM(uintmax_t) / 100 + && total != 0) { + uintmax_t u100 = value * 100; + pct = u100 / total + (u100 % total != 0); + } else { + /* Possible rounding errors - see coreutils' df for more explanation */ + double u = value; + double t = total; + if (t) { + long int lipct = pct = u * 100 / t; + double ipct = lipct; + + /* Like 'pct = ceil (dpct);', but without ceil - from coreutils again */ + if (ipct - 1 < pct && pct <= ipct + 1) + pct = ipct + (ipct < pct); + } + } + return pct; +} - /* process command-line arguments */ int process_arguments (int argc, char **argv) { - int c; - struct name_list *se; - struct name_list **pathtail = &path_select_list; - struct name_list **fstail = &fs_exclude_list; - struct name_list **dptail = &dp_exclude_list; - struct name_list *temp_list; - int result = OK; - - int option_index = 0; - static struct option long_options[] = { - {"timeout", required_argument, 0, 't'}, - {"warning", required_argument, 0, 'w'}, - {"critical", required_argument, 0, 'c'}, - {"local", required_argument, 0, 'l'}, - {"kilobytes", required_argument, 0, 'k'}, - {"megabytes", required_argument, 0, 'm'}, - {"units", required_argument, 0, 'u'}, - {"path", required_argument, 0, 'p'}, - {"partition", required_argument, 0, 'p'}, - {"exclude_device", required_argument, 0, 'x'}, - {"exclude-type", required_argument, 0, 'X'}, - {"mountpoint", no_argument, 0, 'M'}, - {"errors-only", no_argument, 0, 'e'}, - {"verbose", no_argument, 0, 'v'}, - {"quiet", no_argument, 0, 'q'}, - {"clear", no_argument, 0, 'C'}, - {"version", no_argument, 0, 'V'}, - {"help", no_argument, 0, 'h'}, - {0, 0, 0, 0} - }; - - if (argc < 2) - return ERROR; - - se = (struct name_list *) malloc (sizeof (struct name_list)); - se->name = strdup ("iso9660"); - se->name_next = NULL; - *fstail = se; - fstail = &se->name_next; - - for (c = 1; c < argc; c++) - if (strcmp ("-to", argv[c]) == 0) - strcpy (argv[c], "-t"); - - while (1) { - c = getopt_long (argc, argv, "+?VqhveCt:c:w:u:p:x:X:mklM", long_options, &option_index); - - if (c == -1 || c == EOF) - break; - - switch (c) { - case 't': /* timeout period */ - if (is_integer (optarg)) { - timeout_interval = atoi (optarg); - break; - } - else { - usage (_("Timeout Interval must be an integer!\n")); - } - case 'w': /* warning threshold */ - if (is_intnonneg (optarg)) { - w_df = atoi (optarg); - break; - } - else if (strpbrk (optarg, ",:") && - strstr (optarg, "%") && - sscanf (optarg, "%d%*[:,]%lf%%", &w_df, &w_dfp) == 2) { - break; - } - else if (strstr (optarg, "%") && sscanf (optarg, "%lf%%", &w_dfp) == 1) { - break; - } - else { - usage (_("Warning threshold must be integer or percentage!\n")); - } - case 'c': /* critical threshold */ - if (is_intnonneg (optarg)) { - c_df = atoi (optarg); - break; - } - else if (strpbrk (optarg, ",:") && - strstr (optarg, "%") && - sscanf (optarg, "%d%*[,:]%lf%%", &c_df, &c_dfp) == 2) { - break; - } - else if (strstr (optarg, "%") && sscanf (optarg, "%lf%%", &c_dfp) == 1) { - break; - } - else { - usage (_("Critical threshold must be integer or percentage!\n")); - } - case 'u': - if (! strcmp (optarg, "bytes")) { - mult = 1; - units = "B"; - } else if (! strcmp (optarg, "kB")) { - mult = 1024; - units = "kB"; - } else if (! strcmp (optarg, "MB")) { - mult = 1024 * 1024; - units = "MB"; - } else if (! strcmp (optarg, "GB")) { - mult = 1024 * 1024 * 1024; - units = "GB"; - } else if (! strcmp (optarg, "TB")) { - mult = (unsigned long)1024 * 1024 * 1024 * 1024; - units = "TB"; - } else { - terminate (STATE_UNKNOWN, _("unit type %s not known\n"), optarg); - } - break; - case 'k': /* display mountpoint */ - mult = 1024; - units = "kB"; - break; - case 'm': /* display mountpoint */ - mult = 1024 * 1024; - units = "MB"; - break; - case 'l': - show_local_fs = 1; - break; - case 'p': /* select path */ - se = (struct name_list *) malloc (sizeof (struct name_list)); - se->name = strdup (optarg); - se->name_next = NULL; - se->w_df = w_df; - se->c_df = c_df; - se->w_dfp = w_dfp; - se->c_dfp = c_dfp; - *pathtail = se; - pathtail = &se->name_next; - break; - case 'x': /* exclude path or partition */ - se = (struct name_list *) malloc (sizeof (struct name_list)); - se->name = strdup (optarg); - se->name_next = NULL; - *dptail = se; - dptail = &se->name_next; - break; - case 'X': /* exclude file system type */ - se = (struct name_list *) malloc (sizeof (struct name_list)); - se->name = strdup (optarg); - se->name_next = NULL; - *fstail = se; - fstail = &se->name_next; - break; - case 'v': /* verbose */ - verbose++; - break; - case 'q': /* verbose */ - verbose--; - break; - case 'e': - erronly = TRUE; - break; - case 'M': /* display mountpoint */ - display_mntp = TRUE; - break; - case 'C': - w_df = -1; - c_df = -1; - w_dfp = -1.0; - c_dfp = -1.0; - break; - case 'V': /* version */ - print_revision (progname, revision); - exit (STATE_OK); - case 'h': /* help */ - print_help (); - exit (STATE_OK); - case '?': /* help */ - usage (_("check_disk: unrecognized option\n")); - break; - } - } - - /* Support for "check_disk warn crit [fs]" with thresholds at used level */ - c = optind; - if (w_dfp == -1 && argc > c && is_intnonneg (argv[c])) - w_dfp = (100.0 - atof (argv[c++])); - - if (c_dfp == -1 && argc > c && is_intnonneg (argv[c])) - c_dfp = (100.0 - atof (argv[c++])); - - if (argc > c && strlen (path) == 0) { - se = (struct name_list *) malloc (sizeof (struct name_list)); - se->name = strdup (argv[c++]); - se->name_next = NULL; - se->w_df = w_df; - se->c_df = c_df; - se->w_dfp = w_dfp; - se->c_dfp = c_dfp; - *pathtail = se; - } - - if (path_select_list) { - temp_list = path_select_list; - while (temp_list) { - if (validate_arguments (temp_list->w_df, - temp_list->c_df, - temp_list->w_dfp, - temp_list->c_dfp, - temp_list->name) == ERROR) - result = ERROR; - temp_list = temp_list->name_next; - } - return result; - } else { - return validate_arguments (w_df, c_df, w_dfp, c_dfp, NULL); - } + int c, err; + struct parameter_list *se; + struct parameter_list *temp_list = NULL, *previous = NULL; + struct parameter_list *temp_path_select_list = NULL; + struct mount_entry *me, *temp_me; + int result = OK; + regex_t re; + int cflags = REG_NOSUB | REG_EXTENDED; + int default_cflags = cflags; + char errbuf[MAX_INPUT_BUFFER]; + int fnd = 0; + + int option = 0; + static struct option longopts[] = { + {"timeout", required_argument, 0, 't'}, + {"warning", required_argument, 0, 'w'}, + {"critical", required_argument, 0, 'c'}, + {"iwarning", required_argument, 0, 'W'}, + /* Dang, -C is taken. We might want to reshuffle this. */ + {"icritical", required_argument, 0, 'K'}, + {"kilobytes", no_argument, 0, 'k'}, + {"megabytes", no_argument, 0, 'm'}, + {"units", required_argument, 0, 'u'}, + {"path", required_argument, 0, 'p'}, + {"partition", required_argument, 0, 'p'}, + {"exclude_device", required_argument, 0, 'x'}, + {"exclude-type", required_argument, 0, 'X'}, + {"group", required_argument, 0, 'g'}, + {"eregi-path", required_argument, 0, 'R'}, + {"eregi-partition", required_argument, 0, 'R'}, + {"ereg-path", required_argument, 0, 'r'}, + {"ereg-partition", required_argument, 0, 'r'}, + {"ignore-ereg-path", required_argument, 0, 'i'}, + {"ignore-ereg-partition", required_argument, 0, 'i'}, + {"ignore-eregi-path", required_argument, 0, 'I'}, + {"ignore-eregi-partition", required_argument, 0, 'I'}, + {"local", no_argument, 0, 'l'}, + {"stat-remote-fs", no_argument, 0, 'L'}, + {"mountpoint", no_argument, 0, 'M'}, + {"errors-only", no_argument, 0, 'e'}, + {"exact-match", no_argument, 0, 'E'}, + {"all", no_argument, 0, 'A'}, + {"verbose", no_argument, 0, 'v'}, + {"quiet", no_argument, 0, 'q'}, + {"clear", no_argument, 0, 'C'}, + {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + if (argc < 2) + return ERROR; + + np_add_name(&fs_exclude_list, "iso9660"); + + for (c = 1; c < argc; c++) + if (strcmp ("-to", argv[c]) == 0) + strcpy (argv[c], "-t"); + + while (1) { + c = getopt_long (argc, argv, "+?VqhveCt:c:w:K:W:u:p:x:X:mklLg:R:r:i:I:MEA", longopts, &option); + + if (c == -1 || c == EOF) + break; + + switch (c) { + case 't': /* timeout period */ + if (is_integer (optarg)) { + timeout_interval = atoi (optarg); + break; + } + else { + usage2 (_("Timeout interval must be a positive integer"), optarg); + } + + /* See comments for 'c' */ + case 'w': /* warning threshold */ + if (strstr(optarg, "%")) { + if (*optarg == '@') { + warn_freespace_percent = optarg; + } else { + asprintf(&warn_freespace_percent, "@%s", optarg); + } + } else { + if (*optarg == '@') { + warn_freespace_units = optarg; + } else { + asprintf(&warn_freespace_units, "@%s", optarg); + } + } + break; + + /* Awful mistake where the range values do not make sense. Normally, + you alert if the value is within the range, but since we are using + freespace, we have to alert if outside the range. Thus we artifically + force @ at the beginning of the range, so that it is backwards compatible + */ + case 'c': /* critical threshold */ + if (strstr(optarg, "%")) { + if (*optarg == '@') { + crit_freespace_percent = optarg; + } else { + asprintf(&crit_freespace_percent, "@%s", optarg); + } + } else { + if (*optarg == '@') { + crit_freespace_units = optarg; + } else { + asprintf(&crit_freespace_units, "@%s", optarg); + } + } + break; + + case 'W': /* warning inode threshold */ + if (*optarg == '@') { + warn_freeinodes_percent = optarg; + } else { + asprintf(&warn_freeinodes_percent, "@%s", optarg); + } + break; + case 'K': /* critical inode threshold */ + if (*optarg == '@') { + crit_freeinodes_percent = optarg; + } else { + asprintf(&crit_freeinodes_percent, "@%s", optarg); + } + break; + case 'u': + if (units) + free(units); + if (! strcmp (optarg, "bytes")) { + mult = (uintmax_t)1; + units = strdup ("B"); + } else if (! strcmp (optarg, "kB")) { + mult = (uintmax_t)1024; + units = strdup ("kB"); + } else if (! strcmp (optarg, "MB")) { + mult = (uintmax_t)1024 * 1024; + units = strdup ("MB"); + } else if (! strcmp (optarg, "GB")) { + mult = (uintmax_t)1024 * 1024 * 1024; + units = strdup ("GB"); + } else if (! strcmp (optarg, "TB")) { + mult = (uintmax_t)1024 * 1024 * 1024 * 1024; + units = strdup ("TB"); + } else { + die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg); + } + if (units == NULL) + die (STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units"); + break; + case 'k': /* display mountpoint */ + mult = 1024; + if (units) + free(units); + units = strdup ("kB"); + break; + case 'm': /* display mountpoint */ + mult = 1024 * 1024; + if (units) + free(units); + units = strdup ("MB"); + break; + case 'L': + stat_remote_fs = 1; + case 'l': + show_local_fs = 1; + break; + case 'p': /* select path */ + if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent || + crit_freespace_percent || warn_usedspace_units || crit_usedspace_units || + warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent || + crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) { + die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n")); + } + + /* add parameter if not found. overwrite thresholds if path has already been added */ + if (! (se = np_find_parameter(path_select_list, optarg))) { + se = np_add_parameter(&path_select_list, optarg); + } + se->group = group; + set_all_thresholds(se); + + /* With autofs, it is required to stat() the path before re-populating the mount_list */ + stat_path(se); + /* NB: We can't free the old mount_list "just like that": both list pointers and struct + * pointers are copied around. One of the reason it wasn't done yet is that other parts + * of check_disk need the same kind of cleanup so it'd better be done as a whole */ + mount_list = read_file_system_list (0); + np_set_best_match(se, mount_list, exact_match); + + path_selected = TRUE; + break; + case 'x': /* exclude path or partition */ + np_add_name(&dp_exclude_list, optarg); + break; + case 'X': /* exclude file system type */ + np_add_name(&fs_exclude_list, optarg); + break; + case 'v': /* verbose */ + verbose++; + break; + case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */ + /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */ + erronly = TRUE; + break; + case 'e': + erronly = TRUE; + break; + case 'E': + if (path_selected) + die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n")); + exact_match = TRUE; + break; + case 'g': + if (path_selected) + die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n")); + group = optarg; + break; + case 'I': + cflags |= REG_ICASE; + case 'i': + if (!path_selected) + die (STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"), _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly")); + err = regcomp(&re, optarg, cflags); + if (err != 0) { + regerror (err, &re, errbuf, MAX_INPUT_BUFFER); + die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf); + } + + temp_list = path_select_list; + + previous = NULL; + while (temp_list) { + if (temp_list->best_match) { + if (np_regex_match_mount_entry(temp_list->best_match, &re)) { + + if (verbose >=3) + printf("ignoring %s matching regex\n", temp_list->name); + + temp_list = np_del_parameter(temp_list, previous); + /* pointer to first element needs to be updated if first item gets deleted */ + if (previous == NULL) + path_select_list = temp_list; + } else { + previous = temp_list; + temp_list = temp_list->name_next; + } + } else { + previous = temp_list; + temp_list = temp_list->name_next; + } + } + + + cflags = default_cflags; + break; + + case 'A': + optarg = strdup(".*"); + case 'R': + cflags |= REG_ICASE; + case 'r': + if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent || + crit_freespace_percent || warn_usedspace_units || crit_usedspace_units || + warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent || + crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) { + die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -r/-R\n")); + } + + err = regcomp(&re, optarg, cflags); + if (err != 0) { + regerror (err, &re, errbuf, MAX_INPUT_BUFFER); + die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf); + } + + for (me = mount_list; me; me = me->me_next) { + if (np_regex_match_mount_entry(me, &re)) { + fnd = TRUE; + if (verbose >= 3) + printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg); + + /* add parameter if not found. overwrite thresholds if path has already been added */ + if (! (se = np_find_parameter(path_select_list, me->me_mountdir))) { + se = np_add_parameter(&path_select_list, me->me_mountdir); + } + se->group = group; + set_all_thresholds(se); + } + } + + if (!fnd) + die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), + _("Regular expression did not match any path or disk"), optarg); + + fnd = FALSE; + path_selected = TRUE; + np_set_best_match(path_select_list, mount_list, exact_match); + cflags = default_cflags; + + break; + case 'M': /* display mountpoint */ + display_mntp = TRUE; + break; + case 'C': + /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */ + if (path_selected == FALSE) { + struct parameter_list *path; + for (me = mount_list; me; me = me->me_next) { + if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) + path = np_add_parameter(&path_select_list, me->me_mountdir); + path->best_match = me; + path->group = group; + set_all_thresholds(path); + } + } + warn_freespace_units = NULL; + crit_freespace_units = NULL; + warn_usedspace_units = NULL; + crit_usedspace_units = NULL; + warn_freespace_percent = NULL; + crit_freespace_percent = NULL; + warn_usedspace_percent = NULL; + crit_usedspace_percent = NULL; + warn_usedinodes_percent = NULL; + crit_usedinodes_percent = NULL; + warn_freeinodes_percent = NULL; + crit_freeinodes_percent = NULL; + + path_selected = FALSE; + group = NULL; + break; + case 'V': /* version */ + print_revision (progname, NP_VERSION); + exit (STATE_OK); + case 'h': /* help */ + print_help (); + exit (STATE_OK); + case '?': /* help */ + usage (_("Unknown argument")); + } + } + + /* Support for "check_disk warn crit [fs]" with thresholds at used% level */ + c = optind; + if (warn_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c])) + warn_usedspace_percent = argv[c++]; + + if (crit_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c])) + crit_usedspace_percent = argv[c++]; + + if (argc > c && path == NULL) { + se = np_add_parameter(&path_select_list, strdup(argv[c++])); + path_selected = TRUE; + set_all_thresholds(se); + } + + if (units == NULL) { + units = strdup ("MB"); + mult = (uintmax_t)1024 * 1024; + } + + return TRUE; } -void print_path (char *mypath) + +void +print_path (const char *mypath) { - if (mypath) - printf (" for %s", mypath); - printf ("\n"); + if (mypath == NULL) + printf ("\n"); + else + printf (_(" for %s\n"), mypath); } + +void +set_all_thresholds (struct parameter_list *path) +{ + if (path->freespace_units != NULL) free(path->freespace_units); + set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units); + if (path->freespace_percent != NULL) free (path->freespace_percent); + set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent); + if (path->usedspace_units != NULL) free (path->usedspace_units); + set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units); + if (path->usedspace_percent != NULL) free (path->usedspace_percent); + set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent); + if (path->usedinodes_percent != NULL) free (path->usedinodes_percent); + set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent); + if (path->freeinodes_percent != NULL) free (path->freeinodes_percent); + set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent); +} + +/* TODO: Remove? + int -validate_arguments (int w, int c, double wp, double cp, char *mypath) +validate_arguments (uintmax_t w, uintmax_t c, double wp, double cp, double iwp, double icp, char *mypath) { - if (w < 0 && c < 0 && wp < 0.0 && cp < 0.0) { - printf (_("INPUT ERROR: No thresholds specified")); - print_path (mypath); - return ERROR; - } - else if ((wp >= 0.0 || cp >= 0.0) && - (wp < 0.0 || cp < 0.0 || wp > 100.0 || cp > 100.0 || cp > wp)) { - printf (_("\ + if (w < 0 && c < 0 && wp < 0.0 && cp < 0.0) { + printf (_("INPUT ERROR: No thresholds specified")); + print_path (mypath); + return ERROR; + } + else if ((wp >= 0.0 || cp >= 0.0) && + (wp < 0.0 || cp < 0.0 || wp > 100.0 || cp > 100.0 || cp > wp)) { + printf (_("\ INPUT ERROR: C_DFP (%f) should be less than W_DFP (%.1f) and both should be between zero and 100 percent, inclusive"), - cp, wp); - print_path (path); - return ERROR; - } - else if ((w > 0 || c > 0) && (w < 0 || c < 0 || c > w)) { - printf (_("\ -INPUT ERROR: C_DF (%d) should be less than W_DF (%d) and both should be greater than zero"), - c, w); - print_path (path); - return ERROR; - } - else { - return OK; - } + cp, wp); + print_path (mypath); + return ERROR; + } + else if ((iwp >= 0.0 || icp >= 0.0) && + (iwp < 0.0 || icp < 0.0 || iwp > 100.0 || icp > 100.0 || icp > iwp)) { + printf (_("\ +INPUT ERROR: C_IDFP (%f) should be less than W_IDFP (%.1f) and both should be between zero and 100 percent, inclusive"), + icp, iwp); + print_path (mypath); + return ERROR; + } + else if ((w > 0 || c > 0) && (w == 0 || c == 0 || c > w)) { + printf (_("\ +INPUT ERROR: C_DF (%lu) should be less than W_DF (%lu) and both should be greater than zero"), + (unsigned long)c, (unsigned long)w); + print_path (mypath); + return ERROR; + } + + return OK; } +*/ - -int -check_disk (int usp, int free_disk) + + + + + +void +print_help (void) { - int result = STATE_UNKNOWN; - /* check the percent used space against thresholds */ - if (usp >= 0 && usp >= (100.0 - c_dfp)) - result = STATE_CRITICAL; - else if (c_df >= 0 && free_disk <= c_df) - result = STATE_CRITICAL; - else if (usp >= 0 && usp >= (100.0 - w_dfp)) - result = STATE_WARNING; - else if (w_df >= 0 && free_disk <= w_df) - result = STATE_WARNING; - else if (usp >= 0.0) - result = STATE_OK; - return result; + print_revision (progname, NP_VERSION); + + printf ("Copyright (c) 1999 Ethan Galstad \n"); + printf (COPYRIGHT, copyright, email); + + printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system")); + printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values")); + + printf ("\n\n"); + + print_usage (); + + printf (UT_HELP_VRSN); + printf (UT_EXTRA_OPTS); + + printf (" %s\n", "-w, --warning=INTEGER"); + printf (" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free")); + printf (" %s\n", "-w, --warning=PERCENT%"); + printf (" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free")); + printf (" %s\n", "-c, --critical=INTEGER"); + printf (" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free")); + printf (" %s\n", "-c, --critical=PERCENT%"); + printf (" %s\n", _("Exit with CRITCAL status if less than PERCENT of disk space is free")); + printf (" %s\n", "-W, --iwarning=PERCENT%"); + printf (" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free")); + printf (" %s\n", "-K, --icritical=PERCENT%"); + printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free")); + printf (" %s\n", "-p, --path=PATH, --partition=PARTITION"); + printf (" %s\n", _("Path or partition (may be repeated)")); + printf (" %s\n", "-x, --exclude_device=PATH "); + printf (" %s\n", _("Ignore device (only works if -p unspecified)")); + printf (" %s\n", "-C, --clear"); + printf (" %s\n", _("Clear thresholds")); + printf (" %s\n", "-E, --exact-match"); + printf (" %s\n", _("For paths or partitions specified with -p, only check for exact paths")); + printf (" %s\n", "-e, --errors-only"); + printf (" %s\n", _("Display only devices/mountpoints with errors")); + printf (" %s\n", "-g, --group=NAME"); + printf (" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together")); + printf (" %s\n", "-k, --kilobytes"); + printf (" %s\n", _("Same as '--units kB'")); + printf (" %s\n", "-l, --local"); + printf (" %s\n", _("Only check local filesystems")); + printf (" %s\n", "-L, --stat-remote-fs"); + printf (" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems")); + printf (" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)")); + printf (" %s\n", "-M, --mountpoint"); + printf (" %s\n", _("Display the mountpoint instead of the partition")); + printf (" %s\n", "-m, --megabytes"); + printf (" %s\n", _("Same as '--units MB'")); + printf (" %s\n", "-A, --all"); + printf (" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'")); + printf (" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION"); + printf (" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)")); + printf (" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION"); + printf (" %s\n", _("Regular expression for path or partition (may be repeated)")); + printf (" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION"); + printf (" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)")); + printf (" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION"); + printf (" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)")); + printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); + printf (" %s\n", "-u, --units=STRING"); + printf (" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)")); + printf (UT_VERBOSE); + printf (" %s\n", "-X, --exclude-type=TYPE"); + printf (" %s\n", _("Ignore all filesystems of indicated type (may be repeated)")); + + printf ("\n"); + printf ("%s\n", _("Examples:")); + printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /"); + printf (" %s\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB")); + printf (" %s\n", "check_disk -w 100M -c 50M -C -w 1000M -c 500M -g sidDATA -r '^/oracle/SID/data.*$'"); + printf (" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex")); + printf (" %s\n", _("are grouped which means the freespace thresholds are applied to all disks together")); + printf (" %s\n", "check_disk -w 100M -c 50M -C -w 1000M -c 500M -p /foo -C -w 5% -c 3% -p /bar"); + printf (" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M")); + + printf (UT_SUPPORT); } -int -walk_name_list (struct name_list *list, const char *name) +void +print_usage (void) +{ + printf (_("Usage:")); + printf (" %s -w limit -c limit [-W limit] [-K limit] {-p path | -x device}\n", progname); + printf ("[-C] [-E] [-e] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n"); + printf ("[-t timeout] [-u unit] [-v] [-X type]\n"); +} + +void +stat_path (struct parameter_list *p) { - while (list) { - if (! strcmp(list->name, name)) { - list->found = 1; - /* if required for name_lists that have not saved w_df, etc (eg exclude lists) */ - if (list->w_df) w_df = list->w_df; - if (list->c_df) c_df = list->c_df; - if (list->w_dfp) w_dfp = list->w_dfp; - if (list->c_dfp) c_dfp = list->c_dfp; - return TRUE; - } - list = list->name_next; - } - return FALSE; + /* Stat entry to check that dir exists and is accessible */ + if (verbose >= 3) + printf("calling stat on %s\n", p->name); + if (stat (p->name, &stat_buf[0])) { + if (verbose >= 3) + printf("stat failed on %s\n", p->name); + printf("DISK %s - ", _("CRITICAL")); + die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno)); + } }