Introduce the idea of a filename encoding, which is *literally* the
[platform/upstream/glib.git] / glib / gstdio.c
1 /* gstdio.c - wrappers for C library functions
2  *
3  * Copyright 2004 Tor Lillqvist
4  *
5  * GLib is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * GLib is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with GLib; see the file COPYING.LIB.  If not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30
31 #ifdef G_OS_WIN32
32 #include <wchar.h>
33 #include <io.h>
34 #endif
35
36 #include "galias.h"
37 #include "glib.h"
38 #include "gstdio.h"
39
40 #if !defined (G_OS_UNIX) && !defined (G_OS_WIN32)
41 #error Please port this to your operating system
42 #endif
43
44
45 /**
46  * g_open:
47  * @filename: a pathname in the GLib file name encoding
48  * @flags: as in open()
49  * @mode: as in open()
50  *
51  * A wrapper for the POSIX open() function. The open() function is used 
52  * to convert a pathname into a file descriptor.
53  *
54  * See the C library manual for more details about open().
55  *
56  * The point of these wrappers is to make it possible to handle file
57  * names with any Unicode characters in them on Windows without having
58  * to use ifdefs and the wide character API in the application code.
59  *
60  * The pathname argument should be in the GLib file name encoding. On
61  * POSIX this is the actual on-disk encoding which might correspond to
62  * the locale settings of the process (or the 
63  * <envar>G_FILENAME_ENCODING</envar> environment variable), or not.
64  *
65  * On Windows the GLib file name encoding is UTF-8. Note that the
66  * Microsoft C library does not use UTF-8, but has separate APIs for
67  * current system code page and wide characters (UTF-16). The GLib
68  * wrappers call the wide character API if present (on modern Windows
69  * systems), otherwise convert to/from the system code page.
70  * 
71  * Returns: a new file descriptor, or -1 if an error occurred
72  * 
73  * Since: 2.6
74  */
75 int
76 g_open (const gchar *filename,
77         int          flags,
78         int          mode)
79 {
80 #ifdef G_OS_WIN32
81   if (G_WIN32_HAVE_WIDECHAR_API ())
82     {
83       wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
84       int retval = _wopen (wfilename, flags, mode);
85       int save_errno = errno;
86       
87       g_free (wfilename);
88
89       errno = save_errno;
90       return retval;
91     }
92   else
93     {    
94       gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
95       int retval = open (cp_filename, flags, mode);
96       int save_errno = errno;
97
98       g_free (cp_filename);
99
100       errno = save_errno;
101       return retval;
102     }
103 #else
104   return open (filename, flags, mode);
105 #endif
106 }
107
108 /**
109  * g_rename:
110  * @oldfilename: a pathname in the GLib file name encoding
111  * @newfilename: a pathname in the GLib file name encoding
112  *
113  * A wrapper for the POSIX rename() function. The rename() function 
114  * renames a file, moving it between directories if required.
115  * 
116  * See the C library manual for more details about rename().
117  *
118  * Returns: 0 if the renaming succeeded, -1 if an error occurred
119  * 
120  * Since: 2.6
121  */
122 int
123 g_rename (const gchar *oldfilename,
124           const gchar *newfilename)
125 {
126 #ifdef G_OS_WIN32
127   if (G_WIN32_HAVE_WIDECHAR_API ())
128     {
129       wchar_t *woldfilename = g_utf8_to_utf16 (oldfilename, -1, NULL, NULL, NULL);
130       wchar_t *wnewfilename = g_utf8_to_utf16 (newfilename, -1, NULL, NULL, NULL);
131       int retval = _wrename (woldfilename, wnewfilename);
132       int save_errno = errno;
133       
134       g_free (woldfilename);
135       g_free (wnewfilename);
136       
137       errno = save_errno;
138       return retval;
139     }
140   else
141     {
142       gchar *cp_oldfilename = g_locale_from_utf8 (oldfilename, -1, NULL, NULL, NULL);
143       gchar *cp_newfilename = g_locale_from_utf8 (newfilename, -1, NULL, NULL, NULL);
144       int retval = rename (cp_oldfilename, cp_newfilename);
145       int save_errno = errno;
146
147       g_free (cp_oldfilename);
148       g_free (cp_newfilename);
149
150       errno = save_errno;
151       return retval;
152     }
153 #else
154   return rename (oldfilename, newfilename);
155 #endif
156 }
157
158 /**
159  * g_mkdir: 
160  * @filename: a pathname in the GLib file name encoding
161  * @mode: permissions to use for the newly created directory
162  *
163  * A wrapper for the POSIX mkdir() function. The mkdir() function 
164  * attempts to create a directory with the given name and permissions.
165  * 
166  * See the C library manual for more details about mkdir().
167  *
168  * Returns: 0 if the directory was successfully created, -1 if an error 
169  *    occurred
170  * 
171  * Since: 2.6
172  */
173 int
174 g_mkdir (const gchar *filename,
175          int          mode)
176 {
177 #ifdef G_OS_WIN32
178   if (G_WIN32_HAVE_WIDECHAR_API ())
179     {
180       wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
181       int retval = _wmkdir (wfilename);
182       int save_errno = errno;
183
184       g_free (wfilename);
185       
186       errno = save_errno;
187       return retval;
188     }
189   else
190     {
191       gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
192       int retval = mkdir (cp_filename);
193       int 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
205 /**
206  * g_stat: 
207  * @filename: a pathname in the GLib file name encoding
208  * @buf: a pointer to a <structname>stat</structname> struct, which
209  *    will be filled with the file information
210  *
211  * A wrapper for the POSIX stat() function. The stat() function 
212  * returns information about a file.
213  * 
214  * See the C library manual for more details about stat().
215  *
216  * Returns: 0 if the directory was successfully created, -1 if an error 
217  *    occurred
218  * 
219  * Since: 2.6
220  */
221 int
222 g_stat (const gchar *filename,
223         struct stat *buf)
224 {
225 #ifdef G_OS_WIN32
226   if (G_WIN32_HAVE_WIDECHAR_API ())
227     {
228       wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
229       int retval = _wstat (wfilename, (struct _stat *) buf);
230       int save_errno = errno;
231
232       g_free (wfilename);
233
234       errno = save_errno;
235       return retval;
236     }
237   else
238     {
239       gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
240       int retval = stat (cp_filename, buf);
241       int save_errno = errno;
242
243       g_free (cp_filename);
244
245       errno = save_errno;
246       return retval;
247     }
248 #else
249   return stat (filename, buf);
250 #endif
251 }
252
253 /**
254  * g_unlink:
255  * @filename: a pathname in the GLib file name encoding
256  *
257  * A wrapper for the POSIX unlink() function. The unlink() function 
258  * deletes a name from the filesystem. If this was the last link to the 
259  * file and no processes have it opened, the diskspace occupied by the
260  * file is freed.
261  * 
262  * See the C library manual for more details about unlink().
263  *
264  * Returns: 0 if the directory was successfully created, -1 if an error 
265  *    occurred
266  * 
267  * Since: 2.6
268  */
269 int
270 g_unlink (const gchar *filename)
271 {
272 #ifdef G_OS_WIN32
273   if (G_WIN32_HAVE_WIDECHAR_API ())
274     {
275       wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
276       int retval = _wunlink (wfilename);
277       int save_errno = errno;
278
279       g_free (wfilename);
280
281       errno = save_errno;
282       return retval;
283     }
284   else
285     {
286       gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
287       int retval = unlink (cp_filename);
288       int save_errno = errno;
289
290       g_free (cp_filename);
291
292       errno = save_errno;
293       return retval;
294     }
295 #else
296   return unlink (filename);
297 #endif
298 }
299
300 /**
301  * g_remove:
302  * @filename: a pathname in the GLib file name encoding
303  *
304  * A wrapper for the POSIX remove() function. The remove() function 
305  * deletes a name from the filesystem. It calls unlink() for files
306  * and rmdir() for directories.
307  * 
308  * See the C library manual for more details about remove().
309  *
310  * Returns: 0 if the directory was successfully created, -1 if an error 
311  *    occurred
312  * 
313  * Since: 2.6
314  */
315 int
316 g_remove (const gchar *filename)
317 {
318 #ifdef G_OS_WIN32
319   if (G_WIN32_HAVE_WIDECHAR_API ())
320     {
321       wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
322       int retval = _wremove (wfilename);
323       int save_errno = errno;
324
325       g_free (wfilename);
326
327       errno = save_errno;
328       return retval;
329     }
330   else
331     {
332       gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
333       int retval = remove (cp_filename);
334       int save_errno = errno;
335
336       g_free (cp_filename);
337
338       errno = save_errno;
339       return retval;
340     }
341 #else
342   return remove (filename);
343 #endif
344 }
345
346 /**
347  * g_fopen:
348  * @filename: a pathname in the GLib file name encoding
349  * @mode: a string describing the mode in which the file should be 
350  *   opened
351  *
352  * A wrapper for the POSIX fopen() function. The fopen() function opens
353  * a file and associates a new stream with it. 
354  * 
355  * See the C library manual for more details about fopen().
356  *
357  * Returns: A <typename>FILE</typename> pointer if the file was successfully
358  *    opened, or %NULL if an error occurred
359  * 
360  * Since: 2.6
361  */
362 FILE *
363 g_fopen (const gchar *filename,
364          const gchar *mode)
365 {
366 #ifdef G_OS_WIN32
367   if (G_WIN32_HAVE_WIDECHAR_API ())
368     {
369       wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
370       wchar_t *wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
371       FILE *retval = _wfopen (wfilename, wmode);
372       int save_errno = errno;
373
374       g_free (wfilename);
375       g_free (wmode);
376
377       errno = save_errno;
378       return retval;
379     }
380   else
381     {
382       gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
383       FILE *retval = fopen (cp_filename, mode);
384       int save_errno = errno;
385
386       g_free (cp_filename);
387
388       errno = save_errno;
389       return retval;
390     }
391 #else
392   return fopen (filename, mode);
393 #endif
394 }
395
396 /**
397  * g_freopen:
398  * @filename: a pathname in the GLib file name encoding
399  * @mode: a string describing the mode in which the file should be 
400  *   opened
401  * @stream: an existing stream which will be reused, or %NULL
402  *
403  * A wrapper for the POSIX freopen() function. The freopen() function
404  * opens a file and associates it with an existing stream.
405  * 
406  * See the C library manual for more details about freopen().
407  *
408  * Returns: A <typename>FILE</typename> pointer if the file was successfully
409  *    opened, or %NULL if an error occurred.
410  * 
411  * Since: 2.6
412  */
413 FILE *
414 g_freopen (const gchar *filename,
415            const gchar *mode,
416            FILE        *stream)
417 {
418 #ifdef G_OS_WIN32
419   if (G_WIN32_HAVE_WIDECHAR_API ())
420     {
421       wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
422       wchar_t *wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
423       FILE *retval = _wfreopen (wfilename, wmode, stream);
424       int save_errno = errno;
425
426       g_free (wfilename);
427       g_free (wmode);
428
429       errno = save_errno;
430       return retval;
431     }
432   else
433     {
434       gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
435       FILE *retval = freopen (cp_filename, mode, stream);
436       int save_errno = errno;
437
438       g_free (cp_filename);
439
440       errno = save_errno;
441       return retval;
442     }
443 #else
444   return freopen (filename, mode, stream);
445 #endif
446 }