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.c2330
1 files changed, 1244 insertions, 1086 deletions
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index b3dd301c..d42b5486 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -1,1146 +1,1304 @@
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 34#include "states.h"
35#include "common.h" 35#include "common.h"
36#include "output.h"
37#include "perfdata.h"
38#include "utils_base.h"
39#include "lib/thresholds.h"
40
36#ifdef HAVE_SYS_STAT_H 41#ifdef HAVE_SYS_STAT_H
37# include <sys/stat.h> 42# include <sys/stat.h>
38#endif 43#endif
44
39#if HAVE_INTTYPES_H 45#if HAVE_INTTYPES_H
40# include <inttypes.h> 46# include <inttypes.h>
41#endif 47#endif
48
42#include <assert.h> 49#include <assert.h>
43#include "popen.h"
44#include "utils.h"
45#include "utils_disk.h"
46#include <stdarg.h> 50#include <stdarg.h>
47#include "fsusage.h" 51#include <stdint.h>
48#include "mountlist.h"
49#include <float.h> 52#include <float.h>
53#include "./popen.h"
54#include "./utils.h"
55#include "../gl/fsusage.h"
56#include "../gl/mountlist.h"
57#include "./check_disk.d/utils_disk.h"
58
50#if HAVE_LIMITS_H 59#if HAVE_LIMITS_H
51# include <limits.h> 60# include <limits.h>
52#endif 61#endif
62
53#include "regex.h" 63#include "regex.h"
54 64
55#ifdef __CYGWIN__ 65#ifdef __CYGWIN__
56# include <windows.h> 66# include <windows.h>
57# undef ERROR 67# undef ERROR
58# define ERROR -1 68# define ERROR -1
59#endif 69#endif
60 70
61/* If nonzero, show even filesystems with zero size or 71#ifdef _AIX
62 uninteresting types. */ 72# pragma alloca
63static int show_all_fs = 1; 73#endif
64
65/* If nonzero, show only local filesystems. */
66static int show_local_fs = 0;
67
68/* If nonzero, show only local filesystems but call stat() on remote ones. */
69static int stat_remote_fs = 0;
70
71/* If positive, the units to use when printing sizes;
72 if negative, the human-readable base. */
73/* static int output_block_size; */
74
75/* If nonzero, invoke the `sync' system call before getting any usage data.
76 Using this option can make df very slow, especially with many or very
77 busy disks. Note that this may make a difference on some systems --
78 SunOs4.1.3, for one. It is *not* necessary on Linux. */
79/* static int require_sync = 0; */
80
81/* Linked list of filesystem types to display.
82 If `fs_select_list' is NULL, list all types.
83 This table is generated dynamically from command-line options,
84 rather than hardcoding into the program what it thinks are the
85 valid filesystem types; let the user specify any filesystem type
86 they want to, and if there are any filesystems of that type, they
87 will be shown.
88
89 Some filesystem types:
90 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
91 74
92/* static struct parameter_list *fs_select_list; */ 75typedef struct {
76 int errorcode;
77 check_disk_config config;
78} check_disk_config_wrapper;
79static check_disk_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
80
81static void set_all_thresholds(parameter_list_elem *path, char *warn_freespace_units,
82 char *crit_freespace_units, char *warn_freespace_percent,
83 char *crit_freespace_percent, char *warn_freeinodes_percent,
84 char *crit_freeinodes_percent);
85static double calculate_percent(uintmax_t /*value*/, uintmax_t /*total*/);
86static bool stat_path(parameter_list_elem * /*parameters*/, bool /*ignore_missing*/);
87
88/*
89 * Puts the values from a struct fs_usage into a parameter_list with an additional flag to control
90 * how reserved and inodes should be judged (ignored or not)
91 */
92static parameter_list_elem get_path_stats(parameter_list_elem parameters, struct fs_usage fsp,
93 bool freespace_ignore_reserved);
94static mp_subcheck evaluate_filesystem(measurement_unit measurement_unit,
95 bool display_inodes_perfdata, byte_unit unit);
96
97void print_usage(void);
98static void print_help(void);
93 99
94/* Linked list of filesystem types to omit. 100static int verbose = 0;
95 If the list is empty, don't exclude any types. */
96static struct regex_list *fs_exclude_list = NULL;
97 101
98/* Linked list of filesystem types to check. 102// This would not be necessary in C23!!
99 If the list is empty, include all types. */ 103const byte_unit Bytes_Factor = 1;
100static struct regex_list *fs_include_list; 104const byte_unit KibiBytes_factor = 1024;
105const byte_unit MebiBytes_factor = 1048576;
106const byte_unit GibiBytes_factor = 1073741824;
107const byte_unit TebiBytes_factor = 1099511627776;
108const byte_unit PebiBytes_factor = 1125899906842624;
109const byte_unit ExbiBytes_factor = 1152921504606846976;
110const byte_unit KiloBytes_factor = 1000;
111const byte_unit MegaBytes_factor = 1000000;
112const byte_unit GigaBytes_factor = 1000000000;
113const byte_unit TeraBytes_factor = 1000000000000;
114const byte_unit PetaBytes_factor = 1000000000000000;
115const byte_unit ExaBytes_factor = 1000000000000000000;
116
117int main(int argc, char **argv) {
118 setlocale(LC_ALL, "");
119 bindtextdomain(PACKAGE, LOCALEDIR);
120 textdomain(PACKAGE);
101 121
102static struct name_list *dp_exclude_list; 122#ifdef __CYGWIN__
123 char mountdir[32];
124#endif
103 125
104static struct parameter_list *path_select_list = NULL; 126 // Parse extra opts if any
127 argv = np_extra_opts(&argc, argv, progname);
128
129 check_disk_config_wrapper tmp_config = process_arguments(argc, argv);
130 if (tmp_config.errorcode == ERROR) {
131 usage4(_("Could not parse arguments"));
132 }
133
134 check_disk_config config = tmp_config.config;
135
136 if (config.output_format_is_set) {
137 mp_set_format(config.output_format);
138 }
139
140 if (config.erronly) {
141 mp_set_level_of_detail(MP_DETAIL_NON_OK_ONLY);
142 }
143
144 if (!config.path_ignored) {
145 mp_int_fs_list_set_best_match(config.path_select_list, config.mount_list,
146 config.exact_match);
147 }
148
149 // Error if no match found for specified paths
150 for (parameter_list_elem *elem = config.path_select_list.first; elem;) {
151 if (!elem->best_match && config.ignore_missing) {
152 /* Delete the path from the list so that it is not stat-checked later in the code. */
153 elem = mp_int_fs_list_del(&config.path_select_list, elem);
154 continue;
155 }
156 if (!elem->best_match) {
157 /* Without --ignore-missing option, exit with Critical state. */
158 die(STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), elem->name);
159 }
160
161 elem = mp_int_fs_list_get_next(elem);
162 }
163
164 mp_check overall = mp_check_init();
165 if (config.path_select_list.length == 0) {
166 mp_subcheck none_sc = mp_subcheck_init();
167 xasprintf(&none_sc.output, "No filesystems were found for the provided parameters");
168 if (config.ignore_missing) {
169 none_sc = mp_set_subcheck_state(none_sc, STATE_OK);
170 } else {
171 none_sc = mp_set_subcheck_state(none_sc, STATE_UNKNOWN);
172 if (verbose >= 2) {
173 printf("None of the provided paths were found\n");
174 }
175 }
176 mp_add_subcheck_to_check(&overall, none_sc);
177 mp_exit(overall);
178 }
105 179
106/* Linked list of mounted filesystems. */ 180 // Filter list first
107static struct mount_entry *mount_list; 181 for (parameter_list_elem *path = config.path_select_list.first; path;) {
182 if (!path->best_match) {
183 path = mp_int_fs_list_del(&config.path_select_list, path);
184 continue;
185 }
108 186
109/* For long options that have no equivalent short option, use a 187 struct mount_entry *mount_entry = path->best_match;
110 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
111enum
112{
113 SYNC_OPTION = CHAR_MAX + 1,
114 NO_SYNC_OPTION,
115 BLOCK_SIZE_OPTION
116};
117 188
118#ifdef _AIX 189#ifdef __CYGWIN__
119#pragma alloca 190 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11) {
191 path = mp_int_fs_list_del(&config.path_select_list, path);
192 continue;
193 }
194
195 char *mountdir = NULL;
196 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10);
197 if (GetDriveType(mountdir) != DRIVE_FIXED) {
198 mount_entry->me_remote = 1;
199 }
120#endif 200#endif
121 201
122static int process_arguments (int, char **); 202 /* Remove filesystems already seen */
123static void set_all_thresholds (struct parameter_list *path); 203 if (np_seen_name(config.seen, mount_entry->me_mountdir)) {
124static void print_help (void); 204 path = mp_int_fs_list_del(&config.path_select_list, path);
125void print_usage (void); 205 continue;
126static double calculate_percent(uintmax_t, uintmax_t); 206 }
127static bool stat_path (struct parameter_list *p); 207
128static void get_stats (struct parameter_list *p, struct fs_usage *fsp); 208 if (path->group == NULL) {
129static void get_path_stats (struct parameter_list *p, struct fs_usage *fsp); 209 if (config.fs_exclude_list &&
130 210 np_find_regmatch(config.fs_exclude_list, mount_entry->me_type)) {
131static char *units; 211 // Skip excluded fs's
132static uintmax_t mult = 1024 * 1024; 212 path = mp_int_fs_list_del(&config.path_select_list, path);
133static int verbose = 0; 213 continue;
134static bool erronly = false; 214 }
135static bool display_mntp = false;
136static bool exact_match = false;
137static bool ignore_missing = false;
138static bool freespace_ignore_reserved = false;
139static bool display_inodes_perfdata = false;
140static char *warn_freespace_units = NULL;
141static char *crit_freespace_units = NULL;
142static char *warn_freespace_percent = NULL;
143static char *crit_freespace_percent = NULL;
144static char *warn_usedspace_units = NULL;
145static char *crit_usedspace_units = NULL;
146static char *warn_usedspace_percent = NULL;
147static char *crit_usedspace_percent = NULL;
148static char *warn_usedinodes_percent = NULL;
149static char *crit_usedinodes_percent = NULL;
150static char *warn_freeinodes_percent = NULL;
151static char *crit_freeinodes_percent = NULL;
152static bool path_selected = false;
153static bool path_ignored = false;
154static char *group = NULL;
155static struct stat *stat_buf;
156static struct name_list *seen = NULL;
157
158
159int
160main (int argc, char **argv)
161{
162 int result = STATE_UNKNOWN;
163 int disk_result = STATE_UNKNOWN;
164 char *output;
165 char *ignored;
166 char *details;
167 char *perf;
168 char *perf_ilabel;
169 char *preamble = " - free space:";
170 char *ignored_preamble = " - ignored paths:";
171 char *flag_header;
172 int temp_result;
173
174 struct mount_entry *me;
175 struct fs_usage fsp;
176 struct parameter_list *temp_list, *path;
177 215
178#ifdef __CYGWIN__ 216 if (config.device_path_exclude_list &&
179 char mountdir[32]; 217 (np_find_name(config.device_path_exclude_list, mount_entry->me_devname) ||
180#endif 218 np_find_name(config.device_path_exclude_list, mount_entry->me_mountdir))) {
219 // Skip excluded device or mount paths
220 path = mp_int_fs_list_del(&config.path_select_list, path);
221 continue;
222 }
181 223
182 output = strdup (""); 224 if (config.fs_include_list &&
183 ignored = strdup (""); 225 !np_find_regmatch(config.fs_include_list, mount_entry->me_type)) {
184 details = strdup (""); 226 // Skip not included fstypes
185 perf = strdup (""); 227 path = mp_int_fs_list_del(&config.path_select_list, path);
186 perf_ilabel = strdup (""); 228 continue;
187 stat_buf = malloc(sizeof *stat_buf); 229 }
188
189 setlocale (LC_ALL, "");
190 bindtextdomain (PACKAGE, LOCALEDIR);
191 textdomain (PACKAGE);
192
193 mount_list = read_file_system_list (0);
194
195 /* Parse extra opts if any */
196 argv = np_extra_opts (&argc, argv, progname);
197
198 if (process_arguments (argc, argv) == ERROR)
199 usage4 (_("Could not parse arguments"));
200
201 /* If a list of paths has not been selected, find entire
202 mount list and create list of paths
203 */
204 if (path_selected == false && path_ignored == false) {
205 for (me = mount_list; me; me = me->me_next) {
206 if (! (path = np_find_parameter(path_select_list, me->me_mountdir))) {
207 path = np_add_parameter(&path_select_list, me->me_mountdir);
208 }
209 path->best_match = me;
210 path->group = group;
211 set_all_thresholds(path);
212 }
213 }
214
215 if (path_ignored == false) {
216 np_set_best_match(path_select_list, mount_list, exact_match);
217 }
218
219 /* Error if no match found for specified paths */
220 temp_list = path_select_list;
221
222 while (path_select_list) {
223 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 */
225 if (path_select_list == temp_list) {
226 temp_list = path_select_list->name_next;
227 }
228 /* 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);
230 /* 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);
232 } else if (! path_select_list->best_match) {
233 /* Without --ignore-missing option, exit with Critical state. */
234 die (STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name);
235 } else {
236 /* Continue jumping through the list */
237 path_select_list = path_select_list->name_next;
238 }
239 }
240
241 path_select_list = temp_list;
242
243 if (! path_select_list && ignore_missing == true) {
244 result = STATE_OK;
245 if (verbose >= 2) {
246 printf ("None of the provided paths were found\n");
247 }
248 }
249
250 /* Process for every path in list */
251 for (path = path_select_list; path; path=path->name_next) {
252 if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL)
253 printf("Thresholds(pct) for %s warn: %f crit %f\n",
254 path->name,
255 path->freespace_percent->warning->end,
256 path->freespace_percent->critical->end);
257
258 if (verbose >= 3 && path->group != NULL)
259 printf("Group of %s: %s\n",path->name,path->group);
260
261 /* reset disk result */
262 disk_result = STATE_UNKNOWN;
263
264 me = path->best_match;
265
266 if (!me) {
267 continue;
268 }
269 230
270#ifdef __CYGWIN__ 231 /* Skip remote filesystems if we're not interested in them */
271 if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11) 232 if (mount_entry->me_remote && config.show_local_fs) {
272 continue; 233 if (config.stat_remote_fs) {
273 snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10); 234 // TODO Stat here
274 if (GetDriveType(mountdir) != DRIVE_FIXED) 235 if (!stat_path(path, config.ignore_missing) && config.ignore_missing) {
275 me->me_remote = 1; 236 }
276#endif 237 }
277 /* Filters */ 238 continue;
278 239 }
279 /* Remove filesystems already seen */
280 if (np_seen_name(seen, me->me_mountdir)) {
281 continue;
282 }
283 np_add_name(&seen, me->me_mountdir);
284
285 if (path->group == NULL) {
286 /* Skip remote filesystems if we're not interested in them */
287 if (me->me_remote && show_local_fs) {
288 if (stat_remote_fs) {
289 if (!stat_path(path) && ignore_missing == true) {
290 result = STATE_OK;
291 xasprintf (&ignored, "%s %s;", ignored, path->name);
292 }
293 }
294 continue;
295 /* Skip pseudo fs's if we haven't asked for all fs's */
296 } else if (me->me_dummy && !show_all_fs) {
297 continue;
298 /* Skip excluded fstypes */
299 } else if (fs_exclude_list && np_find_regmatch (fs_exclude_list, me->me_type)) {
300 continue;
301 /* Skip excluded fs's */
302 } else if (dp_exclude_list &&
303 (np_find_name (dp_exclude_list, me->me_devname) ||
304 np_find_name (dp_exclude_list, me->me_mountdir))) {
305 continue;
306 /* Skip not included fstypes */
307 } else if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) {
308 continue;
309 }
310 }
311
312 if (!stat_path(path)) {
313 if (ignore_missing == true) {
314 result = STATE_OK;
315 xasprintf (&ignored, "%s %s;", ignored, path->name);
316 }
317 continue;
318 }
319 get_fs_usage (me->me_mountdir, me->me_devname, &fsp);
320
321 if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) {
322 get_stats (path, &fsp);
323
324 if (verbose >= 3) {
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",
326 me->me_mountdir,
327 path->dused_pct,
328 path->dfree_pct,
329 path->dused_units,
330 path->dfree_units,
331 path->dtotal_units,
332 path->dused_inodes_percent,
333 path->dfree_inodes_percent,
334 fsp.fsu_blocksize,
335 mult);
336 }
337
338 /* Threshold comparisons */
339
340 temp_result = get_status(path->dfree_units, path->freespace_units);
341 if (verbose >=3) printf("Freespace_units result=%d\n", temp_result);
342 disk_result = max_state( disk_result, temp_result );
343
344 temp_result = get_status(path->dfree_pct, path->freespace_percent);
345 if (verbose >=3) printf("Freespace%% result=%d\n", temp_result);
346 disk_result = max_state( disk_result, temp_result );
347
348 temp_result = get_status(path->dused_units, path->usedspace_units);
349 if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result);
350 disk_result = max_state( disk_result, temp_result );
351
352 temp_result = get_status(path->dused_pct, path->usedspace_percent);
353 if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result);
354 disk_result = max_state( disk_result, temp_result );
355
356 temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
357 if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result);
358 disk_result = max_state( disk_result, temp_result );
359
360 temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
361 if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result);
362 disk_result = max_state( disk_result, temp_result );
363
364 result = max_state(result, disk_result);
365
366 /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
367 Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
368 data. Assumption that start=0. Roll on new syntax...
369 */
370
371 /* *_high_tide must be reinitialized at each run */
372 uint64_t warning_high_tide = UINT64_MAX;
373
374 if (path->freespace_units->warning != NULL) {
375 warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
376 }
377 if (path->freespace_percent->warning != NULL) {
378 warning_high_tide = min( warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end/100) * (path->dtotal_units * mult)) );
379 }
380
381 uint64_t critical_high_tide = UINT64_MAX;
382
383 if (path->freespace_units->critical != NULL) {
384 critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
385 }
386 if (path->freespace_percent->critical != NULL) {
387 critical_high_tide = min( critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end/100) * (path->dtotal_units * mult)) );
388 }
389
390 /* Nb: *_high_tide are unset when == UINT64_MAX */
391 xasprintf (&perf, "%s %s", perf,
392 perfdata_uint64 (
393 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
394 path->dused_units * mult, "B",
395 (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
396 (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide,
397 true, 0,
398 true, path->dtotal_units * mult));
399
400 if (display_inodes_perfdata) {
401 /* *_high_tide must be reinitialized at each run */
402 warning_high_tide = UINT64_MAX;
403 critical_high_tide = UINT64_MAX;
404
405 if (path->freeinodes_percent->warning != NULL) {
406 warning_high_tide = (uint64_t) fabs( min( (double) warning_high_tide, (double) (1.0 - path->freeinodes_percent->warning->end/100)*path->inodes_total ));
407 }
408 if (path->freeinodes_percent->critical != NULL) {
409 critical_high_tide = (uint64_t) fabs( min( (double) critical_high_tide, (double) (1.0 - path->freeinodes_percent->critical->end/100)*path->inodes_total ));
410 }
411
412 xasprintf (&perf_ilabel, "%s (inodes)", (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
413 /* Nb: *_high_tide are unset when == UINT64_MAX */
414 xasprintf (&perf, "%s %s", perf,
415 perfdata_uint64 (perf_ilabel,
416 path->inodes_used, "",
417 (warning_high_tide != UINT64_MAX ? true : false), warning_high_tide,
418 (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide,
419 true, 0,
420 true, path->inodes_total));
421 }
422
423 if (disk_result==STATE_OK && erronly && !verbose)
424 continue;
425
426 if(disk_result && verbose >= 1) {
427 xasprintf(&flag_header, " %s [", state_text (disk_result));
428 } else {
429 xasprintf(&flag_header, "");
430 }
431 xasprintf (&output, "%s%s %s %llu%s (%.1f%%",
432 output, flag_header,
433 (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
434 path->dfree_units,
435 units,
436 path->dfree_pct);
437 if (path->dused_inodes_percent < 0) {
438 xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
439 } else {
440 xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
441 }
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 240
241 // TODO why stat here? remove unstatable fs?
242 if (!stat_path(path, config.ignore_missing)) {
243 // if (config.ignore_missing) {
244 // xasprintf(&ignored, "%s %s;", ignored, path->name);
245 // }
246 // not accessible, remove from list
247 path = mp_int_fs_list_del(&config.path_select_list, path);
248 continue;
249 }
250 }
251
252 path = mp_int_fs_list_get_next(path);
253 }
254
255 // now get the actual measurements
256 for (parameter_list_elem *filesystem = config.path_select_list.first; filesystem;) {
257 // Get actual metrics here
258 struct mount_entry *mount_entry = filesystem->best_match;
259 struct fs_usage fsp = {0};
260 get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp);
261
262 if (fsp.fsu_blocks != 0 && strcmp("none", mount_entry->me_mountdir) != 0) {
263 *filesystem = get_path_stats(*filesystem, fsp, config.freespace_ignore_reserved);
264
265 if (verbose >= 3) {
266 printf("For %s, used_units=%lu free_units=%lu total_units=%lu "
267 "fsp.fsu_blocksize=%lu\n",
268 mount_entry->me_mountdir, filesystem->used_bytes, filesystem->free_bytes,
269 filesystem->total_bytes, fsp.fsu_blocksize);
270 }
271 } else {
272 // failed to retrieve file system data or not mounted?
273 filesystem = mp_int_fs_list_del(&config.path_select_list, filesystem);
274 continue;
275 }
276 filesystem = mp_int_fs_list_get_next(filesystem);
277 }
278
279 if (verbose > 2) {
280 for (parameter_list_elem *filesystem = config.path_select_list.first; filesystem;
281 filesystem = mp_int_fs_list_get_next(filesystem)) {
282 assert(filesystem->best_match != NULL);
283 if (filesystem->best_match == NULL) {
284 printf("Filesystem path %s has no mount_entry!\n", filesystem->name);
285 } else {
286 // printf("Filesystem path %s has a mount_entry!\n", filesystem->name);
287 }
288 }
289 }
290
291 measurement_unit_list *measurements = NULL;
292 measurement_unit_list *current = NULL;
293 // create measuring units, because of groups
294 for (parameter_list_elem *filesystem = config.path_select_list.first; filesystem;
295 filesystem = mp_int_fs_list_get_next(filesystem)) {
296 assert(filesystem->best_match != NULL);
297
298 if (filesystem->group == NULL) {
299 // create a measurement unit for the fs
300 measurement_unit unit =
301 create_measurement_unit_from_filesystem(*filesystem, config.display_mntp);
302 if (measurements == NULL) {
303 measurements = current = add_measurement_list(NULL, unit);
304 } else {
305 current = add_measurement_list(measurements, unit);
306 }
307 } else {
308 // Grouped elements are consecutive
309 if (measurements == NULL) {
310 // first entry
311 measurement_unit unit =
312 create_measurement_unit_from_filesystem(*filesystem, config.display_mntp);
313 unit.name = strdup(filesystem->group);
314 measurements = current = add_measurement_list(NULL, unit);
315 } else {
316 // if this is the first element of a group, the name of the previous entry is
317 // different
318 if (strcmp(filesystem->group, current->unit.name) != 0) {
319 // so, this must be the first element of a group
320 measurement_unit unit =
321 create_measurement_unit_from_filesystem(*filesystem, config.display_mntp);
322 unit.name = filesystem->group;
323 current = add_measurement_list(measurements, unit);
324
325 } else {
326 // NOT the first entry of a group, add info to the other one
327 current->unit = add_filesystem_to_measurement_unit(current->unit, *filesystem);
328 }
329 }
330 }
331 }
332
333 /* Process for every path in list */
334 if (measurements != NULL) {
335 for (measurement_unit_list *unit = measurements; unit; unit = unit->next) {
336 mp_subcheck unit_sc = evaluate_filesystem(unit->unit, config.display_inodes_perfdata,
337 config.display_unit);
338 mp_add_subcheck_to_check(&overall, unit_sc);
339 }
340 } else {
341 // Apparently no machting fs found
342 mp_subcheck none_sc = mp_subcheck_init();
343 xasprintf(&none_sc.output, "No filesystems were found for the provided parameters");
344
345 if (config.ignore_missing) {
346 none_sc = mp_set_subcheck_state(none_sc, STATE_OK);
347 } else {
348 none_sc = mp_set_subcheck_state(none_sc, STATE_UNKNOWN);
349 }
350 mp_add_subcheck_to_check(&overall, none_sc);
351 }
352
353 mp_exit(overall);
354}
458 355
459double calculate_percent(uintmax_t value, uintmax_t total) { 356double calculate_percent(uintmax_t value, uintmax_t total) {
460 double pct = -1; 357 double pct = -1;
461 if(value <= DBL_MAX && total != 0) { 358 if (value <= DBL_MAX && total != 0) {
462 pct = (double)value / total * 100.0; 359 pct = (double)value / (double)total * 100.0;
463 } 360 }
464 return pct; 361
362 return pct;
465} 363}
466 364
467/* process command-line arguments */ 365/* process command-line arguments */
468int 366check_disk_config_wrapper process_arguments(int argc, char **argv) {
469process_arguments (int argc, char **argv) 367
470{ 368 check_disk_config_wrapper result = {
471 int c, err; 369 .errorcode = OK,
472 struct parameter_list *se; 370 .config = check_disk_config_init(),
473 struct parameter_list *temp_list = NULL, *previous = NULL; 371 };
474 struct mount_entry *me; 372
475 regex_t re; 373 if (argc < 2) {
476 int cflags = REG_NOSUB | REG_EXTENDED; 374 result.errorcode = ERROR;
477 int default_cflags = cflags; 375 return result;
478 char errbuf[MAX_INPUT_BUFFER]; 376 }
479 int fnd = 0; 377
480 378 enum {
481 int option = 0; 379 output_format_index = CHAR_MAX + 1,
482 static struct option longopts[] = { 380 display_unit_index,
483 {"timeout", required_argument, 0, 't'}, 381 };
484 {"warning", required_argument, 0, 'w'}, 382
485 {"critical", required_argument, 0, 'c'}, 383 static struct option longopts[] = {{"timeout", required_argument, 0, 't'},
486 {"iwarning", required_argument, 0, 'W'}, 384 {"warning", required_argument, 0, 'w'},
487 /* Dang, -C is taken. We might want to reshuffle this. */ 385 {"critical", required_argument, 0, 'c'},
488 {"icritical", required_argument, 0, 'K'}, 386 {"iwarning", required_argument, 0, 'W'},
489 {"kilobytes", no_argument, 0, 'k'}, 387 {"icritical", required_argument, 0, 'K'},
490 {"megabytes", no_argument, 0, 'm'}, 388 {"kilobytes", no_argument, 0, 'k'},
491 {"units", required_argument, 0, 'u'}, 389 {"megabytes", no_argument, 0, 'm'},
492 {"path", required_argument, 0, 'p'}, 390 {"units", required_argument, 0, 'u'},
493 {"partition", required_argument, 0, 'p'}, 391 {"path", required_argument, 0, 'p'},
494 {"exclude_device", required_argument, 0, 'x'}, 392 {"partition", required_argument, 0, 'p'},
495 {"exclude-type", required_argument, 0, 'X'}, 393 {"exclude_device", required_argument, 0, 'x'},
496 {"include-type", required_argument, 0, 'N'}, 394 {"exclude-type", required_argument, 0, 'X'},
497 {"group", required_argument, 0, 'g'}, 395 {"include-type", required_argument, 0, 'N'},
498 {"eregi-path", required_argument, 0, 'R'}, 396 {"group", required_argument, 0, 'g'},
499 {"eregi-partition", required_argument, 0, 'R'}, 397 {"eregi-path", required_argument, 0, 'R'},
500 {"ereg-path", required_argument, 0, 'r'}, 398 {"eregi-partition", required_argument, 0, 'R'},
501 {"ereg-partition", required_argument, 0, 'r'}, 399 {"ereg-path", required_argument, 0, 'r'},
502 {"freespace-ignore-reserved", no_argument, 0, 'f'}, 400 {"ereg-partition", required_argument, 0, 'r'},
503 {"ignore-ereg-path", required_argument, 0, 'i'}, 401 {"freespace-ignore-reserved", no_argument, 0, 'f'},
504 {"ignore-ereg-partition", required_argument, 0, 'i'}, 402 {"ignore-ereg-path", required_argument, 0, 'i'},
505 {"ignore-eregi-path", required_argument, 0, 'I'}, 403 {"ignore-ereg-partition", required_argument, 0, 'i'},
506 {"ignore-eregi-partition", required_argument, 0, 'I'}, 404 {"ignore-eregi-path", required_argument, 0, 'I'},
507 {"ignore-missing", no_argument, 0, 'n'}, 405 {"ignore-eregi-partition", required_argument, 0, 'I'},
508 {"local", no_argument, 0, 'l'}, 406 {"ignore-missing", no_argument, 0, 'n'},
509 {"stat-remote-fs", no_argument, 0, 'L'}, 407 {"local", no_argument, 0, 'l'},
510 {"iperfdata", no_argument, 0, 'P'}, 408 {"stat-remote-fs", no_argument, 0, 'L'},
511 {"mountpoint", no_argument, 0, 'M'}, 409 {"iperfdata", no_argument, 0, 'P'},
512 {"errors-only", no_argument, 0, 'e'}, 410 {"mountpoint", no_argument, 0, 'M'},
513 {"exact-match", no_argument, 0, 'E'}, 411 {"errors-only", no_argument, 0, 'e'},
514 {"all", no_argument, 0, 'A'}, 412 {"exact-match", no_argument, 0, 'E'},
515 {"verbose", no_argument, 0, 'v'}, 413 {"all", no_argument, 0, 'A'},
516 {"quiet", no_argument, 0, 'q'}, 414 {"verbose", no_argument, 0, 'v'},
517 {"clear", no_argument, 0, 'C'}, 415 {"quiet", no_argument, 0, 'q'},
518 {"version", no_argument, 0, 'V'}, 416 {"clear", no_argument, 0, 'C'},
519 {"help", no_argument, 0, 'h'}, 417 {"version", no_argument, 0, 'V'},
520 {0, 0, 0, 0} 418 {"help", no_argument, 0, 'h'},
521 }; 419 {"output-format", required_argument, 0, output_format_index},
522 420 {"display-unit", required_argument, 0, display_unit_index},
523 if (argc < 2) 421 {0, 0, 0, 0}};
524 return ERROR; 422
525 423 for (int index = 1; index < argc; index++) {
526 np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED); 424 if (strcmp("-to", argv[index]) == 0) {
527 425 strcpy(argv[index], "-t");
528 for (c = 1; c < argc; c++) 426 }
529 if (strcmp ("-to", argv[c]) == 0) 427 }
530 strcpy (argv[c], "-t"); 428
531 429 int cflags = REG_NOSUB | REG_EXTENDED;
532 while (1) { 430 int default_cflags = cflags;
533 c = getopt_long (argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option); 431 char *warn_freespace_units = NULL;
534 432 char *crit_freespace_units = NULL;
535 if (c == -1 || c == EOF) 433 char *warn_freespace_percent = NULL;
536 break; 434 char *crit_freespace_percent = NULL;
537 435 char *warn_freeinodes_percent = NULL;
538 switch (c) { 436 char *crit_freeinodes_percent = NULL;
539 case 't': /* timeout period */ 437
540 if (is_integer (optarg)) { 438 bool path_selected = false;
541 timeout_interval = atoi (optarg); 439 char *group = NULL;
542 break; 440 byte_unit unit = MebiBytes_factor;
543 } 441
544 else { 442 result.config.mount_list = read_file_system_list(false);
545 usage2 (_("Timeout interval must be a positive integer"), optarg); 443
546 } 444 np_add_regex(&result.config.fs_exclude_list, "iso9660", REG_EXTENDED);
547 445
548 /* See comments for 'c' */ 446 while (true) {
549 case 'w': /* warning threshold */ 447 int option = 0;
448 int option_index = getopt_long(
449 argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option);
450
451 if (option_index == -1 || option_index == EOF) {
452 break;
453 }
454
455 switch (option_index) {
456 case 't': /* timeout period */
457 if (is_integer(optarg)) {
458 timeout_interval = atoi(optarg);
459 break;
460 } else {
461 usage2(_("Timeout interval must be a positive integer"), optarg);
462 }
463
464 /* See comments for 'c' */
465 case 'w': /* warning threshold */
550 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) { 466 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
551 die(STATE_UNKNOWN, "Argument for --warning invalid or missing: %s\n", optarg); 467 die(STATE_UNKNOWN, "Argument for --warning invalid or missing: %s\n", optarg);
552 } 468 }
553 469
554 if (strstr(optarg, "%")) { 470 if (strstr(optarg, "%")) {
555 if (*optarg == '@') { 471 if (*optarg == '@') {
556 warn_freespace_percent = optarg; 472 warn_freespace_percent = optarg;
557 } else { 473 } else {
558 xasprintf(&warn_freespace_percent, "@%s", optarg); 474 xasprintf(&warn_freespace_percent, "@%s", optarg);
559 } 475 }
560 } else { 476 } else {
561 if (*optarg == '@') { 477 if (*optarg == '@') {
562 warn_freespace_units = optarg; 478 warn_freespace_units = optarg;
563 } else { 479 } else {
564 xasprintf(&warn_freespace_units, "@%s", optarg); 480 xasprintf(&warn_freespace_units, "@%s", optarg);
565 } 481 }
566 } 482 }
567 break; 483 break;
568 484
569 /* Awful mistake where the range values do not make sense. Normally, 485 /* 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 486 * 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 487 * 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 488 * force @ at the beginning of the range, so that it is backwards compatible
573 */ 489 */
574 case 'c': /* critical threshold */ 490 case 'c': /* critical threshold */
575 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) { 491 if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
576 die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg); 492 die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg);
577 } 493 }
578 494
579 if (strstr(optarg, "%")) { 495 if (strstr(optarg, "%")) {
580 if (*optarg == '@') { 496 if (*optarg == '@') {
581 crit_freespace_percent = optarg; 497 crit_freespace_percent = optarg;
582 } else { 498 } else {
583 xasprintf(&crit_freespace_percent, "@%s", optarg); 499 xasprintf(&crit_freespace_percent, "@%s", optarg);
584 } 500 }
585 } else { 501 } else {
586 if (*optarg == '@') { 502 if (*optarg == '@') {
587 crit_freespace_units = optarg; 503 crit_freespace_units = optarg;
588 } else { 504 } else {
589 xasprintf(&crit_freespace_units, "@%s", optarg); 505 xasprintf(&crit_freespace_units, "@%s", optarg);
590 } 506 }
591 } 507 }
592 break; 508 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 509
899void 510 case 'W': /* warning inode threshold */
900set_all_thresholds (struct parameter_list *path) 511 if (*optarg == '@') {
901{ 512 warn_freeinodes_percent = optarg;
902 if (path->freespace_units != NULL) free(path->freespace_units); 513 } else {
903 set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units); 514 xasprintf(&warn_freeinodes_percent, "@%s", optarg);
904 if (path->freespace_percent != NULL) free (path->freespace_percent); 515 }
905 set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent); 516 break;
906 if (path->usedspace_units != NULL) free (path->usedspace_units); 517 case 'K': /* critical inode threshold */
907 set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units); 518 if (*optarg == '@') {
908 if (path->usedspace_percent != NULL) free (path->usedspace_percent); 519 crit_freeinodes_percent = optarg;
909 set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent); 520 } else {
910 if (path->usedinodes_percent != NULL) free (path->usedinodes_percent); 521 xasprintf(&crit_freeinodes_percent, "@%s", optarg);
911 set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent); 522 }
912 if (path->freeinodes_percent != NULL) free (path->freeinodes_percent); 523 break;
913 set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent); 524 case 'u':
914} 525 if (!strcasecmp(optarg, "bytes")) {
526 unit = Bytes_Factor;
527 } else if (!strcmp(optarg, "KiB")) {
528 unit = KibiBytes_factor;
529 } else if (!strcmp(optarg, "kB")) {
530 unit = KiloBytes_factor;
531 } else if (!strcmp(optarg, "MiB")) {
532 unit = MebiBytes_factor;
533 } else if (!strcmp(optarg, "MB")) {
534 unit = MegaBytes_factor;
535 } else if (!strcmp(optarg, "GiB")) {
536 unit = GibiBytes_factor;
537 } else if (!strcmp(optarg, "GB")) {
538 unit = GigaBytes_factor;
539 } else if (!strcmp(optarg, "TiB")) {
540 unit = TebiBytes_factor;
541 } else if (!strcmp(optarg, "TB")) {
542 unit = TeraBytes_factor;
543 } else if (!strcmp(optarg, "PiB")) {
544 unit = PebiBytes_factor;
545 } else if (!strcmp(optarg, "PB")) {
546 unit = PetaBytes_factor;
547 } else {
548 die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
549 }
550 break;
551 case 'k':
552 unit = KibiBytes_factor;
553 break;
554 case 'm':
555 unit = MebiBytes_factor;
556 break;
557 case display_unit_index:
558 if (!strcasecmp(optarg, "bytes")) {
559 result.config.display_unit = Bytes;
560 } else if (!strcmp(optarg, "KiB")) {
561 result.config.display_unit = KibiBytes;
562 } else if (!strcmp(optarg, "kB")) {
563 result.config.display_unit = KiloBytes;
564 } else if (!strcmp(optarg, "MiB")) {
565 result.config.display_unit = MebiBytes;
566 } else if (!strcmp(optarg, "MB")) {
567 result.config.display_unit = MegaBytes;
568 } else if (!strcmp(optarg, "GiB")) {
569 result.config.display_unit = GibiBytes;
570 } else if (!strcmp(optarg, "GB")) {
571 result.config.display_unit = GigaBytes;
572 } else if (!strcmp(optarg, "TiB")) {
573 result.config.display_unit = TebiBytes;
574 } else if (!strcmp(optarg, "TB")) {
575 result.config.display_unit = TeraBytes;
576 } else if (!strcmp(optarg, "PiB")) {
577 result.config.display_unit = PebiBytes;
578 } else if (!strcmp(optarg, "PB")) {
579 result.config.display_unit = PetaBytes;
580 } else {
581 die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
582 }
583 break;
584 case 'L':
585 result.config.stat_remote_fs = true;
586 /* fallthrough */
587 case 'l':
588 result.config.show_local_fs = true;
589 break;
590 case 'P':
591 result.config.display_inodes_perfdata = true;
592 break;
593 case 'p': /* select path */ {
594 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
595 crit_freespace_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
596 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"),
597 _("Must set a threshold value before using -p\n"));
598 }
915 599
916void 600 /* add parameter if not found. overwrite thresholds if path has already been added */
917print_help (void) 601 parameter_list_elem *search_entry;
918{ 602 if (!(search_entry = mp_int_fs_list_find(result.config.path_select_list, optarg))) {
919 print_revision (progname, NP_VERSION); 603 search_entry = mp_int_fs_list_append(&result.config.path_select_list, optarg);
920 604
921 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 605 // struct stat stat_buf = {};
922 printf (COPYRIGHT, copyright, email); 606 // if (stat(optarg, &stat_buf) && result.config.ignore_missing) {
923 607 // result.config.path_ignored = true;
924 printf ("%s\n", _("This plugin checks the amount of used disk space on a mounted file system")); 608 // break;
925 printf ("%s\n", _("and generates an alert if free space is less than one of the threshold values")); 609 // }
926 610 }
927 printf ("\n\n"); 611 search_entry->group = group;
928 612 set_all_thresholds(search_entry, warn_freespace_units, crit_freespace_units,
929 print_usage (); 613 warn_freespace_percent, crit_freespace_percent,
930 614
931 printf (UT_HELP_VRSN); 615 warn_freeinodes_percent, crit_freeinodes_percent);
932 printf (UT_EXTRA_OPTS); 616
933 617 /* With autofs, it is required to stat() the path before re-populating the mount_list */
934 printf (" %s\n", "-w, --warning=INTEGER"); 618 // if (!stat_path(se, result.config.ignore_missing)) {
935 printf (" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free")); 619 // break;
936 printf (" %s\n", "-w, --warning=PERCENT%"); 620 // }
937 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free")); 621 mp_int_fs_list_set_best_match(result.config.path_select_list, result.config.mount_list,
938 printf (" %s\n", "-c, --critical=INTEGER"); 622 result.config.exact_match);
939 printf (" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free")); 623
940 printf (" %s\n", "-c, --critical=PERCENT%"); 624 path_selected = true;
941 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free")); 625 } break;
942 printf (" %s\n", "-W, --iwarning=PERCENT%"); 626 case 'x': /* exclude path or partition */
943 printf (" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free")); 627 np_add_name(&result.config.device_path_exclude_list, optarg);
944 printf (" %s\n", "-K, --icritical=PERCENT%"); 628 break;
945 printf (" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free")); 629 case 'X': /* exclude file system type */ {
946 printf (" %s\n", "-p, --path=PATH, --partition=PARTITION"); 630 int err = np_add_regex(&result.config.fs_exclude_list, optarg, REG_EXTENDED);
947 printf (" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)")); 631 if (err != 0) {
948 printf (" %s\n", "-x, --exclude_device=PATH <STRING>"); 632 char errbuf[MAX_INPUT_BUFFER];
949 printf (" %s\n", _("Ignore device (only works if -p unspecified)")); 633 regerror(err, &result.config.fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
950 printf (" %s\n", "-C, --clear"); 634 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"),
951 printf (" %s\n", _("Clear thresholds")); 635 _("Could not compile regular expression"), errbuf);
952 printf (" %s\n", "-E, --exact-match"); 636 }
953 printf (" %s\n", _("For paths or partitions specified with -p, only check for exact paths")); 637 break;
954 printf (" %s\n", "-e, --errors-only"); 638 case 'N': /* include file system type */
955 printf (" %s\n", _("Display only devices/mountpoints with errors")); 639 err = np_add_regex(&result.config.fs_include_list, optarg, REG_EXTENDED);
956 printf (" %s\n", "-f, --freespace-ignore-reserved"); 640 if (err != 0) {
957 printf (" %s\n", _("Don't account root-reserved blocks into freespace in perfdata")); 641 char errbuf[MAX_INPUT_BUFFER];
958 printf (" %s\n", "-P, --iperfdata"); 642 regerror(err, &result.config.fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
959 printf (" %s\n", _("Display inode usage in perfdata")); 643 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"),
960 printf (" %s\n", "-g, --group=NAME"); 644 _("Could not compile regular expression"), errbuf);
961 printf (" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together")); 645 }
962 printf (" %s\n", "-k, --kilobytes"); 646 } break;
963 printf (" %s\n", _("Same as '--units kB'")); 647 case 'v': /* verbose */
964 printf (" %s\n", "-l, --local"); 648 verbose++;
965 printf (" %s\n", _("Only check local filesystems")); 649 break;
966 printf (" %s\n", "-L, --stat-remote-fs"); 650 case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
967 printf (" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems")); 651 /* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
968 printf (" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)")); 652 result.config.erronly = true;
969 printf (" %s\n", "-M, --mountpoint"); 653 break;
970 printf (" %s\n", _("Display the (block) device instead of the mount point")); 654 case 'e':
971 printf (" %s\n", "-m, --megabytes"); 655 result.config.erronly = true;
972 printf (" %s\n", _("Same as '--units MB'")); 656 break;
973 printf (" %s\n", "-A, --all"); 657 case 'E':
974 printf (" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'")); 658 if (path_selected) {
975 printf (" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION"); 659 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"),
976 printf (" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)")); 660 _("Must set -E before selecting paths\n"));
977 printf (" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION"); 661 }
978 printf (" %s\n", _("Regular expression for path or partition (may be repeated)")); 662 result.config.exact_match = true;
979 printf (" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION"); 663 break;
980 printf (" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)")); 664 case 'f':
981 printf (" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION"); 665 result.config.freespace_ignore_reserved = true;
982 printf (" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)")); 666 break;
983 printf (" %s\n", "-n, --ignore-missing"); 667 case 'g':
984 printf (" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible.")); 668 if (path_selected) {
985 printf (" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)")); 669 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"),
986 printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 670 _("Must set group value before selecting paths\n"));
987 printf (" %s\n", "-u, --units=STRING"); 671 }
988 printf (" %s\n", _("Choose bytes, kB, MB, GB, TB (default: MB)")); 672 group = optarg;
989 printf (UT_VERBOSE); 673 break;
990 printf (" %s\n", "-X, --exclude-type=TYPE_REGEX"); 674 case 'I':
991 printf (" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)")); 675 cflags |= REG_ICASE;
992 printf (" %s\n", "-N, --include-type=TYPE_REGEX"); 676 // Intentional fallthrough
993 printf (" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)")); 677 case 'i': {
994 678 if (!path_selected) {
995 printf ("\n"); 679 die(STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"),
996 printf ("%s\n", _("General usage hints:")); 680 _("Paths need to be selected before using -i/-I. Use -A to select all paths "
997 printf (" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as")); 681 "explicitly"));
998 printf (" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\".")); 682 }
999 printf (" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\"")); 683 regex_t regex;
1000 684 int err = regcomp(&regex, optarg, cflags);
1001 685 if (err != 0) {
1002 686 char errbuf[MAX_INPUT_BUFFER];
1003 printf ("\n"); 687 regerror(err, &regex, errbuf, MAX_INPUT_BUFFER);
1004 printf ("%s\n", _("Examples:")); 688 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"),
1005 printf (" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /"); 689 _("Could not compile regular expression"), errbuf);
1006 printf (" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB")); 690 }
1007 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'"); 691
1008 printf (" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex")); 692 for (parameter_list_elem *elem = result.config.path_select_list.first; elem;) {
1009 printf (" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together")); 693 if (elem->best_match) {
1010 printf (" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar"); 694 if (np_regex_match_mount_entry(elem->best_match, &regex)) {
1011 printf (" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M")); 695
1012 696 if (verbose >= 3) {
1013 printf (UT_SUPPORT); 697 printf("ignoring %s matching regex\n", elem->name);
1014} 698 }
699
700 elem = mp_int_fs_list_del(&result.config.path_select_list, elem);
701 continue;
702 }
703 }
704
705 elem = mp_int_fs_list_get_next(elem);
706 }
707
708 cflags = default_cflags;
709 } break;
710 case 'n':
711 result.config.ignore_missing = true;
712 break;
713 case 'A':
714 optarg = strdup(".*");
715 // Intentional fallthrough
716 case 'R':
717 cflags |= REG_ICASE;
718 // Intentional fallthrough
719 case 'r': {
720 if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent ||
721 crit_freespace_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
722 die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"),
723 _("Must set a threshold value before using -r/-R/-A "
724 "(--ereg-path/--eregi-path/--all)\n"));
725 }
726
727 regex_t regex;
728 int err = regcomp(&regex, optarg, cflags);
729 if (err != 0) {
730 char errbuf[MAX_INPUT_BUFFER];
731 regerror(err, &regex, errbuf, MAX_INPUT_BUFFER);
732 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"),
733 _("Could not compile regular expression"), errbuf);
734 }
735
736 bool found = false;
737 for (struct mount_entry *me = result.config.mount_list; me; me = me->me_next) {
738 if (np_regex_match_mount_entry(me, &regex)) {
739 found = true;
740 if (verbose >= 3) {
741 printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir,
742 optarg);
743 }
744
745 /* add parameter if not found. overwrite thresholds if path has already been
746 * added */
747 parameter_list_elem *se = NULL;
748 if (!(se = mp_int_fs_list_find(result.config.path_select_list,
749 me->me_mountdir))) {
750 se =
751 mp_int_fs_list_append(&result.config.path_select_list, me->me_mountdir);
752 }
753 se->group = group;
754 set_all_thresholds(se, warn_freespace_units, crit_freespace_units,
755 warn_freespace_percent, crit_freespace_percent,
756 warn_freeinodes_percent, crit_freeinodes_percent);
757 }
758 }
759
760 if (!found) {
761 if (result.config.ignore_missing) {
762 result.config.path_ignored = true;
763 path_selected = true;
764 break;
765 }
766
767 die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"),
768 _("Regular expression did not match any path or disk"), optarg);
769 }
1015 770
771 path_selected = true;
772 mp_int_fs_list_set_best_match(result.config.path_select_list, result.config.mount_list,
773 result.config.exact_match);
774 cflags = default_cflags;
775
776 } break;
777 case 'M': /* display mountpoint */
778 result.config.display_mntp = true;
779 break;
780 case 'C': {
781 /* add all mount entries to path_select list if no partitions have been explicitly
782 * defined using -p */
783 if (!path_selected) {
784 parameter_list_elem *path;
785 for (struct mount_entry *me = result.config.mount_list; me; me = me->me_next) {
786 if (!(path = mp_int_fs_list_find(result.config.path_select_list,
787 me->me_mountdir))) {
788 path =
789 mp_int_fs_list_append(&result.config.path_select_list, me->me_mountdir);
790 }
791 path->best_match = me;
792 path->group = group;
793 set_all_thresholds(path, warn_freespace_units, crit_freespace_units,
794 warn_freespace_percent, crit_freespace_percent,
795 warn_freeinodes_percent, crit_freeinodes_percent);
796 }
797 }
1016 798
799 warn_freespace_units = NULL;
800 crit_freespace_units = NULL;
801 warn_freespace_percent = NULL;
802 crit_freespace_percent = NULL;
803 warn_freeinodes_percent = NULL;
804 crit_freeinodes_percent = NULL;
805
806 path_selected = false;
807 group = NULL;
808 } break;
809 case 'V': /* version */
810 print_revision(progname, NP_VERSION);
811 exit(STATE_UNKNOWN);
812 case 'h': /* help */
813 print_help();
814 exit(STATE_UNKNOWN);
815 case '?': /* help */
816 usage(_("Unknown argument"));
817 case output_format_index: {
818 parsed_output_format parser = mp_parse_output_format(optarg);
819 if (!parser.parsing_success) {
820 // TODO List all available formats here, maybe add anothoer usage function
821 printf("Invalid output format: %s\n", optarg);
822 exit(STATE_UNKNOWN);
823 }
1017 824
1018void 825 result.config.output_format_is_set = true;
1019print_usage (void) 826 result.config.output_format = parser.output_format;
1020{ 827 break;
1021 printf ("%s\n", _("Usage:")); 828 }
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); 829 }
1023 printf ("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n"); 830 }
1024 printf ("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n"); 831
832 /* Support for "check_disk warn crit [fs]" with thresholds at used% level */
833 int index = optind;
834
835 if (argc > index && is_intnonneg(argv[index])) {
836 if (verbose > 0) {
837 printf("Got an positional warn threshold: %s\n", argv[index]);
838 }
839 char *range = argv[index++];
840 mp_range_parsed tmp = mp_parse_range_string(range);
841 if (tmp.error != MP_PARSING_SUCCES) {
842 die(STATE_UNKNOWN, "failed to parse warning threshold");
843 }
844
845 mp_range tmp_range = tmp.range;
846 // Invert range to use it for free instead of used
847 // tmp_range.alert_on_inside_range = !tmp_range.alert_on_inside_range;
848
849 warn_freespace_percent = mp_range_to_string(tmp_range);
850
851 if (verbose > 0) {
852 printf("Positional warning threshold transformed to: %s\n", warn_freespace_percent);
853 }
854 }
855
856 if (argc > index && is_intnonneg(argv[index])) {
857 if (verbose > 0) {
858 printf("Got an positional crit threshold: %s\n", argv[index]);
859 }
860 char *range = argv[index++];
861 mp_range_parsed tmp = mp_parse_range_string(range);
862 if (tmp.error != MP_PARSING_SUCCES) {
863 die(STATE_UNKNOWN, "failed to parse warning threshold");
864 }
865
866 mp_range tmp_range = tmp.range;
867 // Invert range to use it for free instead of used
868 // tmp_range.alert_on_inside_range = !tmp_range.alert_on_inside_range;
869
870 crit_freespace_percent = mp_range_to_string(tmp_range);
871
872 if (verbose > 0) {
873 printf("Positional critical threshold transformed to: %s\n", crit_freespace_percent);
874 }
875 }
876
877 if (argc > index) {
878 if (verbose > 0) {
879 printf("Got an positional filesystem: %s\n", argv[index]);
880 }
881 struct parameter_list *se =
882 mp_int_fs_list_append(&result.config.path_select_list, strdup(argv[index++]));
883 path_selected = true;
884 set_all_thresholds(se, warn_freespace_units, crit_freespace_units, warn_freespace_percent,
885 crit_freespace_percent, warn_freeinodes_percent,
886 crit_freeinodes_percent);
887 }
888
889 // If a list of paths has not been explicitly selected, find entire
890 // mount list and create list of paths
891 if (!path_selected && !result.config.path_ignored) {
892 for (struct mount_entry *me = result.config.mount_list; me; me = me->me_next) {
893 if (me->me_dummy != 0) {
894 // just do not add dummy filesystems
895 continue;
896 }
897
898 parameter_list_elem *path = NULL;
899 if (!(path = mp_int_fs_list_find(result.config.path_select_list, me->me_mountdir))) {
900 path = mp_int_fs_list_append(&result.config.path_select_list, me->me_mountdir);
901 }
902 path->best_match = me;
903 path->group = group;
904 set_all_thresholds(path, warn_freespace_units, crit_freespace_units,
905 warn_freespace_percent, crit_freespace_percent,
906 warn_freeinodes_percent, crit_freeinodes_percent);
907 }
908 }
909
910 // Set thresholds to the appropriate unit
911 for (parameter_list_elem *tmp = result.config.path_select_list.first; tmp;
912 tmp = mp_int_fs_list_get_next(tmp)) {
913
914 mp_perfdata_value factor = mp_create_pd_value(unit);
915
916 if (tmp->freespace_units.critical_is_set) {
917 tmp->freespace_units.critical =
918 mp_range_multiply(tmp->freespace_units.critical, factor);
919 }
920 if (tmp->freespace_units.warning_is_set) {
921 tmp->freespace_units.warning = mp_range_multiply(tmp->freespace_units.warning, factor);
922 }
923 }
924
925 return result;
1025} 926}
1026 927
1027bool 928void set_all_thresholds(parameter_list_elem *path, char *warn_freespace_units,
1028stat_path (struct parameter_list *p) 929 char *crit_freespace_units, char *warn_freespace_percent,
1029{ 930 char *crit_freespace_percent, char *warn_freeinodes_percent,
1030 /* Stat entry to check that dir exists and is accessible */ 931 char *crit_freeinodes_percent) {
1031 if (verbose >= 3) 932 mp_range_parsed tmp;
1032 printf("calling stat on %s\n", p->name); 933
1033 if (stat (p->name, &stat_buf[0])) { 934 if (warn_freespace_units) {
1034 if (verbose >= 3) 935 tmp = mp_parse_range_string(warn_freespace_units);
1035 printf("stat failed on %s\n", p->name); 936 path->freespace_units = mp_thresholds_set_warn(path->freespace_units, tmp.range);
1036 if (ignore_missing == true) { 937 }
1037 return false; 938
1038 } else { 939 if (crit_freespace_units) {
1039 printf("DISK %s - ", _("CRITICAL")); 940 tmp = mp_parse_range_string(crit_freespace_units);
1040 die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno)); 941 path->freespace_units = mp_thresholds_set_crit(path->freespace_units, tmp.range);
1041 } 942 }
1042 } 943
1043 return true; 944 if (warn_freespace_percent) {
945 tmp = mp_parse_range_string(warn_freespace_percent);
946 path->freespace_percent = mp_thresholds_set_warn(path->freespace_percent, tmp.range);
947 }
948
949 if (crit_freespace_percent) {
950 tmp = mp_parse_range_string(crit_freespace_percent);
951 path->freespace_percent = mp_thresholds_set_crit(path->freespace_percent, tmp.range);
952 }
953
954 if (warn_freeinodes_percent) {
955 tmp = mp_parse_range_string(warn_freeinodes_percent);
956 path->freeinodes_percent = mp_thresholds_set_warn(path->freeinodes_percent, tmp.range);
957 }
958
959 if (crit_freeinodes_percent) {
960 tmp = mp_parse_range_string(crit_freeinodes_percent);
961 path->freeinodes_percent = mp_thresholds_set_crit(path->freeinodes_percent, tmp.range);
962 }
1044} 963}
1045 964
965void print_help(void) {
966 print_revision(progname, NP_VERSION);
967
968 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
969 printf(COPYRIGHT, copyright, email);
970
971 printf("%s\n", _("This plugin checks the amount of used disk space on a mounted file system"));
972 printf("%s\n",
973 _("and generates an alert if free space is less than one of the threshold values"));
974
975 printf("\n\n");
976
977 print_usage();
978
979 printf(UT_HELP_VRSN);
980 printf(UT_EXTRA_OPTS);
981
982 printf(" %s\n", "-w, --warning=INTEGER");
983 printf(" %s\n", _("Exit with WARNING status if less than INTEGER units of disk are free"));
984 printf(" %s\n", "-w, --warning=PERCENT%");
985 printf(" %s\n", _("Exit with WARNING status if less than PERCENT of disk space is free"));
986 printf(" %s\n", "-c, --critical=INTEGER");
987 printf(" %s\n", _("Exit with CRITICAL status if less than INTEGER units of disk are free"));
988 printf(" %s\n", "-c, --critical=PERCENT%");
989 printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of disk space is free"));
990 printf(" %s\n", "-W, --iwarning=PERCENT%");
991 printf(" %s\n", _("Exit with WARNING status if less than PERCENT of inode space is free"));
992 printf(" %s\n", "-K, --icritical=PERCENT%");
993 printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free"));
994 printf(" %s\n", "-p, --path=PATH, --partition=PARTITION");
995 printf(" %s\n",
996 _("Mount point or block device as emitted by the mount(8) command (may be repeated)"));
997 printf(" %s\n", "-x, --exclude_device=PATH <STRING>");
998 printf(" %s\n", _("Ignore device (only works if -p unspecified)"));
999 printf(" %s\n", "-C, --clear");
1000 printf(" %s\n", _("Clear thresholds"));
1001 printf(" %s\n", "-E, --exact-match");
1002 printf(" %s\n", _("For paths or partitions specified with -p, only check for exact paths"));
1003 printf(" %s\n", "-e, --errors-only");
1004 printf(" %s\n", _("Display only devices/mountpoints with errors"));
1005 printf(" %s\n", "-f, --freespace-ignore-reserved");
1006 printf(" %s\n", _("Don't account root-reserved blocks into freespace in perfdata"));
1007 printf(" %s\n", "-P, --iperfdata");
1008 printf(" %s\n", _("Display inode usage in perfdata"));
1009 printf(" %s\n", "-g, --group=NAME");
1010 printf(" %s\n",
1011 _("Group paths. Thresholds apply to (free-)space of all partitions together"));
1012 printf(" %s\n", "-l, --local");
1013 printf(" %s\n", _("Only check local filesystems"));
1014 printf(" %s\n", "-L, --stat-remote-fs");
1015 printf(
1016 " %s\n",
1017 _("Only check local filesystems against thresholds. Yet call stat on remote filesystems"));
1018 printf(" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)"));
1019 printf(" %s\n", "-M, --mountpoint");
1020 printf(" %s\n", _("Display the (block) device instead of the mount point"));
1021 printf(" %s\n", "-A, --all");
1022 printf(" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'"));
1023 printf(" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION");
1024 printf(" %s\n",
1025 _("Case insensitive regular expression for path/partition (may be repeated)"));
1026 printf(" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION");
1027 printf(" %s\n", _("Regular expression for path or partition (may be repeated)"));
1028 printf(" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION");
1029 printf(" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) "
1030 "(may be repeated)"));
1031 printf(" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION");
1032 printf(" %s\n",
1033 _("Regular expression to ignore selected path or partition (may be repeated)"));
1034 printf(" %s\n", "-n, --ignore-missing");
1035 printf(" %s\n",
1036 _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible."));
1037 printf(" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)"));
1038 printf(UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
1039 printf(" %s\n", "-u, --units=STRING");
1040 printf(" %s\n", _("Select the unit used for the absolute value thresholds"));
1041 printf(" %s\n", _("Choose one of \"bytes\", \"KiB\", \"kB\", \"MiB\", \"MB\", \"GiB\", "
1042 "\"GB\", \"TiB\", \"TB\", \"PiB\", \"PB\" (default: MiB)"));
1043 printf(" %s\n", "-k, --kilobytes");
1044 printf(" %s\n", _("Same as '--units kB'"));
1045 printf(" %s\n", "--display-unit");
1046 printf(" %s\n", _("Select the unit used for in the output"));
1047 printf(" %s\n", _("Choose one of \"bytes\", \"KiB\", \"kB\", \"MiB\", \"MB\", \"GiB\", "
1048 "\"GB\", \"TiB\", \"TB\", \"PiB\", \"PB\" (default: MiB)"));
1049 printf(" %s\n", "-m, --megabytes");
1050 printf(" %s\n", _("Same as '--units MB'"));
1051 printf(UT_VERBOSE);
1052 printf(" %s\n", "-X, --exclude-type=TYPE_REGEX");
1053 printf(" %s\n",
1054 _("Ignore all filesystems of types matching given regex(7) (may be repeated)"));
1055 printf(" %s\n", "-N, --include-type=TYPE_REGEX");
1056 printf(
1057 " %s\n",
1058 _("Check only filesystems where the type matches this given regex(7) (may be repeated)"));
1059 printf(UT_OUTPUT_FORMAT);
1060
1061 printf("\n");
1062 printf("%s\n", _("General usage hints:"));
1063 printf(
1064 " %s\n",
1065 _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as"));
1066 printf(" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\"."));
1067 printf(" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} "
1068 "{thresholds b} ...\""));
1069
1070 printf("\n");
1071 printf("%s\n", _("Examples:"));
1072 printf(" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /");
1073 printf(" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB"));
1074 printf(" %s\n",
1075 "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'");
1076 printf(
1077 " %s\n",
1078 _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex"));
1079 printf(" %s\n\n",
1080 _("are grouped which means the freespace thresholds are applied to all disks together"));
1081 printf(" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar");
1082 printf(" %s\n",
1083 _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M"));
1084
1085 printf(UT_SUPPORT);
1086}
1046 1087
1047void 1088void print_usage(void) {
1048get_stats (struct parameter_list *p, struct fs_usage *fsp) { 1089 printf("%s\n", _("Usage:"));
1049 struct parameter_list *p_list; 1090 printf(" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c "
1050 struct fs_usage tmpfsp; 1091 "absolute_limit|-c percentage_limit%% | -K "
1051 int first = 1; 1092 "inode_percentage_limit } {-p path | -x device}\n",
1093 progname);
1094 printf("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n");
1095 printf("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n");
1096}
1052 1097
1053 if (p->group == NULL) { 1098bool stat_path(parameter_list_elem *parameters, bool ignore_missing) {
1054 get_path_stats(p,fsp); 1099 /* Stat entry to check that dir exists and is accessible */
1055 } else { 1100 if (verbose >= 3) {
1056 /* find all group members */ 1101 printf("calling stat on %s\n", parameters->name);
1057 for (p_list = path_select_list; p_list; p_list=p_list->name_next) { 1102 }
1058#ifdef __CYGWIN__ 1103
1059 if (strncmp(p_list->name, "/cygdrive/", 10) != 0) 1104 struct stat stat_buf = {0};
1060 continue; 1105 if (stat(parameters->name, &stat_buf)) {
1061#endif 1106 if (verbose >= 3) {
1062 if (p_list->group && ! (strcmp(p_list->group, p->group))) { 1107 printf("stat failed on %s\n", parameters->name);
1063 if (! stat_path(p_list)) 1108 }
1064 continue; 1109 if (ignore_missing) {
1065 get_fs_usage (p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp); 1110 return false;
1066 get_path_stats(p_list, &tmpfsp); 1111 }
1067 if (verbose >= 3) 1112 printf("DISK %s - ", _("CRITICAL"));
1068 printf("Group %s: adding %lu blocks sized %lu, (%s) used_units=%lu free_units=%lu total_units=%lu mult=%lu\n", 1113 die(STATE_CRITICAL, _("%s %s: %s\n"), parameters->name, _("is not accessible"),
1069 p_list->group, 1114 strerror(errno));
1070 tmpfsp.fsu_blocks, 1115 }
1071 tmpfsp.fsu_blocksize, 1116
1072 p_list->best_match->me_mountdir, 1117 return true;
1073 p_list->dused_units, 1118}
1074 p_list->dfree_units,
1075 p_list->dtotal_units,
1076 mult);
1077
1078 /* prevent counting the first FS of a group twice since its parameter_list entry
1079 * is used to carry the information of all file systems of the entire group */
1080 if (! first) {
1081 p->total += p_list->total;
1082 p->available += p_list->available;
1083 p->available_to_root += p_list->available_to_root;
1084 p->used += p_list->used;
1085
1086 p->dused_units += p_list->dused_units;
1087 p->dfree_units += p_list->dfree_units;
1088 p->dtotal_units += p_list->dtotal_units;
1089 p->inodes_total += p_list->inodes_total;
1090 p->inodes_free += p_list->inodes_free;
1091 p->inodes_free_to_root += p_list->inodes_free_to_root;
1092 p->inodes_used += p_list->inodes_used;
1093 }
1094 first = 0;
1095 }
1096 if (verbose >= 3)
1097 printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n",
1098 p->group,
1099 p->dused_units,
1100 p->dfree_units,
1101 p->dtotal_units,
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 1119
1120static parameter_list_elem get_path_stats(parameter_list_elem parameters, const struct fs_usage fsp,
1121 bool freespace_ignore_reserved) {
1122 uintmax_t available = fsp.fsu_bavail;
1123 uintmax_t available_to_root = fsp.fsu_bfree;
1124 uintmax_t used = fsp.fsu_blocks - fsp.fsu_bfree;
1125 uintmax_t total;
1126
1127 if (freespace_ignore_reserved) {
1128 /* option activated : we subtract the root-reserved space from the total */
1129 total = fsp.fsu_blocks - available_to_root + available;
1130 } else {
1131 /* default behaviour : take all the blocks into account */
1132 total = fsp.fsu_blocks;
1133 }
1134
1135 parameters.used_bytes = used * fsp.fsu_blocksize;
1136 parameters.free_bytes = available * fsp.fsu_blocksize;
1137 parameters.total_bytes = total * fsp.fsu_blocksize;
1138
1139 /* Free file nodes. Not sure the workaround is required, but in case...*/
1140 parameters.inodes_free = fsp.fsu_ffree;
1141 parameters.inodes_free_to_root = fsp.fsu_ffree; /* Free file nodes for root. */
1142 parameters.inodes_used = fsp.fsu_files - fsp.fsu_ffree;
1143
1144 if (freespace_ignore_reserved) {
1145 /* option activated : we subtract the root-reserved inodes from the total */
1146 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */
1147 /* for others, fsp->fsu_ffree == fsp->fsu_favail */
1148 parameters.inodes_total =
1149 fsp.fsu_files - parameters.inodes_free_to_root + parameters.inodes_free;
1150 } else {
1151 /* default behaviour : take all the inodes into account */
1152 parameters.inodes_total = fsp.fsu_files;
1153 }
1154
1155 return parameters;
1114} 1156}
1115 1157
1116void 1158mp_subcheck evaluate_filesystem(measurement_unit measurement_unit, bool display_inodes_perfdata,
1117get_path_stats (struct parameter_list *p, struct fs_usage *fsp) { 1159 byte_unit unit) {
1118 p->available = fsp->fsu_bavail; 1160 mp_subcheck result = mp_subcheck_init();
1119 p->available_to_root = fsp->fsu_bfree; 1161 result = mp_set_subcheck_default_state(result, STATE_UNKNOWN);
1120 p->used = fsp->fsu_blocks - fsp->fsu_bfree; 1162 xasprintf(&result.output, "%s", measurement_unit.name);
1121 if (freespace_ignore_reserved) { 1163
1122 /* option activated : we subtract the root-reserved space from the total */ 1164 if (!measurement_unit.is_group && measurement_unit.filesystem_type) {
1123 p->total = fsp->fsu_blocks - p->available_to_root + p->available; 1165 xasprintf(&result.output, "%s (%s)", result.output, measurement_unit.filesystem_type);
1124 } else { 1166 }
1125 /* default behaviour : take all the blocks into account */ 1167
1126 p->total = fsp->fsu_blocks; 1168 /* Threshold comparisons */
1127 } 1169
1128 1170 // ===============================
1129 p->dused_units = p->used*fsp->fsu_blocksize/mult; 1171 // Free space absolute values test
1130 p->dfree_units = p->available*fsp->fsu_blocksize/mult; 1172 mp_subcheck freespace_bytes_sc = mp_subcheck_init();
1131 p->dtotal_units = p->total*fsp->fsu_blocksize/mult; 1173 freespace_bytes_sc = mp_set_subcheck_default_state(freespace_bytes_sc, STATE_OK);
1132 /* Free file nodes. Not sure the workaround is required, but in case...*/ 1174
1133 p->inodes_free = fsp->fsu_ffree; 1175 if (unit != Humanized) {
1134 p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */ 1176 xasprintf(&freespace_bytes_sc.output, "Free space absolute: %ju%s (of %ju%s)",
1135 p->inodes_used = fsp->fsu_files - fsp->fsu_ffree; 1177 (uintmax_t)(measurement_unit.free_bytes / unit), get_unit_string(unit),
1136 if (freespace_ignore_reserved) { 1178 (uintmax_t)(measurement_unit.total_bytes / unit), get_unit_string(unit));
1137 /* option activated : we subtract the root-reserved inodes from the total */ 1179 } else {
1138 /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */ 1180 xasprintf(&freespace_bytes_sc.output, "Free space absolute: %s (of %s)",
1139 /* for others, fsp->fsu_ffree == fsp->fsu_favail */ 1181 humanize_byte_value(measurement_unit.free_bytes, false),
1140 p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->inodes_free; 1182 humanize_byte_value((unsigned long long)measurement_unit.total_bytes, false));
1141 } else { 1183 }
1142 /* default behaviour : take all the inodes into account */ 1184
1143 p->inodes_total = fsp->fsu_files; 1185 mp_perfdata used_space = perfdata_init();
1144 } 1186 used_space.label = measurement_unit.name;
1145 np_add_name(&seen, p->best_match->me_mountdir); 1187 used_space.value = mp_create_pd_value(measurement_unit.free_bytes);
1188 used_space = mp_set_pd_max_value(used_space, mp_create_pd_value(measurement_unit.total_bytes));
1189 used_space = mp_set_pd_min_value(used_space, mp_create_pd_value(0));
1190 used_space.uom = "B";
1191 used_space = mp_pd_set_thresholds(used_space, measurement_unit.freespace_bytes_thresholds);
1192 freespace_bytes_sc = mp_set_subcheck_state(freespace_bytes_sc, mp_get_pd_status(used_space));
1193
1194 // special case for absolute space thresholds here:
1195 // if absolute values are not set, compute the thresholds from percentage thresholds
1196 mp_thresholds temp_thlds = measurement_unit.freespace_bytes_thresholds;
1197 if (!temp_thlds.critical_is_set &&
1198 measurement_unit.freespace_percent_thresholds.critical_is_set) {
1199 mp_range tmp_range = measurement_unit.freespace_percent_thresholds.critical;
1200
1201 if (!tmp_range.end_infinity) {
1202 tmp_range.end = mp_create_pd_value(mp_get_pd_value(tmp_range.end) / 100 *
1203 measurement_unit.total_bytes);
1204 }
1205
1206 if (!tmp_range.start_infinity) {
1207 tmp_range.start = mp_create_pd_value(mp_get_pd_value(tmp_range.start) / 100 *
1208 measurement_unit.total_bytes);
1209 }
1210 measurement_unit.freespace_bytes_thresholds =
1211 mp_thresholds_set_crit(measurement_unit.freespace_bytes_thresholds, tmp_range);
1212 used_space = mp_pd_set_thresholds(used_space, measurement_unit.freespace_bytes_thresholds);
1213 }
1214
1215 if (!temp_thlds.warning_is_set &&
1216 measurement_unit.freespace_percent_thresholds.warning_is_set) {
1217 mp_range tmp_range = measurement_unit.freespace_percent_thresholds.warning;
1218 if (!tmp_range.end_infinity) {
1219 tmp_range.end = mp_create_pd_value(mp_get_pd_value(tmp_range.end) / 100 *
1220 measurement_unit.total_bytes);
1221 }
1222 if (!tmp_range.start_infinity) {
1223 tmp_range.start = mp_create_pd_value(mp_get_pd_value(tmp_range.start) / 100 *
1224 measurement_unit.total_bytes);
1225 }
1226 measurement_unit.freespace_bytes_thresholds =
1227 mp_thresholds_set_warn(measurement_unit.freespace_bytes_thresholds, tmp_range);
1228 used_space = mp_pd_set_thresholds(used_space, measurement_unit.freespace_bytes_thresholds);
1229 }
1230
1231 mp_add_perfdata_to_subcheck(&freespace_bytes_sc, used_space);
1232 mp_add_subcheck_to_subcheck(&result, freespace_bytes_sc);
1233
1234 // ==========================
1235 // Free space percentage test
1236 mp_subcheck freespace_percent_sc = mp_subcheck_init();
1237 freespace_percent_sc = mp_set_subcheck_default_state(freespace_percent_sc, STATE_OK);
1238
1239 double free_percentage =
1240 calculate_percent(measurement_unit.free_bytes, measurement_unit.total_bytes);
1241 xasprintf(&freespace_percent_sc.output, "Free space percentage: %g%%", free_percentage);
1242
1243 // Using perfdata here just to get to the test result
1244 mp_perfdata free_space_percent_pd = perfdata_init();
1245 free_space_percent_pd.value = mp_create_pd_value(free_percentage);
1246 free_space_percent_pd =
1247 mp_pd_set_thresholds(free_space_percent_pd, measurement_unit.freespace_percent_thresholds);
1248
1249 freespace_percent_sc =
1250 mp_set_subcheck_state(freespace_percent_sc, mp_get_pd_status(free_space_percent_pd));
1251 mp_add_subcheck_to_subcheck(&result, freespace_percent_sc);
1252
1253 // ================
1254 // Free inodes test
1255 // Only ever useful if the number of inodes is static (e.g. ext4),
1256 // not when it is dynamic (e.g btrfs)
1257 // Assumption: if the total number of inodes == 0, we have such a case and just skip the test
1258 if (measurement_unit.inodes_total > 0) {
1259 mp_subcheck freeindodes_percent_sc = mp_subcheck_init();
1260 freeindodes_percent_sc = mp_set_subcheck_default_state(freeindodes_percent_sc, STATE_OK);
1261
1262 double free_inode_percentage =
1263 calculate_percent(measurement_unit.inodes_free, measurement_unit.inodes_total);
1264
1265 if (verbose > 0) {
1266 printf("free inode percentage computed: %g\n", free_inode_percentage);
1267 }
1268
1269 xasprintf(&freeindodes_percent_sc.output, "Inodes free: %g%% (%ju of %ju)",
1270 free_inode_percentage, measurement_unit.inodes_free,
1271 measurement_unit.inodes_total);
1272
1273 mp_perfdata inodes_pd = perfdata_init();
1274 xasprintf(&inodes_pd.label, "%s (inodes)", measurement_unit.name);
1275 inodes_pd = mp_set_pd_value(inodes_pd, measurement_unit.inodes_used);
1276 inodes_pd =
1277 mp_set_pd_max_value(inodes_pd, mp_create_pd_value(measurement_unit.inodes_total));
1278 inodes_pd = mp_set_pd_min_value(inodes_pd, mp_create_pd_value(0));
1279
1280 mp_thresholds absolut_inode_thresholds = measurement_unit.freeinodes_percent_thresholds;
1281
1282 if (absolut_inode_thresholds.critical_is_set) {
1283 absolut_inode_thresholds.critical =
1284 mp_range_multiply(absolut_inode_thresholds.critical,
1285 mp_create_pd_value(measurement_unit.inodes_total / 100));
1286 }
1287 if (absolut_inode_thresholds.warning_is_set) {
1288 absolut_inode_thresholds.warning =
1289 mp_range_multiply(absolut_inode_thresholds.warning,
1290 mp_create_pd_value(measurement_unit.inodes_total / 100));
1291 }
1292
1293 inodes_pd = mp_pd_set_thresholds(inodes_pd, absolut_inode_thresholds);
1294
1295 freeindodes_percent_sc =
1296 mp_set_subcheck_state(freeindodes_percent_sc, mp_get_pd_status(inodes_pd));
1297 if (display_inodes_perfdata) {
1298 mp_add_perfdata_to_subcheck(&freeindodes_percent_sc, inodes_pd);
1299 }
1300 mp_add_subcheck_to_subcheck(&result, freeindodes_percent_sc);
1301 }
1302
1303 return result;
1146} 1304}