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.c220
1 files changed, 77 insertions, 143 deletions
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index 485ae822..2558f6d3 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. */
68static int inode_format;
69
70/* If nonzero, show even filesystems with zero size or
71 uninteresting types. */
72static int show_all_fs;
73
74/* If nonzero, show only local filesystems. */
75static 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. */
79static int show_listed_fs;
80
81/* If positive, the units to use when printing sizes;
82 if negative, the human-readable base. */
83static 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. */
89static int require_sync = 0;
90
91/* A filesystem type to display. */
92
93struct 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
110static 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
115static struct fs_type_list *fs_exclude_list;
116
117/* Linked list of mounted filesystems. */
118static 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. */
122enum
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
70int process_arguments (int, char **); 133int process_arguments (int, char **);
71int validate_arguments (void); 134int validate_arguments (void);
72int check_disk (int usp, int free_disk); 135int 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}