1 /**
2 * RRDtool - src/rrd_utils.c
3 * Copyright (C) 2009 Kevin Brintnall
4 * Copyright (C) 2008 Sebastian Harl
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; only version 2 of the License is applicable.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * Authors:
20 * kevin brintnall <kbrint@rufus.net>
21 * Sebastian Harl <sh@tokkee.org>
22 **/
24 #include "rrd_tool.h"
26 #include <assert.h>
27 #include <errno.h>
28 #include <libgen.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
35 #ifdef WIN32
36 # define random() rand()
37 # define srandom(x) srand(x)
38 # define getpid() 0
39 #endif /* WIN32 */
41 /* make sure that the random number generator seeded EXACTLY ONCE */
42 long rrd_random(void)
43 {
44 static int rand_init = 0;
45 if (!rand_init) {
46 srandom((unsigned int) time(NULL) + (unsigned int) getpid());
47 rand_init++;
48 }
50 return random();
51 }
53 /* rrd_add_ptr: add a pointer to a dynamically sized array of pointers,
54 * realloc as necessary. returns 1 on success, 0 on failure.
55 */
57 int rrd_add_ptr(void ***dest, size_t *dest_size, void *src)
58 {
59 void **temp;
61 assert(dest != NULL);
63 temp = (void **) rrd_realloc(*dest, (*dest_size+1) * sizeof(*dest));
64 if (!temp)
65 return 0;
67 *dest = temp;
68 temp[*dest_size] = src;
69 (*dest_size)++;
71 return 1;
72 }
74 /* like rrd_add_ptr, but calls strdup() on a string first. */
75 int rrd_add_strdup(char ***dest, size_t *dest_size, char *src)
76 {
77 char *dup_src;
78 int add_ok;
80 assert(dest != NULL);
81 assert(src != NULL);
83 dup_src = strdup(src);
84 if (!dup_src)
85 return 0;
87 add_ok = rrd_add_ptr((void ***)dest, dest_size, (void *)dup_src);
88 if (!add_ok)
89 free(dup_src);
91 return add_ok;
92 }
94 void rrd_free_ptrs(void ***src, size_t *cnt)
95 {
96 void **sp;
98 assert(src != NULL);
99 sp = *src;
101 if (sp == NULL)
102 return;
104 while (*cnt > 0) {
105 (*cnt)--;
106 free(sp[*cnt]);
107 }
109 free (sp);
110 *src = NULL;
111 }
113 /* recursively create the directory named by 'pathname'
114 * (similar to "mkdir -p" on the command line) */
115 int rrd_mkdir_p(const char *pathname, mode_t mode)
116 {
117 struct stat sb;
119 char *pathname_copy;
120 char *base_dir;
122 if ((NULL == pathname) || ('\0' == *pathname)) {
123 errno = EINVAL;
124 return -1;
125 }
127 if (0 == stat(pathname, &sb)) {
128 if (! S_ISDIR(sb.st_mode)) {
129 errno = ENOTDIR;
130 return -1;
131 }
132 return 0;
133 }
135 /* keep errno as set by stat() */
136 if (ENOENT != errno)
137 return -1;
139 /* dirname might modify its first argument */
140 if (NULL == (pathname_copy = strdup(pathname)))
141 return -1;
143 base_dir = dirname(pathname_copy);
145 if (0 != rrd_mkdir_p(base_dir, mode)) {
146 int orig_errno = errno;
147 free(pathname_copy);
148 errno = orig_errno;
149 return -1;
150 }
152 free(pathname_copy);
154 /* keep errno as set by mkdir() */
155 if (0 != mkdir(pathname, mode))
156 return -1;
157 return 0;
158 } /* rrd_mkdir_p */