summaryrefslogtreecommitdiffstats
path: root/plugins/check_disk.c
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2024-11-02 13:37:39 +0100
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2024-11-02 13:37:39 +0100
commit3faeed07c4825d5c3ceb323e814e703d9262cd82 (patch)
treeb6a61e24ffa0fbb4af5f145c137f1f584aaba1bc /plugins/check_disk.c
parent735b04eff721a28e791714c0da4c8ac5726bfbcf (diff)
parent6d1d1dac32841d5ca6ee51bb09b30a6c604b17e2 (diff)
downloadmonitoring-plugins-3faeed07c4825d5c3ceb323e814e703d9262cd82.tar.gz
Merge branch 'master' into check_swap_again
Diffstat (limited to 'plugins/check_disk.c')
-rw-r--r--plugins/check_disk.c2066
1 files changed, 1005 insertions, 1061 deletions
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index c6bba243..d1d1b92a 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -1,43 +1,42 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_disk plugin 3 * Monitoring check_disk plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2008 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_disk plugin 10 * This file contains the check_disk plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29const char *progname = "check_disk"; 29const char *progname = "check_disk";
30const char *program_name = "check_disk"; /* Required for coreutils libs */ 30const char *program_name = "check_disk"; /* Required for coreutils libs */
31const char *copyright = "1999-2008"; 31const char *copyright = "1999-2024";
32const char *email = "devel@monitoring-plugins.org"; 32const char *email = "devel@monitoring-plugins.org";
33 33
34
35#include "common.h" 34#include "common.h"
36#ifdef HAVE_SYS_STAT_H 35#ifdef HAVE_SYS_STAT_H
37# include <sys/stat.h> 36# include <sys/stat.h>
38#endif 37#endif
39#if HAVE_INTTYPES_H 38#if HAVE_INTTYPES_H
40# include <inttypes.h> 39# include <inttypes.h>
41#endif 40#endif
42#include <assert.h> 41#include <assert.h>
43#include "popen.h" 42#include "popen.h"
@@ -46,16 +45,16 @@ const char *email = "devel@monitoring-plugins.org";
46#include <stdarg.h> 45#include <stdarg.h>
47#include "fsusage.h" 46#include "fsusage.h"
48#include "mountlist.h" 47#include "mountlist.h"
49#include "intprops.h" /* necessary for TYPE_MAXIMUM */ 48#include <float.h>
50#if HAVE_LIMITS_H 49#if HAVE_LIMITS_H
51# include <limits.h> 50# include <limits.h>
52#endif 51#endif
53#include "regex.h" 52#include "regex.h"
54 53
55#ifdef __CYGWIN__ 54#ifdef __CYGWIN__
56# include <windows.h> 55# include <windows.h>
57# undef ERROR 56# undef ERROR
58# define ERROR -1 57# define ERROR -1
59#endif 58#endif
60 59
61/* If nonzero, show even filesystems with zero size or 60/* If nonzero, show even filesystems with zero size or
@@ -108,1062 +107,1007 @@ static struct mount_entry *mount_list;
108 107
109/* For long options that have no equivalent short option, use a 108/* For long options that have no equivalent short option, use a
110 non-character as a pseudo short option, starting with CHAR_MAX + 1. */ 109 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
111enum 110enum {
112{ 111 SYNC_OPTION = CHAR_MAX + 1,
113 SYNC_OPTION = CHAR_MAX + 1, 112 NO_SYNC_OPTION,
114 NO_SYNC_OPTION, 113 BLOCK_SIZE_OPTION
115 BLOCK_SIZE_OPTION
116}; 114};
117 115
118#ifdef _AIX 116#ifdef _AIX
119#pragma alloca 117# pragma alloca
120#endif 118#endif
121 119
122int process_arguments (int, char **); 120static int process_arguments(int /*argc*/, char ** /*argv*/);
123void print_path (const char *mypath); 121static void set_all_thresholds(struct parameter_list *path);
124void set_all_thresholds (struct parameter_list *path); 122static void print_help(void);
125int validate_arguments (uintmax_t, uintmax_t, double, double, double, double, char *); 123void print_usage(void);
126void print_help (void); 124static double calculate_percent(uintmax_t, uintmax_t);
127void print_usage (void); 125static bool stat_path(struct parameter_list *p);
128double calculate_percent(uintmax_t, uintmax_t); 126static void get_stats(struct parameter_list *p, struct fs_usage *fsp);
129bool stat_path (struct parameter_list *p); 127static void get_path_stats(struct parameter_list *p, struct fs_usage *fsp);
130void get_stats (struct parameter_list *p, struct fs_usage *fsp); 128
131void get_path_stats (struct parameter_list *p, struct fs_usage *fsp); 129static char *units;
132 130static uintmax_t mult = 1024 * 1024;
133char *exclude_device; 131static int verbose = 0;
134char *units; 132static bool erronly = false;
135uintmax_t mult = 1024 * 1024; 133static bool display_mntp = false;
136int verbose = 0; 134static bool exact_match = false;
137bool erronly = false; 135static bool ignore_missing = false;
138bool display_mntp = false; 136static bool freespace_ignore_reserved = false;
139bool exact_match = false; 137static bool display_inodes_perfdata = false;
140bool ignore_missing = false; 138static char *warn_freespace_units = NULL;
141bool freespace_ignore_reserved = false; 139static char *crit_freespace_units = NULL;
142bool display_inodes_perfdata = false; 140static char *warn_freespace_percent = NULL;
143char *warn_freespace_units = NULL; 141static char *crit_freespace_percent = NULL;
144char *crit_freespace_units = NULL; 142static char *warn_usedspace_units = NULL;
145char *warn_freespace_percent = NULL; 143static char *crit_usedspace_units = NULL;
146char *crit_freespace_percent = NULL; 144static char *warn_usedspace_percent = NULL;
147char *warn_usedspace_units = NULL; 145static char *crit_usedspace_percent = NULL;
148char *crit_usedspace_units = NULL; 146static char *warn_usedinodes_percent = NULL;
149char *warn_usedspace_percent = NULL; 147static char *crit_usedinodes_percent = NULL;
150char *crit_usedspace_percent = NULL; 148static char *warn_freeinodes_percent = NULL;
151char *warn_usedinodes_percent = NULL; 149static char *crit_freeinodes_percent = NULL;
152char *crit_usedinodes_percent = NULL; 150static bool path_selected = false;
153char *warn_freeinodes_percent = NULL; 151static bool path_ignored = false;
154char *crit_freeinodes_percent = NULL; 152static char *group = NULL;
155bool path_selected = false; 153static struct stat *stat_buf;
156bool path_ignored = false; 154static struct name_list *seen = NULL;
157char *group = NULL; 155
158struct stat *stat_buf; 156int main(int argc, char **argv) {
159struct name_list *seen = NULL; 157 int result = STATE_UNKNOWN;
160 158 int disk_result = STATE_UNKNOWN;
161 159 char *output;
162int 160 char *ignored;
163main (int argc, char **argv) 161 char *details;
164{ 162 char *perf;
165 int result = STATE_UNKNOWN; 163 char *perf_ilabel;
166 int disk_result = STATE_UNKNOWN; 164 char *preamble = " - free space:";
167 char *output; 165 char *ignored_preamble = " - ignored paths:";
168 char *ignored; 166 char *flag_header;
169 char *details; 167 int temp_result;
170 char *perf; 168
171 char *perf_ilabel; 169 struct mount_entry *me;
172 char *preamble = " - free space:"; 170 struct fs_usage fsp;
173 char *ignored_preamble = " - ignored paths:"; 171 struct parameter_list *temp_list;
174 char *flag_header; 172 struct parameter_list *path;
175 int temp_result;
176
177 struct mount_entry *me;
178 struct fs_usage fsp;
179 struct parameter_list *temp_list, *path;
180 173
181#ifdef __CYGWIN__ 174#ifdef __CYGWIN__
182 char mountdir[32]; 175 char mountdir[32];
183#endif 176#endif
184 177
185 output = strdup (""); 178 output = strdup("");
186 ignored = strdup (""); 179 ignored = strdup("");
187 details = strdup (""); 180 details = strdup("");
188 perf = strdup (""); 181 perf = strdup("");
189 perf_ilabel = strdup (""); 182 perf_ilabel = strdup("");
190 stat_buf = malloc(sizeof *stat_buf); 183 stat_buf = malloc(sizeof *stat_buf);
191 184
192 setlocale (LC_ALL, ""); 185 setlocale(LC_ALL, "");
193 bindtextdomain (PACKAGE, LOCALEDIR); 186 bindtextdomain(PACKAGE, LOCALEDIR);
194 textdomain (PACKAGE); 187 textdomain(PACKAGE);
195 188
196 mount_list = read_file_system_list (0); 189 mount_list = read_file_system_list(0);
197 190
198 /* Parse extra opts if any */ 191 /* Parse extra opts if any */
199 argv = np_extra_opts (&argc, argv, progname); 192 argv = np_extra_opts(&argc, argv, progname);
200 193
201 if (process_arguments (argc, argv) == ERROR) 194 if (process_arguments(argc, argv) == ERROR)
202 usage4 (_("Could not parse arguments")); 195 usage4(_("Could not parse arguments"));
203 196
204 /* If a list of paths has not been selected, find entire 197 /* If a list of paths has not been selected, find entire
205 mount list and create list of paths 198 mount list and create list of paths
206 */ 199 */
207 if (path_selected == false && path_ignored == false) { 200 if (path_selected == false && path_ignored == false) {
208 for (me = mount_list; me; me = me->me_next) { 201 for (me = mount_list; me; me = me->me_next) {
209 if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) { 202 if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
210 path = np_add_parameter(&path_select_list, me->me_mountdir); 203 path = np_add_parameter(&path_select_list, me->me_mountdir);
211 } 204 }
212 path->best_match = me; 205 path->best_match = me;
213 path->group = group; 206 path->group = group;
214 set_all_thresholds(path); 207 set_all_thresholds(path);
215 } 208 }
216 } 209 }
217 210
218 if (path_ignored == false) { 211 if (path_ignored == false) {
219 np_set_best_match(path_select_list, mount_list, exact_match); 212 np_set_best_match(path_select_list, mount_list, exact_match);
220 } 213 }
221 214
222 /* Error if no match found for specified paths */ 215 /* Error if no match found for specified paths */
223 temp_list = path_select_list; 216 temp_list = path_select_list;
224 217
225 while (path_select_list) { 218 while (path_select_list) {
226 if (! path_select_list->best_match && ignore_missing == true) { 219 if (!path_select_list->best_match && ignore_missing == true) {
227 /* If the first element will be deleted, the temp_list must be updated with the new start address as well */ 220 /* If the first element will be deleted, the temp_list must be updated with the new start address as well */
228 if (path_select_list == temp_list) { 221 if (path_select_list == temp_list) {
229 temp_list = path_select_list->name_next; 222 temp_list = path_select_list->name_next;
230 } 223 }
231 /* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */ 224 /* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */
232 xasprintf (&ignored, "%s %s;", ignored, path_select_list->name); 225 xasprintf(&ignored, "%s %s;", ignored, path_select_list->name);
233 /* Delete the path from the list so that it is not stat-checked later in the code. */ 226 /* Delete the path from the list so that it is not stat-checked later in the code. */
234 path_select_list = np_del_parameter(path_select_list, path_select_list->name_prev); 227 path_select_list = np_del_parameter(path_select_list, path_select_list->name_prev);
235 } else if (! path_select_list->best_match) { 228 } else if (!path_select_list->best_match) {
236 /* Without --ignore-missing option, exit with Critical state. */ 229 /* Without --ignore-missing option, exit with Critical state. */
237 die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name); 230 die(STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name);
238 } else { 231 } else {
239 /* Continue jumping through the list */ 232 /* Continue jumping through the list */
240 path_select_list = path_select_list->name_next; 233 path_select_list = path_select_list->name_next;
241 } 234 }
242 } 235 }
243 236
244 path_select_list = temp_list; 237 path_select_list = temp_list;
245 238
246 if (! path_select_list && ignore_missing == true) { 239 if (!path_select_list && ignore_missing == true) {
247 result = STATE_OK; 240 result = STATE_OK;
248 if (verbose >= 2) { 241 if (verbose >= 2) {
249 printf ("None of the provided paths were found\n"); 242 printf("None of the provided paths were found\n");
250 } 243 }
251 } 244 }
252 245
253 /* Process for every path in list */ 246 /* Process for every path in list */
254 for (path = path_select_list; path; path=path->name_next) { 247 for (path = path_select_list; path; path = path->name_next) {
255 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) 248 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL)
256 printf("Thresholds(pct) for %s warn: %f crit %f\n", 249 printf("Thresholds(pct) for %s warn: %f crit %f\n", path->name, path->freespace_percent->warning->end,
257 path->name, 250 path->freespace_percent->critical->end);
258 path->freespace_percent->warning->end, 251
259 path->freespace_percent->critical->end); 252 if (verbose >= 3 && path->group != NULL)
260 253 printf("Group of %s: %s\n", path->name, path->group);
261 if (verbose >= 3 && path->group != NULL) 254
262 printf("Group of %s: %s\n",path->name,path->group); 255 /* reset disk result */
263 256 disk_result = STATE_UNKNOWN;
264 /* reset disk result */ 257
265 disk_result = STATE_UNKNOWN; 258 me = path->best_match;
266 259
267 me = path->best_match; 260 if (!me) {
268 261 continue;
269 if (!me) { 262 }
270 continue;
271 }
272 263
273#ifdef __CYGWIN__ 264#ifdef __CYGWIN__
274 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11) 265 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11)
275 continue; 266 continue;
276 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10); 267 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10);
277 if (GetDriveType(mountdir) != DRIVE_FIXED) 268 if (GetDriveType(mountdir) != DRIVE_FIXED)
278 me->me_remote = 1; 269 me->me_remote = 1;
279#endif 270#endif
280 /* Filters */ 271 /* Filters */
281 272
282 /* Remove filesystems already seen */ 273 /* Remove filesystems already seen */
283 if (np_seen_name(seen, me->me_mountdir)) { 274 if (np_seen_name(seen, me->me_mountdir)) {
284 continue; 275 continue;
285 } 276 }
286 np_add_name(&seen, me->me_mountdir); 277 np_add_name(&seen, me->me_mountdir);
287 278
288 if (path->group == NULL) { 279 if (path->group == NULL) {
289 /* Skip remote filesystems if we're not interested in them */ 280 /* Skip remote filesystems if we're not interested in them */
290 if (me->me_remote && show_local_fs) { 281 if (me->me_remote && show_local_fs) {
291 if (stat_remote_fs) { 282 if (stat_remote_fs) {
292 if (!stat_path(path) && ignore_missing == true) { 283 if (!stat_path(path) && ignore_missing == true) {
293 result = STATE_OK; 284 result = STATE_OK;
294 xasprintf (&ignored, "%s %s;", ignored, path->name); 285 xasprintf(&ignored, "%s %s;", ignored, path->name);
295 } 286 }
296 } 287 }
297 continue; 288 continue;
298 /* Skip pseudo fs's if we haven't asked for all fs's */ 289 /* Skip pseudo fs's if we haven't asked for all fs's */
299 } else if (me->me_dummy && !show_all_fs) { 290 }
300 continue; 291 if (me->me_dummy && !show_all_fs) {
301 /* Skip excluded fstypes */ 292 continue;
302 } else if (fs_exclude_list && np_find_regmatch (fs_exclude_list, me->me_type)) { 293 /* Skip excluded fstypes */
303 continue; 294 }
304 /* Skip excluded fs's */ 295 if (fs_exclude_list && np_find_regmatch(fs_exclude_list, me->me_type)) {
305 } else if (dp_exclude_list && 296 continue;
306 (np_find_name (dp_exclude_list, me->me_devname) || 297 /* Skip excluded fs's */
307 np_find_name (dp_exclude_list, me->me_mountdir))) { 298 }
308 continue; 299 if (dp_exclude_list && (np_find_name(dp_exclude_list, me->me_devname) || np_find_name(dp_exclude_list, me->me_mountdir))) {
309 /* Skip not included fstypes */ 300 continue;
310 } else if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) { 301 /* Skip not included fstypes */
311 continue; 302 }
312 } 303 if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) {
313 } 304 continue;
314 305 }
315 if (!stat_path(path)) { 306 }
316 if (ignore_missing == true) { 307
317 result = STATE_OK; 308 if (!stat_path(path)) {
318 xasprintf (&ignored, "%s %s;", ignored, path->name); 309 if (ignore_missing == true) {
319 } 310 result = STATE_OK;
320 continue; 311 xasprintf(&ignored, "%s %s;", ignored, path->name);
321 } 312 }
322 get_fs_usage (me->me_mountdir, me->me_devname, &fsp); 313 continue;
323 314 }
324 if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { 315 get_fs_usage(me->me_mountdir, me->me_devname, &fsp);
325 get_stats (path, &fsp); 316
326 317 if (fsp.fsu_blocks && strcmp("none", me->me_mountdir)) {
327 if (verbose >= 3) { 318 get_stats(path, &fsp);
328 printf ("For %s, used_pct=%g free_pct=%g used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%g free_inodes_pct=%g fsp.fsu_blocksize=%lu mult=%lu\n", 319
329 me->me_mountdir, 320 if (verbose >= 3) {
330 path->dused_pct, 321 printf("For %s, used_pct=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f "
331 path->dfree_pct, 322 "free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n",
332 path->dused_units, 323 me->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units,
333 path->dfree_units, 324 path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, mult);
334 path->dtotal_units, 325 }
335 path->dused_inodes_percent, 326
336 path->dfree_inodes_percent, 327 /* Threshold comparisons */
337 fsp.fsu_blocksize, 328
338 mult); 329 temp_result = get_status(path->dfree_units, path->freespace_units);
339 } 330 if (verbose >= 3)
340 331 printf("Freespace_units result=%d\n", temp_result);
341 /* Threshold comparisons */ 332 disk_result = max_state(disk_result, temp_result);
342 333
343 temp_result = get_status(path->dfree_units, path->freespace_units); 334 temp_result = get_status(path->dfree_pct, path->freespace_percent);
344 if (verbose >=3) printf("Freespace_units result=%d\n", temp_result); 335 if (verbose >= 3)
345 disk_result = max_state( disk_result, temp_result ); 336 printf("Freespace%% result=%d\n", temp_result);
346 337 disk_result = max_state(disk_result, temp_result);
347 temp_result = get_status(path->dfree_pct, path->freespace_percent); 338
348 if (verbose >=3) printf("Freespace%% result=%d\n", temp_result); 339 temp_result = get_status(path->dused_units, path->usedspace_units);
349 disk_result = max_state( disk_result, temp_result ); 340 if (verbose >= 3)
350 341 printf("Usedspace_units result=%d\n", temp_result);
351 temp_result = get_status(path->dused_units, path->usedspace_units); 342 disk_result = max_state(disk_result, temp_result);
352 if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result); 343
353 disk_result = max_state( disk_result, temp_result ); 344 temp_result = get_status(path->dused_pct, path->usedspace_percent);
354 345 if (verbose >= 3)
355 temp_result = get_status(path->dused_pct, path->usedspace_percent); 346 printf("Usedspace_percent result=%d\n", temp_result);
356 if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result); 347 disk_result = max_state(disk_result, temp_result);
357 disk_result = max_state( disk_result, temp_result ); 348
358 349 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
359 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent); 350 if (verbose >= 3)
360 if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result); 351 printf("Usedinodes_percent result=%d\n", temp_result);
361 disk_result = max_state( disk_result, temp_result ); 352 disk_result = max_state(disk_result, temp_result);
362 353
363 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent); 354 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
364 if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result); 355 if (verbose >= 3)
365 disk_result = max_state( disk_result, temp_result ); 356 printf("Freeinodes_percent result=%d\n", temp_result);
366 357 disk_result = max_state(disk_result, temp_result);
367 result = max_state(result, disk_result); 358
368 359 result = max_state(result, disk_result);
369 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes! 360
370 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf 361 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
371 data. Assumption that start=0. Roll on new syntax... 362 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
372 */ 363 data. Assumption that start=0. Roll on new syntax...
373 364 */
374 /* *_high_tide must be reinitialized at each run */ 365
375 uint64_t warning_high_tide = UINT64_MAX; 366 /* *_high_tide must be reinitialized at each run */
376 367 uint64_t warning_high_tide = UINT64_MAX;
377 if (path->freespace_units->warning != NULL) { 368
378 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult; 369 if (path->freespace_units->warning != NULL) {
379 } 370 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
380 if (path->freespace_percent->warning != NULL) { 371 }
381 warning_high_tide = min( warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end/100) * (path->dtotal_units * mult)) ); 372 if (path->freespace_percent->warning != NULL) {
382 } 373 warning_high_tide =
383 374 min(warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end / 100) * (path->dtotal_units * mult)));
384 uint64_t critical_high_tide = UINT64_MAX; 375 }
385 376
386 if (path->freespace_units->critical != NULL) { 377 uint64_t critical_high_tide = UINT64_MAX;
387 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult; 378
388 } 379 if (path->freespace_units->critical != NULL) {
389 if (path->freespace_percent->critical != NULL) { 380 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
390 critical_high_tide = min( critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end/100) * (path->dtotal_units * mult)) ); 381 }
391 } 382 if (path->freespace_percent->critical != NULL) {
392 383 critical_high_tide =
393 /* Nb: *_high_tide are unset when == UINT64_MAX */ 384 min(critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end / 100) * (path->dtotal_units * mult)));
394 xasprintf (&perf, "%s %s", perf, 385 }
395 perfdata_uint64 ( 386
396 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, 387 /* Nb: *_high_tide are unset when == UINT64_MAX */
397 path->dused_units * mult, "B", 388 xasprintf(&perf, "%s %s", perf,
398 (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide, 389 perfdata_uint64((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
399 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide, 390 path->dused_units * mult, "B", (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
400 true, 0, 391 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide, true, 0, true,
401 true, path->dtotal_units * mult)); 392 path->dtotal_units * mult));
402 393
403 if (display_inodes_perfdata) { 394 if (display_inodes_perfdata) {
404 /* *_high_tide must be reinitialized at each run */ 395 /* *_high_tide must be reinitialized at each run */
405 warning_high_tide = UINT64_MAX; 396 warning_high_tide = UINT64_MAX;
406 critical_high_tide = UINT64_MAX; 397 critical_high_tide = UINT64_MAX;
407 398
408 if (path->freeinodes_percent->warning != NULL) { 399 if (path->freeinodes_percent->warning != NULL) {
409 warning_high_tide = (uint64_t) fabs( min( (double) warning_high_tide, (double) (1.0 - path->freeinodes_percent->warning->end/100)*path->inodes_total )); 400 warning_high_tide = (uint64_t)fabs(
410 } 401 min((double)warning_high_tide, (double)(1.0 - path->freeinodes_percent->warning->end / 100) * path->inodes_total));
411 if (path->freeinodes_percent->critical != NULL) { 402 }
412 critical_high_tide = (uint64_t) fabs( min( (double) critical_high_tide, (double) (1.0 - path->freeinodes_percent->critical->end/100)*path->inodes_total )); 403 if (path->freeinodes_percent->critical != NULL) {
413 } 404 critical_high_tide = (uint64_t)fabs(min(
414 405 (double)critical_high_tide, (double)(1.0 - path->freeinodes_percent->critical->end / 100) * path->inodes_total));
415 xasprintf (&perf_ilabel, "%s (inodes)", (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir); 406 }
416 /* Nb: *_high_tide are unset when == UINT64_MAX */ 407
417 xasprintf (&perf, "%s %s", perf, 408 xasprintf(&perf_ilabel, "%s (inodes)",
418 perfdata_uint64 (perf_ilabel, 409 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
419 path->inodes_used, "", 410 /* Nb: *_high_tide are unset when == UINT64_MAX */
420 (warning_high_tide != UINT64_MAX ? true : false), warning_high_tide, 411 xasprintf(&perf, "%s %s", perf,
421 (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide, 412 perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX ? true : false),
422 true, 0, 413 warning_high_tide, (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide, true, 0,
423 true, path->inodes_total)); 414 true, path->inodes_total));
424 } 415 }
425 416
426 if (disk_result==STATE_OK && erronly && !verbose) 417 if (disk_result == STATE_OK && erronly && !verbose)
427 continue; 418 continue;
428 419
429 if(disk_result && verbose >= 1) { 420 if (disk_result && verbose >= 1) {
430 xasprintf(&flag_header, " %s [", state_text (disk_result)); 421 xasprintf(&flag_header, " %s [", state_text(disk_result));
431 } else { 422 } else {
432 xasprintf(&flag_header, ""); 423 xasprintf(&flag_header, "");
433 } 424 }
434 xasprintf (&output, "%s%s %s %llu%s (%.0f%%", 425 xasprintf(&output, "%s%s %s %llu%s (%.1f%%", output, flag_header,
435 output, flag_header, 426 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, path->dfree_units, units,
436 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, 427 path->dfree_pct);
437 path->dfree_units, 428 if (path->dused_inodes_percent < 0) {
438 units, 429 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
439 path->dfree_pct); 430 } else {
440 if (path->dused_inodes_percent < 0) { 431 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
441 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : "")); 432 }
442 } else { 433 free(flag_header);
443 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : "")); 434 }
444 } 435 }
445 free(flag_header); 436
446 } 437 if (verbose >= 2)
447 } 438 xasprintf(&output, "%s%s", output, details);
448 439
449 if (verbose >= 2) 440 if (strcmp(output, "") == 0 && !erronly) {
450 xasprintf (&output, "%s%s", output, details); 441 preamble = "";
451 442 xasprintf(&output, " - No disks were found for provided parameters");
452 if (strcmp(output, "") == 0 && ! erronly) { 443 }
453 preamble = ""; 444
454 xasprintf (&output, " - No disks were found for provided parameters"); 445 printf("DISK %s%s%s%s%s|%s\n", state_text(result), ((erronly && result == STATE_OK)) ? "" : preamble, output,
455 } 446 (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
456 447 return result;
457 printf ("DISK %s%s%s%s%s|%s\n", state_text (result), ((erronly && result==STATE_OK)) ? "" : preamble, output, (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
458 return result;
459} 448}
460 449
461
462double calculate_percent(uintmax_t value, uintmax_t total) { 450double calculate_percent(uintmax_t value, uintmax_t total) {
463 double pct = -1; 451 double pct = -1;
464 /* I don't understand the below, but it is taken from coreutils' df */ 452 if (value <= DBL_MAX && total != 0) {
465 /* Seems to be calculating pct, in the best possible way */ 453 pct = (double)value / total * 100.0;
466 if (value <= TYPE_MAXIMUM(uintmax_t) / 100 454 }
467 && total != 0) { 455 return pct;
468 uintmax_t u100 = value * 100;
469 pct = u100 / total + (u100 % total != 0);
470 } else {
471 /* Possible rounding errors - see coreutils' df for more explanation */
472 double u = value;
473 double t = total;
474 if (t) {
475 long int lipct = pct = u * 100 / t;
476 double ipct = lipct;
477
478 /* Like 'pct = ceil (dpct);', but without ceil - from coreutils again */
479 if (ipct - 1 < pct && pct <= ipct + 1)
480 pct = ipct + (ipct < pct);
481 }
482 }
483 return pct;
484} 456}
485 457
486/* process command-line arguments */ 458/* process command-line arguments */
487int 459int process_arguments(int argc, char **argv) {
488process_arguments (int argc, char **argv) 460 int c;
489{ 461 int err;
490 int c, err; 462 struct parameter_list *se;
491 struct parameter_list *se; 463 struct parameter_list *temp_list = NULL;
492 struct parameter_list *temp_list = NULL, *previous = NULL; 464 struct parameter_list *previous = NULL;
493 struct mount_entry *me; 465 struct mount_entry *me;
494 regex_t re; 466 regex_t re;
495 int cflags = REG_NOSUB | REG_EXTENDED; 467 int cflags = REG_NOSUB | REG_EXTENDED;
496 int default_cflags = cflags; 468 int default_cflags = cflags;
497 char errbuf[MAX_INPUT_BUFFER]; 469 char errbuf[MAX_INPUT_BUFFER];
498 int fnd = 0; 470 int fnd = 0;
499 471
500 int option = 0; 472 int option = 0;
501 static struct option longopts[] = { 473 static struct option longopts[] = {{"timeout", required_argument, 0, 't'},
502 {"timeout", required_argument, 0, 't'}, 474 {"warning", required_argument, 0, 'w'},
503 {"warning", required_argument, 0, 'w'}, 475 {"critical", required_argument, 0, 'c'},
504 {"critical", required_argument, 0, 'c'}, 476 {"iwarning", required_argument, 0, 'W'},
505 {"iwarning", required_argument, 0, 'W'}, 477 /* Dang, -C is taken. We might want to reshuffle this. */
506 /* Dang, -C is taken. We might want to reshuffle this. */ 478 {"icritical", required_argument, 0, 'K'},
507 {"icritical", required_argument, 0, 'K'}, 479 {"kilobytes", no_argument, 0, 'k'},
508 {"kilobytes", no_argument, 0, 'k'}, 480 {"megabytes", no_argument, 0, 'm'},
509 {"megabytes", no_argument, 0, 'm'}, 481 {"units", required_argument, 0, 'u'},
510 {"units", required_argument, 0, 'u'}, 482 {"path", required_argument, 0, 'p'},
511 {"path", required_argument, 0, 'p'}, 483 {"partition", required_argument, 0, 'p'},
512 {"partition", required_argument, 0, 'p'}, 484 {"exclude_device", required_argument, 0, 'x'},
513 {"exclude_device", required_argument, 0, 'x'}, 485 {"exclude-type", required_argument, 0, 'X'},
514 {"exclude-type", required_argument, 0, 'X'}, 486 {"include-type", required_argument, 0, 'N'},
515 {"include-type", required_argument, 0, 'N'}, 487 {"group", required_argument, 0, 'g'},
516 {"group", required_argument, 0, 'g'}, 488 {"eregi-path", required_argument, 0, 'R'},
517 {"eregi-path", required_argument, 0, 'R'}, 489 {"eregi-partition", required_argument, 0, 'R'},
518 {"eregi-partition", required_argument, 0, 'R'}, 490 {"ereg-path", required_argument, 0, 'r'},
519 {"ereg-path", required_argument, 0, 'r'}, 491 {"ereg-partition", required_argument, 0, 'r'},
520 {"ereg-partition", required_argument, 0, 'r'}, 492 {"freespace-ignore-reserved", no_argument, 0, 'f'},
521 {"freespace-ignore-reserved", no_argument, 0, 'f'}, 493 {"ignore-ereg-path", required_argument, 0, 'i'},
522 {"ignore-ereg-path", required_argument, 0, 'i'}, 494 {"ignore-ereg-partition", required_argument, 0, 'i'},
523 {"ignore-ereg-partition", required_argument, 0, 'i'}, 495 {"ignore-eregi-path", required_argument, 0, 'I'},
524 {"ignore-eregi-path", required_argument, 0, 'I'}, 496 {"ignore-eregi-partition", required_argument, 0, 'I'},
525 {"ignore-eregi-partition", required_argument, 0, 'I'}, 497 {"ignore-missing", no_argument, 0, 'n'},
526 {"ignore-missing", no_argument, 0, 'n'}, 498 {"local", no_argument, 0, 'l'},
527 {"local", no_argument, 0, 'l'}, 499 {"stat-remote-fs", no_argument, 0, 'L'},
528 {"stat-remote-fs", no_argument, 0, 'L'}, 500 {"iperfdata", no_argument, 0, 'P'},
529 {"iperfdata", no_argument, 0, 'P'}, 501 {"mountpoint", no_argument, 0, 'M'},
530 {"mountpoint", no_argument, 0, 'M'}, 502 {"errors-only", no_argument, 0, 'e'},
531 {"errors-only", no_argument, 0, 'e'}, 503 {"exact-match", no_argument, 0, 'E'},
532 {"exact-match", no_argument, 0, 'E'}, 504 {"all", no_argument, 0, 'A'},
533 {"all", no_argument, 0, 'A'}, 505 {"verbose", no_argument, 0, 'v'},
534 {"verbose", no_argument, 0, 'v'}, 506 {"quiet", no_argument, 0, 'q'},
535 {"quiet", no_argument, 0, 'q'}, 507 {"clear", no_argument, 0, 'C'},
536 {"clear", no_argument, 0, 'C'}, 508 {"version", no_argument, 0, 'V'},
537 {"version", no_argument, 0, 'V'}, 509 {"help", no_argument, 0, 'h'},
538 {"help", no_argument, 0, 'h'}, 510 {0, 0, 0, 0}};
539 {0, 0, 0, 0} 511
540 }; 512 if (argc < 2)
541 513 return ERROR;
542 if (argc < 2) 514
543 return ERROR; 515 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED);
544 516
545 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED); 517 for (c = 1; c < argc; c++)
546 518 if (strcmp("-to", argv[c]) == 0)
547 for (c = 1; c < argc; c++) 519 strcpy(argv[c], "-t");
548 if (strcmp ("-to", argv[c]) == 0) 520
549 strcpy (argv[c], "-t"); 521 while (1) {
550 522 c = getopt_long(argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option);
551 while (1) { 523
552 c = getopt_long (argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option); 524 if (c == -1 || c == EOF)
553 525 break;
554 if (c == -1 || c == EOF) 526
555 break; 527 switch (c) {
556 528 case 't': /* timeout period */
557 switch (c) { 529 if (is_integer(optarg)) {
558 case 't': /* timeout period */ 530 timeout_interval = atoi(optarg);
559 if (is_integer (optarg)) { 531 break;
560 timeout_interval = atoi (optarg); 532 } else {
561 break; 533 usage2(_("Timeout interval must be a positive integer"), optarg);
562 } 534 }
563 else { 535
564 usage2 (_("Timeout interval must be a positive integer"), optarg); 536 /* See comments for 'c' */
565 } 537 case 'w': /* warning threshold */
566 538 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
567 /* See comments for 'c' */ 539 die(STATE_UNKNOWN, "Argument for --warning invalid or missing: %s\n", optarg);
568 case 'w': /* warning threshold */ 540 }
569 if (strstr(optarg, "%")) { 541
570 if (*optarg == '@') { 542 if (strstr(optarg, "%")) {
571 warn_freespace_percent = optarg; 543 if (*optarg == '@') {
572 } else { 544 warn_freespace_percent = optarg;
573 xasprintf(&warn_freespace_percent, "@%s", optarg); 545 } else {
574 } 546 xasprintf(&warn_freespace_percent, "@%s", optarg);
575 } else { 547 }
576 if (*optarg == '@') { 548 } else {
577 warn_freespace_units = optarg; 549 if (*optarg == '@') {
578 } else { 550 warn_freespace_units = optarg;
579 xasprintf(&warn_freespace_units, "@%s", optarg); 551 } else {
580 } 552 xasprintf(&warn_freespace_units, "@%s", optarg);
581 } 553 }
582 break; 554 }
583 555 break;
584 /* Awful mistake where the range values do not make sense. Normally, 556
585 you alert if the value is within the range, but since we are using 557 /* Awful mistake where the range values do not make sense. Normally,
586 freespace, we have to alert if outside the range. Thus we artificially 558 you alert if the value is within the range, but since we are using
587 force @ at the beginning of the range, so that it is backwards compatible 559 freespace, we have to alert if outside the range. Thus we artificially
588 */ 560 force @ at the beginning of the range, so that it is backwards compatible
589 case 'c': /* critical threshold */ 561 */
590 if (strstr(optarg, "%")) { 562 case 'c': /* critical threshold */
591 if (*optarg == '@') { 563 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
592 crit_freespace_percent = optarg; 564 die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg);
593 } else { 565 }
594 xasprintf(&crit_freespace_percent, "@%s", optarg); 566
595 } 567 if (strstr(optarg, "%")) {
596 } else { 568 if (*optarg == '@') {
597 if (*optarg == '@') { 569 crit_freespace_percent = optarg;
598 crit_freespace_units = optarg; 570 } else {
599 } else { 571 xasprintf(&crit_freespace_percent, "@%s", optarg);
600 xasprintf(&crit_freespace_units, "@%s", optarg); 572 }
601 } 573 } else {
602 } 574 if (*optarg == '@') {
603 break; 575 crit_freespace_units = optarg;
604 576 } else {
605 case 'W': /* warning inode threshold */ 577 xasprintf(&crit_freespace_units, "@%s", optarg);
606 if (*optarg == '@') { 578 }
607 warn_freeinodes_percent = optarg; 579 }
608 } else { 580 break;
609 xasprintf(&warn_freeinodes_percent, "@%s", optarg); 581
610 } 582 case 'W': /* warning inode threshold */
611 break; 583 if (*optarg == '@') {
612 case 'K': /* critical inode threshold */ 584 warn_freeinodes_percent = optarg;
613 if (*optarg == '@') { 585 } else {
614 crit_freeinodes_percent = optarg; 586 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
615 } else { 587 }
616 xasprintf(&crit_freeinodes_percent, "@%s", optarg); 588 break;
617 } 589 case 'K': /* critical inode threshold */
618 break; 590 if (*optarg == '@') {
619 case 'u': 591 crit_freeinodes_percent = optarg;
620 if (units) 592 } else {
621 free(units); 593 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
622 if (! strcasecmp (optarg, "bytes")) { 594 }
623 mult = (uintmax_t)1; 595 break;
624 units = strdup ("B"); 596 case 'u':
625 } else if (!strcmp(optarg, "KiB")) { 597 if (units)
626 mult = (uintmax_t)1024; 598 free(units);
627 units = strdup ("KiB"); 599 if (!strcasecmp(optarg, "bytes")) {
628 } else if (! strcmp (optarg, "kB")) { 600 mult = (uintmax_t)1;
629 mult = (uintmax_t)1000; 601 units = strdup("B");
630 units = strdup ("kB"); 602 } else if (!strcmp(optarg, "KiB")) {
631 } else if (!strcmp(optarg, "MiB")) { 603 mult = (uintmax_t)1024;
632 mult = (uintmax_t)1024 * 1024; 604 units = strdup("KiB");
633 units = strdup ("MiB"); 605 } else if (!strcmp(optarg, "kB")) {
634 } else if (! strcmp (optarg, "MB")) { 606 mult = (uintmax_t)1000;
635 mult = (uintmax_t)1000 * 1000; 607 units = strdup("kB");
636 units = strdup ("MB"); 608 } else if (!strcmp(optarg, "MiB")) {
637 } else if (!strcmp(optarg, "GiB")) { 609 mult = (uintmax_t)1024 * 1024;
638 mult = (uintmax_t)1024 * 1024 * 1024; 610 units = strdup("MiB");
639 units = strdup ("GiB"); 611 } else if (!strcmp(optarg, "MB")) {
640 } else if (! strcmp (optarg, "GB")){ 612 mult = (uintmax_t)1000 * 1000;
641 mult = (uintmax_t)1000 * 1000 * 1000; 613 units = strdup("MB");
642 units = strdup ("GB"); 614 } else if (!strcmp(optarg, "GiB")) {
643 } else if (!strcmp(optarg, "TiB")) { 615 mult = (uintmax_t)1024 * 1024 * 1024;
644 mult = (uintmax_t)1024 * 1024 * 1024 * 1024; 616 units = strdup("GiB");
645 units = strdup ("TiB"); 617 } else if (!strcmp(optarg, "GB")) {
646 } else if (! strcmp (optarg, "TB")) { 618 mult = (uintmax_t)1000 * 1000 * 1000;
647 mult = (uintmax_t)1000 * 1000 * 1000 * 1000; 619 units = strdup("GB");
648 units = strdup ("TB"); 620 } else if (!strcmp(optarg, "TiB")) {
649 } else if (!strcmp(optarg, "PiB")) { 621 mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
650 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024; 622 units = strdup("TiB");
651 units = strdup ("PiB"); 623 } else if (!strcmp(optarg, "TB")) {
652 } else if (! strcmp (optarg, "PB")){ 624 mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
653 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000; 625 units = strdup("TB");
654 units = strdup ("PB"); 626 } else if (!strcmp(optarg, "PiB")) {
655 } else { 627 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
656 die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg); 628 units = strdup("PiB");
657 } 629 } else if (!strcmp(optarg, "PB")) {
658 if (units == NULL) 630 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
659 die (STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units"); 631 units = strdup("PB");
660 break; 632 } else {
661 case 'k': /* display mountpoint */ 633 die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
662 mult = 1024; 634 }
663 if (units) 635 if (units == NULL)
664 free(units); 636 die(STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
665 units = strdup ("kiB"); 637 break;
666 break; 638 case 'k': /* display mountpoint */
667 case 'm': /* display mountpoint */ 639 mult = 1024;
668 mult = 1024 * 1024; 640 if (units)
669 if (units) 641 free(units);
670 free(units); 642 units = strdup("kiB");
671 units = strdup ("MiB"); 643 break;
672 break; 644 case 'm': /* display mountpoint */
673 case 'L': 645 mult = 1024 * 1024;
674 stat_remote_fs = 1; 646 if (units)
675 /* fallthrough */ 647 free(units);
676 case 'l': 648 units = strdup("MiB");
677 show_local_fs = 1; 649 break;
678 break; 650 case 'L':
679 case 'P': 651 stat_remote_fs = 1;
680 display_inodes_perfdata = 1; 652 /* fallthrough */
681 break; 653 case 'l':
682 case 'p': /* select path */ 654 show_local_fs = 1;
683 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent || 655 break;
684 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units || 656 case 'P':
685 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent || 657 display_inodes_perfdata = 1;
686 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) { 658 break;
687 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n")); 659 case 'p': /* select path */
688 } 660 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
689 661 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
690 /* add parameter if not found. overwrite thresholds if path has already been added */ 662 warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
691 if (! (se = np_find_parameter(path_select_list, optarg))) { 663 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
692 se = np_add_parameter(&path_select_list, optarg); 664 }
693 665
694 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) { 666 /* add parameter if not found. overwrite thresholds if path has already been added */
695 path_ignored = true; 667 if (!(se = np_find_parameter(path_select_list, optarg))) {
696 break; 668 se = np_add_parameter(&path_select_list, optarg);
697 } 669
698 } 670 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
699 se->group = group; 671 path_ignored = true;
700 set_all_thresholds(se); 672 break;
701 673 }
702 /* With autofs, it is required to stat() the path before re-populating the mount_list */ 674 }
703 if (!stat_path(se)) { 675 se->group = group;
704 break; 676 set_all_thresholds(se);
705 } 677
706 /* NB: We can't free the old mount_list "just like that": both list pointers and struct 678 /* With autofs, it is required to stat() the path before re-populating the mount_list */
707 * pointers are copied around. One of the reason it wasn't done yet is that other parts 679 if (!stat_path(se)) {
708 * of check_disk need the same kind of cleanup so it'd better be done as a whole */ 680 break;
709 mount_list = read_file_system_list (0); 681 }
710 np_set_best_match(se, mount_list, exact_match); 682 /* NB: We can't free the old mount_list "just like that": both list pointers and struct
711 683 * pointers are copied around. One of the reason it wasn't done yet is that other parts
712 path_selected = true; 684 * of check_disk need the same kind of cleanup so it'd better be done as a whole */
713 break; 685 mount_list = read_file_system_list(0);
714 case 'x': /* exclude path or partition */ 686 np_set_best_match(se, mount_list, exact_match);
715 np_add_name(&dp_exclude_list, optarg); 687
716 break; 688 path_selected = true;
717 case 'X': /* exclude file system type */ 689 break;
718 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED); 690 case 'x': /* exclude path or partition */
719 if (err != 0) { 691 np_add_name(&dp_exclude_list, optarg);
720 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER); 692 break;
721 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf); 693 case 'X': /* exclude file system type */
722 } 694 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
723 break; 695 if (err != 0) {
724 case 'N': /* include file system type */ 696 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
725 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED); 697 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
726 if (err != 0) { 698 }
727 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER); 699 break;
728 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf); 700 case 'N': /* include file system type */
729 } 701 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
730 break; 702 if (err != 0) {
731 case 'v': /* verbose */ 703 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
732 verbose++; 704 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
733 break; 705 }
734 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */ 706 break;
735 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */ 707 case 'v': /* verbose */
736 erronly = true; 708 verbose++;
737 break; 709 break;
738 case 'e': 710 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
739 erronly = true; 711 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
740 break; 712 erronly = true;
741 case 'E': 713 break;
742 if (path_selected) 714 case 'e':
743 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n")); 715 erronly = true;
744 exact_match = true; 716 break;
745 break; 717 case 'E':
746 case 'f': 718 if (path_selected)
747 freespace_ignore_reserved = true; 719 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
748 break; 720 exact_match = true;
749 case 'g': 721 break;
750 if (path_selected) 722 case 'f':
751 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n")); 723 freespace_ignore_reserved = true;
752 group = optarg; 724 break;
753 break; 725 case 'g':
754 case 'I': 726 if (path_selected)
755 cflags |= REG_ICASE; 727 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
756 // Intentional fallthrough 728 group = optarg;
757 case 'i': 729 break;
758 if (!path_selected) 730 case 'I':
759 die (STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"), _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly")); 731 cflags |= REG_ICASE;
760 err = regcomp(&re, optarg, cflags); 732 // Intentional fallthrough
761 if (err != 0) { 733 case 'i':
762 regerror (err, &re, errbuf, MAX_INPUT_BUFFER); 734 if (!path_selected)
763 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf); 735 die(STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"),
764 } 736 _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly"));
765 737 err = regcomp(&re, optarg, cflags);
766 temp_list = path_select_list; 738 if (err != 0) {
767 739 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
768 previous = NULL; 740 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
769 while (temp_list) { 741 }
770 if (temp_list->best_match) { 742
771 if (np_regex_match_mount_entry(temp_list->best_match, &re)) { 743 temp_list = path_select_list;
772 744
773 if (verbose >=3) 745 previous = NULL;
774 printf("ignoring %s matching regex\n", temp_list->name); 746 while (temp_list) {
775 747 if (temp_list->best_match) {
776 temp_list = np_del_parameter(temp_list, previous); 748 if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
777 /* pointer to first element needs to be updated if first item gets deleted */ 749
778 if (previous == NULL) 750 if (verbose >= 3)
779 path_select_list = temp_list; 751 printf("ignoring %s matching regex\n", temp_list->name);
780 } else { 752
781 previous = temp_list; 753 temp_list = np_del_parameter(temp_list, previous);
782 temp_list = temp_list->name_next; 754 /* pointer to first element needs to be updated if first item gets deleted */
783 } 755 if (previous == NULL)
784 } else { 756 path_select_list = temp_list;
785 previous = temp_list; 757 } else {
786 temp_list = temp_list->name_next; 758 previous = temp_list;
787 } 759 temp_list = temp_list->name_next;
788 } 760 }
789 761 } else {
790 762 previous = temp_list;
791 cflags = default_cflags; 763 temp_list = temp_list->name_next;
792 break; 764 }
793 765 }
794 case 'n': 766
795 ignore_missing = true; 767 cflags = default_cflags;
796 break; 768 break;
797 case 'A': 769
798 optarg = strdup(".*"); 770 case 'n':
799 // Intentional fallthrough 771 ignore_missing = true;
800 case 'R': 772 break;
801 cflags |= REG_ICASE; 773 case 'A':
802 // Intentional fallthrough 774 optarg = strdup(".*");
803 case 'r': 775 // Intentional fallthrough
804 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent || 776 case 'R':
805 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units || 777 cflags |= REG_ICASE;
806 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent || 778 // Intentional fallthrough
807 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) { 779 case 'r':
808 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n")); 780 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
809 } 781 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
810 782 warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
811 err = regcomp(&re, optarg, cflags); 783 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"),
812 if (err != 0) { 784 _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n"));
813 regerror (err, &re, errbuf, MAX_INPUT_BUFFER); 785 }
814 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf); 786
815 } 787 err = regcomp(&re, optarg, cflags);
816 788 if (err != 0) {
817 for (me = mount_list; me; me = me->me_next) { 789 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
818 if (np_regex_match_mount_entry(me, &re)) { 790 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
819 fnd = true; 791 }
820 if (verbose >= 3) 792
821 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg); 793 for (me = mount_list; me; me = me->me_next) {
822 794 if (np_regex_match_mount_entry(me, &re)) {
823 /* add parameter if not found. overwrite thresholds if path has already been added */ 795 fnd = true;
824 if (! (se = np_find_parameter(path_select_list, me->me_mountdir))) { 796 if (verbose >= 3)
825 se = np_add_parameter(&path_select_list, me->me_mountdir); 797 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg);
826 } 798
827 se->group = group; 799 /* add parameter if not found. overwrite thresholds if path has already been added */
828 set_all_thresholds(se); 800 if (!(se = np_find_parameter(path_select_list, me->me_mountdir))) {
829 } 801 se = np_add_parameter(&path_select_list, me->me_mountdir);
830 } 802 }
831 803 se->group = group;
832 if (!fnd && ignore_missing == true) { 804 set_all_thresholds(se);
833 path_ignored = true; 805 }
834 path_selected = true; 806 }
835 break; 807
836 } else if (!fnd) 808 if (!fnd && ignore_missing == true) {
837 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), 809 path_ignored = true;
838 _("Regular expression did not match any path or disk"), optarg); 810 path_selected = true;
839 811 break;
840 fnd = false; 812 }
841 path_selected = true; 813 if (!fnd)
842 np_set_best_match(path_select_list, mount_list, exact_match); 814 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Regular expression did not match any path or disk"), optarg);
843 cflags = default_cflags; 815
844 816 fnd = false;
845 break; 817 path_selected = true;
846 case 'M': /* display mountpoint */ 818 np_set_best_match(path_select_list, mount_list, exact_match);
847 display_mntp = true; 819 cflags = default_cflags;
848 break; 820
849 case 'C': 821 break;
850 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */ 822 case 'M': /* display mountpoint */
851 if (path_selected == false) { 823 display_mntp = true;
852 struct parameter_list *path; 824 break;
853 for (me = mount_list; me; me = me->me_next) { 825 case 'C':
854 if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) 826 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
855 path = np_add_parameter(&path_select_list, me->me_mountdir); 827 if (path_selected == false) {
856 path->best_match = me; 828 struct parameter_list *path;
857 path->group = group; 829 for (me = mount_list; me; me = me->me_next) {
858 set_all_thresholds(path); 830 if (!(path = np_find_parameter(path_select_list, me->me_mountdir)))
859 } 831 path = np_add_parameter(&path_select_list, me->me_mountdir);
860 } 832 path->best_match = me;
861 warn_freespace_units = NULL; 833 path->group = group;
862 crit_freespace_units = NULL; 834 set_all_thresholds(path);
863 warn_usedspace_units = NULL; 835 }
864 crit_usedspace_units = NULL; 836 }
865 warn_freespace_percent = NULL; 837 warn_freespace_units = NULL;
866 crit_freespace_percent = NULL; 838 crit_freespace_units = NULL;
867 warn_usedspace_percent = NULL; 839 warn_usedspace_units = NULL;
868 crit_usedspace_percent = NULL; 840 crit_usedspace_units = NULL;
869 warn_usedinodes_percent = NULL; 841 warn_freespace_percent = NULL;
870 crit_usedinodes_percent = NULL; 842 crit_freespace_percent = NULL;
871 warn_freeinodes_percent = NULL; 843 warn_usedspace_percent = NULL;
872 crit_freeinodes_percent = NULL; 844 crit_usedspace_percent = NULL;
873 845 warn_usedinodes_percent = NULL;
874 path_selected = false; 846 crit_usedinodes_percent = NULL;
875 group = NULL; 847 warn_freeinodes_percent = NULL;
876 break; 848 crit_freeinodes_percent = NULL;
877 case 'V': /* version */ 849
878 print_revision (progname, NP_VERSION); 850 path_selected = false;
879 exit (STATE_UNKNOWN); 851 group = NULL;
880 case 'h': /* help */ 852 break;
881 print_help (); 853 case 'V': /* version */
882 exit (STATE_UNKNOWN); 854 print_revision(progname, NP_VERSION);
883 case '?': /* help */ 855 exit(STATE_UNKNOWN);
884 usage (_("Unknown argument")); 856 case 'h': /* help */
885 } 857 print_help();
886 } 858 exit(STATE_UNKNOWN);
887 859 case '?': /* help */
888 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */ 860 usage(_("Unknown argument"));
889 c = optind; 861 }
890 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c])) 862 }
891 warn_usedspace_percent = argv[c++]; 863
892 864 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
893 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c])) 865 c = optind;
894 crit_usedspace_percent = argv[c++]; 866 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
895 867 warn_usedspace_percent = argv[c++];
896 if (argc > c) { 868
897 se = np_add_parameter(&path_select_list, strdup(argv[c++])); 869 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
898 path_selected = true; 870 crit_usedspace_percent = argv[c++];
899 set_all_thresholds(se); 871
900 } 872 if (argc > c) {
901 873 se = np_add_parameter(&path_select_list, strdup(argv[c++]));
902 if (units == NULL) { 874 path_selected = true;
903 units = strdup ("MiB"); 875 set_all_thresholds(se);
904 mult = (uintmax_t)1024 * 1024; 876 }
905 } 877
906 878 if (units == NULL) {
907 return true; 879 units = strdup("MiB");
880 mult = (uintmax_t)1024 * 1024;
881 }
882
883 return true;
908} 884}
909 885
910 886void set_all_thresholds(struct parameter_list *path) {
911 887 if (path->freespace_units != NULL)
912void 888 free(path->freespace_units);
913print_path (const char *mypath) 889 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
914{ 890 if (path->freespace_percent != NULL)
915 if (mypath == NULL) 891 free(path->freespace_percent);
916 printf ("\n"); 892 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
917 else 893 if (path->usedspace_units != NULL)
918 printf (_(" for %s\n"), mypath); 894 free(path->usedspace_units);
895 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
896 if (path->usedspace_percent != NULL)
897 free(path->usedspace_percent);
898 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
899 if (path->usedinodes_percent != NULL)
900 free(path->usedinodes_percent);
901 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
902 if (path->freeinodes_percent != NULL)
903 free(path->freeinodes_percent);
904 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent);
919} 905}
920 906
921 907void print_help(void) {
922void 908 print_revision(progname, NP_VERSION);
923set_all_thresholds (struct parameter_list *path) 909
924{ 910 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
925 if (path->freespace_units != NULL) free(path->freespace_units); 911 printf(COPYRIGHT, copyright, email);
926 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units); 912
927 if (path->freespace_percent != NULL) free (path->freespace_percent); 913 printf("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
928 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent); 914 printf("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
929 if (path->usedspace_units != NULL) free (path->usedspace_units); 915
930 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units); 916 printf("\n\n");
931 if (path->usedspace_percent != NULL) free (path->usedspace_percent); 917
932 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent); 918 print_usage();
933 if (path->usedinodes_percent != NULL) free (path->usedinodes_percent); 919
934 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent); 920 printf(UT_HELP_VRSN);
935 if (path->freeinodes_percent != NULL) free (path->freeinodes_percent); 921 printf(UT_EXTRA_OPTS);
936 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent); 922
923 printf(" %s\n", "-w, --warning=INTEGER");
924 printf(" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
925 printf(" %s\n", "-w, --warning=PERCENT%");
926 printf(" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
927 printf(" %s\n", "-c, --critical=INTEGER");
928 printf(" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
929 printf(" %s\n", "-c, --critical=PERCENT%");
930 printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free"));
931 printf(" %s\n", "-W, --iwarning=PERCENT%");
932 printf(" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
933 printf(" %s\n", "-K, --icritical=PERCENT%");
934 printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
935 printf(" %s\n", "-p, --path=PATH, --partition=PARTITION");
936 printf(" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)"));
937 printf(" %s\n", "-x, --exclude_device=PATH <STRING>");
938 printf(" %s\n", _("Ignore device (only works if -p unspecified)"));
939 printf(" %s\n", "-C, --clear");
940 printf(" %s\n", _("Clear thresholds"));
941 printf(" %s\n", "-E, --exact-match");
942 printf(" %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
943 printf(" %s\n", "-e, --errors-only");
944 printf(" %s\n", _("Display only devices/mountpoints with errors"));
945 printf(" %s\n", "-f, --freespace-ignore-reserved");
946 printf(" %s\n", _("Don't account root-reserved blocks into freespace in perfdata"));
947 printf(" %s\n", "-P, --iperfdata");
948 printf(" %s\n", _("Display inode usage in perfdata"));
949 printf(" %s\n", "-g, --group=NAME");
950 printf(" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together"));
951 printf(" %s\n", "-k, --kilobytes");
952 printf(" %s\n", _("Same as '--units kB'"));
953 printf(" %s\n", "-l, --local");
954 printf(" %s\n", _("Only check local filesystems"));
955 printf(" %s\n", "-L, --stat-remote-fs");
956 printf(" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems"));
957 printf(" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)"));
958 printf(" %s\n", "-M, --mountpoint");
959 printf(" %s\n", _("Display the (block) device instead of the mount point"));
960 printf(" %s\n", "-m, --megabytes");
961 printf(" %s\n", _("Same as '--units MB'"));
962 printf(" %s\n", "-A, --all");
963 printf(" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'"));
964 printf(" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION");
965 printf(" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)"));
966 printf(" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION");
967 printf(" %s\n", _("Regular expression for path or partition (may be repeated)"));
968 printf(" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION");
969 printf(" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)"));
970 printf(" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
971 printf(" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)"));
972 printf(" %s\n", "-n, --ignore-missing");
973 printf(" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible."));
974 printf(" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)"));
975 printf(UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
976 printf(" %s\n", "-u, --units=STRING");
977 printf(" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
978 printf(UT_VERBOSE);
979 printf(" %s\n", "-X, --exclude-type=TYPE_REGEX");
980 printf(" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)"));
981 printf(" %s\n", "-N, --include-type=TYPE_REGEX");
982 printf(" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)"));
983
984 printf("\n");
985 printf("%s\n", _("General usage hints:"));
986 printf(" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as"));
987 printf(" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\"."));
988 printf(" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\""));
989
990 printf("\n");
991 printf("%s\n", _("Examples:"));
992 printf(" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
993 printf(" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
994 printf(" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'");
995 printf(" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex"));
996 printf(" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together"));
997 printf(" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar");
998 printf(" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M"));
999
1000 printf(UT_SUPPORT);
937} 1001}
938 1002
939void 1003void print_usage(void) {
940print_help (void) 1004 printf("%s\n", _("Usage:"));
941{ 1005 printf(" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c absolute_limit|-c percentage_limit%% | -K "
942 print_revision (progname, NP_VERSION); 1006 "inode_percentage_limit } {-p path | -x device}\n",
943 1007 progname);
944 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 1008 printf("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n");
945 printf (COPYRIGHT, copyright, email); 1009 printf("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n");
946
947 printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
948 printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
949
950 printf ("\n\n");
951
952 print_usage ();
953
954 printf (UT_HELP_VRSN);
955 printf (UT_EXTRA_OPTS);
956
957 printf (" %s\n", "-w, --warning=INTEGER");
958 printf (" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
959 printf (" %s\n", "-w, --warning=PERCENT%");
960 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
961 printf (" %s\n", "-c, --critical=INTEGER");
962 printf (" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
963 printf (" %s\n", "-c, --critical=PERCENT%");
964 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free"));
965 printf (" %s\n", "-W, --iwarning=PERCENT%");
966 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
967 printf (" %s\n", "-K, --icritical=PERCENT%");
968 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
969 printf (" %s\n", "-p, --path=PATH, --partition=PARTITION");
970 printf (" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)"));
971 printf (" %s\n", "-x, --exclude_device=PATH <STRING>");
972 printf (" %s\n", _("Ignore device (only works if -p unspecified)"));
973 printf (" %s\n", "-C, --clear");
974 printf (" %s\n", _("Clear thresholds"));
975 printf (" %s\n", "-E, --exact-match");
976 printf (" %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
977 printf (" %s\n", "-e, --errors-only");
978 printf (" %s\n", _("Display only devices/mountpoints with errors"));
979 printf (" %s\n", "-f, --freespace-ignore-reserved");
980 printf (" %s\n", _("Don't account root-reserved blocks into freespace in perfdata"));
981 printf (" %s\n", "-P, --iperfdata");
982 printf (" %s\n", _("Display inode usage in perfdata"));
983 printf (" %s\n", "-g, --group=NAME");
984 printf (" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together"));
985 printf (" %s\n", "-k, --kilobytes");
986 printf (" %s\n", _("Same as '--units kB'"));
987 printf (" %s\n", "-l, --local");
988 printf (" %s\n", _("Only check local filesystems"));
989 printf (" %s\n", "-L, --stat-remote-fs");
990 printf (" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems"));
991 printf (" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)"));
992 printf (" %s\n", "-M, --mountpoint");
993 printf (" %s\n", _("Display the (block) device instead of the mount point"));
994 printf (" %s\n", "-m, --megabytes");
995 printf (" %s\n", _("Same as '--units MB'"));
996 printf (" %s\n", "-A, --all");
997 printf (" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'"));
998 printf (" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION");
999 printf (" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)"));
1000 printf (" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION");
1001 printf (" %s\n", _("Regular expression for path or partition (may be repeated)"));
1002 printf (" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION");
1003 printf (" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)"));
1004 printf (" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
1005 printf (" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)"));
1006 printf (" %s\n", "-n, --ignore-missing");
1007 printf (" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible."));
1008 printf (" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)"));
1009 printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1010 printf (" %s\n", "-u, --units=STRING");
1011 printf (" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
1012 printf (UT_VERBOSE);
1013 printf (" %s\n", "-X, --exclude-type=TYPE_REGEX");
1014 printf (" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)"));
1015 printf (" %s\n", "-N, --include-type=TYPE_REGEX");
1016 printf (" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)"));
1017
1018 printf ("\n");
1019 printf ("%s\n", _("General usage hints:"));
1020 printf (" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as"));
1021 printf (" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\"."));
1022 printf (" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\""));
1023
1024
1025
1026 printf ("\n");
1027 printf ("%s\n", _("Examples:"));
1028 printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
1029 printf (" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
1030 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'");
1031 printf (" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex"));
1032 printf (" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together"));
1033 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar");
1034 printf (" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M"));
1035
1036 printf (UT_SUPPORT);
1037} 1010}
1038 1011
1039 1012bool stat_path(struct parameter_list *p) {
1040 1013 /* Stat entry to check that dir exists and is accessible */
1041void 1014 if (verbose >= 3)
1042print_usage (void) 1015 printf("calling stat on %s\n", p->name);
1043{ 1016 if (stat(p->name, &stat_buf[0])) {
1044 printf ("%s\n", _("Usage:")); 1017 if (verbose >= 3)
1045 printf (" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c absolute_limit|-c percentage_limit%% | -K inode_percentage_limit } {-p path | -x device}\n", progname); 1018 printf("stat failed on %s\n", p->name);
1046 printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n"); 1019 if (ignore_missing == true) {
1047 printf ("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n"); 1020 return false;
1048} 1021 }
1049 1022 printf("DISK %s - ", _("CRITICAL"));
1050bool 1023 die(STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
1051stat_path (struct parameter_list *p) 1024 }
1052{ 1025 return true;
1053 /* Stat entry to check that dir exists and is accessible */
1054 if (verbose >= 3)
1055 printf("calling stat on %s\n", p->name);
1056 if (stat (p->name, &stat_buf[0])) {
1057 if (verbose >= 3)
1058 printf("stat failed on %s\n", p->name);
1059 if (ignore_missing == true) {
1060 return false;
1061 } else {
1062 printf("DISK %s - ", _("CRITICAL"));
1063 die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
1064 }
1065 }
1066 return true;
1067} 1026}
1068 1027
1028void get_stats(struct parameter_list *p, struct fs_usage *fsp) {
1029 struct parameter_list *p_list;
1030 struct fs_usage tmpfsp;
1031 int first = 1;
1069 1032
1070void 1033 if (p->group == NULL) {
1071get_stats (struct parameter_list *p, struct fs_usage *fsp) { 1034 get_path_stats(p, fsp);
1072 struct parameter_list *p_list; 1035 } else {
1073 struct fs_usage tmpfsp; 1036 /* find all group members */
1074 int first = 1; 1037 for (p_list = path_select_list; p_list; p_list = p_list->name_next) {
1075
1076 if (p->group == NULL) {
1077 get_path_stats(p,fsp);
1078 } else {
1079 /* find all group members */
1080 for (p_list = path_select_list; p_list; p_list=p_list->name_next) {
1081#ifdef __CYGWIN__ 1038#ifdef __CYGWIN__
1082 if (strncmp(p_list->name, "/cygdrive/", 10) != 0) 1039 if (strncmp(p_list->name, "/cygdrive/", 10) != 0)
1083 continue; 1040 continue;
1084#endif 1041#endif
1085 if (p_list->group && ! (strcmp(p_list->group, p->group))) { 1042 if (p_list->group && !(strcmp(p_list->group, p->group))) {
1086 if (! stat_path(p_list)) 1043 if (!stat_path(p_list))
1087 continue; 1044 continue;
1088 get_fs_usage (p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp); 1045 get_fs_usage(p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp);
1089 get_path_stats(p_list, &tmpfsp); 1046 get_path_stats(p_list, &tmpfsp);
1090 if (verbose >= 3) 1047 if (verbose >= 3)
1091 printf("Group %s: adding %lu blocks sized %lu, (%s) used_units=%lu free_units=%lu total_units=%lu mult=%lu\n", 1048 printf("Group %s: adding %lu blocks sized %lu, (%s) used_units=%lu free_units=%lu total_units=%lu mult=%lu\n",
1092 p_list->group, 1049 p_list->group, tmpfsp.fsu_blocks, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units,
1093 tmpfsp.fsu_blocks, 1050 p_list->dfree_units, p_list->dtotal_units, mult);
1094 tmpfsp.fsu_blocksize, 1051
1095 p_list->best_match->me_mountdir, 1052 /* prevent counting the first FS of a group twice since its parameter_list entry
1096 p_list->dused_units, 1053 * is used to carry the information of all file systems of the entire group */
1097 p_list->dfree_units, 1054 if (!first) {
1098 p_list->dtotal_units, 1055 p->total += p_list->total;
1099 mult); 1056 p->available += p_list->available;
1100 1057 p->available_to_root += p_list->available_to_root;
1101 /* prevent counting the first FS of a group twice since its parameter_list entry 1058 p->used += p_list->used;
1102 * is used to carry the information of all file systems of the entire group */ 1059
1103 if (! first) { 1060 p->dused_units += p_list->dused_units;
1104 p->total += p_list->total; 1061 p->dfree_units += p_list->dfree_units;
1105 p->available += p_list->available; 1062 p->dtotal_units += p_list->dtotal_units;
1106 p->available_to_root += p_list->available_to_root; 1063 p->inodes_total += p_list->inodes_total;
1107 p->used += p_list->used; 1064 p->inodes_free += p_list->inodes_free;
1108 1065 p->inodes_free_to_root += p_list->inodes_free_to_root;
1109 p->dused_units += p_list->dused_units; 1066 p->inodes_used += p_list->inodes_used;
1110 p->dfree_units += p_list->dfree_units; 1067 }
1111 p->dtotal_units += p_list->dtotal_units; 1068 first = 0;
1112 p->inodes_total += p_list->inodes_total; 1069 }
1113 p->inodes_free += p_list->inodes_free; 1070 if (verbose >= 3)
1114 p->inodes_free_to_root += p_list->inodes_free_to_root; 1071 printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n", p->group,
1115 p->inodes_used += p_list->inodes_used; 1072 p->dused_units, p->dfree_units, p->dtotal_units, tmpfsp.fsu_blocksize, mult);
1116 } 1073 }
1117 first = 0; 1074 /* modify devname and mountdir for output */
1118 } 1075 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1119 if (verbose >= 3) 1076 }
1120 printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n", 1077 /* finally calculate percentages for either plain FS or summed up group */
1121 p->group, 1078 p->dused_pct = calculate_percent(p->used, p->used + p->available); /* used + available can never be > uintmax */
1122 p->dused_units, 1079 p->dfree_pct = 100.0 - p->dused_pct;
1123 p->dfree_units, 1080 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1124 p->dtotal_units, 1081 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1125 tmpfsp.fsu_blocksize,
1126 mult);
1127 }
1128 /* modify devname and mountdir for output */
1129 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1130 }
1131 /* finally calculate percentages for either plain FS or summed up group */
1132 p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */
1133 p->dfree_pct = 100 - p->dused_pct;
1134 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1135 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1136
1137} 1082}
1138 1083
1139void 1084void get_path_stats(struct parameter_list *p, struct fs_usage *fsp) {
1140get_path_stats (struct parameter_list *p, struct fs_usage *fsp) { 1085 p->available = fsp->fsu_bavail;
1141 p->available = fsp->fsu_bavail; 1086 p->available_to_root = fsp->fsu_bfree;
1142 p->available_to_root = fsp->fsu_bfree; 1087 p->used = fsp->fsu_blocks - fsp->fsu_bfree;
1143 p->used = fsp->fsu_blocks - fsp->fsu_bfree; 1088 if (freespace_ignore_reserved) {
1144 if (freespace_ignore_reserved) { 1089 /* option activated : we subtract the root-reserved space from the total */
1145 /* option activated : we subtract the root-reserved space from the total */ 1090 p->total = fsp->fsu_blocks - p->available_to_root + p->available;
1146 p->total = fsp->fsu_blocks - p->available_to_root + p->available; 1091 } else {
1147 } else { 1092 /* default behaviour : take all the blocks into account */
1148 /* default behaviour : take all the blocks into account */ 1093 p->total = fsp->fsu_blocks;
1149 p->total = fsp->fsu_blocks; 1094 }
1150 } 1095
1151 1096 p->dused_units = p->used * fsp->fsu_blocksize / mult;
1152 p->dused_units = p->used*fsp->fsu_blocksize/mult; 1097 p->dfree_units = p->available * fsp->fsu_blocksize / mult;
1153 p->dfree_units = p->available*fsp->fsu_blocksize/mult; 1098 p->dtotal_units = p->total * fsp->fsu_blocksize / mult;
1154 p->dtotal_units = p->total*fsp->fsu_blocksize/mult; 1099 /* Free file nodes. Not sure the workaround is required, but in case...*/
1155 /* Free file nodes. Not sure the workaround is required, but in case...*/ 1100 p->inodes_free = fsp->fsu_ffree;
1156 p->inodes_free = fsp->fsu_ffree; 1101 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
1157 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */ 1102 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
1158 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree; 1103 if (freespace_ignore_reserved) {
1159 if (freespace_ignore_reserved) { 1104 /* option activated : we subtract the root-reserved inodes from the total */
1160 /* option activated : we subtract the root-reserved inodes from the total */ 1105 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */
1161 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */ 1106 /* for others, fsp->fsu_ffree == fsp->fsu_favail */
1162 /* for others, fsp->fsu_ffree == fsp->fsu_favail */ 1107 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free;
1163 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free; 1108 } else {
1164 } else { 1109 /* default behaviour : take all the inodes into account */
1165 /* default behaviour : take all the inodes into account */ 1110 p->inodes_total = fsp->fsu_files;
1166 p->inodes_total = fsp->fsu_files; 1111 }
1167 } 1112 np_add_name(&seen, p->best_match->me_mountdir);
1168 np_add_name(&seen, p->best_match->me_mountdir);
1169} 1113}