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

# 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.63 * $Id: tools.c,v 1.62 2004/11/07 12:34:24 ats 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 ats 1.45 return -1;
253 pajs 1.22 }
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 ats 1.45 return -1;
263 pajs 1.22 }
264     strncpy(driver_list[x], device_name, BIG_ENOUGH);
265     list_entries++;
266 pajs 1.17 }
267 tdb 1.15 }
268 pajs 1.14 }
269 tdb 1.15
270 pajs 1.17 return 0;
271 pajs 1.14 }
272    
273     #endif
274    
275 tdb 1.52 #if defined(LINUX) || defined(CYGWIN)
276 ats 1.41 char *sg_f_read_line(FILE *f, const char *string){
277 pajs 1.1 /* Max line length. 8k should be more than enough */
278     static char line[8192];
279    
280 pajs 1.2 while((fgets(line, sizeof(line), f))!=NULL){
281 pajs 1.1 if(strncmp(string, line, strlen(string))==0){
282     return line;
283     }
284     }
285    
286 tdb 1.51 sg_set_error(SG_ERROR_PARSE, NULL);
287 pajs 1.1 return NULL;
288 pajs 1.3 }
289    
290 ats 1.41 char *sg_get_string_match(char *line, regmatch_t *match){
291 pajs 1.3 int len=match->rm_eo - match->rm_so;
292 ats 1.48 char *match_string=sg_malloc(len+1);
293 pajs 1.3
294     match_string=strncpy(match_string, line+match->rm_so, len);
295     match_string[len]='\0';
296    
297     return match_string;
298     }
299 ats 1.7
300 ats 1.62 /* Cygwin (without a recent newlib) doesn't have atoll */
301 ats 1.13 #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 tdb 1.60 }
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 ats 1.13 }
330     #endif
331    
332 ats 1.21 /* $OpenBSD: strlcpy.c,v 1.8 2003/06/17 21:56:24 millert Exp $ */
333 pajs 1.19
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 ats 1.41 size_t sg_strlcpy(char *dst, const char *src, size_t siz){
356 tdb 1.49 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 pajs 1.19
376 tdb 1.49 return(s - src - 1); /* count does not include NUL */
377 pajs 1.19 }
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 ats 1.41 size_t sg_strlcat(char *dst, const char *src, size_t siz){
405 tdb 1.49 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 pajs 1.19
427 tdb 1.49 return(dlen + (s - src)); /* count does not include NUL */
428 pajs 1.19 }
429    
430 ats 1.42 int sg_update_string(char **dest, const char *src) {
431 ats 1.37 char *new;
432    
433 ats 1.42 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 ats 1.48 new = sg_realloc(*dest, strlen(src) + 1);
441 ats 1.37 if (new == NULL) {
442 ats 1.42 return -1;
443 ats 1.37 }
444    
445     strcpy(new, src);
446     *dest = new;
447 ats 1.42 return 0;
448 ats 1.8 }
449    
450 tdb 1.63 /* 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 tdb 1.34 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
466 ats 1.41 kvm_t *sg_get_kvm() {
467 ats 1.8 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 tdb 1.51 if(kvmd == NULL) {
475     sg_set_error(SG_ERROR_KVM_OPENFILES, NULL);
476     }
477 ats 1.8 return kvmd;
478 pajs 1.1 }
479 tdb 1.34
480     /* Can't think of a better name for this function */
481 ats 1.41 kvm_t *sg_get_kvm2() {
482 tdb 1.34 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 tdb 1.51 if(kvmd2 == NULL) {
490     sg_set_error(SG_ERROR_KVM_OPENFILES, NULL);
491     }
492 tdb 1.34 return kvmd2;
493     }
494 pajs 1.4 #endif
495 ats 1.9
496 ats 1.28 #if defined(NETBSD) || defined(OPENBSD)
497 ats 1.41 struct uvmexp *sg_get_uvmexp() {
498 ats 1.28 int mib[2];
499 ats 1.44 size_t size = sizeof(struct uvmexp);
500     static struct uvmexp uvm;
501 ats 1.36 struct uvmexp *new;
502 ats 1.9
503 ats 1.28 mib[0] = CTL_VM;
504     mib[1] = VM_UVMEXP;
505    
506 ats 1.44 if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
507 ats 1.56 sg_set_error_with_errno(SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP");
508 ats 1.9 return NULL;
509     }
510    
511 ats 1.44 return &uvm;
512 ats 1.59 }
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 ats 1.9 }
530     #endif
531    
532 ats 1.41 int sg_init(){
533 tdb 1.55 sg_set_error(SG_ERROR_NONE, NULL);
534 ats 1.53
535 tdb 1.33 #if (defined(FREEBSD) && !defined(FREEBSD5)) || defined(DFBSD)
536 ats 1.41 if (sg_get_kvm() == NULL) {
537 ats 1.45 return -1;
538 ats 1.41 }
539     if (sg_get_kvm2() == NULL) {
540 ats 1.45 return -1;
541 ats 1.32 }
542 pajs 1.14 #endif
543     #ifdef SOLARIS
544 pajs 1.20 /* 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 pajs 1.26 #ifdef HAVE_LIBDEVINFO_H
549 pajs 1.20 build_mapping();
550 pajs 1.25 #endif
551 pajs 1.10 #endif
552 tdb 1.63 #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 pajs 1.10 return 0;
563     }
564 ats 1.18
565 tdb 1.63 int sg_snapshot() {
566     #ifdef WIN32
567     return sg_win32_snapshot();
568     #else
569     return 0;
570     #endif
571     }
572    
573 ats 1.41 int sg_drop_privileges() {
574 tdb 1.63 #ifndef WIN32
575 tdb 1.57 #ifdef HAVE_SETEGID
576 tdb 1.51 if (setegid(getgid()) != 0) {
577 tdb 1.57 #elif defined(HAVE_SETRESGID)
578     if (setresgid(getgid(), getgid(), getgid()) != 0) {
579     #else
580     {
581     #endif
582 ats 1.56 sg_set_error_with_errno(SG_ERROR_SETEGID, NULL);
583 tdb 1.51 return -1;
584     }
585 tdb 1.57 #ifdef HAVE_SETEUID
586 tdb 1.51 if (seteuid(getuid()) != 0) {
587 tdb 1.57 #elif defined(HAVE_SETRESUID)
588     if (setresuid(getuid(), getuid(), getuid()) != 0) {
589     #else
590     {
591     #endif
592 ats 1.56 sg_set_error_with_errno(SG_ERROR_SETEUID, NULL);
593 tdb 1.51 return -1;
594     }
595 tdb 1.63 #endif /* WIN32 */
596 ats 1.18 return 0;
597 tdb 1.46 }
598    
599     void *sg_realloc(void *ptr, size_t size) {
600     void *tmp = NULL;
601     tmp = realloc(ptr, size);
602     if(tmp == NULL) {
603 ats 1.56 sg_set_error_with_errno(SG_ERROR_MALLOC, NULL);
604 tdb 1.46 }
605     return tmp;
606 ats 1.18 }