ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/tools.c
Revision: 1.63
Committed: Sat Sep 24 13:29:23 2005 UTC (18 years, 7 months ago) by tdb
Content type: text/plain
Branch: MAIN
CVS Tags: LIBSTATGRAB_0_13
Changes since 1.62: +39 -1 lines
Log Message:
Add WIN32 support via MINGW. We'll need to add stuff to the README file
about what this requires to build.

All the hard work done by: skel

File Contents

# Content
1 /*
2 * i-scream libstatgrab
3 * http://www.i-scream.org
4 * Copyright (C) 2000-2004 i-scream
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 * 02111-1307 USA
20 *
21 * $Id: tools.c,v 1.62 2004/11/07 12:34:24 ats Exp $
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #ifdef ALLBSD
34 #include <fcntl.h>
35 #endif
36 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
37 #include <kvm.h>
38 #include <paths.h>
39 #endif
40 #if defined(NETBSD) || defined(OPENBSD)
41 #include <uvm/uvm_extern.h>
42 #include <sys/param.h>
43 #include <sys/sysctl.h>
44 #endif
45 #ifdef HPUX
46 #include <sys/param.h>
47 #include <sys/pstat.h>
48 #endif
49
50 #include "tools.h"
51 #include "statgrab.h"
52
53 #ifdef SOLARIS
54 #ifdef HAVE_LIBDEVINFO_H
55 #include <libdevinfo.h>
56 #endif
57 #include <kstat.h>
58 #include <unistd.h>
59 #include <ctype.h>
60 #include <sys/types.h>
61 #include <sys/dkio.h>
62 #include <sys/stat.h>
63 #include <fcntl.h>
64 #include <sys/fcntl.h>
65 #include <dirent.h>
66 #endif
67 #ifdef WIN32
68 #include "win32.h"
69 #endif
70
71 #if defined(SOLARIS) && defined(HAVE_LIBDEVINFO_H)
72 struct map{
73 char *bsd;
74 char *svr;
75
76 struct map *next;
77 };
78 typedef struct map mapping_t;
79
80 static mapping_t *mapping = NULL;
81 #endif
82
83 #ifdef SOLARIS
84 const char *sg_get_svr_from_bsd(const char *bsd){
85 #ifdef HAVE_LIBDEVINFO_H
86 mapping_t *map_ptr;
87 for(map_ptr = mapping; map_ptr != NULL; map_ptr = map_ptr->next)
88 if(!strcmp(map_ptr->bsd, bsd)) return map_ptr->svr;
89 #endif
90 return bsd;
91 }
92 #endif
93
94 #if defined(SOLARIS) && defined(HAVE_LIBDEVINFO_H)
95 static void add_mapping(char *bsd, char *svr){
96 mapping_t *map_ptr;
97 mapping_t *map_end_ptr;
98
99 if (mapping == NULL){
100 mapping = sg_malloc(sizeof(mapping_t));
101 if (mapping == NULL) return;
102 map_ptr = mapping;
103 }else{
104 /* See if its already been added */
105 for(map_ptr = mapping; map_ptr != NULL; map_ptr = map_ptr->next){
106 if( (!strcmp(map_ptr->bsd, bsd)) || (!strcmp(map_ptr->svr, svr)) ){
107 return;
108 }
109 map_end_ptr = map_ptr;
110 }
111
112 /* We've reached end of list and not found the entry.. So we need to malloc
113 * new mapping_t
114 */
115 map_end_ptr->next = sg_malloc(sizeof(mapping_t));
116 if (map_end_ptr->next == NULL) return;
117 map_ptr = map_end_ptr->next;
118 }
119
120 map_ptr->next = NULL;
121 map_ptr->bsd = NULL;
122 map_ptr->svr = NULL;
123 if (sg_update_string(&map_ptr->bsd, bsd) < 0
124 || sg_update_string(&map_ptr->svr, svr) < 0) {
125 return;
126 }
127
128 return;
129 }
130
131
132 static char *read_dir(char *disk_path){
133 DIR *dirp;
134 struct dirent *dp;
135 struct stat stbuf;
136 char *svr_name = NULL;
137 char current_dir[MAXPATHLEN];
138 char file_name[MAXPATHLEN];
139 char temp_name[MAXPATHLEN];
140 char dir_dname[MAXPATHLEN];
141 char *dsk_dir;
142 int x;
143
144 dsk_dir = "/dev/osa/dev/dsk";
145 strncpy(current_dir, dsk_dir, sizeof current_dir);
146 if ((dirp = opendir(current_dir)) == NULL){
147 dsk_dir = "/dev/dsk";
148 snprintf(current_dir, sizeof current_dir, "%s", dsk_dir);
149 if ((dirp = opendir(current_dir)) == NULL){
150 return NULL;
151 }
152 }
153
154 while ((dp = readdir(dirp)) != NULL){
155 snprintf(temp_name, sizeof temp_name, "../..%s", disk_path);
156 snprintf(dir_dname, sizeof dir_dname, "%s/%s", dsk_dir, dp->d_name);
157 stat(dir_dname,&stbuf);
158
159 if (S_ISBLK(stbuf.st_mode)){
160 x = readlink(dir_dname, file_name, sizeof(file_name));
161 file_name[x] = '\0';
162 if (strcmp(file_name, temp_name) == 0) {
163 if (sg_update_string(&svr_name,
164 dp->d_name) < 0) {
165 return NULL;
166 }
167 closedir(dirp);
168 return svr_name;
169 }
170 }
171 }
172 closedir(dirp);
173 return NULL;
174 }
175
176
177 static int get_alias(char *alias){
178 char file[MAXPATHLEN];
179 di_node_t root_node;
180 di_node_t node;
181 di_minor_t minor = DI_MINOR_NIL;
182 char tmpnode[MAXPATHLEN];
183 char *phys_path;
184 char *minor_name;
185 char *value;
186 int instance;
187 if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
188 return -1;
189 }
190 node = di_drv_first_node(alias, root_node);
191 while (node != DI_NODE_NIL) {
192 if ((minor = di_minor_next(node, DI_MINOR_NIL)) != DI_MINOR_NIL) {
193 instance = di_instance(node);
194 phys_path = di_devfs_path(node);
195 minor_name = di_minor_name(minor);
196 strcpy(tmpnode, alias);
197 sprintf(tmpnode, "%s%d", tmpnode, instance);
198 sg_strlcpy(file, "/devices", sizeof file);
199 sg_strlcat(file, phys_path, sizeof file);
200 sg_strlcat(file, ":", sizeof file);
201 sg_strlcat(file, minor_name, sizeof file);
202 value = read_dir(file);
203 if (value != NULL){
204 add_mapping(tmpnode, value);
205 }
206 di_devfs_path_free(phys_path);
207 node = di_drv_next_node(node);
208 }else{
209 node = di_drv_next_node(node);
210 }
211 }
212 di_fini(root_node);
213 return 0;
214 }
215
216
217 #define BIG_ENOUGH 512
218 static int build_mapping(){
219 char device_name[BIG_ENOUGH];
220 int x;
221 kstat_ctl_t *kc;
222 kstat_t *ksp;
223 kstat_io_t kios;
224
225 char driver_list[BIG_ENOUGH][BIG_ENOUGH];
226 int list_entries = 0;
227 int found;
228
229 if ((kc = kstat_open()) == NULL) {
230 return -1;
231 }
232
233 for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
234 if (!strcmp(ksp->ks_class, "disk")) {
235 if(ksp->ks_type != KSTAT_TYPE_IO) continue;
236 /* We dont want metadevices appearing as num_diskio */
237 if(strcmp(ksp->ks_module, "md")==0) continue;
238 if((kstat_read(kc, ksp, &kios))==-1) continue;
239 strncpy(device_name, ksp->ks_name, sizeof device_name);
240 for(x=0;x<(int)(sizeof device_name);x++){
241 if( isdigit((int)device_name[x]) ) break;
242 }
243 if(x == sizeof device_name) x--;
244 device_name[x] = '\0';
245
246 /* Check if we've not already looked it up */
247 found = 0;
248 for(x=0;x<list_entries;x++){
249 if (x>=BIG_ENOUGH){
250 /* We've got bigger than we thought was massive */
251 /* If we hit this.. Make big enough bigger */
252 return -1;
253 }
254 if( !strncmp(driver_list[x], device_name, BIG_ENOUGH)){
255 found = 1;
256 break;
257 }
258 }
259
260 if(!found){
261 if((get_alias(device_name)) != 0){
262 return -1;
263 }
264 strncpy(driver_list[x], device_name, BIG_ENOUGH);
265 list_entries++;
266 }
267 }
268 }
269
270 return 0;
271 }
272
273 #endif
274
275 #if defined(LINUX) || defined(CYGWIN)
276 char *sg_f_read_line(FILE *f, const char *string){
277 /* Max line length. 8k should be more than enough */
278 static char line[8192];
279
280 while((fgets(line, sizeof(line), f))!=NULL){
281 if(strncmp(string, line, strlen(string))==0){
282 return line;
283 }
284 }
285
286 sg_set_error(SG_ERROR_PARSE, NULL);
287 return NULL;
288 }
289
290 char *sg_get_string_match(char *line, regmatch_t *match){
291 int len=match->rm_eo - match->rm_so;
292 char *match_string=sg_malloc(len+1);
293
294 match_string=strncpy(match_string, line+match->rm_so, len);
295 match_string[len]='\0';
296
297 return match_string;
298 }
299
300 /* Cygwin (without a recent newlib) doesn't have atoll */
301 #ifndef HAVE_ATOLL
302 static long long atoll(const char *s) {
303 long long value = 0;
304 int isneg = 0;
305
306 while (*s == ' ' || *s == '\t') {
307 s++;
308 }
309 if (*s == '-') {
310 isneg = 1;
311 s++;
312 }
313 while (*s >= '0' && *s <= '9') {
314 value = (10 * value) + (*s - '0');
315 s++;
316 }
317 return (isneg ? -value : value);
318 }
319 #endif
320
321 long long sg_get_ll_match(char *line, regmatch_t *match){
322 char *ptr;
323 long long num;
324
325 ptr=line+match->rm_so;
326 num=atoll(ptr);
327
328 return num;
329 }
330 #endif
331
332 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
333
334 /*
335 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
336 *
337 * Permission to use, copy, modify, and distribute this software for any
338 * purpose with or without fee is hereby granted, provided that the above
339 * copyright notice and this permission notice appear in all copies.
340 *
341 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
342 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
343 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
344 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
345 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
346 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
347 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
348 */
349
350 /*
351 * Copy src to string dst of size siz. At most siz-1 characters
352 * will be copied. Always NUL terminates (unless siz == 0).
353 * Returns strlen(src); if retval >= siz, truncation occurred.
354 */
355 size_t sg_strlcpy(char *dst, const char *src, size_t siz){
356 register char *d = dst;
357 register const char *s = src;
358 register size_t n = siz;
359
360 /* Copy as many bytes as will fit */
361 if (n != 0 && --n != 0) {
362 do {
363 if ((*d++ = *s++) == 0)
364 break;
365 } while (--n != 0);
366 }
367
368 /* Not enough room in dst, add NUL and traverse rest of src */
369 if (n == 0) {
370 if (siz != 0)
371 *d = '\0'; /* NUL-terminate dst */
372 while (*s++)
373 ;
374 }
375
376 return(s - src - 1); /* count does not include NUL */
377 }
378
379 /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */
380
381 /*
382 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
383 *
384 * Permission to use, copy, modify, and distribute this software for any
385 * purpose with or without fee is hereby granted, provided that the above
386 * copyright notice and this permission notice appear in all copies.
387 *
388 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
389 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
390 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
391 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
392 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
393 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
394 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
395 */
396
397 /*
398 * Appends src to string dst of size siz (unlike strncat, siz is the
399 * full size of dst, not space left). At most siz-1 characters
400 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
401 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
402 * If retval >= siz, truncation occurred.
403 */
404 size_t sg_strlcat(char *dst, const char *src, size_t siz){
405 register char *d = dst;
406 register const char *s = src;
407 register size_t n = siz;
408 size_t dlen;
409
410 /* Find the end of dst and adjust bytes left but don't go past end */
411 while (n-- != 0 && *d != '\0')
412 d++;
413 dlen = d - dst;
414 n = siz - dlen;
415
416 if (n == 0)
417 return(dlen + strlen(s));
418 while (*s != '\0') {
419 if (n != 1) {
420 *d++ = *s;
421 n--;
422 }
423 s++;
424 }
425 *d = '\0';
426
427 return(dlen + (s - src)); /* count does not include NUL */
428 }
429
430 int sg_update_string(char **dest, const char *src) {
431 char *new;
432
433 if (src == NULL) {
434 /* We're being told to set it to NULL. */
435 free(*dest);
436 *dest = NULL;
437 return 0;
438 }
439
440 new = sg_realloc(*dest, strlen(src) + 1);
441 if (new == NULL) {
442 return -1;
443 }
444
445 strcpy(new, src);
446 *dest = new;
447 return 0;
448 }
449
450 /* join two strings together */
451 int sg_concat_string(char **dest, const char *src) {
452 char *new;
453 int len = strlen(*dest) + strlen(src) + 1;
454
455 new = sg_realloc(*dest, len);
456 if (new == NULL) {
457 return -1;
458 }
459
460 *dest = new;
461 strcat(*dest, src);
462 return 0;
463 }
464
465 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
466 kvm_t *sg_get_kvm() {
467 static kvm_t *kvmd = NULL;
468
469 if (kvmd != NULL) {
470 return kvmd;
471 }
472
473 kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
474 if(kvmd == NULL) {
475 sg_set_error(SG_ERROR_KVM_OPENFILES, NULL);
476 }
477 return kvmd;
478 }
479
480 /* Can't think of a better name for this function */
481 kvm_t *sg_get_kvm2() {
482 static kvm_t *kvmd2 = NULL;
483
484 if (kvmd2 != NULL) {
485 return kvmd2;
486 }
487
488 kvmd2 = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, NULL, O_RDONLY, NULL);
489 if(kvmd2 == NULL) {
490 sg_set_error(SG_ERROR_KVM_OPENFILES, NULL);
491 }
492 return kvmd2;
493 }
494 #endif
495
496 #if defined(NETBSD) || defined(OPENBSD)
497 struct uvmexp *sg_get_uvmexp() {
498 int mib[2];
499 size_t size = sizeof(struct uvmexp);
500 static struct uvmexp uvm;
501 struct uvmexp *new;
502
503 mib[0] = CTL_VM;
504 mib[1] = VM_UVMEXP;
505
506 if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
507 sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP");
508 return NULL;
509 }
510
511 return &uvm;
512 }
513 #endif
514
515 #ifdef HPUX
516 struct pst_static *sg_get_pstat_static() {
517 static int got = 0;
518 static struct pst_static pst;
519
520 if (!got) {
521 if (pstat_getstatic(&pst, sizeof pst, 1, 0) == -1) {
522 sg_set_error_with_errno(SG_ERROR_PSTAT,
523 "pstat_static");
524 return NULL;
525 }
526 got = 1;
527 }
528 return &pst;
529 }
530 #endif
531
532 int sg_init(){
533 sg_set_error(SG_ERROR_NONE, NULL);
534
535 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
536 if (sg_get_kvm() == NULL) {
537 return -1;
538 }
539 if (sg_get_kvm2() == NULL) {
540 return -1;
541 }
542 #endif
543 #ifdef SOLARIS
544 /* On solaris 7, this will fail if you are not root. But, everything
545 * will still work, just no disk mappings. So we will ignore the exit
546 * status of this, and carry on merrily.
547 */
548 #ifdef HAVE_LIBDEVINFO_H
549 build_mapping();
550 #endif
551 #endif
552 #ifdef WIN32
553 return sg_win32_start_capture();
554 #endif
555 return 0;
556 }
557
558 int sg_shutdown() {
559 #ifdef WIN32
560 sg_win32_end_capture();
561 #endif
562 return 0;
563 }
564
565 int sg_snapshot() {
566 #ifdef WIN32
567 return sg_win32_snapshot();
568 #else
569 return 0;
570 #endif
571 }
572
573 int sg_drop_privileges() {
574 #ifndef WIN32
575 #ifdef HAVE_SETEGID
576 if (setegid(getgid()) != 0) {
577 #elif defined(HAVE_SETRESGID)
578 if (setresgid(getgid(), getgid(), getgid()) != 0) {
579 #else
580 {
581 #endif
582 sg_set_error_with_errno(SG_ERROR_SETEGID, NULL);
583 return -1;
584 }
585 #ifdef HAVE_SETEUID
586 if (seteuid(getuid()) != 0) {
587 #elif defined(HAVE_SETRESUID)
588 if (setresuid(getuid(), getuid(), getuid()) != 0) {
589 #else
590 {
591 #endif
592 sg_set_error_with_errno(SG_ERROR_SETEUID, NULL);
593 return -1;
594 }
595 #endif /* WIN32 */
596 return 0;
597 }
598
599 void *sg_realloc(void *ptr, size_t size) {
600 void *tmp = NULL;
601 tmp = realloc(ptr, size);
602 if(tmp == NULL) {
603 sg_set_error_with_errno(SG_ERROR_MALLOC, NULL);
604 }
605 return tmp;
606 }