libtool installs/uninstalls the import library, no need to do it
[platform/upstream/glib.git] / glib / gmappedfile.c
1 /* GLIB - Library of useful routines for C programming
2  * gmappedfile.c: Simplified wrapper around the mmap() function.
3  *
4  * Copyright 2005 Matthias Clasen
5  *
6  * 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 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23
24 #include <errno.h>
25 #include <sys/types.h> 
26 #include <sys/stat.h> 
27 #include <fcntl.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #ifdef HAVE_MMAP
32 #include <sys/mman.h>
33 #endif
34
35 #include "glibconfig.h"
36
37 #ifdef G_OS_WIN32
38 #include <windows.h>
39 #endif
40
41 #include "gconvert.h"
42 #include "gerror.h"
43 #include "gfileutils.h"
44 #include "gmappedfile.h"
45 #include "gmem.h"
46 #include "gmessages.h"
47 #include "gstdio.h"
48 #include "gstrfuncs.h"
49
50 #include "glibintl.h"
51
52 #include "galias.h"
53
54 #ifndef _O_BINARY
55 #define _O_BINARY 0
56 #endif
57
58 #ifndef MAP_FAILED
59 #define MAP_FAILED ((void *) -1)
60 #endif
61
62 struct _GMappedFile 
63 {
64   gsize  length;
65   gchar *contents;
66 #ifdef G_OS_WIN32
67   HANDLE mapping;
68 #endif
69 };
70
71 /**
72  * g_mapped_file_new:
73  * @filename: The path of the file to load, in the GLib filename encoding
74  * @writable: wether the mapping should be writable
75  * @error: return location for a #GError, or %NULL
76  *
77  * Maps a file into memory. On UNIX, this is using the mmap() function.
78  *
79  * If @writable is %TRUE, the mapped buffer may be modified, otherwise
80  * it is an error to modify the mapped buffer. Modifications to the buffer 
81  * are not visible to other processes mapping the same file, and are not 
82  * written back to the file.
83  *
84  * Note that modifications of the underlying file might affect the contents
85  * of the #GMappedFile. Therefore, mapping should only be used if the file 
86  * will not be modified, or if all modifications of the file are done
87  * atomically (e.g. using g_file_set_contents()). 
88  *
89  * Return value: a newly allocated #GMappedFile which must be freed
90  *    with g_mapped_file_free(), or %NULL if the mapping failed. 
91  *
92  * Since: 2.8
93  */
94 GMappedFile *
95 g_mapped_file_new (const gchar  *filename,
96                    gboolean      writable,
97                    GError      **error)
98 {
99   GMappedFile *file;
100   int fd;
101   struct stat st;
102
103   g_return_val_if_fail (filename != NULL, NULL);
104   g_return_val_if_fail (!error || *error == NULL, NULL);
105
106   fd = g_open (filename, (writable ? O_RDWR : O_RDONLY) | _O_BINARY, 0);
107   if (fd == -1)
108     {
109       int save_errno = errno;
110       gchar *display_filename = g_filename_display_name (filename);
111       
112       g_set_error (error,
113                    G_FILE_ERROR,
114                    g_file_error_from_errno (save_errno),
115                    _("Failed to open file '%s': open() failed: %s"),
116                    display_filename, 
117                    g_strerror (save_errno));
118       g_free (display_filename);
119       return NULL;
120     }
121
122   file = g_new0 (GMappedFile, 1);
123
124   if (fstat (fd, &st) == -1)
125     {
126       int save_errno = errno;
127       gchar *display_filename = g_filename_display_name (filename);
128
129       g_set_error (error,
130                    G_FILE_ERROR,
131                    g_file_error_from_errno (save_errno),
132                    _("Failed to get attributes of file '%s': fstat() failed: %s"),
133                    display_filename, 
134                    g_strerror (save_errno));
135       g_free (display_filename);
136       goto out;
137     }
138
139   file->contents = MAP_FAILED;
140
141 #ifdef HAVE_MMAP
142   file->length = st.st_size;
143   file->contents = (gchar *) mmap (NULL, st.st_size,
144                                    writable ? PROT_READ|PROT_WRITE : PROT_READ,
145                                    MAP_PRIVATE, fd, 0);
146 #endif
147 #ifdef G_OS_WIN32
148   file->length = st.st_size;
149   file->mapping = CreateFileMapping ((HANDLE) _get_osfhandle (fd), NULL,
150                                      writable ? PAGE_WRITECOPY : PAGE_READONLY,
151                                      0, 0,
152                                      NULL);
153   if (file->mapping != NULL)
154     {
155       file->contents = MapViewOfFile (file->mapping,
156                                       writable ? FILE_MAP_COPY : FILE_MAP_READ,
157                                       0, 0,
158                                       0);
159       if (file->contents == NULL)
160         {
161           file->contents = MAP_FAILED;
162           CloseHandle (file->mapping);
163           file->mapping = NULL;
164         }
165     }
166 #endif
167
168   
169   if (file->contents == MAP_FAILED)
170     {
171       int save_errno = errno;
172       gchar *display_filename = g_filename_display_name (filename);
173       
174       g_set_error (error,
175                    G_FILE_ERROR,
176                    g_file_error_from_errno (save_errno),
177                    _("Failed to map file '%s': mmap() failed: %s"),
178                    display_filename,
179                    g_strerror (save_errno));
180       g_free (display_filename);
181       goto out;
182     }
183
184   close (fd);
185   return file;
186
187  out:
188   close (fd);
189   g_free (file);
190
191   return NULL;
192 }
193
194 /**
195  * g_mapped_file_get_length:
196  * @file: a #GMappedFile
197  *
198  * Returns the length of the contents of a #GMappedFile.
199  *
200  * Returns: the length of the contents of @file.
201  *
202  * Since: 2.8
203  */
204 gsize
205 g_mapped_file_get_length (GMappedFile *file)
206 {
207   g_return_val_if_fail (file != NULL, 0);
208
209   return file->length;
210 }
211
212 /**
213  * g_mapped_file_get_contents:
214  * @file: a #GMappedFile
215  *
216  * Returns the contents of a #GMappedFile. 
217  *
218  * Note that the contents may not be zero-terminated,
219  * even if the #GMappedFile is backed by a text file.
220  *
221  * Returns: the contents of @file.
222  *
223  * Since: 2.8
224  */
225 gchar *
226 g_mapped_file_get_contents (GMappedFile *file)
227 {
228   g_return_val_if_fail (file != NULL, NULL);
229
230   return file->contents;
231 }
232
233 /**
234  * g_mapped_file_free:
235  * @file: a #GMappedFile
236  *
237  * Unmaps the buffer of @file and frees it. 
238  *
239  * Since: 2.8
240  */
241 void
242 g_mapped_file_free (GMappedFile *file)
243 {
244   g_return_if_fail (file != NULL);
245
246 #ifdef HAVE_MMAP
247   munmap (file->contents, file->length);
248 #endif
249 #ifdef G_OS_WIN32
250   UnmapViewOfFile (file->contents);
251   CloseHandle (file->mapping);
252 #endif
253
254   g_free (file);
255 }
256
257
258 #define __G_MAPPED_FILE_C__
259 #include "galiasdef.c"