33bbd1f71f890949c6bac4524b7b4bd67e4e3d0c
[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
36 #include "gconvert.h"
37 #include "gerror.h"
38 #include "gfileutils.h"
39 #include "gmappedfile.h"
40 #include "gmem.h"
41 #include "gmessages.h"
42 #include "gstdio.h"
43 #include "gstrfuncs.h"
44
45 #include "glibintl.h"
46
47 #include "galias.h"
48
49 #ifndef MAP_FAILED
50 #define MAP_FAILED ((void *) -1)
51 #endif
52
53 struct _GMappedFile 
54 {
55   gsize  length;
56   gchar *contents;
57 };
58
59 /**
60  * g_mapped_file_new:
61  * @filename: The path of the file to load, in the GLib filename encoding
62  * @writable: wether the mapping should be writable
63  * @error: return location for a #GError, or %NULL
64  *
65  * Maps a file into memory. On UNIX, this is using the mmap() function.
66  *
67  * If @writable is %TRUE, the mapped buffer may be modified, otherwise
68  * it is an error to modify the mapped buffer. Modifications to the buffer 
69  * are not visible to other processes mapping the same file, and are not 
70  * written back to the file.
71  *
72  * Note that modifications of the underlying file might affect the contents
73  * of the #GMappedFile. Therefore, mapping should only be used if the file 
74  * will not be modified, or if all modifications of the file are done
75  * atomically (e.g. using g_file_set_contents()). 
76  *
77  * Return value: a newly allocated #GMappedFile which must be freed
78  *    with g_mapped_file_free(), or %NULL if the mapping failed. 
79  *
80  * Since: 2.8
81  */
82 GMappedFile *
83 g_mapped_file_new (const gchar  *filename,
84                    gboolean      writable,
85                    GError      **error)
86 {
87   GMappedFile *file;
88   int fd;
89   struct stat st;
90
91   g_return_val_if_fail (filename != NULL, NULL);
92   g_return_val_if_fail (!error || *error == NULL, NULL);
93
94   fd = g_open (filename, writable ? O_RDWR : O_RDONLY);
95   if (fd == -1)
96     {
97       int save_errno = errno;
98       gchar *display_filename = g_filename_display_name (filename);
99       
100       g_set_error (error,
101                    G_FILE_ERROR,
102                    g_file_error_from_errno (save_errno),
103                    _("Failed to open file '%s': open() failed: %s"),
104                    display_filename, 
105                    g_strerror (save_errno));
106       g_free (display_filename);
107       return NULL;
108     }
109
110   file = g_new0 (GMappedFile, 1);
111
112   if (fstat (fd, &st) == -1)
113     {
114       int save_errno = errno;
115       gchar *display_filename = g_filename_display_name (filename);
116
117       g_set_error (error,
118                    G_FILE_ERROR,
119                    g_file_error_from_errno (save_errno),
120                    _("Failed to get attributes of file '%s': fstat() failed: %s"),
121                    display_filename, 
122                    g_strerror (save_errno));
123       g_free (display_filename);
124       goto out;
125     }
126
127   file->contents = MAP_FAILED;
128
129 #ifdef HAVE_MMAP
130   file->length = st.st_size;
131   file->contents = (gchar *) mmap (NULL, st.st_size,
132                                    writable ? PROT_READ|PROT_WRITE : PROT_READ,
133                                    MAP_PRIVATE, fd, 0);
134 #endif
135   
136   if (file->contents == MAP_FAILED)
137     {
138       int save_errno = errno;
139       gchar *display_filename = g_filename_display_name (filename);
140       
141       g_set_error (error,
142                    G_FILE_ERROR,
143                    g_file_error_from_errno (save_errno),
144                    _("Failed to map file '%s': mmap() failed: %s"),
145                    display_filename,
146                    g_strerror (save_errno));
147       g_free (display_filename);
148       goto out;
149     }
150
151   close (fd);
152   return file;
153
154  out:
155   close (fd);
156   g_free (file);
157
158   return NULL;
159 }
160
161 /**
162  * g_mapped_file_get_length:
163  * @file: a #GMappedFile
164  *
165  * Returns the length of the contents of a #GMappedFile.
166  *
167  * Returns: the length of the contents of @file.
168  *
169  * Since: 2.8
170  */
171 gsize
172 g_mapped_file_get_length (GMappedFile *file)
173 {
174   g_return_val_if_fail (file != NULL, 0);
175
176   return file->length;
177 }
178
179 /**
180  * g_mapped_file_get_contents:
181  * @file: a #GMappedFile
182  *
183  * Returns the contents of a #GMappedFile. 
184  *
185  * Note that the contents may not be zero-terminated,
186  * even if the #GMappedFile is backed by a text file.
187  *
188  * Returns: the contents of @file.
189  *
190  * Since: 2.8
191  */
192 gchar *
193 g_mapped_file_get_contents (GMappedFile *file)
194 {
195   g_return_val_if_fail (file != NULL, NULL);
196
197   return file->contents;
198 }
199
200 /**
201  * g_mapped_file_free:
202  * @file: a #GMappedFile
203  *
204  * Unmaps the buffer of @file and frees it. 
205  *
206  * For writable, shared mappings, the contents
207  * will be written back to the file at this point.
208  *
209  * Since: 2.8
210  */
211 void
212 g_mapped_file_free (GMappedFile *file)
213 {
214   g_return_if_fail (file != NULL);
215
216 #ifdef HAVE_MMAP
217   munmap (file->contents, file->length);
218 #endif
219 }
220
221
222 #define __G_MAPPED_FILE_C__
223 #include "galiasdef.c"