ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/tools.c
Revision: 1.64
Committed: Mon Oct 9 14:09:38 2006 UTC (17 years, 7 months ago) by tdb
Content type: text/plain
Branch: MAIN
CVS Tags: LIBSTATGRAB_0_14
Changes since 1.63: +5 -1 lines
Log Message:
Make sure we always close kstat.

Spotted by: "Javier Donaire" <jyuyu@fraguel.org> (in load_stats.c)

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.64 * $Id: tools.c,v 1.63 2005/09/24 13:29:23 tdb 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 ats 1.9 #ifdef ALLBSD
34 ats 1.8 #include <fcntl.h>
35 tdb 1.29 #endif
36 tdb 1.34 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
37 ats 1.8 #include <kvm.h>
38 tdb 1.35 #include <paths.h>
39 ats 1.8 #endif
40 ats 1.28 #if defined(NETBSD) || defined(OPENBSD)
41 ats 1.9 #include <uvm/uvm_extern.h>
42 ats 1.28 #include <sys/param.h>
43     #include <sys/sysctl.h>
44 ats 1.9 #endif
45 ats 1.59 #ifdef HPUX
46     #include <sys/param.h>
47     #include <sys/pstat.h>
48     #endif
49 pajs 1.1
50 ats 1.7 #include "tools.h"
51 tdb 1.46 #include "statgrab.h"
52 ats 1.7
53 pajs 1.14 #ifdef SOLARIS
54 pajs 1.27 #ifdef HAVE_LIBDEVINFO_H
55 pajs 1.14 #include <libdevinfo.h>
56 pajs 1.27 #endif
57 pajs 1.14 #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 tdb 1.63 #ifdef WIN32
68     #include "win32.h"
69     #endif
70 pajs 1.14
71 pajs 1.26 #if defined(SOLARIS) && defined(HAVE_LIBDEVINFO_H)
72 pajs 1.14 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 pajs 1.26 #endif
82 pajs 1.14
83 pajs 1.26 #ifdef SOLARIS
84 ats 1.41 const char *sg_get_svr_from_bsd(const char *bsd){
85 pajs 1.26 #ifdef HAVE_LIBDEVINFO_H
86 pajs 1.14 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 pajs 1.26 #endif
90 pajs 1.14 return bsd;
91     }
92 pajs 1.26 #endif
93 pajs 1.14
94 pajs 1.26 #if defined(SOLARIS) && defined(HAVE_LIBDEVINFO_H)
95 ats 1.41 static void add_mapping(char *bsd, char *svr){
96 pajs 1.14 mapping_t *map_ptr;
97     mapping_t *map_end_ptr;
98    
99     if (mapping == NULL){
100 ats 1.48 mapping = sg_malloc(sizeof(mapping_t));
101 pajs 1.14 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 ats 1.48 map_end_ptr->next = sg_malloc(sizeof(mapping_t));
116 pajs 1.14 if (map_end_ptr->next == NULL) return;
117     map_ptr = map_end_ptr->next;
118     }
119    
120     map_ptr->next = NULL;
121 ats 1.47 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 pajs 1.14
128     return;
129     }
130    
131 ats 1.41
132     static char *read_dir(char *disk_path){
133 pajs 1.14 DIR *dirp;
134 tdb 1.15 struct dirent *dp;
135     struct stat stbuf;
136 ats 1.47 char *svr_name = NULL;
137 tdb 1.15 char current_dir[MAXPATHLEN];
138     char file_name[MAXPATHLEN];
139     char temp_name[MAXPATHLEN];
140     char dir_dname[MAXPATHLEN];
141 pajs 1.14 char *dsk_dir;
142     int x;
143    
144     dsk_dir = "/dev/osa/dev/dsk";
145 tdb 1.15 strncpy(current_dir, dsk_dir, sizeof current_dir);
146     if ((dirp = opendir(current_dir)) == NULL){
147 pajs 1.14 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 tdb 1.15 while ((dp = readdir(dirp)) != NULL){
155 pajs 1.14 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 ats 1.47 if (sg_update_string(&svr_name,
164 tdb 1.49 dp->d_name) < 0) {
165 ats 1.47 return NULL;
166     }
167 pajs 1.14 closedir(dirp);
168     return svr_name;
169     }
170     }
171     }
172 tdb 1.16 closedir(dirp);
173 pajs 1.14 return NULL;
174     }
175    
176    
177 ats 1.41 static int get_alias(char *alias){
178 pajs 1.14 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 ats 1.45 return -1;
189 pajs 1.14 }
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 ats 1.41 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 pajs 1.14 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 tdb 1.15 }
212 pajs 1.14 di_fini(root_node);
213 pajs 1.17 return 0;
214 pajs 1.14 }
215    
216 pajs 1.22
217     #define BIG_ENOUGH 512
218 ats 1.41 static int build_mapping(){
219 pajs 1.22 char device_name[BIG_ENOUGH];
220 pajs 1.14 int x;
221 tdb 1.15 kstat_ctl_t *kc;
222     kstat_t *ksp;
223     kstat_io_t kios;
224 pajs 1.14
225 pajs 1.22 char driver_list[BIG_ENOUGH][BIG_ENOUGH];
226     int list_entries = 0;
227     int found;
228    
229 pajs 1.14 if ((kc = kstat_open()) == NULL) {
230 ats 1.45 return -1;
231 tdb 1.15 }
232 pajs 1.14
233 tdb 1.15 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 pajs 1.14 strncpy(device_name, ksp->ks_name, sizeof device_name);
240 tdb 1.61 for(x=0;x<(int)(sizeof device_name);x++){
241 pajs 1.14 if( isdigit((int)device_name[x]) ) break;
242     }
243     if(x == sizeof device_name) x--;
244     device_name[x] = '\0';
245 pajs 1.22
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 tdb 1.64 kstat_close(kc);
253 ats 1.45 return -1;
254 pajs 1.22 }
255     if( !strncmp(driver_list[x], device_name, BIG_ENOUGH)){
256     found = 1;
257     break;
258     }
259     }
260    
261     if(!found){
262     if((get_alias(device_name)) != 0){
263 tdb 1.64 kstat_close(kc);
264 ats 1.45 return -1;
265 pajs 1.22 }
266     strncpy(driver_list[x], device_name, BIG_ENOUGH);
267     list_entries++;
268 pajs 1.17 }
269 tdb 1.15 }
270 pajs 1.14 }
271 tdb 1.15
272 tdb 1.64 kstat_close(kc);
273    
274 pajs 1.17 return 0;
275 pajs 1.14 }
276    
277     #endif
278    
279 tdb 1.52 #if defined(LINUX) || defined(CYGWIN)
280 ats 1.41 char *sg_f_read_line(FILE *f, const char *string){
281 pajs 1.1 /* Max line length. 8k should be more than enough */
282     static char line[8192];
283    
284 pajs 1.2 while((fgets(line, sizeof(line), f))!=NULL){
285 pajs 1.1 if(strncmp(string, line, strlen(string))==0){
286     return line;
287     }
288     }
289    
290 tdb 1.51 sg_set_error(SG_ERROR_PARSE, NULL);
291 pajs 1.1 return NULL;
292 pajs 1.3 }
293    
294 ats 1.41 char *sg_get_string_match(char *line, regmatch_t *match){
295 pajs 1.3 int len=match->rm_eo - match->rm_so;
296 ats 1.48 char *match_string=sg_malloc(len+1);
297 pajs 1.3
298     match_string=strncpy(match_string, line+match->rm_so, len);
299     match_string[len]='\0';
300    
301     return match_string;
302     }
303 ats 1.7
304 ats 1.62 /* Cygwin (without a recent newlib) doesn't have atoll */
305 ats 1.13 #ifndef HAVE_ATOLL
306     static long long atoll(const char *s) {
307     long long value = 0;
308     int isneg = 0;
309    
310     while (*s == ' ' || *s == '\t') {
311     s++;
312     }
313     if (*s == '-') {
314     isneg = 1;
315     s++;
316     }
317     while (*s >= '0' && *s <= '9') {
318     value = (10 * value) + (*s - '0');
319     s++;
320     }
321     return (isneg ? -value : value);
322 tdb 1.60 }
323     #endif
324    
325     long long sg_get_ll_match(char *line, regmatch_t *match){
326     char *ptr;
327     long long num;
328    
329     ptr=line+match->rm_so;
330     num=atoll(ptr);
331    
332     return num;
333 ats 1.13 }
334     #endif
335    
336 ats 1.21 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
337 pajs 1.19
338     /*
339     * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
340     *
341     * Permission to use, copy, modify, and distribute this software for any
342     * purpose with or without fee is hereby granted, provided that the above
343     * copyright notice and this permission notice appear in all copies.
344     *
345     * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
346     * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
347     * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
348     * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
349     * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
350     * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
351     * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
352     */
353    
354     /*
355     * Copy src to string dst of size siz. At most siz-1 characters
356     * will be copied. Always NUL terminates (unless siz == 0).
357     * Returns strlen(src); if retval >= siz, truncation occurred.
358     */
359 ats 1.41 size_t sg_strlcpy(char *dst, const char *src, size_t siz){
360 tdb 1.49 register char *d = dst;
361     register const char *s = src;
362     register size_t n = siz;
363    
364     /* Copy as many bytes as will fit */
365     if (n != 0 && --n != 0) {
366     do {
367     if ((*d++ = *s++) == 0)
368     break;
369     } while (--n != 0);
370     }
371    
372     /* Not enough room in dst, add NUL and traverse rest of src */
373     if (n == 0) {
374     if (siz != 0)
375     *d = '\0'; /* NUL-terminate dst */
376     while (*s++)
377     ;
378     }
379 pajs 1.19
380 tdb 1.49 return(s - src - 1); /* count does not include NUL */
381 pajs 1.19 }
382    
383     /* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */
384    
385     /*
386     * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
387     *
388     * Permission to use, copy, modify, and distribute this software for any
389     * purpose with or without fee is hereby granted, provided that the above
390     * copyright notice and this permission notice appear in all copies.
391     *
392     * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
393     * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
394     * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
395     * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
396     * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
397     * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
398     * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
399     */
400    
401     /*
402     * Appends src to string dst of size siz (unlike strncat, siz is the
403     * full size of dst, not space left). At most siz-1 characters
404     * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
405     * Returns strlen(src) + MIN(siz, strlen(initial dst)).
406     * If retval >= siz, truncation occurred.
407     */
408 ats 1.41 size_t sg_strlcat(char *dst, const char *src, size_t siz){
409 tdb 1.49 register char *d = dst;
410     register const char *s = src;
411     register size_t n = siz;
412     size_t dlen;
413    
414     /* Find the end of dst and adjust bytes left but don't go past end */
415     while (n-- != 0 && *d != '\0')
416     d++;
417     dlen = d - dst;
418     n = siz - dlen;
419    
420     if (n == 0)
421     return(dlen + strlen(s));
422     while (*s != '\0') {
423     if (n != 1) {
424     *d++ = *s;
425     n--;
426     }
427     s++;
428     }
429     *d = '\0';
430 pajs 1.19
431 tdb 1.49 return(dlen + (s - src)); /* count does not include NUL */
432 pajs 1.19 }
433    
434 ats 1.42 int sg_update_string(char **dest, const char *src) {
435 ats 1.37 char *new;
436    
437 ats 1.42 if (src == NULL) {
438     /* We're being told to set it to NULL. */
439     free(*dest);
440     *dest = NULL;
441     return 0;
442     }
443    
444 ats 1.48 new = sg_realloc(*dest, strlen(src) + 1);
445 ats 1.37 if (new == NULL) {
446 ats 1.42 return -1;
447 ats 1.37 }
448    
449     strcpy(new, src);
450     *dest = new;
451 ats 1.42 return 0;
452 ats 1.8 }
453    
454 tdb 1.63 /* join two strings together */
455     int sg_concat_string(char **dest, const char *src) {
456     char *new;
457     int len = strlen(*dest) + strlen(src) + 1;
458    
459     new = sg_realloc(*dest, len);
460     if (new == NULL) {
461     return -1;
462     }
463    
464     *dest = new;
465     strcat(*dest, src);
466     return 0;
467     }
468    
469 tdb 1.34 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
470 ats 1.41 kvm_t *sg_get_kvm() {
471 ats 1.8 static kvm_t *kvmd = NULL;
472    
473     if (kvmd != NULL) {
474     return kvmd;
475     }
476    
477     kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL);
478 tdb 1.51 if(kvmd == NULL) {
479     sg_set_error(SG_ERROR_KVM_OPENFILES, NULL);
480     }
481 ats 1.8 return kvmd;
482 pajs 1.1 }
483 tdb 1.34
484     /* Can't think of a better name for this function */
485 ats 1.41 kvm_t *sg_get_kvm2() {
486 tdb 1.34 static kvm_t *kvmd2 = NULL;
487    
488     if (kvmd2 != NULL) {
489     return kvmd2;
490     }
491    
492     kvmd2 = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, NULL, O_RDONLY, NULL);
493 tdb 1.51 if(kvmd2 == NULL) {
494     sg_set_error(SG_ERROR_KVM_OPENFILES, NULL);
495     }
496 tdb 1.34 return kvmd2;
497     }
498 pajs 1.4 #endif
499 ats 1.9
500 ats 1.28 #if defined(NETBSD) || defined(OPENBSD)
501 ats 1.41 struct uvmexp *sg_get_uvmexp() {
502 ats 1.28 int mib[2];
503 ats 1.44 size_t size = sizeof(struct uvmexp);
504     static struct uvmexp uvm;
505 ats 1.36 struct uvmexp *new;
506 ats 1.9
507 ats 1.28 mib[0] = CTL_VM;
508     mib[1] = VM_UVMEXP;
509    
510 ats 1.44 if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
511 ats 1.56 sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP");
512 ats 1.9 return NULL;
513     }
514    
515 ats 1.44 return &uvm;
516 ats 1.59 }
517     #endif
518    
519     #ifdef HPUX
520     struct pst_static *sg_get_pstat_static() {
521     static int got = 0;
522     static struct pst_static pst;
523    
524     if (!got) {
525     if (pstat_getstatic(&pst, sizeof pst, 1, 0) == -1) {
526     sg_set_error_with_errno(SG_ERROR_PSTAT,
527     "pstat_static");
528     return NULL;
529     }
530     got = 1;
531     }
532     return &pst;
533 ats 1.9 }
534     #endif
535    
536 ats 1.41 int sg_init(){
537 tdb 1.55 sg_set_error(SG_ERROR_NONE, NULL);
538 ats 1.53
539 tdb 1.33 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
540 ats 1.41 if (sg_get_kvm() == NULL) {
541 ats 1.45 return -1;
542 ats 1.41 }
543     if (sg_get_kvm2() == NULL) {
544 ats 1.45 return -1;
545 ats 1.32 }
546 pajs 1.14 #endif
547     #ifdef SOLARIS
548 pajs 1.20 /* On solaris 7, this will fail if you are not root. But, everything
549     * will still work, just no disk mappings. So we will ignore the exit
550     * status of this, and carry on merrily.
551     */
552 pajs 1.26 #ifdef HAVE_LIBDEVINFO_H
553 pajs 1.20 build_mapping();
554 pajs 1.25 #endif
555 pajs 1.10 #endif
556 tdb 1.63 #ifdef WIN32
557     return sg_win32_start_capture();
558     #endif
559     return 0;
560     }
561    
562     int sg_shutdown() {
563     #ifdef WIN32
564     sg_win32_end_capture();
565     #endif
566 pajs 1.10 return 0;
567     }
568 ats 1.18
569 tdb 1.63 int sg_snapshot() {
570     #ifdef WIN32
571     return sg_win32_snapshot();
572     #else
573     return 0;
574     #endif
575     }
576    
577 ats 1.41 int sg_drop_privileges() {
578 tdb 1.63 #ifndef WIN32
579 tdb 1.57 #ifdef HAVE_SETEGID
580 tdb 1.51 if (setegid(getgid()) != 0) {
581 tdb 1.57 #elif defined(HAVE_SETRESGID)
582     if (setresgid(getgid(), getgid(), getgid()) != 0) {
583     #else
584     {
585     #endif
586 ats 1.56 sg_set_error_with_errno(SG_ERROR_SETEGID, NULL);
587 tdb 1.51 return -1;
588     }
589 tdb 1.57 #ifdef HAVE_SETEUID
590 tdb 1.51 if (seteuid(getuid()) != 0) {
591 tdb 1.57 #elif defined(HAVE_SETRESUID)
592     if (setresuid(getuid(), getuid(), getuid()) != 0) {
593     #else
594     {
595     #endif
596 ats 1.56 sg_set_error_with_errno(SG_ERROR_SETEUID, NULL);
597 tdb 1.51 return -1;
598     }
599 tdb 1.63 #endif /* WIN32 */
600 ats 1.18 return 0;
601 tdb 1.46 }
602    
603     void *sg_realloc(void *ptr, size_t size) {
604     void *tmp = NULL;
605     tmp = realloc(ptr, size);
606     if(tmp == NULL) {
607 ats 1.56 sg_set_error_with_errno(SG_ERROR_MALLOC, NULL);
608 tdb 1.46 }
609     return tmp;
610 ats 1.18 }