diff options
Diffstat (limited to 'plugins/check_disk.c')
-rw-r--r-- | plugins/check_disk.c | 220 |
1 files changed, 77 insertions, 143 deletions
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 | } |