ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/tools.c
Revision: 1.51
Committed: Wed Apr 7 21:08:40 2004 UTC (20 years, 1 month ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.50: +17 -5 lines
Log Message:
The rest of the error handling stuff (except the vector code).

I've been extremely unimaginative with the string names in error.c, but
they're all in one place so much easier to tidy up. I'm also beginning to
wonder if we actually needed an SG_ERROR_SYSTEM_CALL to indicate some call
into the system failed - because the majority of our errors are those :-)

Still to do, then:
 - vector code
 - better string names in error.c
 - deal with arg string in some way
 - make use of the error status in statgrab/saidar/examples

File Contents

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