30 |
|
#include <string.h> |
31 |
|
#include <time.h> |
32 |
|
#include "statgrab.h" |
33 |
+ |
#include "vector.h" |
34 |
|
|
35 |
|
#ifdef SOLARIS |
36 |
|
#include <sys/mnttab.h> |
62 |
|
#include <sys/ucred.h> |
63 |
|
#include <sys/mount.h> |
64 |
|
#endif |
65 |
< |
#ifdef FREEBSD |
65 |
> |
#if defined(FREEBSD) || defined(DFBSD) |
66 |
|
#include <sys/dkstat.h> |
67 |
|
#include <devstat.h> |
68 |
|
#define VALID_FS_TYPES {"hpfs", "msdosfs", "ntfs", "udf", "ext2fs", \ |
76 |
|
"ntfs"} |
77 |
|
#endif |
78 |
|
|
79 |
< |
#define START_VAL 1 |
79 |
> |
static char *copy_string(char **dest, const char *src) { |
80 |
> |
char *new; |
81 |
|
|
82 |
< |
char *copy_string(char *orig_ptr, const char *newtext){ |
82 |
> |
new = realloc(*dest, strlen(src) + 1); |
83 |
> |
if (new == NULL) { |
84 |
> |
return NULL; |
85 |
> |
} |
86 |
|
|
87 |
< |
/* Maybe free if not NULL, and strdup rather than realloc and strcpy? */ |
88 |
< |
orig_ptr=realloc(orig_ptr, (1+strlen(newtext))); |
89 |
< |
if(orig_ptr==NULL){ |
90 |
< |
return NULL; |
86 |
< |
} |
87 |
< |
strcpy(orig_ptr, newtext); |
87 |
> |
strcpy(new, src); |
88 |
> |
*dest = new; |
89 |
> |
return new; |
90 |
> |
} |
91 |
|
|
92 |
< |
return orig_ptr; |
92 |
> |
static void disk_stat_init(disk_stat_t *d) { |
93 |
> |
d->device_name = NULL; |
94 |
> |
d->fs_type = NULL; |
95 |
> |
d->mnt_point = NULL; |
96 |
|
} |
97 |
|
|
98 |
< |
|
99 |
< |
void init_disk_stat(int start, int end, disk_stat_t *disk_stats){ |
100 |
< |
|
101 |
< |
for(disk_stats+=start; start<=end; start++){ |
96 |
< |
disk_stats->device_name=NULL; |
97 |
< |
disk_stats->fs_type=NULL; |
98 |
< |
disk_stats->mnt_point=NULL; |
99 |
< |
|
100 |
< |
disk_stats++; |
101 |
< |
} |
98 |
> |
static void disk_stat_destroy(disk_stat_t *d) { |
99 |
> |
free(d->device_name); |
100 |
> |
free(d->fs_type); |
101 |
> |
free(d->mnt_point); |
102 |
|
} |
103 |
|
|
104 |
|
int is_valid_fs_type(const char *type) { |
114 |
|
} |
115 |
|
|
116 |
|
disk_stat_t *get_disk_stats(int *entries){ |
117 |
+ |
VECTOR_DECLARE_STATIC(disk_stats, disk_stat_t, 10, |
118 |
+ |
disk_stat_init, disk_stat_destroy); |
119 |
|
|
118 |
– |
static disk_stat_t *disk_stats; |
119 |
– |
static int watermark=-1; |
120 |
– |
|
120 |
|
int valid_type; |
121 |
|
int num_disks=0; |
122 |
|
#if defined(LINUX) || defined (SOLARIS) || defined(CYGWIN) |
138 |
|
struct statfs *mp; |
139 |
|
#endif |
140 |
|
|
142 |
– |
if(watermark==-1){ |
143 |
– |
disk_stats=malloc(START_VAL * sizeof(disk_stat_t)); |
144 |
– |
if(disk_stats==NULL){ |
145 |
– |
return NULL; |
146 |
– |
} |
147 |
– |
watermark=START_VAL; |
148 |
– |
init_disk_stat(0, watermark-1, disk_stats); |
149 |
– |
} |
141 |
|
#ifdef ALLBSD |
142 |
|
nummnt=getmntinfo(&mp , MNT_LOCAL); |
143 |
|
if (nummnt<=0){ |
172 |
|
#endif |
173 |
|
|
174 |
|
if(valid_type){ |
175 |
< |
if(num_disks>watermark-1){ |
176 |
< |
disk_ptr=disk_stats; |
186 |
< |
if((disk_stats=realloc(disk_stats, (watermark*2 * sizeof(disk_stat_t))))==NULL){ |
187 |
< |
disk_stats=disk_ptr; |
188 |
< |
return NULL; |
189 |
< |
} |
190 |
< |
|
191 |
< |
watermark=watermark*2; |
192 |
< |
init_disk_stat(num_disks, watermark-1, disk_stats); |
175 |
> |
if (VECTOR_RESIZE(disk_stats, num_disks + 1) < 0) { |
176 |
> |
return NULL; |
177 |
|
} |
194 |
– |
|
178 |
|
disk_ptr=disk_stats+num_disks; |
179 |
+ |
|
180 |
|
#ifdef ALLBSD |
181 |
< |
if((disk_ptr->device_name=copy_string(disk_ptr->device_name, mp->f_mntfromname))==NULL){ |
181 |
> |
if (copy_string(&disk_ptr->device_name, mp->f_mntfromname) == NULL) { |
182 |
|
return NULL; |
183 |
|
} |
184 |
< |
|
201 |
< |
if((disk_ptr->fs_type=copy_string(disk_ptr->fs_type, mp->f_fstypename))==NULL){ |
184 |
> |
if (copy_string(&disk_ptr->fs_type, mp->f_fstypename) == NULL) { |
185 |
|
return NULL; |
186 |
|
} |
187 |
< |
|
205 |
< |
if((disk_ptr->mnt_point=copy_string(disk_ptr->mnt_point, mp->f_mntonname))==NULL){ |
187 |
> |
if (copy_string(&disk_ptr->mnt_point, mp->f_mntonname) == NULL) { |
188 |
|
return NULL; |
189 |
|
} |
190 |
|
|
198 |
|
disk_ptr->used_inodes=disk_ptr->total_inodes-disk_ptr->free_inodes; |
199 |
|
#endif |
200 |
|
#if defined(LINUX) || defined(CYGWIN) |
201 |
< |
if((disk_ptr->device_name=copy_string(disk_ptr->device_name, mp->mnt_fsname))==NULL){ |
201 |
> |
if (copy_string(&disk_ptr->device_name, mp->mnt_fsname) == NULL) { |
202 |
|
return NULL; |
203 |
|
} |
204 |
|
|
205 |
< |
if((disk_ptr->fs_type=copy_string(disk_ptr->fs_type, mp->mnt_type))==NULL){ |
205 |
> |
if (copy_string(&disk_ptr->fs_type, mp->mnt_type) == NULL) { |
206 |
|
return NULL; |
207 |
|
} |
208 |
|
|
209 |
< |
if((disk_ptr->mnt_point=copy_string(disk_ptr->mnt_point, mp->mnt_dir))==NULL){ |
209 |
> |
if (copy_string(&disk_ptr->mnt_point, mp->mnt_dir) == NULL) { |
210 |
|
return NULL; |
211 |
|
} |
212 |
|
disk_ptr->size = (long long)fs.f_bsize * (long long)fs.f_blocks; |
220 |
|
#endif |
221 |
|
|
222 |
|
#ifdef SOLARIS |
241 |
– |
/* Memory leak in event of realloc failing */ |
223 |
|
/* Maybe make this char[bigenough] and do strncpy's and put a null in the end? |
224 |
|
* Downside is its a bit hungry for a lot of mounts, as MNT_MAX_SIZE would prob |
225 |
|
* be upwards of a k each |
226 |
|
*/ |
227 |
< |
if((disk_ptr->device_name=copy_string(disk_ptr->device_name, mp.mnt_special))==NULL){ |
227 |
> |
if (copy_string(&disk_ptr->device_name, mp.mnt_special) == NULL) { |
228 |
|
return NULL; |
229 |
|
} |
230 |
|
|
231 |
< |
if((disk_ptr->fs_type=copy_string(disk_ptr->fs_type, mp.mnt_fstype))==NULL){ |
231 |
> |
if (copy_string(&disk_ptr->fs_type, mp.mnt_fstype) == NULL) { |
232 |
|
return NULL; |
233 |
|
} |
234 |
|
|
235 |
< |
if((disk_ptr->mnt_point=copy_string(disk_ptr->mnt_point, mp.mnt_mountp))==NULL){ |
235 |
> |
if (copy_string(&disk_ptr->mnt_point, mp.mnt_mountp) == NULL) { |
236 |
|
return NULL; |
237 |
|
} |
238 |
|
|
262 |
|
return disk_stats; |
263 |
|
|
264 |
|
} |
284 |
– |
void diskio_stat_init(int start, int end, diskio_stat_t *diskio_stats){ |
265 |
|
|
266 |
< |
for(diskio_stats+=start; start<end; start++){ |
267 |
< |
diskio_stats->disk_name=NULL; |
288 |
< |
|
289 |
< |
diskio_stats++; |
290 |
< |
} |
266 |
> |
static void diskio_stat_init(diskio_stat_t *d) { |
267 |
> |
d->disk_name = NULL; |
268 |
|
} |
269 |
|
|
270 |
< |
diskio_stat_t *diskio_stat_malloc(int needed_entries, int *cur_entries, diskio_stat_t *diskio_stats){ |
271 |
< |
|
295 |
< |
if(diskio_stats==NULL){ |
296 |
< |
|
297 |
< |
if((diskio_stats=malloc(needed_entries * sizeof(diskio_stat_t)))==NULL){ |
298 |
< |
return NULL; |
299 |
< |
} |
300 |
< |
diskio_stat_init(0, needed_entries, diskio_stats); |
301 |
< |
*cur_entries=needed_entries; |
302 |
< |
|
303 |
< |
return diskio_stats; |
304 |
< |
} |
305 |
< |
|
306 |
< |
|
307 |
< |
if(*cur_entries<needed_entries){ |
308 |
< |
diskio_stats=realloc(diskio_stats, (sizeof(diskio_stat_t)*needed_entries)); |
309 |
< |
if(diskio_stats==NULL){ |
310 |
< |
return NULL; |
311 |
< |
} |
312 |
< |
diskio_stat_init(*cur_entries, needed_entries, diskio_stats); |
313 |
< |
*cur_entries=needed_entries; |
314 |
< |
} |
315 |
< |
|
316 |
< |
return diskio_stats; |
270 |
> |
static void diskio_stat_destroy(diskio_stat_t *d) { |
271 |
> |
free(d->disk_name); |
272 |
|
} |
273 |
|
|
274 |
< |
static diskio_stat_t *diskio_stats=NULL; |
275 |
< |
static int num_diskio=0; |
274 |
> |
VECTOR_DECLARE_STATIC(diskio_stats, diskio_stat_t, 10, |
275 |
> |
diskio_stat_init, diskio_stat_destroy); |
276 |
|
|
277 |
|
#ifdef LINUX |
278 |
|
typedef struct { |
282 |
|
#endif |
283 |
|
|
284 |
|
diskio_stat_t *get_diskio_stats(int *entries){ |
285 |
< |
|
331 |
< |
static int sizeof_diskio_stats=0; |
285 |
> |
int num_diskio; |
286 |
|
#ifndef LINUX |
287 |
|
diskio_stat_t *diskio_stats_ptr; |
288 |
|
#endif |
297 |
|
char *line_ptr; |
298 |
|
int major, minor; |
299 |
|
int has_pp_stats = 1; |
300 |
< |
static partition *parts = NULL; |
347 |
< |
static int alloc_parts = 0; |
300 |
> |
VECTOR_DECLARE_STATIC(parts, partition, 16, NULL, NULL); |
301 |
|
int i, n; |
302 |
|
time_t now; |
303 |
|
const char *format; |
304 |
|
#endif |
305 |
< |
#ifdef FREEBSD |
305 |
> |
#if defined(FREEBSD) || defined(DFBSD) |
306 |
|
static struct statinfo stats; |
307 |
|
static int stats_init = 0; |
308 |
|
int counter; |
315 |
|
struct disk_sysctl *stats; |
316 |
|
#endif |
317 |
|
#ifdef OPENBSD |
318 |
+ |
int diskcount; |
319 |
+ |
char *disknames, *name, *bufpp; |
320 |
+ |
char **dk_name; |
321 |
|
struct diskstats *stats; |
322 |
|
#endif |
323 |
|
#ifdef NETBSD |
334 |
|
|
335 |
|
num_diskio=0; |
336 |
|
|
337 |
+ |
#ifdef OPENBSD |
338 |
+ |
mib[0] = CTL_HW; |
339 |
+ |
mib[1] = HW_DISKCOUNT; |
340 |
+ |
|
341 |
+ |
size = sizeof(diskcount); |
342 |
+ |
if (sysctl(mib, MIBSIZE, &diskcount, &size, NULL, 0) < 0) { |
343 |
+ |
return NULL; |
344 |
+ |
} |
345 |
+ |
|
346 |
+ |
mib[0] = CTL_HW; |
347 |
+ |
mib[1] = HW_DISKNAMES; |
348 |
+ |
|
349 |
+ |
if (sysctl(mib, MIBSIZE, NULL, &size, NULL, 0) < 0) { |
350 |
+ |
return NULL; |
351 |
+ |
} |
352 |
+ |
|
353 |
+ |
disknames = malloc(size); |
354 |
+ |
if (disknames == NULL) { |
355 |
+ |
return NULL; |
356 |
+ |
} |
357 |
+ |
|
358 |
+ |
if (sysctl(mib, MIBSIZE, disknames, &size, NULL, 0) < 0) { |
359 |
+ |
return NULL; |
360 |
+ |
} |
361 |
+ |
|
362 |
+ |
dk_name = calloc(diskcount, sizeof(char *)); |
363 |
+ |
bufpp = disknames; |
364 |
+ |
for (i = 0; i < diskcount && (name = strsep(&bufpp, ",")) != NULL; i++) { |
365 |
+ |
dk_name[i] = name; |
366 |
+ |
} |
367 |
+ |
#endif |
368 |
+ |
|
369 |
|
#if defined(NETBSD) || defined(OPENBSD) |
370 |
|
mib[0] = CTL_HW; |
371 |
|
mib[1] = HW_DISKSTATS; |
412 |
|
continue; |
413 |
|
} |
414 |
|
|
415 |
< |
diskio_stats = diskio_stat_malloc(num_diskio + 1, |
428 |
< |
&sizeof_diskio_stats, |
429 |
< |
diskio_stats); |
430 |
< |
if (diskio_stats == NULL) { |
415 |
> |
if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) { |
416 |
|
return NULL; |
417 |
|
} |
418 |
|
diskio_stats_ptr = diskio_stats + num_diskio; |
425 |
|
#ifdef NETBSD |
426 |
|
diskio_stats_ptr->disk_name = strdup(stats[i].dk_name); |
427 |
|
#else |
428 |
< |
asprintf((&diskio_stats_ptr->disk_name), "%s%d", "disk", i); |
428 |
> |
diskio_stats_ptr->disk_name = strdup(dk_name[i]); |
429 |
|
#endif |
430 |
|
diskio_stats_ptr->systime = time(NULL); |
431 |
|
|
433 |
|
} |
434 |
|
|
435 |
|
free(stats); |
436 |
+ |
#ifdef OPENBSD |
437 |
+ |
free(dk_name); |
438 |
+ |
free(disknames); |
439 |
|
#endif |
440 |
+ |
#endif |
441 |
|
|
442 |
< |
#ifdef FREEBSD |
442 |
> |
#if defined(FREEBSD) || defined(DFBSD) |
443 |
|
if (!stats_init) { |
444 |
|
stats.dinfo=malloc(sizeof(struct devinfo)); |
445 |
|
if(stats.dinfo==NULL) return NULL; |
474 |
|
#else |
475 |
|
if((dev_ptr->bytes_read==0) && (dev_ptr->bytes_written==0)) continue; |
476 |
|
#endif |
477 |
< |
if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){ |
477 |
> |
|
478 |
> |
if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) { |
479 |
|
return NULL; |
480 |
|
} |
481 |
|
diskio_stats_ptr=diskio_stats+num_diskio; |
510 |
|
if((kstat_read(kc, ksp, &kios))==-1){ |
511 |
|
} |
512 |
|
|
513 |
< |
if((diskio_stats=diskio_stat_malloc(num_diskio+1, &sizeof_diskio_stats, diskio_stats))==NULL){ |
513 |
> |
if (VECTOR_RESIZE(diskio_stats, num_diskio + 1) < 0) { |
514 |
|
kstat_close(kc); |
515 |
|
return NULL; |
516 |
|
} |
541 |
|
the same format. */ |
542 |
|
|
543 |
|
f = fopen("/proc/diskstats", "r"); |
544 |
< |
format = " %d %d %19s %*d %*d %lld %*d %*d %*d %lld"; |
544 |
> |
format = " %d %d %99s %*d %*d %lld %*d %*d %*d %lld"; |
545 |
|
if (f == NULL) { |
546 |
|
f = fopen("/proc/partitions", "r"); |
547 |
< |
format = " %d %d %*d %19s %*d %*d %lld %*d %*d %*d %lld"; |
547 |
> |
format = " %d %d %*d %99s %*d %*d %lld %*d %*d %*d %lld"; |
548 |
|
} |
549 |
|
if (f == NULL) goto out; |
550 |
|
now = time(NULL); |
551 |
|
|
552 |
|
while ((line_ptr = f_read_line(f, "")) != NULL) { |
553 |
< |
char name[20]; |
553 |
> |
char name[100]; |
554 |
|
char *s; |
555 |
|
long long rsect, wsect; |
556 |
|
|
571 |
|
wsect = 0; |
572 |
|
} |
573 |
|
|
574 |
< |
diskio_stats = diskio_stat_malloc(n + 1, &sizeof_diskio_stats, |
575 |
< |
diskio_stats); |
586 |
< |
if (diskio_stats == NULL) goto out; |
587 |
< |
if (n >= alloc_parts) { |
588 |
< |
alloc_parts += 16; |
589 |
< |
parts = realloc(parts, alloc_parts * sizeof *parts); |
590 |
< |
if (parts == NULL) { |
591 |
< |
alloc_parts = 0; |
592 |
< |
goto out; |
593 |
< |
} |
574 |
> |
if (VECTOR_RESIZE(diskio_stats, n + 1) < 0) { |
575 |
> |
goto out; |
576 |
|
} |
577 |
+ |
if (VECTOR_RESIZE(parts, n + 1) < 0) { |
578 |
+ |
goto out; |
579 |
+ |
} |
580 |
|
|
581 |
|
if (diskio_stats[n].disk_name != NULL) |
582 |
|
free(diskio_stats[n].disk_name); |
675 |
|
} |
676 |
|
|
677 |
|
diskio_stat_t *get_diskio_stats_diff(int *entries){ |
678 |
< |
static diskio_stat_t *diff = NULL; |
679 |
< |
static int diff_count = 0; |
680 |
< |
diskio_stat_t *src, *dest; |
681 |
< |
int i, j, new_count; |
678 |
> |
VECTOR_DECLARE_STATIC(diff, diskio_stat_t, 1, |
679 |
> |
diskio_stat_init, diskio_stat_destroy); |
680 |
> |
diskio_stat_t *src = NULL, *dest; |
681 |
> |
int i, j, diff_count, new_count; |
682 |
|
|
683 |
|
if (diskio_stats == NULL) { |
684 |
|
/* No previous stats, so we can't calculate a difference. */ |
686 |
|
} |
687 |
|
|
688 |
|
/* Resize the results array to match the previous stats. */ |
689 |
< |
diff = diskio_stat_malloc(num_diskio, &diff_count, diff); |
690 |
< |
if (diff == NULL) { |
689 |
> |
diff_count = VECTOR_SIZE(diskio_stats); |
690 |
> |
if (VECTOR_RESIZE(diff, diff_count) < 0) { |
691 |
|
return NULL; |
692 |
|
} |
693 |
|
|