gst/: GLib 2.6 g_flags_get_first_value has a bug that triggers an infinite loop
[platform/upstream/gstreamer.git] / gst / glib-compat.c
1 /*
2  * glib-compat.c
3  * Functions copied from glib 2.6 and 2.8
4  *
5  * Copyright 2005 David Schleef <ds@schleef.org>
6  */
7
8 /* gfileutils.c - File utility functions
9  *
10  *  Copyright 2000 Red Hat, Inc.
11  *
12  * GLib is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU Lesser General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * GLib is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GLib; see the file COPYING.LIB.  If not,
24  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25  *   Boston, MA 02111-1307, USA.
26  */
27
28 #include "config.h"
29
30 #include <glib.h>
31 #if GLIB_CHECK_VERSION (2, 6, 0)
32 #include <glib/gstdio.h>
33 #endif
34
35 #include <stdio.h>
36 #include <errno.h>
37
38 #include "glib-compat.h"
39
40 #include <sys/stat.h>
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #include <sys/types.h>
45 #if 0
46 #include <stdlib.h>
47 #include <stdarg.h>
48 #include <string.h>
49 #ifndef G_OS_WIN32
50 #include <sys/wait.h>
51 #endif
52 #include <fcntl.h>
53 #endif
54
55
56 #ifdef G_OS_WIN32
57 #include <windows.h>
58 #include <io.h>
59 #endif /* G_OS_WIN32 */
60
61
62 #ifdef G_OS_WIN32
63 #define G_DIR_SEPARATOR '\\'
64 #define G_DIR_SEPARATOR_S "\\"
65 #define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR || (c) == '/')
66 #define G_SEARCHPATH_SEPARATOR ';'
67 #define G_SEARCHPATH_SEPARATOR_S ";"
68 #else
69 #define G_DIR_SEPARATOR '/'
70 #define G_DIR_SEPARATOR_S "/"
71 #define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR)
72 #define G_SEARCHPATH_SEPARATOR ':'
73 #define G_SEARCHPATH_SEPARATOR_S ":"
74 #endif
75
76
77 #if !GLIB_CHECK_VERSION (2, 8, 0)
78 /**
79  * g_mkdir_with_parents:
80  * @pathname: a pathname in the GLib file name encoding
81  * @mode: permissions to use for newly created directories
82  *
83  * Create a directory if it doesn't already exist. Create intermediate
84  * parent directories as needed, too.
85  *
86  * Returns: 0 if the directory already exists, or was successfully
87  * created. Returns -1 if an error occurred, with errno set.
88  *
89  * Since: 2.8
90  */
91 int
92 g_mkdir_with_parents (const gchar * pathname, int mode)
93 {
94   gchar *fn, *p;
95
96   if (pathname == NULL || *pathname == '\0') {
97     errno = EINVAL;
98     return -1;
99   }
100
101   fn = g_strdup (pathname);
102
103   if (g_path_is_absolute (fn))
104     p = (gchar *) g_path_skip_root (fn);
105   else
106     p = fn;
107
108   do {
109     while (*p && !G_IS_DIR_SEPARATOR (*p))
110       p++;
111
112     if (!*p)
113       p = NULL;
114     else
115       *p = '\0';
116
117     if (!g_file_test (fn, G_FILE_TEST_EXISTS)) {
118       if (g_mkdir (fn, mode) == -1) {
119         int errno_save = errno;
120
121         g_free (fn);
122         errno = errno_save;
123         return -1;
124       }
125     } else if (!g_file_test (fn, G_FILE_TEST_IS_DIR)) {
126       g_free (fn);
127       errno = ENOTDIR;
128       return -1;
129     }
130     if (p) {
131       *p++ = G_DIR_SEPARATOR;
132       while (*p && G_IS_DIR_SEPARATOR (*p))
133         p++;
134     }
135   }
136   while (p);
137
138   g_free (fn);
139
140   return 0;
141 }
142 #endif
143
144
145 #if !GLIB_CHECK_VERSION (2, 6, 0)
146 /**
147  * g_mkdir: 
148  * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
149  * @mode: permissions to use for the newly created directory
150  *
151  * A wrapper for the POSIX mkdir() function. The mkdir() function 
152  * attempts to create a directory with the given name and permissions.
153  * 
154  * See the C library manual for more details about mkdir().
155  *
156  * Returns: 0 if the directory was successfully created, -1 if an error 
157  *    occurred
158  * 
159  * Since: 2.6
160  */
161 int
162 g_mkdir (const gchar * filename, int mode)
163 {
164 #ifdef G_OS_WIN32
165   if (G_WIN32_HAVE_WIDECHAR_API ()) {
166     wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
167     int retval;
168     int save_errno;
169
170     if (wfilename == NULL) {
171       errno = EINVAL;
172       return -1;
173     }
174
175     retval = _wmkdir (wfilename);
176     save_errno = errno;
177
178     g_free (wfilename);
179
180     errno = save_errno;
181     return retval;
182   } else {
183     gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
184     int retval;
185     int save_errno;
186
187     if (cp_filename == NULL) {
188       errno = EINVAL;
189       return -1;
190     }
191
192     retval = mkdir (cp_filename);
193     save_errno = errno;
194
195     g_free (cp_filename);
196
197     errno = save_errno;
198     return retval;
199   }
200 #else
201   return mkdir (filename, mode);
202 #endif
203 }
204 #endif
205
206 #if !GLIB_CHECK_VERSION (2, 6, 0)
207 /**
208  * g_stat: 
209  * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
210  * @buf: a pointer to a <structname>stat</structname> struct, which
211  *    will be filled with the file information
212  *
213  * A wrapper for the POSIX stat() function. The stat() function 
214  * returns information about a file.
215  * 
216  * See the C library manual for more details about stat().
217  *
218  * Returns: 0 if the information was successfully retrieved, -1 if an error 
219  *    occurred
220  * 
221  * Since: 2.6
222  */
223 int
224 g_stat (const gchar * filename, struct stat *buf)
225 {
226 #ifdef G_OS_WIN32
227   if (G_WIN32_HAVE_WIDECHAR_API ()) {
228     wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
229     int retval;
230     int save_errno;
231
232     if (wfilename == NULL) {
233       errno = EINVAL;
234       return -1;
235     }
236
237     retval = _wstat (wfilename, (struct _stat *) buf);
238     save_errno = errno;
239
240     g_free (wfilename);
241
242     errno = save_errno;
243     return retval;
244   } else {
245     gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
246     int retval;
247     int save_errno;
248
249     if (cp_filename == NULL) {
250       errno = EINVAL;
251       return -1;
252     }
253
254     retval = stat (cp_filename, buf);
255     save_errno = errno;
256
257     g_free (cp_filename);
258
259     errno = save_errno;
260     return retval;
261   }
262 #else
263   return stat (filename, buf);
264 #endif
265 }
266 #endif
267
268 /* This version is copied from GLib 2.8.
269  * In GLib 2.6, it didn't check for a flag value being NULL, hence it
270  * hits an infinite loop in our flags serialize function
271  */
272 GFlagsValue *
273 gst_flags_get_first_value (GFlagsClass * flags_class, guint value)
274 {
275   g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
276
277   if (flags_class->n_values) {
278     GFlagsValue *flags_value;
279
280     if (value == 0) {
281       for (flags_value = flags_class->values; flags_value->value_name;
282           flags_value++)
283         if (flags_value->value == 0)
284           return flags_value;
285     } else {
286       for (flags_value = flags_class->values; flags_value->value_name;
287           flags_value++)
288         if (flags_value->value != 0
289             && (flags_value->value & value) == flags_value->value)
290           return flags_value;
291     }
292   }
293
294   return NULL;
295 }