diff options
-rw-r--r-- | configure.in | 84 | ||||
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | plugins/check_disk.c | 220 |
3 files changed, 126 insertions, 182 deletions
diff --git a/configure.in b/configure.in index 24f66d2..78a454f 100644 --- a/configure.in +++ b/configure.in | |||
@@ -30,31 +30,6 @@ AC_MINIX | |||
30 | AC_PROG_MAKE_SET | 30 | AC_PROG_MAKE_SET |
31 | AC_PROG_AWK | 31 | AC_PROG_AWK |
32 | 32 | ||
33 | # Check for SunOS statfs brokenness wrt partitions 2GB and larger. | ||
34 | # If <sys/vfs.h> exists and struct statfs has a member named f_spare, | ||
35 | # enable the work-around code in fsusage.c. | ||
36 | AC_MSG_CHECKING([for statfs that truncates block counts]) | ||
37 | AC_CACHE_VAL(fu_cv_sys_truncating_statfs, | ||
38 | [AC_TRY_COMPILE([ | ||
39 | #if !defined(sun) && !defined(__sun) | ||
40 | choke -- this is a workaround for a Sun-specific problem | ||
41 | #endif | ||
42 | #include <sys/types.h> | ||
43 | #include <sys/vfs.h>], | ||
44 | [struct statfs t; long c = *(t.f_spare);], | ||
45 | fu_cv_sys_truncating_statfs=yes | ||
46 | AC_MSG_RESULT(yes), | ||
47 | fu_cv_sys_truncating_statfs=no | ||
48 | AC_MSG_RESULT(no), | ||
49 | )]) | ||
50 | if test $fu_cv_sys_truncating_statfs = yes; then | ||
51 | AC_DEFINE(STATFS_TRUNCATES_BLOCK_COUNTS, 1, | ||
52 | [ Define if the block counts reported by statfs may be truncated to 2GB | ||
53 | and the correct values may be stored in the f_spare array. | ||
54 | (SunOS 4.1.2, 4.1.3, and 4.1.3_U1 are reported to have this problem. | ||
55 | SunOS 4.1.1 seems not to be affected.)]) | ||
56 | fi | ||
57 | |||
58 | saved_srcdir=$srcdir | 33 | saved_srcdir=$srcdir |
59 | srcdir=$srcdir/lib | 34 | srcdir=$srcdir/lib |
60 | test -f $srcdir/getloadavg.c \ | 35 | test -f $srcdir/getloadavg.c \ |
@@ -484,19 +459,49 @@ AC_HEADER_TIME | |||
484 | AC_HEADER_SYS_WAIT | 459 | AC_HEADER_SYS_WAIT |
485 | AC_CHECK_HEADERS(signal.h strings.h string.h syslog.h unistd.h uio.h errno.h regex.h sys/types.h sys/time.h sys/socket.h sys/loadavg.h) | 460 | AC_CHECK_HEADERS(signal.h strings.h string.h syslog.h unistd.h uio.h errno.h regex.h sys/types.h sys/time.h sys/socket.h sys/loadavg.h) |
486 | AC_CHECK_HEADERS(stdarg.h sys/unistd.h unistd.h ctype.h stdlib.h) | 461 | AC_CHECK_HEADERS(stdarg.h sys/unistd.h unistd.h ctype.h stdlib.h) |
462 | AC_CHECK_HEADERS(limits.h sys/param.h sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h fcntl.h sys/statfs.h sys/dustat.h sys/statvfs.h) | ||
463 | |||
464 | # Define HAVE_INTTYPES_H if <inttypes.h> exists, | ||
465 | # doesn't clash with <sys/types.h>, and declares uintmax_t. | ||
466 | |||
467 | AC_CACHE_CHECK([for inttypes.h], jm_ac_cv_header_inttypes_h, | ||
468 | [AC_TRY_COMPILE( | ||
469 | [#include <sys/types.h> | ||
470 | #include <inttypes.h>], | ||
471 | [uintmax_t i = (uintmax_t) -1;], | ||
472 | jm_ac_cv_header_inttypes_h=yes, | ||
473 | jm_ac_cv_header_inttypes_h=no)]) | ||
474 | |||
475 | if test $jm_ac_cv_header_inttypes_h = yes; then | ||
476 | AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1, | ||
477 | [Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, | ||
478 | and declares uintmax_t. ]) | ||
479 | fi | ||
487 | 480 | ||
488 | dnl Linux | 481 | # Check for SunOS statfs brokenness wrt partitions 2GB and larger. |
489 | AC_CHECK_HEADERS(sys/vfs.h, | 482 | # If <sys/vfs.h> exists and struct statfs has a member named f_spare, |
490 | [AC_TRY_COMPILE([#include <sys/vfs.h>], | 483 | # enable the work-around code in fsusage.c. |
491 | [struct statfs buf; long foo; statfs ("/", &buf); foo = buf.f_namelen;], | 484 | AC_MSG_CHECKING([for statfs that truncates block counts]) |
492 | [AC_DEFINE(HAVE_STRUCT_STATFS,1,[Define if statfs struct can be found])])]) | 485 | AC_CACHE_VAL(fu_cv_sys_truncating_statfs, |
493 | 486 | [AC_TRY_COMPILE([ | |
494 | dnl FreeBSD | 487 | #if !defined(sun) && !defined(__sun) |
495 | AC_CHECK_HEADERS(sys/param.h sys/mount.h, | 488 | choke -- this is a workaround for a Sun-specific problem |
496 | [AC_TRY_COMPILE([#include <sys/param.h> | 489 | #endif |
497 | #include <sys/mount.h>], | 490 | #include <sys/types.h> |
498 | [struct statfs buf; int foo; statfs ("/", &buf); foo = buf.f_flags;], | 491 | #include <sys/vfs.h>], |
499 | [AC_DEFINE(HAVE_STRUCT_STATFS,1,[Define if statfs struct can be found])])]) | 492 | [struct statfs t; long c = *(t.f_spare);], |
493 | fu_cv_sys_truncating_statfs=yes | ||
494 | AC_MSG_RESULT(yes), | ||
495 | fu_cv_sys_truncating_statfs=no | ||
496 | AC_MSG_RESULT(no), | ||
497 | )]) | ||
498 | if test $fu_cv_sys_truncating_statfs = yes; then | ||
499 | AC_DEFINE(STATFS_TRUNCATES_BLOCK_COUNTS, 1, | ||
500 | [ Define if the block counts reported by statfs may be truncated to 2GB | ||
501 | and the correct values may be stored in the f_spare array. | ||
502 | (SunOS 4.1.2, 4.1.3, and 4.1.3_U1 are reported to have this problem. | ||
503 | SunOS 4.1.1 seems not to be affected.)]) | ||
504 | fi | ||
500 | 505 | ||
501 | dnl Checks for typedefs, structures, and compiler characteristics. | 506 | dnl Checks for typedefs, structures, and compiler characteristics. |
502 | AC_C_CONST | 507 | AC_C_CONST |
@@ -955,6 +960,11 @@ fi | |||
955 | 960 | ||
956 | AC_DEFINE_UNQUOTED(DF_COMMAND,"$with_df_command",[path and args for df command]) | 961 | AC_DEFINE_UNQUOTED(DF_COMMAND,"$with_df_command",[path and args for df command]) |
957 | 962 | ||
963 | dnl jm_LIST_MOUNTED_FILESYSTEMS([list_mounted_fs=yes], [list_mounted_fs=no]) | ||
964 | jm_FSTYPENAME | ||
965 | jm_FILE_SYSTEM_USAGE([space=yes], [space=no]) | ||
966 | jm_AFS | ||
967 | |||
958 | AC_PATH_PROG(PATH_TO_PING,ping) | 968 | AC_PATH_PROG(PATH_TO_PING,ping) |
959 | AC_PATH_PROG(PATH_TO_PING6,ping6) | 969 | AC_PATH_PROG(PATH_TO_PING6,ping6) |
960 | 970 | ||
diff --git a/lib/Makefile.am b/lib/Makefile.am index 9a26e41..6353d01 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | noinst_LIBRARIES = libnagiosplug.a | 3 | noinst_LIBRARIES = libnagiosplug.a |
4 | 4 | ||
5 | noinst_HEADERS = getopt.h | 5 | noinst_HEADERS = getopt.h fsusage.h mountlist.h |
6 | 6 | ||
7 | libnagiosplug_a_SOURCES = getopt.c getopt1.c getloadavg.c snprintf.c | 7 | libnagiosplug_a_SOURCES = getopt.c getopt1.c getloadavg.c snprintf.c fsusage.c mountlist.c |
8 | 8 | ||
9 | INCLUDES = -I$(srcdir) | 9 | INCLUDES = -I$(srcdir) |
diff --git a/plugins/check_disk.c b/plugins/check_disk.c index 485ae82..2558f6d 100644 --- a/plugins/check_disk.c +++ b/plugins/check_disk.c | |||
@@ -55,18 +55,81 @@ const char *options = "\ | |||
55 | Print version information\n"; | 55 | Print version information\n"; |
56 | 56 | ||
57 | #include "common.h" | 57 | #include "common.h" |
58 | #if HAVE_INTTYPES_H | ||
59 | # include <inttypes.h> | ||
60 | #endif | ||
61 | #include <assert.h> | ||
58 | #include "popen.h" | 62 | #include "popen.h" |
59 | #include "utils.h" | 63 | #include "utils.h" |
60 | #include <stdarg.h> | 64 | #include <stdarg.h> |
65 | #include "../lib/fsusage.h" | ||
66 | |||
67 | /* If nonzero, show inode information. */ | ||
68 | static int inode_format; | ||
69 | |||
70 | /* If nonzero, show even filesystems with zero size or | ||
71 | uninteresting types. */ | ||
72 | static int show_all_fs; | ||
73 | |||
74 | /* If nonzero, show only local filesystems. */ | ||
75 | static int show_local_fs; | ||
76 | |||
77 | /* If nonzero, output data for each filesystem corresponding to a | ||
78 | command line argument -- even if it's a dummy (automounter) entry. */ | ||
79 | static int show_listed_fs; | ||
80 | |||
81 | /* If positive, the units to use when printing sizes; | ||
82 | if negative, the human-readable base. */ | ||
83 | static int output_block_size; | ||
84 | |||
85 | /* If nonzero, invoke the `sync' system call before getting any usage data. | ||
86 | Using this option can make df very slow, especially with many or very | ||
87 | busy disks. Note that this may make a difference on some systems -- | ||
88 | SunOs4.1.3, for one. It is *not* necessary on Linux. */ | ||
89 | static int require_sync = 0; | ||
90 | |||
91 | /* A filesystem type to display. */ | ||
92 | |||
93 | struct fs_type_list | ||
94 | { | ||
95 | char *fs_name; | ||
96 | struct fs_type_list *fs_next; | ||
97 | }; | ||
98 | |||
99 | /* Linked list of filesystem types to display. | ||
100 | If `fs_select_list' is NULL, list all types. | ||
101 | This table is generated dynamically from command-line options, | ||
102 | rather than hardcoding into the program what it thinks are the | ||
103 | valid filesystem types; let the user specify any filesystem type | ||
104 | they want to, and if there are any filesystems of that type, they | ||
105 | will be shown. | ||
106 | |||
107 | Some filesystem types: | ||
108 | 4.2 4.3 ufs nfs swap ignore io vm efs dbg */ | ||
109 | |||
110 | static struct fs_type_list *fs_select_list; | ||
111 | |||
112 | /* Linked list of filesystem types to omit. | ||
113 | If the list is empty, don't exclude any types. */ | ||
114 | |||
115 | static struct fs_type_list *fs_exclude_list; | ||
116 | |||
117 | /* Linked list of mounted filesystems. */ | ||
118 | static struct mount_entry *mount_list; | ||
119 | |||
120 | /* For long options that have no equivalent short option, use a | ||
121 | non-character as a pseudo short option, starting with CHAR_MAX + 1. */ | ||
122 | enum | ||
123 | { | ||
124 | SYNC_OPTION = CHAR_MAX + 1, | ||
125 | NO_SYNC_OPTION, | ||
126 | BLOCK_SIZE_OPTION | ||
127 | }; | ||
61 | 128 | ||
62 | #ifdef _AIX | 129 | #ifdef _AIX |
63 | #pragma alloca | 130 | #pragma alloca |
64 | #endif | 131 | #endif |
65 | 132 | ||
66 | #if HAVE_INTTYPES_H | ||
67 | # include <inttypes.h> | ||
68 | #endif | ||
69 | |||
70 | int process_arguments (int, char **); | 133 | int process_arguments (int, char **); |
71 | int validate_arguments (void); | 134 | int validate_arguments (void); |
72 | int check_disk (int usp, int free_disk); | 135 | int check_disk (int usp, int free_disk); |
@@ -99,151 +162,22 @@ main (int argc, char **argv) | |||
99 | char mntp[MAX_INPUT_BUFFER]; | 162 | char mntp[MAX_INPUT_BUFFER]; |
100 | char *output = ""; | 163 | char *output = ""; |
101 | 164 | ||
102 | #ifdef HAVE_STRUCT_STATFS | 165 | struct fs_usage fsp; |
103 | #ifdef HAVE_SYS_VFS_H | 166 | char *disk; |
104 | #include <sys/vfs.h> | ||
105 | #else | ||
106 | #include <sys/param.h> | ||
107 | #include <sys/mount.h> | ||
108 | #endif | ||
109 | struct statfs buf; | ||
110 | #endif | ||
111 | 167 | ||
112 | if (process_arguments (argc, argv) != OK) | 168 | if (process_arguments (argc, argv) != OK) |
113 | usage ("Could not parse arguments\n"); | 169 | usage ("Could not parse arguments\n"); |
114 | 170 | ||
115 | #ifdef HAVE_STRUCT_STATFS | 171 | get_fs_usage (path, disk, &fsp); |
116 | |||
117 | if (statfs (path, &buf) == -1) { | ||
118 | switch (errno) | ||
119 | { | ||
120 | #ifdef ENOTDIR | ||
121 | case ENOTDIR: | ||
122 | terminate (STATE_UNKNOWN, "A component of the path prefix is not a directory.\n"); | ||
123 | #endif | ||
124 | #ifdef ENAMETOOLONG | ||
125 | case ENAMETOOLONG: | ||
126 | terminate (STATE_UNKNOWN, "path is too long.\n"); | ||
127 | #endif | ||
128 | #ifdef ENOENT | ||
129 | case ENOENT: | ||
130 | terminate (STATE_UNKNOWN, "The file referred to by path does not exist.\n"); | ||
131 | #endif | ||
132 | #ifdef EACCES | ||
133 | case EACCES: | ||
134 | terminate (STATE_UNKNOWN, "Search permission is denied for a component of the path prefix of path.\n"); | ||
135 | #endif | ||
136 | #ifdef ELOOP | ||
137 | case ELOOP: | ||
138 | terminate (STATE_UNKNOWN, "Too many symbolic links were encountered in translating path.\n"); | ||
139 | #endif | ||
140 | #ifdef EFAULT | ||
141 | case EFAULT: | ||
142 | terminate (STATE_UNKNOWN, "Buf or path points to an invalid address.\n"); | ||
143 | #endif | ||
144 | #ifdef EIO | ||
145 | case EIO: | ||
146 | terminate (STATE_UNKNOWN, "An I/O error occurred while reading from or writing to the file system.\n"); | ||
147 | #endif | ||
148 | #ifdef ENOMEM | ||
149 | case ENOMEM: | ||
150 | terminate (STATE_UNKNOWN, "Insufficient kernel memory was available.\n"); | ||
151 | #endif | ||
152 | #ifdef ENOSYS | ||
153 | case ENOSYS: | ||
154 | terminate (STATE_UNKNOWN, "The filesystem path is on does not support statfs.\n"); | ||
155 | #endif | ||
156 | } | ||
157 | } | ||
158 | 172 | ||
159 | usp = (buf.f_blocks - buf.f_bavail) / buf.f_blocks; | 173 | usp = (fsp.fsu_blocks - fsp.fsu_bavail) / fsp.fsu_blocks; |
160 | disk_result = check_disk (usp, buf.f_bavail); | 174 | disk_result = check_disk (usp, fsp.fsu_bavail); |
161 | result = disk_result; | 175 | result = disk_result; |
162 | asprintf (&output, "%ld of %ld kB free (%ld-byte blocks)", | 176 | asprintf (&output, "%llu of %llu kB (%2.0f%%) free (%d-byte blocks)", |
163 | buf.f_bavail*buf.f_bsize/1024, buf.f_blocks*buf.f_bsize/1024, buf.f_bsize); | 177 | fsp.fsu_bavail*fsp.fsu_blocksize/1024, |
164 | 178 | fsp.fsu_blocks*fsp.fsu_blocksize/1024, | |
165 | #else | 179 | (double)fsp.fsu_bavail*100/fsp.fsu_blocks, |
166 | 180 | fsp.fsu_blocksize); | |
167 | asprintf (&command_line, "%s %s", DF_COMMAND, path); | ||
168 | |||
169 | if (verbose>0) | ||
170 | printf ("%s ==> ", command_line); | ||
171 | |||
172 | child_process = spopen (command_line); | ||
173 | if (child_process == NULL) { | ||
174 | printf ("Could not open pipe: %s\n", command_line); | ||
175 | return STATE_UNKNOWN; | ||
176 | } | ||
177 | |||
178 | child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); | ||
179 | if (child_stderr == NULL) { | ||
180 | printf ("Could not open stderr for %s\n", command_line); | ||
181 | } | ||
182 | |||
183 | while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { | ||
184 | |||
185 | if (!index (input_buffer, '/')) | ||
186 | continue; | ||
187 | |||
188 | /* Fixes AIX /proc fs which lists - for size values */ | ||
189 | if (strstr (input_buffer, "/proc ") == input_buffer) | ||
190 | continue; | ||
191 | |||
192 | if (sscanf (input_buffer, "%s %d %d %d %d%% %s", file_system, | ||
193 | &total_disk, &used_disk, &free_disk, &usp, mntp) == 6 || | ||
194 | sscanf (input_buffer, "%s %*s %d %d %d %d%% %s", file_system, | ||
195 | &total_disk, &used_disk, &free_disk, &usp, mntp) == 6) { | ||
196 | |||
197 | if (strcmp(exclude_device,file_system) == 0 || | ||
198 | strcmp(exclude_device,mntp) == 0) { | ||
199 | if (verbose>0) | ||
200 | printf ("ignoring %s.", file_system); | ||
201 | continue; | ||
202 | } | ||
203 | |||
204 | disk_result = check_disk (usp, free_disk); | ||
205 | |||
206 | if (strcmp (file_system, "none") == 0) | ||
207 | strncpy (file_system, mntp, MAX_INPUT_BUFFER-1); | ||
208 | |||
209 | if (disk_result==STATE_OK && erronly && !verbose) | ||
210 | continue; | ||
211 | |||
212 | if (disk_result!=STATE_OK || verbose>=0) | ||
213 | asprintf (&output, "%s [%d kB (%d%%) free on %s]", output, | ||
214 | free_disk, 100 - usp, display_mntp ? mntp : file_system); | ||
215 | |||
216 | result = max_state (result, disk_result); | ||
217 | } | ||
218 | |||
219 | else { | ||
220 | printf ("Unable to read output:\n%s\n%s\n", command_line, input_buffer); | ||
221 | return result; | ||
222 | } | ||
223 | |||
224 | } | ||
225 | |||
226 | /* If we get anything on stderr, at least set warning */ | ||
227 | while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { | ||
228 | if (result != STATE_CRITICAL) { | ||
229 | result = STATE_WARNING; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | /* close stderr */ | ||
234 | if (child_stderr) | ||
235 | (void) fclose (child_stderr); | ||
236 | |||
237 | /* close the pipe */ | ||
238 | if (spclose(child_process)!=0 && result!=STATE_CRITICAL) | ||
239 | result = STATE_WARNING; | ||
240 | |||
241 | if (usp < 0) | ||
242 | terminate (result, "Disk \"%s\" not mounted or nonexistant\n", path); | ||
243 | else if (result == STATE_UNKNOWN) | ||
244 | terminate (result, "Unable to read output\n%s\n%s\n", command_line, input_buffer); | ||
245 | |||
246 | #endif | ||
247 | 181 | ||
248 | terminate (result, "DISK %s %s\n", state_text (result), output); | 182 | terminate (result, "DISK %s %s\n", state_text (result), output); |
249 | } | 183 | } |