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