ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/tools.c
Revision: 1.60
Committed: Sat Nov 6 19:09:00 2004 UTC (19 years, 6 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.59: +13 -12 lines
Log Message:
atoll is only used in one place in libstatgrab, so move it's definition to
before that one use. Given this hasn't caused us problems I'm guessing that
atoll is actually available on Linux and Cygwin, which would make having
the function here void.

If so, it can simply be removed instead.

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