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

# 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.50 2004/04/07 15:46:34 pajs 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 #include <regex.h>
34 #ifdef ALLBSD
35 #include <fcntl.h>
36 #endif
37 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
38 #include <kvm.h>
39 #include <paths.h>
40 #endif
41 #if defined(NETBSD) || defined(OPENBSD)
42 #include <uvm/uvm_extern.h>
43 #include <sys/param.h>
44 #include <sys/sysctl.h>
45 #endif
46
47 #include "tools.h"
48 #include "statgrab.h"
49
50 #ifdef SOLARIS
51 #ifdef HAVE_LIBDEVINFO_H
52 #include <libdevinfo.h>
53 #endif
54 #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 #if defined(SOLARIS) && defined(HAVE_LIBDEVINFO_H)
66 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 #endif
76
77 #ifdef SOLARIS
78 const char *sg_get_svr_from_bsd(const char *bsd){
79 #ifdef HAVE_LIBDEVINFO_H
80 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 #endif
84 return bsd;
85 }
86 #endif
87
88 #if defined(SOLARIS) && defined(HAVE_LIBDEVINFO_H)
89 static void add_mapping(char *bsd, char *svr){
90 mapping_t *map_ptr;
91 mapping_t *map_end_ptr;
92
93 if (mapping == NULL){
94 mapping = sg_malloc(sizeof(mapping_t));
95 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 map_end_ptr->next = sg_malloc(sizeof(mapping_t));
110 if (map_end_ptr->next == NULL) return;
111 map_ptr = map_end_ptr->next;
112 }
113
114 map_ptr->next = NULL;
115 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
122 return;
123 }
124
125
126 static char *read_dir(char *disk_path){
127 DIR *dirp;
128 struct dirent *dp;
129 struct stat stbuf;
130 char *svr_name = NULL;
131 char current_dir[MAXPATHLEN];
132 char file_name[MAXPATHLEN];
133 char temp_name[MAXPATHLEN];
134 char dir_dname[MAXPATHLEN];
135 char *dsk_dir;
136 int x;
137
138 dsk_dir = "/dev/osa/dev/dsk";
139 strncpy(current_dir, dsk_dir, sizeof current_dir);
140 if ((dirp = opendir(current_dir)) == NULL){
141 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 while ((dp = readdir(dirp)) != NULL){
149 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 if (sg_update_string(&svr_name,
158 dp->d_name) < 0) {
159 return NULL;
160 }
161 closedir(dirp);
162 return svr_name;
163 }
164 }
165 }
166 closedir(dirp);
167 return NULL;
168 }
169
170
171 static int get_alias(char *alias){
172 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 return -1;
183 }
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 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 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 }
206 di_fini(root_node);
207 return 0;
208 }
209
210
211 #define BIG_ENOUGH 512
212 static int build_mapping(){
213 char device_name[BIG_ENOUGH];
214 int x;
215 kstat_ctl_t *kc;
216 kstat_t *ksp;
217 kstat_io_t kios;
218
219 char driver_list[BIG_ENOUGH][BIG_ENOUGH];
220 int list_entries = 0;
221 int found;
222
223 if ((kc = kstat_open()) == NULL) {
224 return -1;
225 }
226
227 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 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
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 return -1;
247 }
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 return -1;
257 }
258 strncpy(driver_list[x], device_name, BIG_ENOUGH);
259 list_entries++;
260 }
261 }
262 }
263
264 return 0;
265 }
266
267 #endif
268
269
270 char *sg_f_read_line(FILE *f, const char *string){
271 /* Max line length. 8k should be more than enough */
272 static char line[8192];
273
274 while((fgets(line, sizeof(line), f))!=NULL){
275 if(strncmp(string, line, strlen(string))==0){
276 return line;
277 }
278 }
279
280 sg_set_error(SG_ERROR_PARSE, NULL);
281 return NULL;
282 }
283
284 char *sg_get_string_match(char *line, regmatch_t *match){
285 int len=match->rm_eo - match->rm_so;
286 char *match_string=sg_malloc(len+1);
287
288 match_string=strncpy(match_string, line+match->rm_so, len);
289 match_string[len]='\0';
290
291 return match_string;
292 }
293
294
295 #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 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
316
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 size_t sg_strlcpy(char *dst, const char *src, size_t siz){
339 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
359 return(s - src - 1); /* count does not include NUL */
360 }
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 size_t sg_strlcat(char *dst, const char *src, size_t siz){
388 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
410 return(dlen + (s - src)); /* count does not include NUL */
411 }
412
413 int sg_update_string(char **dest, const char *src) {
414 char *new;
415
416 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 new = sg_realloc(*dest, strlen(src) + 1);
424 if (new == NULL) {
425 return -1;
426 }
427
428 strcpy(new, src);
429 *dest = new;
430 return 0;
431 }
432
433 long long sg_get_ll_match(char *line, regmatch_t *match){
434 char *ptr;
435 long long num;
436
437 ptr=line+match->rm_so;
438 num=atoll(ptr);
439
440 return num;
441 }
442
443 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
444 kvm_t *sg_get_kvm() {
445 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 if(kvmd == NULL) {
453 sg_set_error(SG_ERROR_KVM_OPENFILES, NULL);
454 }
455 return kvmd;
456 }
457
458 /* Can't think of a better name for this function */
459 kvm_t *sg_get_kvm2() {
460 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 if(kvmd2 == NULL) {
468 sg_set_error(SG_ERROR_KVM_OPENFILES, NULL);
469 }
470 return kvmd2;
471 }
472 #endif
473
474 #if defined(NETBSD) || defined(OPENBSD)
475 struct uvmexp *sg_get_uvmexp() {
476 int mib[2];
477 size_t size = sizeof(struct uvmexp);
478 static struct uvmexp uvm;
479 struct uvmexp *new;
480
481 mib[0] = CTL_VM;
482 mib[1] = VM_UVMEXP;
483
484 if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
485 sg_set_error(SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP");
486 return NULL;
487 }
488
489 return &uvm;
490 }
491 #endif
492
493 int sg_init(){
494 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
495 if (sg_get_kvm() == NULL) {
496 return -1;
497 }
498 if (sg_get_kvm2() == NULL) {
499 return -1;
500 }
501 #endif
502 #ifdef SOLARIS
503 /* 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 #ifdef HAVE_LIBDEVINFO_H
508 build_mapping();
509 #endif
510 #endif
511 return 0;
512 }
513
514 int sg_drop_privileges() {
515 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 return 0;
524 }
525
526 void *sg_realloc(void *ptr, size_t size) {
527 void *tmp = NULL;
528 tmp = realloc(ptr, size);
529 if(tmp == NULL) {
530 sg_set_error(SG_ERROR_MALLOC, NULL);
531 }
532 return tmp;
533 }
534