summaryrefslogtreecommitdiffstats
path: root/plugins/check_disk.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_disk.c')
-rw-r--r--plugins/check_disk.c2036
1 files changed, 994 insertions, 1042 deletions
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index 24de2d4..d1d1b92 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"
@@ -48,14 +47,14 @@ const char *email = "devel@monitoring-plugins.org";
48#include "mountlist.h" 47#include "mountlist.h"
49#include <float.h> 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,1054 +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=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f free_inodes_pct=%f 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
343 temp_result = get_status(path->dfree_units, path->freespace_units);
344 if (verbose >=3) printf("Freespace_units result=%d\n", temp_result);
345 disk_result = max_state( disk_result, temp_result );
346
347 temp_result = get_status(path->dfree_pct, path->freespace_percent);
348 if (verbose >=3) printf("Freespace%% result=%d\n", temp_result);
349 disk_result = max_state( disk_result, temp_result );
350
351 temp_result = get_status(path->dused_units, path->usedspace_units);
352 if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result);
353 disk_result = max_state( disk_result, temp_result );
354
355 temp_result = get_status(path->dused_pct, path->usedspace_percent);
356 if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result);
357 disk_result = max_state( disk_result, temp_result );
358
359 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
360 if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result);
361 disk_result = max_state( disk_result, temp_result );
362
363 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
364 if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result);
365 disk_result = max_state( disk_result, temp_result );
366
367 result = max_state(result, disk_result);
368
369 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
370 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
371 data. Assumption that start=0. Roll on new syntax...
372 */
373
374 /* *_high_tide must be reinitialized at each run */
375 uint64_t warning_high_tide = UINT64_MAX;
376
377 if (path->freespace_units->warning != NULL) {
378 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
379 }
380 if (path->freespace_percent->warning != NULL) {
381 warning_high_tide = min( warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end/100) * (path->dtotal_units * mult)) );
382 }
383
384 uint64_t critical_high_tide = UINT64_MAX;
385
386 if (path->freespace_units->critical != NULL) {
387 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
388 }
389 if (path->freespace_percent->critical != NULL) {
390 critical_high_tide = min( critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end/100) * (path->dtotal_units * mult)) );
391 }
392
393 /* Nb: *_high_tide are unset when == UINT64_MAX */
394 xasprintf (&perf, "%s %s", perf,
395 perfdata_uint64 (
396 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
397 path->dused_units * mult, "B",
398 (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
399 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide,
400 true, 0,
401 true, path->dtotal_units * mult));
402
403 if (display_inodes_perfdata) {
404 /* *_high_tide must be reinitialized at each run */
405 warning_high_tide = UINT64_MAX;
406 critical_high_tide = UINT64_MAX;
407
408 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 ));
410 }
411 if (path->freeinodes_percent->critical != NULL) {
412 critical_high_tide = (uint64_t) fabs( min( (double) critical_high_tide, (double) (1.0 - path->freeinodes_percent->critical->end/100)*path->inodes_total ));
413 }
414
415 xasprintf (&perf_ilabel, "%s (inodes)", (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
416 /* Nb: *_high_tide are unset when == UINT64_MAX */
417 xasprintf (&perf, "%s %s", perf,
418 perfdata_uint64 (perf_ilabel,
419 path->inodes_used, "",
420 (warning_high_tide != UINT64_MAX ? true : false), warning_high_tide,
421 (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide,
422 true, 0,
423 true, path->inodes_total));
424 }
425
426 if (disk_result==STATE_OK && erronly && !verbose)
427 continue;
428
429 if(disk_result && verbose >= 1) {
430 xasprintf(&flag_header, " %s [", state_text (disk_result));
431 } else {
432 xasprintf(&flag_header, "");
433 }
434 xasprintf (&output, "%s%s %s %llu%s (%.1f%%",
435 output, flag_header,
436 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
437 path->dfree_units,
438 units,
439 path->dfree_pct);
440 if (path->dused_inodes_percent < 0) {
441 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
442 } else {
443 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
444 }
445 free(flag_header);
446 }
447 }
448
449 if (verbose >= 2)
450 xasprintf (&output, "%s%s", output, details);
451
452 if (strcmp(output, "") == 0 && ! erronly) {
453 preamble = "";
454 xasprintf (&output, " - No disks were found for provided parameters");
455 }
456
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}
460 333
334 temp_result = get_status(path->dfree_pct, path->freespace_percent);
335 if (verbose >= 3)
336 printf("Freespace%% result=%d\n", temp_result);
337 disk_result = max_state(disk_result, temp_result);
338
339 temp_result = get_status(path->dused_units, path->usedspace_units);
340 if (verbose >= 3)
341 printf("Usedspace_units result=%d\n", temp_result);
342 disk_result = max_state(disk_result, temp_result);
343
344 temp_result = get_status(path->dused_pct, path->usedspace_percent);
345 if (verbose >= 3)
346 printf("Usedspace_percent result=%d\n", temp_result);
347 disk_result = max_state(disk_result, temp_result);
348
349 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
350 if (verbose >= 3)
351 printf("Usedinodes_percent result=%d\n", temp_result);
352 disk_result = max_state(disk_result, temp_result);
353
354 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
355 if (verbose >= 3)
356 printf("Freeinodes_percent result=%d\n", temp_result);
357 disk_result = max_state(disk_result, temp_result);
358
359 result = max_state(result, disk_result);
360
361 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
362 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
363 data. Assumption that start=0. Roll on new syntax...
364 */
365
366 /* *_high_tide must be reinitialized at each run */
367 uint64_t warning_high_tide = UINT64_MAX;
368
369 if (path->freespace_units->warning != NULL) {
370 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
371 }
372 if (path->freespace_percent->warning != NULL) {
373 warning_high_tide =
374 min(warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end / 100) * (path->dtotal_units * mult)));
375 }
376
377 uint64_t critical_high_tide = UINT64_MAX;
378
379 if (path->freespace_units->critical != NULL) {
380 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
381 }
382 if (path->freespace_percent->critical != NULL) {
383 critical_high_tide =
384 min(critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end / 100) * (path->dtotal_units * mult)));
385 }
386
387 /* Nb: *_high_tide are unset when == UINT64_MAX */
388 xasprintf(&perf, "%s %s", perf,
389 perfdata_uint64((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
390 path->dused_units * mult, "B", (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
391 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide, true, 0, true,
392 path->dtotal_units * mult));
393
394 if (display_inodes_perfdata) {
395 /* *_high_tide must be reinitialized at each run */
396 warning_high_tide = UINT64_MAX;
397 critical_high_tide = UINT64_MAX;
398
399 if (path->freeinodes_percent->warning != NULL) {
400 warning_high_tide = (uint64_t)fabs(
401 min((double)warning_high_tide, (double)(1.0 - path->freeinodes_percent->warning->end / 100) * path->inodes_total));
402 }
403 if (path->freeinodes_percent->critical != NULL) {
404 critical_high_tide = (uint64_t)fabs(min(
405 (double)critical_high_tide, (double)(1.0 - path->freeinodes_percent->critical->end / 100) * path->inodes_total));
406 }
407
408 xasprintf(&perf_ilabel, "%s (inodes)",
409 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
410 /* Nb: *_high_tide are unset when == UINT64_MAX */
411 xasprintf(&perf, "%s %s", perf,
412 perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX ? true : false),
413 warning_high_tide, (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide, true, 0,
414 true, path->inodes_total));
415 }
416
417 if (disk_result == STATE_OK && erronly && !verbose)
418 continue;
419
420 if (disk_result && verbose >= 1) {
421 xasprintf(&flag_header, " %s [", state_text(disk_result));
422 } else {
423 xasprintf(&flag_header, "");
424 }
425 xasprintf(&output, "%s%s %s %llu%s (%.1f%%", output, flag_header,
426 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, path->dfree_units, units,
427 path->dfree_pct);
428 if (path->dused_inodes_percent < 0) {
429 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
430 } else {
431 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
432 }
433 free(flag_header);
434 }
435 }
436
437 if (verbose >= 2)
438 xasprintf(&output, "%s%s", output, details);
439
440 if (strcmp(output, "") == 0 && !erronly) {
441 preamble = "";
442 xasprintf(&output, " - No disks were found for provided parameters");
443 }
444
445 printf("DISK %s%s%s%s%s|%s\n", state_text(result), ((erronly && result == STATE_OK)) ? "" : preamble, output,
446 (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
447 return result;
448}
461 449
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 if(value <= DBL_MAX && total != 0) { 452 if (value <= DBL_MAX && total != 0) {
465 pct = (double)value / total * 100.0; 453 pct = (double)value / total * 100.0;
466 } 454 }
467 return pct; 455 return pct;
468} 456}
469 457
470/* process command-line arguments */ 458/* process command-line arguments */
471int 459int process_arguments(int argc, char **argv) {
472process_arguments (int argc, char **argv) 460 int c;
473{ 461 int err;
474 int c, err; 462 struct parameter_list *se;
475 struct parameter_list *se; 463 struct parameter_list *temp_list = NULL;
476 struct parameter_list *temp_list = NULL, *previous = NULL; 464 struct parameter_list *previous = NULL;
477 struct mount_entry *me; 465 struct mount_entry *me;
478 regex_t re; 466 regex_t re;
479 int cflags = REG_NOSUB | REG_EXTENDED; 467 int cflags = REG_NOSUB | REG_EXTENDED;
480 int default_cflags = cflags; 468 int default_cflags = cflags;
481 char errbuf[MAX_INPUT_BUFFER]; 469 char errbuf[MAX_INPUT_BUFFER];
482 int fnd = 0; 470 int fnd = 0;
483 471
484 int option = 0; 472 int option = 0;
485 static struct option longopts[] = { 473 static struct option longopts[] = {{"timeout", required_argument, 0, 't'},
486 {"timeout", required_argument, 0, 't'}, 474 {"warning", required_argument, 0, 'w'},
487 {"warning", required_argument, 0, 'w'}, 475 {"critical", required_argument, 0, 'c'},
488 {"critical", required_argument, 0, 'c'}, 476 {"iwarning", required_argument, 0, 'W'},
489 {"iwarning", required_argument, 0, 'W'}, 477 /* Dang, -C is taken. We might want to reshuffle this. */
490 /* Dang, -C is taken. We might want to reshuffle this. */ 478 {"icritical", required_argument, 0, 'K'},
491 {"icritical", required_argument, 0, 'K'}, 479 {"kilobytes", no_argument, 0, 'k'},
492 {"kilobytes", no_argument, 0, 'k'}, 480 {"megabytes", no_argument, 0, 'm'},
493 {"megabytes", no_argument, 0, 'm'}, 481 {"units", required_argument, 0, 'u'},
494 {"units", required_argument, 0, 'u'}, 482 {"path", required_argument, 0, 'p'},
495 {"path", required_argument, 0, 'p'}, 483 {"partition", required_argument, 0, 'p'},
496 {"partition", required_argument, 0, 'p'}, 484 {"exclude_device", required_argument, 0, 'x'},
497 {"exclude_device", required_argument, 0, 'x'}, 485 {"exclude-type", required_argument, 0, 'X'},
498 {"exclude-type", required_argument, 0, 'X'}, 486 {"include-type", required_argument, 0, 'N'},
499 {"include-type", required_argument, 0, 'N'}, 487 {"group", required_argument, 0, 'g'},
500 {"group", required_argument, 0, 'g'}, 488 {"eregi-path", required_argument, 0, 'R'},
501 {"eregi-path", required_argument, 0, 'R'}, 489 {"eregi-partition", required_argument, 0, 'R'},
502 {"eregi-partition", required_argument, 0, 'R'}, 490 {"ereg-path", required_argument, 0, 'r'},
503 {"ereg-path", required_argument, 0, 'r'}, 491 {"ereg-partition", required_argument, 0, 'r'},
504 {"ereg-partition", required_argument, 0, 'r'}, 492 {"freespace-ignore-reserved", no_argument, 0, 'f'},
505 {"freespace-ignore-reserved", no_argument, 0, 'f'}, 493 {"ignore-ereg-path", required_argument, 0, 'i'},
506 {"ignore-ereg-path", required_argument, 0, 'i'}, 494 {"ignore-ereg-partition", required_argument, 0, 'i'},
507 {"ignore-ereg-partition", required_argument, 0, 'i'}, 495 {"ignore-eregi-path", required_argument, 0, 'I'},
508 {"ignore-eregi-path", required_argument, 0, 'I'}, 496 {"ignore-eregi-partition", required_argument, 0, 'I'},
509 {"ignore-eregi-partition", required_argument, 0, 'I'}, 497 {"ignore-missing", no_argument, 0, 'n'},
510 {"ignore-missing", no_argument, 0, 'n'}, 498 {"local", no_argument, 0, 'l'},
511 {"local", no_argument, 0, 'l'}, 499 {"stat-remote-fs", no_argument, 0, 'L'},
512 {"stat-remote-fs", no_argument, 0, 'L'}, 500 {"iperfdata", no_argument, 0, 'P'},
513 {"iperfdata", no_argument, 0, 'P'}, 501 {"mountpoint", no_argument, 0, 'M'},
514 {"mountpoint", no_argument, 0, 'M'}, 502 {"errors-only", no_argument, 0, 'e'},
515 {"errors-only", no_argument, 0, 'e'}, 503 {"exact-match", no_argument, 0, 'E'},
516 {"exact-match", no_argument, 0, 'E'}, 504 {"all", no_argument, 0, 'A'},
517 {"all", no_argument, 0, 'A'}, 505 {"verbose", no_argument, 0, 'v'},
518 {"verbose", no_argument, 0, 'v'}, 506 {"quiet", no_argument, 0, 'q'},
519 {"quiet", no_argument, 0, 'q'}, 507 {"clear", no_argument, 0, 'C'},
520 {"clear", no_argument, 0, 'C'}, 508 {"version", no_argument, 0, 'V'},
521 {"version", no_argument, 0, 'V'}, 509 {"help", no_argument, 0, 'h'},
522 {"help", no_argument, 0, 'h'}, 510 {0, 0, 0, 0}};
523 {0, 0, 0, 0} 511
524 }; 512 if (argc < 2)
525 513 return ERROR;
526 if (argc < 2) 514
527 return ERROR; 515 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED);
528 516
529 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED); 517 for (c = 1; c < argc; c++)
530 518 if (strcmp("-to", argv[c]) == 0)
531 for (c = 1; c < argc; c++) 519 strcpy(argv[c], "-t");
532 if (strcmp ("-to", argv[c]) == 0) 520
533 strcpy (argv[c], "-t"); 521 while (1) {
534 522 c = getopt_long(argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option);
535 while (1) { 523
536 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)
537 525 break;
538 if (c == -1 || c == EOF) 526
539 break; 527 switch (c) {
540 528 case 't': /* timeout period */
541 switch (c) { 529 if (is_integer(optarg)) {
542 case 't': /* timeout period */ 530 timeout_interval = atoi(optarg);
543 if (is_integer (optarg)) { 531 break;
544 timeout_interval = atoi (optarg); 532 } else {
545 break; 533 usage2(_("Timeout interval must be a positive integer"), optarg);
546 } 534 }
547 else { 535
548 usage2 (_("Timeout interval must be a positive integer"), optarg); 536 /* See comments for 'c' */
549 } 537 case 'w': /* warning threshold */
550
551 /* See comments for 'c' */
552 case 'w': /* warning threshold */
553 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) { 538 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
554 die(STATE_UNKNOWN, "Argument for --warning invalid or missing: %s\n", optarg); 539 die(STATE_UNKNOWN, "Argument for --warning invalid or missing: %s\n", optarg);
555 } 540 }
556 541
557 if (strstr(optarg, "%")) { 542 if (strstr(optarg, "%")) {
558 if (*optarg == '@') { 543 if (*optarg == '@') {
559 warn_freespace_percent = optarg; 544 warn_freespace_percent = optarg;
560 } else { 545 } else {
561 xasprintf(&warn_freespace_percent, "@%s", optarg); 546 xasprintf(&warn_freespace_percent, "@%s", optarg);
562 } 547 }
563 } else { 548 } else {
564 if (*optarg == '@') { 549 if (*optarg == '@') {
565 warn_freespace_units = optarg; 550 warn_freespace_units = optarg;
566 } else { 551 } else {
567 xasprintf(&warn_freespace_units, "@%s", optarg); 552 xasprintf(&warn_freespace_units, "@%s", optarg);
568 } 553 }
569 } 554 }
570 break; 555 break;
571 556
572 /* Awful mistake where the range values do not make sense. Normally, 557 /* Awful mistake where the range values do not make sense. Normally,
573 you alert if the value is within the range, but since we are using 558 you alert if the value is within the range, but since we are using
574 freespace, we have to alert if outside the range. Thus we artificially 559 freespace, we have to alert if outside the range. Thus we artificially
575 force @ at the beginning of the range, so that it is backwards compatible 560 force @ at the beginning of the range, so that it is backwards compatible
576 */ 561 */
577 case 'c': /* critical threshold */ 562 case 'c': /* critical threshold */
578 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) { 563 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
579 die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg); 564 die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg);
580 } 565 }
581 566
582 if (strstr(optarg, "%")) { 567 if (strstr(optarg, "%")) {
583 if (*optarg == '@') { 568 if (*optarg == '@') {
584 crit_freespace_percent = optarg; 569 crit_freespace_percent = optarg;
585 } else { 570 } else {
586 xasprintf(&crit_freespace_percent, "@%s", optarg); 571 xasprintf(&crit_freespace_percent, "@%s", optarg);
587 } 572 }
588 } else { 573 } else {
589 if (*optarg == '@') { 574 if (*optarg == '@') {
590 crit_freespace_units = optarg; 575 crit_freespace_units = optarg;
591 } else { 576 } else {
592 xasprintf(&crit_freespace_units, "@%s", optarg); 577 xasprintf(&crit_freespace_units, "@%s", optarg);
593 } 578 }
594 } 579 }
595 break; 580 break;
596
597 case 'W': /* warning inode threshold */
598 if (*optarg == '@') {
599 warn_freeinodes_percent = optarg;
600 } else {
601 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
602 }
603 break;
604 case 'K': /* critical inode threshold */
605 if (*optarg == '@') {
606 crit_freeinodes_percent = optarg;
607 } else {
608 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
609 }
610 break;
611 case 'u':
612 if (units)
613 free(units);
614 if (! strcasecmp (optarg, "bytes")) {
615 mult = (uintmax_t)1;
616 units = strdup ("B");
617 } else if (!strcmp(optarg, "KiB")) {
618 mult = (uintmax_t)1024;
619 units = strdup ("KiB");
620 } else if (! strcmp (optarg, "kB")) {
621 mult = (uintmax_t)1000;
622 units = strdup ("kB");
623 } else if (!strcmp(optarg, "MiB")) {
624 mult = (uintmax_t)1024 * 1024;
625 units = strdup ("MiB");
626 } else if (! strcmp (optarg, "MB")) {
627 mult = (uintmax_t)1000 * 1000;
628 units = strdup ("MB");
629 } else if (!strcmp(optarg, "GiB")) {
630 mult = (uintmax_t)1024 * 1024 * 1024;
631 units = strdup ("GiB");
632 } else if (! strcmp (optarg, "GB")){
633 mult = (uintmax_t)1000 * 1000 * 1000;
634 units = strdup ("GB");
635 } else if (!strcmp(optarg, "TiB")) {
636 mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
637 units = strdup ("TiB");
638 } else if (! strcmp (optarg, "TB")) {
639 mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
640 units = strdup ("TB");
641 } else if (!strcmp(optarg, "PiB")) {
642 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
643 units = strdup ("PiB");
644 } else if (! strcmp (optarg, "PB")){
645 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
646 units = strdup ("PB");
647 } else {
648 die (STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
649 }
650 if (units == NULL)
651 die (STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
652 break;
653 case 'k': /* display mountpoint */
654 mult = 1024;
655 if (units)
656 free(units);
657 units = strdup ("kiB");
658 break;
659 case 'm': /* display mountpoint */
660 mult = 1024 * 1024;
661 if (units)
662 free(units);
663 units = strdup ("MiB");
664 break;
665 case 'L':
666 stat_remote_fs = 1;
667 /* fallthrough */
668 case 'l':
669 show_local_fs = 1;
670 break;
671 case 'P':
672 display_inodes_perfdata = 1;
673 break;
674 case 'p': /* select path */
675 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
676 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
677 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
678 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) {
679 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
680 }
681
682 /* add parameter if not found. overwrite thresholds if path has already been added */
683 if (! (se = np_find_parameter(path_select_list, optarg))) {
684 se = np_add_parameter(&path_select_list, optarg);
685
686 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
687 path_ignored = true;
688 break;
689 }
690 }
691 se->group = group;
692 set_all_thresholds(se);
693
694 /* With autofs, it is required to stat() the path before re-populating the mount_list */
695 if (!stat_path(se)) {
696 break;
697 }
698 /* NB: We can't free the old mount_list "just like that": both list pointers and struct
699 * pointers are copied around. One of the reason it wasn't done yet is that other parts
700 * of check_disk need the same kind of cleanup so it'd better be done as a whole */
701 mount_list = read_file_system_list (0);
702 np_set_best_match(se, mount_list, exact_match);
703
704 path_selected = true;
705 break;
706 case 'x': /* exclude path or partition */
707 np_add_name(&dp_exclude_list, optarg);
708 break;
709 case 'X': /* exclude file system type */
710 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
711 if (err != 0) {
712 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
713 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
714 }
715 break;
716 case 'N': /* include file system type */
717 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
718 if (err != 0) {
719 regerror (err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
720 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
721 }
722 break;
723 case 'v': /* verbose */
724 verbose++;
725 break;
726 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
727 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
728 erronly = true;
729 break;
730 case 'e':
731 erronly = true;
732 break;
733 case 'E':
734 if (path_selected)
735 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
736 exact_match = true;
737 break;
738 case 'f':
739 freespace_ignore_reserved = true;
740 break;
741 case 'g':
742 if (path_selected)
743 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
744 group = optarg;
745 break;
746 case 'I':
747 cflags |= REG_ICASE;
748 // Intentional fallthrough
749 case 'i':
750 if (!path_selected)
751 die (STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"), _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly"));
752 err = regcomp(&re, optarg, cflags);
753 if (err != 0) {
754 regerror (err, &re, errbuf, MAX_INPUT_BUFFER);
755 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
756 }
757
758 temp_list = path_select_list;
759
760 previous = NULL;
761 while (temp_list) {
762 if (temp_list->best_match) {
763 if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
764
765 if (verbose >=3)
766 printf("ignoring %s matching regex\n", temp_list->name);
767
768 temp_list = np_del_parameter(temp_list, previous);
769 /* pointer to first element needs to be updated if first item gets deleted */
770 if (previous == NULL)
771 path_select_list = temp_list;
772 } else {
773 previous = temp_list;
774 temp_list = temp_list->name_next;
775 }
776 } else {
777 previous = temp_list;
778 temp_list = temp_list->name_next;
779 }
780 }
781
782
783 cflags = default_cflags;
784 break;
785
786 case 'n':
787 ignore_missing = true;
788 break;
789 case 'A':
790 optarg = strdup(".*");
791 // Intentional fallthrough
792 case 'R':
793 cflags |= REG_ICASE;
794 // Intentional fallthrough
795 case 'r':
796 if (! (warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
797 crit_freespace_percent || warn_usedspace_units || crit_usedspace_units ||
798 warn_usedspace_percent || crit_usedspace_percent || warn_usedinodes_percent ||
799 crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent )) {
800 die (STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n"));
801 }
802
803 err = regcomp(&re, optarg, cflags);
804 if (err != 0) {
805 regerror (err, &re, errbuf, MAX_INPUT_BUFFER);
806 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"), _("Could not compile regular expression"), errbuf);
807 }
808
809 for (me = mount_list; me; me = me->me_next) {
810 if (np_regex_match_mount_entry(me, &re)) {
811 fnd = true;
812 if (verbose >= 3)
813 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg);
814
815 /* add parameter if not found. overwrite thresholds if path has already been added */
816 if (! (se = np_find_parameter(path_select_list, me->me_mountdir))) {
817 se = np_add_parameter(&path_select_list, me->me_mountdir);
818 }
819 se->group = group;
820 set_all_thresholds(se);
821 }
822 }
823
824 if (!fnd && ignore_missing == true) {
825 path_ignored = true;
826 path_selected = true;
827 break;
828 } else if (!fnd)
829 die (STATE_UNKNOWN, "DISK %s: %s - %s\n",_("UNKNOWN"),
830 _("Regular expression did not match any path or disk"), optarg);
831
832 fnd = false;
833 path_selected = true;
834 np_set_best_match(path_select_list, mount_list, exact_match);
835 cflags = default_cflags;
836
837 break;
838 case 'M': /* display mountpoint */
839 display_mntp = true;
840 break;
841 case 'C':
842 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
843 if (path_selected == false) {
844 struct parameter_list *path;
845 for (me = mount_list; me; me = me->me_next) {
846 if (! (path = np_find_parameter(path_select_list, me->me_mountdir)))
847 path = np_add_parameter(&path_select_list, me->me_mountdir);
848 path->best_match = me;
849 path->group = group;
850 set_all_thresholds(path);
851 }
852 }
853 warn_freespace_units = NULL;
854 crit_freespace_units = NULL;
855 warn_usedspace_units = NULL;
856 crit_usedspace_units = NULL;
857 warn_freespace_percent = NULL;
858 crit_freespace_percent = NULL;
859 warn_usedspace_percent = NULL;
860 crit_usedspace_percent = NULL;
861 warn_usedinodes_percent = NULL;
862 crit_usedinodes_percent = NULL;
863 warn_freeinodes_percent = NULL;
864 crit_freeinodes_percent = NULL;
865
866 path_selected = false;
867 group = NULL;
868 break;
869 case 'V': /* version */
870 print_revision (progname, NP_VERSION);
871 exit (STATE_UNKNOWN);
872 case 'h': /* help */
873 print_help ();
874 exit (STATE_UNKNOWN);
875 case '?': /* help */
876 usage (_("Unknown argument"));
877 }
878 }
879
880 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
881 c = optind;
882 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
883 warn_usedspace_percent = argv[c++];
884
885 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg (argv[c]))
886 crit_usedspace_percent = argv[c++];
887
888 if (argc > c) {
889 se = np_add_parameter(&path_select_list, strdup(argv[c++]));
890 path_selected = true;
891 set_all_thresholds(se);
892 }
893
894 if (units == NULL) {
895 units = strdup ("MiB");
896 mult = (uintmax_t)1024 * 1024;
897 }
898
899 return true;
900}
901 581
582 case 'W': /* warning inode threshold */
583 if (*optarg == '@') {
584 warn_freeinodes_percent = optarg;
585 } else {
586 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
587 }
588 break;
589 case 'K': /* critical inode threshold */
590 if (*optarg == '@') {
591 crit_freeinodes_percent = optarg;
592 } else {
593 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
594 }
595 break;
596 case 'u':
597 if (units)
598 free(units);
599 if (!strcasecmp(optarg, "bytes")) {
600 mult = (uintmax_t)1;
601 units = strdup("B");
602 } else if (!strcmp(optarg, "KiB")) {
603 mult = (uintmax_t)1024;
604 units = strdup("KiB");
605 } else if (!strcmp(optarg, "kB")) {
606 mult = (uintmax_t)1000;
607 units = strdup("kB");
608 } else if (!strcmp(optarg, "MiB")) {
609 mult = (uintmax_t)1024 * 1024;
610 units = strdup("MiB");
611 } else if (!strcmp(optarg, "MB")) {
612 mult = (uintmax_t)1000 * 1000;
613 units = strdup("MB");
614 } else if (!strcmp(optarg, "GiB")) {
615 mult = (uintmax_t)1024 * 1024 * 1024;
616 units = strdup("GiB");
617 } else if (!strcmp(optarg, "GB")) {
618 mult = (uintmax_t)1000 * 1000 * 1000;
619 units = strdup("GB");
620 } else if (!strcmp(optarg, "TiB")) {
621 mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
622 units = strdup("TiB");
623 } else if (!strcmp(optarg, "TB")) {
624 mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
625 units = strdup("TB");
626 } else if (!strcmp(optarg, "PiB")) {
627 mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
628 units = strdup("PiB");
629 } else if (!strcmp(optarg, "PB")) {
630 mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
631 units = strdup("PB");
632 } else {
633 die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
634 }
635 if (units == NULL)
636 die(STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
637 break;
638 case 'k': /* display mountpoint */
639 mult = 1024;
640 if (units)
641 free(units);
642 units = strdup("kiB");
643 break;
644 case 'm': /* display mountpoint */
645 mult = 1024 * 1024;
646 if (units)
647 free(units);
648 units = strdup("MiB");
649 break;
650 case 'L':
651 stat_remote_fs = 1;
652 /* fallthrough */
653 case 'l':
654 show_local_fs = 1;
655 break;
656 case 'P':
657 display_inodes_perfdata = 1;
658 break;
659 case 'p': /* select path */
660 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
661 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
662 warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
663 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n"));
664 }
902 665
666 /* add parameter if not found. overwrite thresholds if path has already been added */
667 if (!(se = np_find_parameter(path_select_list, optarg))) {
668 se = np_add_parameter(&path_select_list, optarg);
903 669
904void 670 if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
905print_path (const char *mypath) 671 path_ignored = true;
906{ 672 break;
907 if (mypath == NULL) 673 }
908 printf ("\n"); 674 }
909 else 675 se->group = group;
910 printf (_(" for %s\n"), mypath); 676 set_all_thresholds(se);
911} 677
678 /* With autofs, it is required to stat() the path before re-populating the mount_list */
679 if (!stat_path(se)) {
680 break;
681 }
682 /* NB: We can't free the old mount_list "just like that": both list pointers and struct
683 * pointers are copied around. One of the reason it wasn't done yet is that other parts
684 * of check_disk need the same kind of cleanup so it'd better be done as a whole */
685 mount_list = read_file_system_list(0);
686 np_set_best_match(se, mount_list, exact_match);
687
688 path_selected = true;
689 break;
690 case 'x': /* exclude path or partition */
691 np_add_name(&dp_exclude_list, optarg);
692 break;
693 case 'X': /* exclude file system type */
694 err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
695 if (err != 0) {
696 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
697 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
698 }
699 break;
700 case 'N': /* include file system type */
701 err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
702 if (err != 0) {
703 regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
704 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
705 }
706 break;
707 case 'v': /* verbose */
708 verbose++;
709 break;
710 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
711 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
712 erronly = true;
713 break;
714 case 'e':
715 erronly = true;
716 break;
717 case 'E':
718 if (path_selected)
719 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
720 exact_match = true;
721 break;
722 case 'f':
723 freespace_ignore_reserved = true;
724 break;
725 case 'g':
726 if (path_selected)
727 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
728 group = optarg;
729 break;
730 case 'I':
731 cflags |= REG_ICASE;
732 // Intentional fallthrough
733 case 'i':
734 if (!path_selected)
735 die(STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"),
736 _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly"));
737 err = regcomp(&re, optarg, cflags);
738 if (err != 0) {
739 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
740 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
741 }
912 742
743 temp_list = path_select_list;
744
745 previous = NULL;
746 while (temp_list) {
747 if (temp_list->best_match) {
748 if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
749
750 if (verbose >= 3)
751 printf("ignoring %s matching regex\n", temp_list->name);
752
753 temp_list = np_del_parameter(temp_list, previous);
754 /* pointer to first element needs to be updated if first item gets deleted */
755 if (previous == NULL)
756 path_select_list = temp_list;
757 } else {
758 previous = temp_list;
759 temp_list = temp_list->name_next;
760 }
761 } else {
762 previous = temp_list;
763 temp_list = temp_list->name_next;
764 }
765 }
913 766
914void 767 cflags = default_cflags;
915set_all_thresholds (struct parameter_list *path) 768 break;
916{ 769
917 if (path->freespace_units != NULL) free(path->freespace_units); 770 case 'n':
918 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units); 771 ignore_missing = true;
919 if (path->freespace_percent != NULL) free (path->freespace_percent); 772 break;
920 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent); 773 case 'A':
921 if (path->usedspace_units != NULL) free (path->usedspace_units); 774 optarg = strdup(".*");
922 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units); 775 // Intentional fallthrough
923 if (path->usedspace_percent != NULL) free (path->usedspace_percent); 776 case 'R':
924 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent); 777 cflags |= REG_ICASE;
925 if (path->usedinodes_percent != NULL) free (path->usedinodes_percent); 778 // Intentional fallthrough
926 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent); 779 case 'r':
927 if (path->freeinodes_percent != NULL) free (path->freeinodes_percent); 780 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
928 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent); 781 warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
929} 782 warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
783 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"),
784 _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n"));
785 }
930 786
931void 787 err = regcomp(&re, optarg, cflags);
932print_help (void) 788 if (err != 0) {
933{ 789 regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
934 print_revision (progname, NP_VERSION); 790 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
935 791 }
936 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
937 printf (COPYRIGHT, copyright, email);
938
939 printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
940 printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
941
942 printf ("\n\n");
943
944 print_usage ();
945
946 printf (UT_HELP_VRSN);
947 printf (UT_EXTRA_OPTS);
948
949 printf (" %s\n", "-w, --warning=INTEGER");
950 printf (" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
951 printf (" %s\n", "-w, --warning=PERCENT%");
952 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
953 printf (" %s\n", "-c, --critical=INTEGER");
954 printf (" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
955 printf (" %s\n", "-c, --critical=PERCENT%");
956 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free"));
957 printf (" %s\n", "-W, --iwarning=PERCENT%");
958 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
959 printf (" %s\n", "-K, --icritical=PERCENT%");
960 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
961 printf (" %s\n", "-p, --path=PATH, --partition=PARTITION");
962 printf (" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)"));
963 printf (" %s\n", "-x, --exclude_device=PATH <STRING>");
964 printf (" %s\n", _("Ignore device (only works if -p unspecified)"));
965 printf (" %s\n", "-C, --clear");
966 printf (" %s\n", _("Clear thresholds"));
967 printf (" %s\n", "-E, --exact-match");
968 printf (" %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
969 printf (" %s\n", "-e, --errors-only");
970 printf (" %s\n", _("Display only devices/mountpoints with errors"));
971 printf (" %s\n", "-f, --freespace-ignore-reserved");
972 printf (" %s\n", _("Don't account root-reserved blocks into freespace in perfdata"));
973 printf (" %s\n", "-P, --iperfdata");
974 printf (" %s\n", _("Display inode usage in perfdata"));
975 printf (" %s\n", "-g, --group=NAME");
976 printf (" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together"));
977 printf (" %s\n", "-k, --kilobytes");
978 printf (" %s\n", _("Same as '--units kB'"));
979 printf (" %s\n", "-l, --local");
980 printf (" %s\n", _("Only check local filesystems"));
981 printf (" %s\n", "-L, --stat-remote-fs");
982 printf (" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems"));
983 printf (" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)"));
984 printf (" %s\n", "-M, --mountpoint");
985 printf (" %s\n", _("Display the (block) device instead of the mount point"));
986 printf (" %s\n", "-m, --megabytes");
987 printf (" %s\n", _("Same as '--units MB'"));
988 printf (" %s\n", "-A, --all");
989 printf (" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'"));
990 printf (" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION");
991 printf (" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)"));
992 printf (" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION");
993 printf (" %s\n", _("Regular expression for path or partition (may be repeated)"));
994 printf (" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION");
995 printf (" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)"));
996 printf (" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
997 printf (" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)"));
998 printf (" %s\n", "-n, --ignore-missing");
999 printf (" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible."));
1000 printf (" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)"));
1001 printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1002 printf (" %s\n", "-u, --units=STRING");
1003 printf (" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
1004 printf (UT_VERBOSE);
1005 printf (" %s\n", "-X, --exclude-type=TYPE_REGEX");
1006 printf (" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)"));
1007 printf (" %s\n", "-N, --include-type=TYPE_REGEX");
1008 printf (" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)"));
1009
1010 printf ("\n");
1011 printf ("%s\n", _("General usage hints:"));
1012 printf (" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as"));
1013 printf (" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\"."));
1014 printf (" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\""));
1015
1016
1017
1018 printf ("\n");
1019 printf ("%s\n", _("Examples:"));
1020 printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
1021 printf (" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
1022 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'");
1023 printf (" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex"));
1024 printf (" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together"));
1025 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar");
1026 printf (" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M"));
1027
1028 printf (UT_SUPPORT);
1029}
1030 792
793 for (me = mount_list; me; me = me->me_next) {
794 if (np_regex_match_mount_entry(me, &re)) {
795 fnd = true;
796 if (verbose >= 3)
797 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg);
798
799 /* add parameter if not found. overwrite thresholds if path has already been added */
800 if (!(se = np_find_parameter(path_select_list, me->me_mountdir))) {
801 se = np_add_parameter(&path_select_list, me->me_mountdir);
802 }
803 se->group = group;
804 set_all_thresholds(se);
805 }
806 }
1031 807
808 if (!fnd && ignore_missing == true) {
809 path_ignored = true;
810 path_selected = true;
811 break;
812 }
813 if (!fnd)
814 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Regular expression did not match any path or disk"), optarg);
815
816 fnd = false;
817 path_selected = true;
818 np_set_best_match(path_select_list, mount_list, exact_match);
819 cflags = default_cflags;
820
821 break;
822 case 'M': /* display mountpoint */
823 display_mntp = true;
824 break;
825 case 'C':
826 /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
827 if (path_selected == false) {
828 struct parameter_list *path;
829 for (me = mount_list; me; me = me->me_next) {
830 if (!(path = np_find_parameter(path_select_list, me->me_mountdir)))
831 path = np_add_parameter(&path_select_list, me->me_mountdir);
832 path->best_match = me;
833 path->group = group;
834 set_all_thresholds(path);
835 }
836 }
837 warn_freespace_units = NULL;
838 crit_freespace_units = NULL;
839 warn_usedspace_units = NULL;
840 crit_usedspace_units = NULL;
841 warn_freespace_percent = NULL;
842 crit_freespace_percent = NULL;
843 warn_usedspace_percent = NULL;
844 crit_usedspace_percent = NULL;
845 warn_usedinodes_percent = NULL;
846 crit_usedinodes_percent = NULL;
847 warn_freeinodes_percent = NULL;
848 crit_freeinodes_percent = NULL;
849
850 path_selected = false;
851 group = NULL;
852 break;
853 case 'V': /* version */
854 print_revision(progname, NP_VERSION);
855 exit(STATE_UNKNOWN);
856 case 'h': /* help */
857 print_help();
858 exit(STATE_UNKNOWN);
859 case '?': /* help */
860 usage(_("Unknown argument"));
861 }
862 }
863
864 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
865 c = optind;
866 if (warn_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
867 warn_usedspace_percent = argv[c++];
868
869 if (crit_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
870 crit_usedspace_percent = argv[c++];
871
872 if (argc > c) {
873 se = np_add_parameter(&path_select_list, strdup(argv[c++]));
874 path_selected = true;
875 set_all_thresholds(se);
876 }
877
878 if (units == NULL) {
879 units = strdup("MiB");
880 mult = (uintmax_t)1024 * 1024;
881 }
882
883 return true;
884}
1032 885
1033void 886void set_all_thresholds(struct parameter_list *path) {
1034print_usage (void) 887 if (path->freespace_units != NULL)
1035{ 888 free(path->freespace_units);
1036 printf ("%s\n", _("Usage:")); 889 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
1037 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); 890 if (path->freespace_percent != NULL)
1038 printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n"); 891 free(path->freespace_percent);
1039 printf ("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n"); 892 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
893 if (path->usedspace_units != NULL)
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);
1040} 905}
1041 906
1042bool 907void print_help(void) {
1043stat_path (struct parameter_list *p) 908 print_revision(progname, NP_VERSION);
1044{ 909
1045 /* Stat entry to check that dir exists and is accessible */ 910 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1046 if (verbose >= 3) 911 printf(COPYRIGHT, copyright, email);
1047 printf("calling stat on %s\n", p->name); 912
1048 if (stat (p->name, &stat_buf[0])) { 913 printf("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
1049 if (verbose >= 3) 914 printf("%s\n", _("and generates an alert if free space is less than one of the threshold values"));
1050 printf("stat failed on %s\n", p->name); 915
1051 if (ignore_missing == true) { 916 printf("\n\n");
1052 return false; 917
1053 } else { 918 print_usage();
1054 printf("DISK %s - ", _("CRITICAL")); 919
1055 die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno)); 920 printf(UT_HELP_VRSN);
1056 } 921 printf(UT_EXTRA_OPTS);
1057 } 922
1058 return true; 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);
1059} 1001}
1060 1002
1003void print_usage(void) {
1004 printf("%s\n", _("Usage:"));
1005 printf(" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c absolute_limit|-c percentage_limit%% | -K "
1006 "inode_percentage_limit } {-p path | -x device}\n",
1007 progname);
1008 printf("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n");
1009 printf("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n");
1010}
1061 1011
1062void 1012bool stat_path(struct parameter_list *p) {
1063get_stats (struct parameter_list *p, struct fs_usage *fsp) { 1013 /* Stat entry to check that dir exists and is accessible */
1064 struct parameter_list *p_list; 1014 if (verbose >= 3)
1065 struct fs_usage tmpfsp; 1015 printf("calling stat on %s\n", p->name);
1066 int first = 1; 1016 if (stat(p->name, &stat_buf[0])) {
1017 if (verbose >= 3)
1018 printf("stat failed on %s\n", p->name);
1019 if (ignore_missing == true) {
1020 return false;
1021 }
1022 printf("DISK %s - ", _("CRITICAL"));
1023 die(STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
1024 }
1025 return true;
1026}
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;
1067 1032
1068 if (p->group == NULL) { 1033 if (p->group == NULL) {
1069 get_path_stats(p,fsp); 1034 get_path_stats(p, fsp);
1070 } else { 1035 } else {
1071 /* find all group members */ 1036 /* find all group members */
1072 for (p_list = path_select_list; p_list; p_list=p_list->name_next) { 1037 for (p_list = path_select_list; p_list; p_list = p_list->name_next) {
1073#ifdef __CYGWIN__ 1038#ifdef __CYGWIN__
1074 if (strncmp(p_list->name, "/cygdrive/", 10) != 0) 1039 if (strncmp(p_list->name, "/cygdrive/", 10) != 0)
1075 continue; 1040 continue;
1076#endif 1041#endif
1077 if (p_list->group && ! (strcmp(p_list->group, p->group))) { 1042 if (p_list->group && !(strcmp(p_list->group, p->group))) {
1078 if (! stat_path(p_list)) 1043 if (!stat_path(p_list))
1079 continue; 1044 continue;
1080 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);
1081 get_path_stats(p_list, &tmpfsp); 1046 get_path_stats(p_list, &tmpfsp);
1082 if (verbose >= 3) 1047 if (verbose >= 3)
1083 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",
1084 p_list->group, 1049 p_list->group, tmpfsp.fsu_blocks, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units,
1085 tmpfsp.fsu_blocks, 1050 p_list->dfree_units, p_list->dtotal_units, mult);
1086 tmpfsp.fsu_blocksize, 1051
1087 p_list->best_match->me_mountdir, 1052 /* prevent counting the first FS of a group twice since its parameter_list entry
1088 p_list->dused_units, 1053 * is used to carry the information of all file systems of the entire group */
1089 p_list->dfree_units, 1054 if (!first) {
1090 p_list->dtotal_units, 1055 p->total += p_list->total;
1091 mult); 1056 p->available += p_list->available;
1092 1057 p->available_to_root += p_list->available_to_root;
1093 /* prevent counting the first FS of a group twice since its parameter_list entry 1058 p->used += p_list->used;
1094 * is used to carry the information of all file systems of the entire group */ 1059
1095 if (! first) { 1060 p->dused_units += p_list->dused_units;
1096 p->total += p_list->total; 1061 p->dfree_units += p_list->dfree_units;
1097 p->available += p_list->available; 1062 p->dtotal_units += p_list->dtotal_units;
1098 p->available_to_root += p_list->available_to_root; 1063 p->inodes_total += p_list->inodes_total;
1099 p->used += p_list->used; 1064 p->inodes_free += p_list->inodes_free;
1100 1065 p->inodes_free_to_root += p_list->inodes_free_to_root;
1101 p->dused_units += p_list->dused_units; 1066 p->inodes_used += p_list->inodes_used;
1102 p->dfree_units += p_list->dfree_units; 1067 }
1103 p->dtotal_units += p_list->dtotal_units; 1068 first = 0;
1104 p->inodes_total += p_list->inodes_total; 1069 }
1105 p->inodes_free += p_list->inodes_free; 1070 if (verbose >= 3)
1106 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,
1107 p->inodes_used += p_list->inodes_used; 1072 p->dused_units, p->dfree_units, p->dtotal_units, tmpfsp.fsu_blocksize, mult);
1108 } 1073 }
1109 first = 0; 1074 /* modify devname and mountdir for output */
1110 } 1075 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1111 if (verbose >= 3) 1076 }
1112 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 */
1113 p->group, 1078 p->dused_pct = calculate_percent(p->used, p->used + p->available); /* used + available can never be > uintmax */
1114 p->dused_units, 1079 p->dfree_pct = 100.0 - p->dused_pct;
1115 p->dfree_units, 1080 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1116 p->dtotal_units, 1081 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1117 tmpfsp.fsu_blocksize,
1118 mult);
1119 }
1120 /* modify devname and mountdir for output */
1121 p->best_match->me_mountdir = p->best_match->me_devname = p->group;
1122 }
1123 /* finally calculate percentages for either plain FS or summed up group */
1124 p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */
1125 p->dfree_pct = 100.0 - p->dused_pct;
1126 p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
1127 p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
1128
1129} 1082}
1130 1083
1131void 1084void get_path_stats(struct parameter_list *p, struct fs_usage *fsp) {
1132get_path_stats (struct parameter_list *p, struct fs_usage *fsp) { 1085 p->available = fsp->fsu_bavail;
1133 p->available = fsp->fsu_bavail; 1086 p->available_to_root = fsp->fsu_bfree;
1134 p->available_to_root = fsp->fsu_bfree; 1087 p->used = fsp->fsu_blocks - fsp->fsu_bfree;
1135 p->used = fsp->fsu_blocks - fsp->fsu_bfree; 1088 if (freespace_ignore_reserved) {
1136 if (freespace_ignore_reserved) { 1089 /* option activated : we subtract the root-reserved space from the total */
1137 /* option activated : we subtract the root-reserved space from the total */ 1090 p->total = fsp->fsu_blocks - p->available_to_root + p->available;
1138 p->total = fsp->fsu_blocks - p->available_to_root + p->available; 1091 } else {
1139 } else { 1092 /* default behaviour : take all the blocks into account */
1140 /* default behaviour : take all the blocks into account */ 1093 p->total = fsp->fsu_blocks;
1141 p->total = fsp->fsu_blocks; 1094 }
1142 } 1095
1143 1096 p->dused_units = p->used * fsp->fsu_blocksize / mult;
1144 p->dused_units = p->used*fsp->fsu_blocksize/mult; 1097 p->dfree_units = p->available * fsp->fsu_blocksize / mult;
1145 p->dfree_units = p->available*fsp->fsu_blocksize/mult; 1098 p->dtotal_units = p->total * fsp->fsu_blocksize / mult;
1146 p->dtotal_units = p->total*fsp->fsu_blocksize/mult; 1099 /* Free file nodes. Not sure the workaround is required, but in case...*/
1147 /* Free file nodes. Not sure the workaround is required, but in case...*/ 1100 p->inodes_free = fsp->fsu_ffree;
1148 p->inodes_free = fsp->fsu_ffree; 1101 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
1149 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */ 1102 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
1150 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree; 1103 if (freespace_ignore_reserved) {
1151 if (freespace_ignore_reserved) { 1104 /* option activated : we subtract the root-reserved inodes from the total */
1152 /* 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 */
1153 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */ 1106 /* for others, fsp->fsu_ffree == fsp->fsu_favail */
1154 /* for others, fsp->fsu_ffree == fsp->fsu_favail */ 1107 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free;
1155 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free; 1108 } else {
1156 } else { 1109 /* default behaviour : take all the inodes into account */
1157 /* default behaviour : take all the inodes into account */ 1110 p->inodes_total = fsp->fsu_files;
1158 p->inodes_total = fsp->fsu_files; 1111 }
1159 } 1112 np_add_name(&seen, p->best_match->me_mountdir);
1160 np_add_name(&seen, p->best_match->me_mountdir);
1161} 1113}